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:
parent
230ad972f0
commit
eef34c972a
@ -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;
|
||||
};
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user