1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 02:12:45 +01:00

Script pickups: implement weapon pickups, improve pickup code

This commit is contained in:
Daniel Evans 2016-05-25 22:59:41 +01:00
parent 230ad972f0
commit eef34c972a
9 changed files with 184 additions and 94 deletions

View File

@ -1,15 +0,0 @@
#pragma once
#include <objects/PickupObject.hpp>
class GenericPickup : public PickupObject
{
public:
GenericPickup(GameWorld* world, const glm::vec3& position, int modelID, int type);
virtual bool onCharacterTouch(CharacterObject* character);
private:
int type;
};

View File

@ -15,7 +15,7 @@ class ItemPickup : public PickupObject
InventoryItem* item;
public:
ItemPickup(GameWorld* world, const glm::vec3& position, InventoryItem* item);
ItemPickup(GameWorld* world, const glm::vec3& position, PickupType type, InventoryItem* item);
bool onCharacterTouch(CharacterObject* character);
};

View File

@ -15,20 +15,37 @@ class CharacterObject;
*/
class PickupObject : public GameObject
{
btPairCachingGhostObject* _ghost;
btSphereShape* _shape;
bool _enabled;
float _enableTimer;
bool collected;
int _modelID;
VisualFX* corona;
public:
enum PickupType {
InShop = 1,
OnStreet = 2,
Once = 3,
OnceTimeout = 4,
Collectable = 5,
OutOfStock = 6,
Money = 7,
MineInactive= 8,
MineArmed = 9,
NauticalMineInactive=10,
NauticalMineArmed=11,
FloatingPackage=12,
FloatingPackageFloating=13,
OnStreetSlow=14
};
enum /*BehaviourFlags*/ {
PickupOnFoot = 1,
PickupInVehicle = 2
};
PickupObject(GameWorld* world, const glm::vec3& position, int modelID);
static bool doesRespawn(PickupType type);
static float respawnTime(PickupType type);
static uint32_t behaviourFlags(PickupType type);
PickupObject(GameWorld* world, const glm::vec3& position, int modelID, PickupType type);
~PickupObject();
int getModelID() const { return _modelID; }
int getModelID() const { return m_model; }
Type type() { return Pickup; }
@ -36,10 +53,22 @@ public:
virtual bool onCharacterTouch(CharacterObject* character) = 0;
bool isEnabled() const { return _enabled; }
bool isEnabled() const { return m_enabled; }
void setEnabled(bool enabled);
bool isCollected() const { return collected; }
bool isCollected() const { return m_collected; }
private:
btPairCachingGhostObject* m_ghost;
btSphereShape* m_shape;
bool m_enabled;
float m_enableTimer;
bool m_collected;
int m_model;
VisualFX* m_corona;
PickupType m_type;
};
#endif

View File

@ -1,13 +0,0 @@
#include <objects/GenericPickup.hpp>
GenericPickup::GenericPickup(GameWorld* world, const glm::vec3& position, int modelID, int type)
: PickupObject(world, position, modelID), type(type)
{
}
bool GenericPickup::onCharacterTouch(CharacterObject* character)
{
RW_UNUSED(character);
return true;
}

View File

@ -4,8 +4,8 @@
#include <items/WeaponItem.hpp>
#include <rw/defines.hpp>
ItemPickup::ItemPickup(GameWorld *world, const glm::vec3 &position, InventoryItem* item)
: PickupObject(world, position, item->getModelID())
ItemPickup::ItemPickup(GameWorld *world, const glm::vec3 &position, PickupType type, InventoryItem* item)
: PickupObject(world, position, item->getModelID(), type)
, item(item)
{
RW_CHECK(item != nullptr, "Pickup created with null item");

View File

@ -3,56 +3,126 @@
#include <engine/GameWorld.hpp>
#include <engine/GameData.hpp>
PickupObject::PickupObject(GameWorld *world, const glm::vec3 &position, int modelID)
: GameObject(world, position, glm::quat(), nullptr),
_ghost(nullptr), _shape(nullptr), _enabled(false), collected(false), _modelID(modelID)
bool PickupObject::doesRespawn(PickupType type)
{
switch(type) {
case Once:
case OnceTimeout:
case Collectable:
case OutOfStock:
case Money:
case MineInactive:
case MineArmed:
case NauticalMineInactive:
case NauticalMineArmed:
case FloatingPackage:
case FloatingPackageFloating:
return false;
default:
return true;
}
}
float PickupObject::respawnTime(PickupType type)
{
switch(type) {
case InShop:
return 5.f;
case OnStreet:
case OnStreetSlow:
return 30.f;
default:
return 30.f;
}
}
uint32_t PickupObject::behaviourFlags(PickupType type)
{
switch(type) {
case InShop:
case OnStreet:
case Once:
case OnceTimeout:
case Collectable:
case Money:
case OnStreetSlow:
return PickupOnFoot;
case OutOfStock:
case MineInactive:
case MineArmed:
case NauticalMineInactive:
case NauticalMineArmed:
return 0;
case FloatingPackage:
case FloatingPackageFloating:
return PickupInVehicle;
default:
return 0;
}
}
PickupObject::PickupObject(GameWorld *world, const glm::vec3 &position, int modelID, PickupType type)
: GameObject(world, position, glm::quat(), nullptr)
, m_ghost(nullptr)
, m_shape(nullptr)
, m_enabled(false)
, m_collected(false)
, m_model(modelID)
, m_type(type)
{
btTransform tf;
tf.setIdentity();
tf.setOrigin(btVector3(position.x, position.y, position.z));
_ghost = new btPairCachingGhostObject;
_ghost->setUserPointer(this);
_ghost->setWorldTransform(tf);
_shape = new btSphereShape(0.5f);
_ghost->setCollisionShape(_shape);
_ghost->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT|btCollisionObject::CF_NO_CONTACT_RESPONSE);
m_ghost = new btPairCachingGhostObject;
m_ghost->setUserPointer(this);
m_ghost->setWorldTransform(tf);
m_shape = new btSphereShape(0.5f);
m_ghost->setCollisionShape(m_shape);
m_ghost->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT|btCollisionObject::CF_NO_CONTACT_RESPONSE);
corona = world->createEffect(VisualFX::Particle);
corona->particle.position = getPosition();
corona->particle.direction = glm::vec3(0.f, 0.f, 1.f);
corona->particle.orientation = VisualFX::ParticleData::Camera;
corona->particle.colour = glm::vec4(1.0f, 0.3f, 0.3f, 0.3f);
corona->particle.texture = engine->data->findTexture("coronacircle");
m_corona = world->createEffect(VisualFX::Particle);
m_corona->particle.position = getPosition();
m_corona->particle.direction = glm::vec3(0.f, 0.f, 1.f);
m_corona->particle.orientation = VisualFX::ParticleData::Camera;
m_corona->particle.colour = glm::vec4(1.0f, 0.3f, 0.3f, 0.3f);
m_corona->particle.texture = engine->data->findTexture("coronacircle");
auto flags = behaviourFlags(m_type);
RW_CHECK((flags & PickupInVehicle)==0, "In Vehicle pickup not implemented yet");
setEnabled(true);
}
PickupObject::~PickupObject()
{
if(_ghost) {
if(m_ghost) {
setEnabled(false);
engine->destroyEffect(corona);
delete _ghost;
delete _shape;
engine->destroyEffect(m_corona);
delete m_ghost;
delete m_shape;
}
}
void PickupObject::tick(float dt)
{
if(! _enabled) {
_enableTimer -= dt;
if( _enableTimer <= 0.f ) {
setEnabled(true);
collected = false;
if(! m_enabled) {
// Check if our type of pickup respawns
if (doesRespawn(m_type)) {
m_enableTimer -= dt;
if( m_enableTimer <= 0.f ) {
setEnabled(true);
m_collected = false;
}
}
}
if(_enabled) {
if(m_enabled) {
// Sort out interactions with things that may or may not be players.
btManifoldArray manifoldArray;
btBroadphasePairArray& pairArray = _ghost->getOverlappingPairCache()->getOverlappingPairArray();
btBroadphasePairArray& pairArray = m_ghost->getOverlappingPairCache()->getOverlappingPairArray();
int numPairs = pairArray.size();
auto flags = behaviourFlags(m_type);
for (int i=0;i<numPairs;i++)
{
@ -60,15 +130,18 @@ void PickupObject::tick(float dt)
const btBroadphasePair& pair = pairArray[i];
auto otherObject = static_cast<const btCollisionObject*>(
pair.m_pProxy0->m_clientObject == _ghost ? pair.m_pProxy1->m_clientObject : pair.m_pProxy0->m_clientObject);
pair.m_pProxy0->m_clientObject == m_ghost ? pair.m_pProxy1->m_clientObject : pair.m_pProxy0->m_clientObject);
if(otherObject->getUserPointer()) {
GameObject* object = static_cast<GameObject*>(otherObject->getUserPointer());
if(object->type() == Character) {
if((flags & PickupOnFoot) == PickupOnFoot
&& object->type() == Character)
{
CharacterObject* character = static_cast<CharacterObject*>(object);
collected = onCharacterTouch(character);
setEnabled( !collected );
if( ! _enabled ) {
_enableTimer = 60.f;
m_collected = onCharacterTouch(character);
setEnabled( !m_collected );
if( ! m_enabled ) {
m_enableTimer = respawnTime(m_type);
}
}
}
@ -78,14 +151,14 @@ void PickupObject::tick(float dt)
void PickupObject::setEnabled(bool enabled)
{
if( ! _enabled && enabled ) {
engine->dynamicsWorld->addCollisionObject(_ghost, btBroadphaseProxy::SensorTrigger);
corona->particle.size = glm::vec2(1.5f, 1.5f);
if( ! m_enabled && enabled ) {
engine->dynamicsWorld->addCollisionObject(m_ghost, btBroadphaseProxy::SensorTrigger);
m_corona->particle.size = glm::vec2(1.5f, 1.5f);
}
else if( _enabled && ! enabled ) {
engine->dynamicsWorld->removeCollisionObject(_ghost);
corona->particle.size = glm::vec2(0.f, 0.f);
else if( m_enabled && ! enabled ) {
engine->dynamicsWorld->removeCollisionObject(m_ghost);
m_corona->particle.size = glm::vec2(0.f, 0.f);
}
_enabled = enabled;
m_enabled = enabled;
}

View File

@ -18,9 +18,9 @@
#include <data/CutsceneData.hpp>
#include <data/Skeleton.hpp>
#include <objects/CutsceneObject.hpp>
#include <objects/PickupObject.hpp>
#include <objects/GenericPickup.hpp>
#include <objects/ItemPickup.hpp>
#include <core/Logger.hpp>
#include <items/InventoryItem.hpp>
#include <glm/gtx/string_cast.hpp>
@ -801,12 +801,31 @@ void game_create_pickup(const ScriptArguments& args)
args.getWorld()->data->loadTXD(data->textureName+".txd");
}
PickupObject* pickup = nullptr;
if ( id >= 170 && id <= 184 )
{
// Find the item for this model ID
auto world = args.getWorld();
InventoryItem *item = nullptr;
for (auto i = 0; i < maxInventorySlots; ++i)
{
item = world->getInventoryItem(i);
if (item->getModelID() == id) {
auto pickuptype = (PickupObject::PickupType)type;
pickup = new ItemPickup(args.getWorld(), pos, pickuptype, item);
world->pickupPool.insert( pickup );
world->allObjects.push_back(pickup);
*args[5].globalInteger = pickup->getGameObjectID();
}
}
}
else
{
RW_UNIMPLEMENTED("non-item pickups");
*args[5].globalInteger = 0;
}
auto pickup = new GenericPickup(args.getWorld(), pos, id, type);
args.getWorld()->pickupPool.insert( pickup );
*args[5].globalInteger = pickup->getGameObjectID();
}
bool game_is_pickup_collected(const ScriptArguments& args)

View File

@ -41,16 +41,13 @@ void IngameState::startTest()
getWorld()->state->playerObject = playerChar->getGameObjectID();
/*auto bat = new WeaponItem(getWorld()->data.weaponData["ak47"]);
_playerCharacter->addToInventory(bat);
_playerCharacter->setActiveItem(bat->getInventorySlot());*/
glm::vec3 itemspawn( 276.5f, -609.f, 36.5f);
for(int i = 1; i < maxInventorySlots; ++i) {
ItemPickup* pickup =
new ItemPickup(
getWorld(),
itemspawn,
PickupObject::OnStreet,
getWorld()->getInventoryItem(i));
getWorld()->pickupPool.insert(pickup);
getWorld()->allObjects.push_back(pickup);

View File

@ -12,7 +12,7 @@ public:
bool picked_up = false;
TestPickup(GameWorld* engine, const glm::vec3& position)
: PickupObject(engine, position, 0)
: PickupObject(engine, position, 0, OnStreet)
{}
bool onCharacterTouch(CharacterObject *character) {
@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(test_item_pickup)
auto item = Global::get().e->getInventoryItem(3);
BOOST_REQUIRE(item != nullptr);
ItemPickup* p = new ItemPickup(Global::get().e, { 30.f, 0.f, 0.f }, item );
ItemPickup* p = new ItemPickup(Global::get().e, { 30.f, 0.f, 0.f }, PickupObject::OnStreet, item);
Global::get().e->allObjects.push_back(p);