diff --git a/rwengine/include/objects/GenericPickup.hpp b/rwengine/include/objects/GenericPickup.hpp deleted file mode 100644 index 2d4eb4d0..00000000 --- a/rwengine/include/objects/GenericPickup.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -class GenericPickup : public PickupObject -{ -public: - - GenericPickup(GameWorld* world, const glm::vec3& position, int modelID, int type); - - virtual bool onCharacterTouch(CharacterObject* character); - -private: - int type; -}; \ No newline at end of file diff --git a/rwengine/include/objects/ItemPickup.hpp b/rwengine/include/objects/ItemPickup.hpp index 1ab7b641..6a5702e3 100644 --- a/rwengine/include/objects/ItemPickup.hpp +++ b/rwengine/include/objects/ItemPickup.hpp @@ -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); }; diff --git a/rwengine/include/objects/PickupObject.hpp b/rwengine/include/objects/PickupObject.hpp index 802cc534..8ce58429 100644 --- a/rwengine/include/objects/PickupObject.hpp +++ b/rwengine/include/objects/PickupObject.hpp @@ -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 diff --git a/rwengine/src/objects/GenericPickup.cpp b/rwengine/src/objects/GenericPickup.cpp deleted file mode 100644 index 14c0c1fb..00000000 --- a/rwengine/src/objects/GenericPickup.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include - -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; -} diff --git a/rwengine/src/objects/ItemPickup.cpp b/rwengine/src/objects/ItemPickup.cpp index 4fc6a280..f8de67d8 100644 --- a/rwengine/src/objects/ItemPickup.cpp +++ b/rwengine/src/objects/ItemPickup.cpp @@ -4,8 +4,8 @@ #include #include -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"); diff --git a/rwengine/src/objects/PickupObject.cpp b/rwengine/src/objects/PickupObject.cpp index 0d423e51..cd92c1b2 100644 --- a/rwengine/src/objects/PickupObject.cpp +++ b/rwengine/src/objects/PickupObject.cpp @@ -3,56 +3,126 @@ #include #include -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( - 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(otherObject->getUserPointer()); - if(object->type() == Character) { + if((flags & PickupOnFoot) == PickupOnFoot + && object->type() == Character) + { CharacterObject* character = static_cast(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; } diff --git a/rwengine/src/script/modules/ObjectModule.cpp b/rwengine/src/script/modules/ObjectModule.cpp index c42764bc..d7c02fab 100644 --- a/rwengine/src/script/modules/ObjectModule.cpp +++ b/rwengine/src/script/modules/ObjectModule.cpp @@ -18,9 +18,9 @@ #include #include #include -#include -#include +#include #include +#include #include @@ -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) diff --git a/rwgame/ingamestate.cpp b/rwgame/ingamestate.cpp index 2badb448..0819a377 100644 --- a/rwgame/ingamestate.cpp +++ b/rwgame/ingamestate.cpp @@ -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); diff --git a/tests/test_pickup.cpp b/tests/test_pickup.cpp index 1aa2ce64..5870522b 100644 --- a/tests/test_pickup.cpp +++ b/tests/test_pickup.cpp @@ -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);