1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-15 15:02:34 +02:00

Remove InventoryItem and WeaponItem

They served no purpose other than to awkwardly implement weapon firing
This is now handled in the Weapon::fire* functions, and everything else
has been changed to reference weapon data or inventory indices directly
This commit is contained in:
Daniel Evans 2016-10-19 02:22:33 +01:00
parent 44f73af9e9
commit 5c78930c1b
26 changed files with 254 additions and 519 deletions

View File

@ -58,9 +58,8 @@ set(RWENGINE_SOURCES
src/engine/SaveGame.hpp src/engine/SaveGame.hpp
src/engine/ScreenText.cpp src/engine/ScreenText.cpp
src/engine/ScreenText.hpp src/engine/ScreenText.hpp
src/items/InventoryItem.hpp src/items/Weapon.cpp
src/items/WeaponItem.cpp src/items/Weapon.hpp
src/items/WeaponItem.hpp
src/loaders/DataLoader.cpp src/loaders/DataLoader.cpp
src/loaders/DataLoader.hpp src/loaders/DataLoader.hpp
src/loaders/GenericDATLoader.cpp src/loaders/GenericDATLoader.cpp

View File

@ -1,11 +1,12 @@
#include <btBulletDynamicsCommon.h> #include <btBulletDynamicsCommon.h>
#include <ai/CharacterController.hpp> #include <ai/CharacterController.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
#include <data/Model.hpp> #include <data/Model.hpp>
#include <engine/Animator.hpp> #include <engine/Animator.hpp>
#include <items/WeaponItem.hpp> #include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
#include <items/Weapon.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
#include <rw/defines.hpp> #include <rw/defines.hpp>
constexpr float kCloseDoorIdleTime = 2.f; constexpr float kCloseDoorIdleTime = 2.f;
@ -384,14 +385,20 @@ bool Activities::ExitVehicle::update(CharacterObject *character,
return false; return false;
} }
#include <data/Model.hpp> bool Activities::UseItem::update(CharacterObject *character,
#include <engine/GameData.hpp> CharacterController *controller) {
#include <engine/GameWorld.hpp>
bool Activities::ShootWeapon::update(CharacterObject *character,
CharacterController *controller) {
RW_UNUSED(controller); RW_UNUSED(controller);
auto &wepdata = _item->getWeaponData(); if (itemslot >= kMaxInventorySlots) {
return true;
}
auto world = character->engine;
const auto &weapon = world->data->weaponData.at(itemslot);
auto &state = character->getCurrentState().weapons[itemslot];
auto animator = character->animator;
auto shootanim = world->data->animations[weapon->animation1];
auto throwanim = world->data->animations[weapon->animation2];
// Instant hit weapons loop their anim // Instant hit weapons loop their anim
// Thrown projectiles have lob / throw. // Thrown projectiles have lob / throw.
@ -400,85 +407,73 @@ bool Activities::ShootWeapon::update(CharacterObject *character,
character->setRotation( character->setRotation(
glm::angleAxis(character->getLook().x, glm::vec3{0.f, 0.f, 1.f})); glm::angleAxis(character->getLook().x, glm::vec3{0.f, 0.f, 1.f}));
RW_CHECK(wepdata->inventorySlot < maxInventorySlots, if (state.bulletsClip == 0 && state.bulletsTotal > 0) {
"Inventory slot out of bounds"); state.bulletsClip +=
auto &itemState = std::min(int(state.bulletsTotal), weapon->clipSize);
character->getCurrentState().weapons[wepdata->inventorySlot]; state.bulletsTotal -= state.bulletsClip;
if (itemState.bulletsClip == 0 && itemState.bulletsTotal > 0) {
itemState.bulletsClip +=
std::min(int(itemState.bulletsTotal), wepdata->clipSize);
itemState.bulletsTotal -= itemState.bulletsClip;
} }
bool hasammo = itemState.bulletsClip > 0; bool hasammo = state.bulletsClip > 0;
if (wepdata->fireType == WeaponData::INSTANT_HIT) { if (weapon->fireType == WeaponData::INSTANT_HIT) {
if (_item->isFiring(character) && hasammo) { if (!character->getCurrentState().primaryActive) {
auto shootanim = // Character is no longer firing
character->engine->data->animations[wepdata->animation1]; return true;
if (shootanim) { }
if (character->animator->getAnimation(AnimIndexAction) != if (hasammo && shootanim) {
shootanim) { if (animator->getAnimation(AnimIndexAction) != shootanim) {
character->playActivityAnimation(shootanim, false, false); character->playActivityAnimation(shootanim, false, false);
}
auto loopstart = wepdata->animLoopStart / 100.f;
auto loopend = wepdata->animLoopEnd / 100.f;
auto firetime = wepdata->animFirePoint / 100.f;
auto currID =
character->animator->getAnimationTime(AnimIndexAction);
if (currID >= firetime && !_fired) {
itemState.bulletsClip--;
_item->fire(character);
_fired = true;
}
if (currID > loopend) {
character->animator->setAnimationTime(AnimIndexAction,
loopstart);
_fired = false;
}
} }
} else {
if (character->animator->isCompleted(AnimIndexAction)) { auto loopstart = weapon->animLoopStart / 100.f;
return true; auto loopend = weapon->animLoopEnd / 100.f;
auto firetime = weapon->animFirePoint / 100.f;
auto currenttime = animator->getAnimationTime(AnimIndexAction);
if (currenttime >= firetime && !fired) {
state.bulletsClip--;
Weapon::fireHitscan(weapon.get(), character);
fired = true;
} }
if (currenttime > loopend) {
animator->setAnimationTime(AnimIndexAction, loopstart);
fired = false;
}
} else if (animator->isCompleted(AnimIndexAction)) {
// Should we exit this state when out of ammo?
return true;
} }
} }
/// @todo Use Thrown flag instead of project (RPG isn't thrown eg.) /// @todo Use Thrown flag instead of project (RPG isn't thrown eg.)
else if (wepdata->fireType == WeaponData::PROJECTILE && hasammo) { else if (weapon->fireType == WeaponData::PROJECTILE && hasammo) {
auto shootanim = if (animator->getAnimation(AnimIndexAction) == shootanim) {
character->engine->data->animations[wepdata->animation1]; if (character->getCurrentState().primaryActive) {
auto throwanim = power = animator->getAnimationTime(AnimIndexAction) / 0.5f;
character->engine->data->animations[wepdata->animation2]; }
if (animator->isCompleted(AnimIndexAction)) {
if (character->animator->getAnimation(AnimIndexAction) == shootanim) {
if (character->animator->isCompleted(AnimIndexAction)) {
character->playActivityAnimation(throwanim, false, false); character->playActivityAnimation(throwanim, false, false);
} }
} else if (character->animator->getAnimation(AnimIndexAction) == } else if (animator->getAnimation(AnimIndexAction) == throwanim) {
throwanim) { auto firetime = weapon->animCrouchFirePoint / 100.f;
auto firetime = wepdata->animCrouchFirePoint / 100.f; auto currID = animator->getAnimationTime(AnimIndexAction);
auto currID =
character->animator->getAnimationTime(AnimIndexAction);
if (currID >= firetime && !_fired) { if (currID >= firetime && !fired) {
itemState.bulletsClip--; state.bulletsClip--;
_item->fire(character); Weapon::fireProjectile(weapon.get(), character, power);
_fired = true; fired = true;
} }
if (character->animator->isCompleted(AnimIndexAction)) { if (animator->isCompleted(AnimIndexAction)) {
return true; return true;
} }
} else { } else {
character->playActivityAnimation(throwanim, false, true); character->playActivityAnimation(shootanim, false, true);
} }
} else if (wepdata->fireType == WeaponData::MELEE) { } else if (weapon->fireType == WeaponData::MELEE) {
RW_CHECK(wepdata->fireType != WeaponData::MELEE, RW_CHECK(weapon->fireType != WeaponData::MELEE,
"Melee attacks not implemented"); "Melee attacks not implemented");
return true; return true;
} else { } else {
RW_ERROR("Unrecognized fireType: " << wepdata->fireType); RW_ERROR("Unrecognized fireType: " << weapon->fireType);
return true; return true;
} }

View File

@ -148,7 +148,6 @@ public:
} }
// TODO: Refactor this with an ugly macro to reduce code dup. // TODO: Refactor this with an ugly macro to reduce code dup.
class WeaponItem;
/** /**
* @brief Activities for CharacterController behaviour * @brief Activities for CharacterController behaviour
@ -217,13 +216,14 @@ struct ExitVehicle : public CharacterController::Activity {
bool update(CharacterObject* character, CharacterController* controller); bool update(CharacterObject* character, CharacterController* controller);
}; };
struct ShootWeapon : public CharacterController::Activity { struct UseItem : public CharacterController::Activity {
DECL_ACTIVITY(ShootWeapon) DECL_ACTIVITY(UseItem)
WeaponItem* _item; int itemslot;
bool _fired; bool fired = false;
float power = 0.f;
ShootWeapon(WeaponItem* item) : _item(item), _fired(false) { UseItem(int slot) : itemslot(slot) {
} }
bool update(CharacterObject* character, CharacterController* controller); bool update(CharacterObject* character, CharacterController* controller);

View File

@ -9,7 +9,6 @@
#include <ai/TrafficDirector.hpp> #include <ai/TrafficDirector.hpp>
#include <data/Model.hpp> #include <data/Model.hpp>
#include <data/WeaponData.hpp> #include <data/WeaponData.hpp>
#include <items/WeaponItem.hpp>
#include <job/WorkContext.hpp> #include <job/WorkContext.hpp>
#include <loaders/LoaderIDE.hpp> #include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderIPL.hpp> #include <loaders/LoaderIPL.hpp>
@ -99,11 +98,6 @@ GameWorld::GameWorld(Logger* log, WorkContext* work, GameData* dat)
new btGhostPairCallback()); new btGhostPairCallback());
gContactProcessedCallback = ContactProcessedCallback; gContactProcessedCallback = ContactProcessedCallback;
dynamicsWorld->setInternalTickCallback(PhysicsTickCallback, this); dynamicsWorld->setInternalTickCallback(PhysicsTickCallback, this);
// Populate inventory items
for (auto& w : data->weaponData) {
inventoryItems.push_back(new WeaponItem(inventoryItems.size(), w));
}
} }
GameWorld::~GameWorld() { GameWorld::~GameWorld() {
@ -433,14 +427,13 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
PickupObject* pickup = nullptr; PickupObject* pickup = nullptr;
auto pickuptype = (PickupObject::PickupType)type; auto pickuptype = (PickupObject::PickupType)type;
// Attempt to find an InventoryItem associated with this model
auto it = std::find_if( auto it = std::find_if(
inventoryItems.begin(), inventoryItems.end(), data->weaponData.begin(), data->weaponData.end(),
[=](InventoryItem* itm) { return itm->getModelID() == id; }); [=](const std::shared_ptr<WeaponData>& x) { return x->modelID == id; });
// If nothing, create a generic pickup instead of an item pickup // If nothing, create a generic pickup instead of an item pickup
if (it != inventoryItems.end()) { if (it != data->weaponData.end()) {
pickup = new ItemPickup(this, pos, modelInfo, pickuptype, *it); pickup = new ItemPickup(this, pos, modelInfo, pickuptype, it->get());
} else { } else {
RW_UNIMPLEMENTED("Non-weapon pickups"); RW_UNIMPLEMENTED("Non-weapon pickups");
pickup = new PickupObject(this, pos, modelInfo, pickuptype); pickup = new PickupObject(this, pos, modelInfo, pickuptype);
@ -640,14 +633,6 @@ float GameWorld::getGameTime() const {
return state->gameTime; return state->gameTime;
} }
InventoryItem* GameWorld::getInventoryItem(uint16_t weaponId) const {
RW_CHECK(weaponId < inventoryItems.size(), "InventoryItem ID out of range");
if (weaponId >= inventoryItems.size()) {
return nullptr;
}
return inventoryItems[weaponId];
}
void handleVehicleResponse(GameObject* object, btManifoldPoint& mp, bool isA) { void handleVehicleResponse(GameObject* object, btManifoldPoint& mp, bool isA) {
bool isVehicle = object->type() == GameObject::Vehicle; bool isVehicle = object->type() == GameObject::Vehicle;
if (!isVehicle) return; if (!isVehicle) return;

View File

@ -27,7 +27,6 @@ class ViewCamera;
#include <render/VisualFX.hpp> #include <render/VisualFX.hpp>
struct BlipData; struct BlipData;
class InventoryItem;
struct WeaponScan; struct WeaponScan;
struct VehicleGenerator; struct VehicleGenerator;
@ -179,13 +178,6 @@ public:
float getGameTime() const; float getGameTime() const;
/**
* @brief getInventoryItem
* @param weaponId The Weapon ID (inventory slot) of the weapon to fetch
* @return Instance of the weapon
*/
InventoryItem* getInventoryItem(uint16_t weaponId) const;
/** /**
* Game data * Game data
*/ */
@ -353,11 +345,6 @@ private:
std::vector<AreaIndicatorInfo> areaIndicators; std::vector<AreaIndicatorInfo> areaIndicators;
/**
* Inventory Item instances
*/
std::vector<InventoryItem*> inventoryItems;
/** /**
* Flag for pausing the simulation * Flag for pausing the simulation
*/ */

View File

@ -4,7 +4,6 @@
#include <engine/GameState.hpp> #include <engine/GameState.hpp>
#include <engine/GameWorld.hpp> #include <engine/GameWorld.hpp>
#include <engine/SaveGame.hpp> #include <engine/SaveGame.hpp>
#include <items/WeaponItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/GameObject.hpp> #include <objects/GameObject.hpp>
#include <objects/InstanceObject.hpp> #include <objects/InstanceObject.hpp>

View File

@ -1,66 +0,0 @@
#pragma once
#ifndef _INVENTORYITEM_HPP_
#define _INVENTORYITEM_HPP_
class GameObject;
class CharacterObject;
/**
* @brief The InventoryItem class
*
* Instanciated once per item type
*/
class InventoryItem {
int _itemID;
int _inventorySlot;
int _modelID;
protected:
InventoryItem(int itemID, int invSlot, int model)
: _itemID(itemID), _inventorySlot(invSlot), _modelID(model) {
}
public:
virtual ~InventoryItem() {
}
/**
* @brief getObject
* @return The ID of the model associated with the item.
*/
int getModelID() {
return _modelID;
}
/**
* @brief getItemID
* @return The index of this item in the item list
*/
int getItemID() {
return _itemID;
}
/**
* @brief getInventorySlot
* @return The inventory slot number for this item
*/
int getInventorySlot() const {
return _inventorySlot;
}
/**
* @brief primary Implements mouse 1 action
* @param owner The character using this item
*/
virtual void primary(CharacterObject* owner) = 0;
/**
* @see primary
* @param owner The character using this item
*/
virtual void secondary(CharacterObject* owner) = 0;
constexpr static int NO_INVSLOT = -1;
};
#endif

View File

@ -0,0 +1,48 @@
#include <data/Skeleton.hpp>
#include <engine/GameWorld.hpp>
#include <items/Weapon.hpp>
#include <objects/ProjectileObject.hpp>
void Weapon::fireHitscan(WeaponData* weapon, CharacterObject* owner) {
auto handFrame = owner->getModel()->findFrame("srhand");
glm::mat4 handMatrix;
if (handFrame) {
while (handFrame->getParent()) {
handMatrix =
owner->skeleton->getMatrix(handFrame->getIndex()) * handMatrix;
handFrame = handFrame->getParent();
}
}
auto farTarget =
owner->getPosition() +
owner->getRotation() * glm::vec3(0.f, weapon->hitRange, 0.f);
auto handPos = glm::vec3(handMatrix * glm::vec4(0.f, 0.f, 0.f, 1.f));
auto fireOrigin = owner->getPosition() + owner->getRotation() * handPos;
owner->engine->doWeaponScan(
WeaponScan(weapon->damage, fireOrigin, farTarget, weapon));
}
void Weapon::fireProjectile(WeaponData* weapon, CharacterObject* owner,
float force) {
auto handPos = glm::vec3(0.f, 1.5f, 1.f);
auto fireOrigin = owner->getPosition() + owner->getRotation() * handPos;
auto direction =
owner->getRotation() * glm::normalize(glm::vec3{0.f, 1.f, 1.f});
auto pt = weapon->name == "grenade" ? ProjectileObject::Grenade
: ProjectileObject::Molotov;
force = std::max(0.1f, force);
auto projectile = new ProjectileObject(
owner->engine, fireOrigin,
{pt, direction,
17.f * force, /// @todo pull a better velocity from somewhere
3.5f, weapon});
auto& pool = owner->engine->getTypeObjectPool(projectile);
pool.insert(projectile);
owner->engine->allObjects.push_back(projectile);
}

View File

@ -0,0 +1,12 @@
#ifndef RWENGINE_WEAPON_HPP
#define RWENGINE_WEAPON_HPP
#include <data/WeaponData.hpp>
#include <objects/CharacterObject.hpp>
namespace Weapon {
void fireProjectile(WeaponData* wepon, CharacterObject* character, float force);
void fireHitscan(WeaponData* wepon, CharacterObject* character);
}
#endif

View File

@ -1,160 +0,0 @@
#include <ai/CharacterController.hpp>
#include <data/Model.hpp>
#include <data/Skeleton.hpp>
#include <engine/Animator.hpp>
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
#include <items/WeaponItem.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/ProjectileObject.hpp>
void WeaponItem::fireHitscan(CharacterObject* owner) {
auto handFrame = owner->getModel()->findFrame("srhand");
glm::mat4 handMatrix;
if (handFrame) {
while (handFrame->getParent()) {
handMatrix =
owner->skeleton->getMatrix(handFrame->getIndex()) * handMatrix;
handFrame = handFrame->getParent();
}
}
auto farTarget =
owner->getPosition() +
owner->getRotation() * glm::vec3(0.f, _wepData->hitRange, 0.f);
auto handPos = glm::vec3(handMatrix * glm::vec4(0.f, 0.f, 0.f, 1.f));
auto fireOrigin = owner->getPosition() + owner->getRotation() * handPos;
owner->engine->doWeaponScan(
WeaponScan(_wepData->damage, fireOrigin, farTarget, _wepData.get()));
// Particle FX involved:
// - smokeII emited around barrel
// - Some circle particle used for the tracer
// - smoke emited at hit point
// - gunflash
#if 0 // Should be merged into the VisualFX system
auto flashDir = owner->getRotation() * glm::vec3{0.f, 0.f, 1.f};
auto flashUp = owner->getRotation() * glm::vec3{0.f, -1.f, 0.f};
auto tracerTex = owner->engine->data->findTexture("shad_exp")->getName();
auto flashTex = owner->engine->data->findTexture("gunflash2")->getName();
auto flashTex1 = owner->engine->data->findTexture("gunflash1")->getName();
float tracertime = 0.1f;
auto distance = glm::distance(fireOrigin, farTarget);
const float tracerspeed = distance / tracertime * 0.5f;
float tracersize = _wepData->hitRange / 4.f;
float flashtime = 0.015f;
auto shotdir = glm::normalize(farTarget - fireOrigin);
/// @TODO move this into rendering logic.
/*_character->engine->renderer.addParticle({
fireOrigin + shotdir * tracersize / 2.f,
shotdir,
tracerspeed,
GameRenderer::FXParticle::UpCamera,
_character->engine->gameTime, tracertime,
tracerTex,
{0.04f, tracersize},
{0.f, 0.f, 0.f}
});
_character->engine->renderer.addParticle({
fireOrigin,
flashDir,
0.f,
GameRenderer::FXParticle::Free,
_character->engine->gameTime, flashtime,
flashTex,
{0.2f, 0.2f},
flashUp
});
_character->engine->renderer.addParticle({
fireOrigin + shotdir * 0.1f,
flashDir,
0.f,
GameRenderer::FXParticle::Free,
_character->engine->gameTime, flashtime,
flashTex,
{0.2f, 0.2f},
flashUp
});
_character->engine->renderer.addParticle({
fireOrigin + shotdir * 0.2f,
flashDir,
0.f,
GameRenderer::FXParticle::Free,
_character->engine->gameTime, flashtime,
flashTex1,
{0.2f, 0.2f},
flashUp
});
*/
#endif
}
void WeaponItem::fireProjectile(CharacterObject* owner) {
auto handPos = glm::vec3(0.f, 1.5f, 1.f);
auto fireOrigin = owner->getPosition() + owner->getRotation() * handPos;
auto direction =
owner->getRotation() * glm::normalize(glm::vec3{0.f, 1.f, 1.f});
auto pt = _wepData->name == "grenade" ? ProjectileObject::Grenade
: ProjectileObject::Molotov;
// Work out the velocity multiplier as a function of how long the player
// Was holding down the fire button. If _fireStop < 0.f then the player
// is still holding the button down.
float throwTime = owner->engine->getGameTime() -
owner->getCurrentState().primaryStartTime / 1000.f;
float forceFactor = throwTime;
if (owner->getCurrentState().primaryEndTime >=
owner->getCurrentState().primaryStartTime) {
uint32_t heldTime = owner->getCurrentState().primaryEndTime -
owner->getCurrentState().primaryStartTime;
forceFactor = (heldTime) / 1000.f;
}
forceFactor = std::max(0.1f, forceFactor / throwTime);
auto projectile = new ProjectileObject(
owner->engine, fireOrigin,
{pt, direction,
17.f * forceFactor, /// @todo pull a better velocity from somewhere
3.5f, _wepData});
auto& pool = owner->engine->getTypeObjectPool(projectile);
pool.insert(projectile);
owner->engine->allObjects.push_back(projectile);
}
void WeaponItem::primary(CharacterObject* owner) {
if (owner->getCurrentState().primaryActive) {
// ShootWeapon will call ::fire() on us at the appropriate time.
owner->controller->setNextActivity(new Activities::ShootWeapon(this));
}
}
void WeaponItem::secondary(CharacterObject* owner) {
RW_UNUSED(owner);
}
void WeaponItem::fire(CharacterObject* owner) {
switch (_wepData->fireType) {
case WeaponData::INSTANT_HIT:
fireHitscan(owner);
break;
case WeaponData::PROJECTILE:
fireProjectile(owner);
break;
default:
/// @todo meele
break;
}
}
bool WeaponItem::isFiring(CharacterObject* owner) {
return owner->getCurrentState().primaryActive;
}

View File

@ -1,40 +0,0 @@
#pragma once
#ifndef _WEAPONITEM_HPP_
#define _WEAPONITEM_HPP_
#include <data/WeaponData.hpp>
#include <items/InventoryItem.hpp>
#include <memory>
/**
* @brief The WeaponItem class
* Logic for basic weapon types
*
* This is instanciated once -per item type-, so state is shared between
* all instances of the same weapon. Timing is controlled by the CharacterState
*/
class WeaponItem : public InventoryItem {
std::shared_ptr<WeaponData> _wepData;
void fireHitscan(CharacterObject* owner);
void fireProjectile(CharacterObject* owner);
public:
WeaponItem(int itemID, std::shared_ptr<WeaponData> data)
: InventoryItem(itemID, data->inventorySlot, data->modelID)
, _wepData(data) {
}
void primary(CharacterObject* owner);
void secondary(CharacterObject* owner);
void fire(CharacterObject* owner);
bool isFiring(CharacterObject* owner);
std::shared_ptr<WeaponData>& getWeaponData() {
return _wepData;
}
};
#endif

View File

@ -3,7 +3,6 @@
#include <engine/Animator.hpp> #include <engine/Animator.hpp>
#include <engine/GameData.hpp> #include <engine/GameData.hpp>
#include <engine/GameWorld.hpp> #include <engine/GameWorld.hpp>
#include <items/InventoryItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp> #include <objects/VehicleObject.hpp>
#include <rw/defines.hpp> #include <rw/defines.hpp>
@ -14,8 +13,7 @@ static glm::vec3 enter_offset(0.81756252f, 0.34800607f, -0.486281008f);
const float CharacterObject::DefaultJumpSpeed = 2.f; const float CharacterObject::DefaultJumpSpeed = 2.f;
CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const glm::quat& rot, BaseModelInfo* modelinfo)
BaseModelInfo *modelinfo)
: GameObject(engine, pos, rot, modelinfo) : GameObject(engine, pos, rot, modelinfo)
, currentState({}) , currentState({})
, currentVehicle(nullptr) , currentVehicle(nullptr)
@ -521,12 +519,11 @@ void CharacterObject::activityFinished() {
motionBlockedByActivity = false; motionBlockedByActivity = false;
} }
void CharacterObject::addToInventory(InventoryItem* item) { void CharacterObject::addToInventory(int slot, int ammo) {
RW_CHECK(item->getInventorySlot() < maxInventorySlots, RW_CHECK(slot < kMaxInventorySlots, "Slot greater than kMaxInventorySlots");
"Inventory Slot greater than maxInventorySlots"); if (slot < kMaxInventorySlots) {
if (item->getInventorySlot() < maxInventorySlots) { currentState.weapons[slot].weaponId = slot;
currentState.weapons[item->getInventorySlot()].weaponId = currentState.weapons[slot].bulletsTotal += ammo;
item->getItemID();
} }
} }
@ -534,19 +531,16 @@ void CharacterObject::setActiveItem(int slot) {
currentState.currentWeapon = slot; currentState.currentWeapon = slot;
} }
InventoryItem* CharacterObject::getActiveItem() {
if (currentVehicle) return nullptr;
auto weaponId = currentState.weapons[currentState.currentWeapon].weaponId;
return engine->getInventoryItem(weaponId);
}
void CharacterObject::removeFromInventory(int slot) { void CharacterObject::removeFromInventory(int slot) {
currentState.weapons[slot].weaponId = 0; currentState.weapons[slot].weaponId = 0;
if (currentState.currentWeapon == slot) {
currentState.currentWeapon = 0;
}
} }
void CharacterObject::cycleInventory(bool up) { void CharacterObject::cycleInventory(bool up) {
if (up) { if (up) {
for (int j = currentState.currentWeapon + 1; j < maxInventorySlots; for (int j = currentState.currentWeapon + 1; j < kMaxInventorySlots;
++j) { ++j) {
if (currentState.weapons[j].weaponId != 0) { if (currentState.weapons[j].weaponId != 0) {
currentState.currentWeapon = j; currentState.currentWeapon = j;
@ -565,7 +559,7 @@ void CharacterObject::cycleInventory(bool up) {
} }
// Nothing? set the highest // Nothing? set the highest
for (int j = maxInventorySlots - 1; j >= 0; --j) { for (int j = kMaxInventorySlots - 1; j >= 0; --j) {
if (currentState.weapons[j].weaponId != 0 || j == 0) { if (currentState.weapons[j].weaponId != 0 || j == 0) {
currentState.currentWeapon = j; currentState.currentWeapon = j;
return; return;
@ -575,17 +569,21 @@ void CharacterObject::cycleInventory(bool up) {
} }
void CharacterObject::useItem(bool active, bool primary) { void CharacterObject::useItem(bool active, bool primary) {
if (getActiveItem()) { /// @todo verify if this is the correct logic
auto item = getActiveItem();
if (currentState.weapons[item].weaponId == unsigned(item)) {
if (primary) { if (primary) {
if (active) if (!currentState.primaryActive && active) {
currentState.primaryStartTime = engine->getGameTime() * 1000.f; // If we've just started, activate
else controller->setNextActivity(new Activities::UseItem(item));
currentState.primaryEndTime = engine->getGameTime() * 1000.f; }
else if (currentState.primaryActive && !active) {
// UseItem will cancel itself upon !primaryActive
}
currentState.primaryActive = active; currentState.primaryActive = active;
getActiveItem()->primary(this);
} else { } else {
currentState.secondaryActive = active; currentState.secondaryActive = active;
getActiveItem()->secondary(this); /// @todo handle scopes and sights
} }
} }
} }

View File

@ -8,7 +8,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <objects/GameObject.hpp> #include <objects/GameObject.hpp>
constexpr int maxInventorySlots = 13; constexpr int kMaxInventorySlots = 13;
// Animation slots used for character animation blending // Animation slots used for character animation blending
constexpr unsigned int AnimIndexMovement = 0; constexpr unsigned int AnimIndexMovement = 0;
@ -26,18 +26,15 @@ struct CharacterState {
float rotation; float rotation;
float health = 100.f; float health = 100.f;
float armour = 0.f; float armour = 0.f;
std::array<CharacterWeaponSlot, maxInventorySlots> weapons; std::array<CharacterWeaponSlot, kMaxInventorySlots> weapons;
uint16_t currentWeapon = 0; uint16_t currentWeapon = 0;
uint32_t lastFireTimeMS = 0; uint32_t lastFireTimeMS = 0;
bool primaryActive = false; bool primaryActive = false;
bool secondaryActive = false; bool secondaryActive = false;
uint32_t primaryStartTime = 0;
uint32_t primaryEndTime = 0;
}; };
class VehicleObject; class VehicleObject;
class GameWorld; class GameWorld;
class InventoryItem;
struct AnimationGroup { struct AnimationGroup {
Animation* idle; Animation* idle;
@ -234,9 +231,21 @@ public:
*/ */
void activityFinished(); void activityFinished();
void addToInventory(InventoryItem* item); /**
* @brief addToInventory Adds ammo to the specified item slot
* @param slot The slot to add ammo for
* @param ammo The quanity of ammunition to add
*
* Will give the weapon (set the ID) if it is not possessed
*/
void addToInventory(int slot, int ammo);
void setActiveItem(int slot); void setActiveItem(int slot);
InventoryItem* getActiveItem(); int getActiveItem() const { return currentState.currentWeapon; }
/**
* @brief removeFromInventory Removes item at slot from inventory
*/
void removeFromInventory(int slot); void removeFromInventory(int slot);
/** /**

View File

@ -1,22 +1,20 @@
#include <data/WeaponData.hpp>
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp> #include <engine/GameWorld.hpp>
#include <items/WeaponItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/ItemPickup.hpp> #include <objects/ItemPickup.hpp>
#include <rw/defines.hpp> #include <rw/defines.hpp>
ItemPickup::ItemPickup(GameWorld *world, const glm::vec3 &position, ItemPickup::ItemPickup(GameWorld *world, const glm::vec3 &position,
BaseModelInfo *modelinfo, PickupType type, BaseModelInfo *modelinfo, PickupType type,
InventoryItem *item) WeaponData *item)
: PickupObject(world, position, modelinfo, type), item(item) { : PickupObject(world, position, modelinfo, type), item(item) {
RW_CHECK(item != nullptr, "Pickup created with null item");
} }
bool ItemPickup::onCharacterTouch(CharacterObject *character) { bool ItemPickup::onCharacterTouch(CharacterObject *character) {
character->addToInventory(item); auto totalRounds = 0;
auto &wep = character->getCurrentState().weapons[item->getInventorySlot()];
auto totalRounds = 0, clipRounds = 0;
switch (item->getModelID()) { switch (item->modelID) {
case 173: /* Pistol */ case 173: /* Pistol */
totalRounds = 45; totalRounds = 45;
break; break;
@ -50,8 +48,7 @@ bool ItemPickup::onCharacterTouch(CharacterObject *character) {
totalRounds /= 5; totalRounds /= 5;
} }
wep.bulletsTotal = totalRounds; character->addToInventory(item->inventorySlot, totalRounds);
wep.bulletsClip = clipRounds;
return true; return true;
} }

View File

@ -1,21 +1,19 @@
#pragma once #pragma once
#ifndef _ITEMPICKUP_HPP_ #ifndef _ITEMPICKUP_HPP_
#define _ITEMPICKUP_HPP_ #define _ITEMPICKUP_HPP_
#include <data/WeaponData.hpp>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <objects/PickupObject.hpp> #include <objects/PickupObject.hpp>
class InventoryItem;
/** /**
* @brief The ItemPickup class * @brief The ItemPickup class
* Inserts an item into a characters inventory on pickup. * Inserts an item into a characters inventory on pickup.
*/ */
class ItemPickup : public PickupObject { class ItemPickup : public PickupObject {
InventoryItem* item; WeaponData* item;
public: public:
ItemPickup(GameWorld* world, const glm::vec3& position, BaseModelInfo *modelinfo, PickupType type, ItemPickup(GameWorld* world, const glm::vec3& position,
InventoryItem* item); BaseModelInfo* modelinfo, PickupType type, WeaponData* item);
bool onCharacterTouch(CharacterObject* character); bool onCharacterTouch(CharacterObject* character);
}; };

View File

@ -25,7 +25,7 @@ public:
/** Time to dentonation or removal */ /** Time to dentonation or removal */
float time; float time;
std::shared_ptr<WeaponData> weapon; WeaponData* weapon;
}; };
private: private:

View File

@ -12,7 +12,6 @@
#include <ai/CharacterController.hpp> #include <ai/CharacterController.hpp>
#include <data/ModelData.hpp> #include <data/ModelData.hpp>
#include <items/InventoryItem.hpp>
#include <data/CutsceneData.hpp> #include <data/CutsceneData.hpp>
#include <data/Skeleton.hpp> #include <data/Skeleton.hpp>

View File

@ -32,7 +32,6 @@ class ProjectileObject;
class CutsceneObject; class CutsceneObject;
class Animator; class Animator;
class InventoryItem;
class Renderer; class Renderer;

View File

@ -7,7 +7,6 @@
#include <render/ObjectRenderer.hpp> #include <render/ObjectRenderer.hpp>
// Objects that we know how to turn into renderlist entries // Objects that we know how to turn into renderlist entries
#include <items/InventoryItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/CutsceneObject.hpp> #include <objects/CutsceneObject.hpp>
#include <objects/InstanceObject.hpp> #include <objects/InstanceObject.hpp>
@ -302,31 +301,30 @@ void ObjectRenderer::renderCharacter(CharacterObject* pedestrian,
renderFrame(pedestrian->getModel(), root->getChildren()[0], matrixModel, renderFrame(pedestrian->getModel(), root->getChildren()[0], matrixModel,
pedestrian, 1.f, outList); pedestrian, 1.f, outList);
if (pedestrian->getActiveItem()) { auto item = pedestrian->getActiveItem();
auto item = pedestrian->getActiveItem(); const auto& weapon = pedestrian->engine->data->weaponData[item];
if (item->getModelID() == -1) { if (weapon->modelID == -1) {
return; // No model for this item return; // No model for this item
}
auto handFrame = pedestrian->getModel()->findFrame("srhand");
glm::mat4 localMatrix;
if (handFrame) {
while (handFrame->getParent()) {
localMatrix =
pedestrian->skeleton->getMatrix(handFrame->getIndex()) *
localMatrix;
handFrame = handFrame->getParent();
}
}
// Assume items are all simple
auto simple =
m_world->data->findModelInfo<SimpleModelInfo>(item->getModelID());
auto geometry = simple->getAtomic(0)->getGeometries().at(0);
renderGeometry(simple->getModel(), geometry, matrixModel * localMatrix,
1.f, nullptr, outList);
} }
auto handFrame = pedestrian->getModel()->findFrame("srhand");
glm::mat4 localMatrix;
if (handFrame) {
while (handFrame->getParent()) {
localMatrix =
pedestrian->skeleton->getMatrix(handFrame->getIndex()) *
localMatrix;
handFrame = handFrame->getParent();
}
}
// Assume items are all simple
auto simple =
m_world->data->findModelInfo<SimpleModelInfo>(weapon->modelID);
auto geometry = simple->getAtomic(0)->getGeometries().at(0);
renderGeometry(simple->getModel(), geometry, matrixModel * localMatrix, 1.f,
nullptr, outList);
} }
void ObjectRenderer::renderVehicle(VehicleObject* vehicle, void ObjectRenderer::renderVehicle(VehicleObject* vehicle,

View File

@ -1,8 +1,8 @@
#include "DrawUI.hpp" #include "DrawUI.hpp"
#include <ai/PlayerController.hpp> #include <ai/PlayerController.hpp>
#include <engine/GameState.hpp> #include <engine/GameState.hpp>
#include <items/WeaponItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <data/WeaponData.hpp>
#include <render/GameRenderer.hpp> #include <render/GameRenderer.hpp>
#include <glm/gtc/constants.hpp> #include <glm/gtc/constants.hpp>
@ -152,16 +152,14 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world,
render->text.renderText(ti); render->text.renderText(ti);
#endif #endif
InventoryItem* current = player->getCharacter()->getActiveItem(); auto item = player->getCharacter()->getActiveItem();
auto weapon = world->data->weaponData[item];
std::string itemTextureName = "fist"; std::string itemTextureName = "fist";
if (current) { if (weapon && weapon->modelID > 0) {
uint16_t model = current->getModelID(); auto model =
if (model > 0) { world->data->findModelInfo<SimpleModelInfo>(weapon->modelID);
auto weaponData = if (model != nullptr) {
world->data->findModelInfo<SimpleModelInfo>(model); itemTextureName = model->name;
if (weaponData != nullptr) {
itemTextureName = weaponData->name;
}
} }
} }
// Urgh // Urgh
@ -179,25 +177,20 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world,
glm::vec4(iconX, iconY, ui_weaponSize, ui_weaponSize)); glm::vec4(iconX, iconY, ui_weaponSize, ui_weaponSize));
} }
if (current) { if (weapon->fireType != WeaponData::MELEE) {
WeaponItem* wep = static_cast<WeaponItem*>(current); const CharacterState& cs = player->getCharacter()->getCurrentState();
if (wep->getWeaponData()->fireType != WeaponData::MELEE) { const CharacterWeaponSlot& slotInfo = cs.weapons[cs.currentWeapon];
const CharacterState& cs = ti.text = GameStringUtil::fromString(
player->getCharacter()->getCurrentState(); std::to_string(slotInfo.bulletsClip) + "-" +
const CharacterWeaponSlot& slotInfo = cs.weapons[cs.currentWeapon]; std::to_string(slotInfo.bulletsTotal));
ti.text = GameStringUtil::fromString(
std::to_string(slotInfo.bulletsClip) + "-" +
std::to_string(slotInfo.bulletsTotal));
ti.baseColour = ui_shadowColour; ti.baseColour = ui_shadowColour;
ti.font = 2; ti.font = 2;
ti.size = ui_ammoSize; ti.size = ui_ammoSize;
ti.align = TextRenderer::TextInfo::Center; ti.align = TextRenderer::TextInfo::Center;
ti.screenPosition = ti.screenPosition = glm::vec2(iconX + ui_weaponSize / 2.f,
glm::vec2(iconX + ui_weaponSize / 2.f, iconY + ui_weaponSize - ui_ammoHeight);
iconY + ui_weaponSize - ui_ammoHeight); render->text.renderText(ti);
render->text.renderText(ti);
}
} }
} }

View File

@ -4,7 +4,6 @@
#include <engine/GameState.hpp> #include <engine/GameState.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <glm/gtx/string_cast.hpp> #include <glm/gtx/string_cast.hpp>
#include <items/InventoryItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/InstanceObject.hpp> #include <objects/InstanceObject.hpp>
#include <objects/VehicleObject.hpp> #include <objects/VehicleObject.hpp>
@ -279,11 +278,10 @@ Menu* DebugState::createWeaponMenu() {
[=] { this->enterMenu(createDebugMenu()); }, [=] { this->enterMenu(createDebugMenu()); },
kDebugEntryHeight)); kDebugEntryHeight));
for (int i = 1; i < maxInventorySlots; ++i) { for (int i = 1; i < kMaxInventorySlots; ++i) {
auto item = getWorld()->getInventoryItem(i);
auto& name = getWorld()->data->weaponData[i]->name; auto& name = getWorld()->data->weaponData[i]->name;
m->addEntry( m->addEntry(
Menu::lambda(name, [=] { giveItem(item); }, kDebugEntryHeight)); Menu::lambda(name, [=] { giveItem(i); }, kDebugEntryHeight));
} }
return m; return m;
@ -475,17 +473,14 @@ void DebugState::spawnFollower(unsigned int id) {
} }
} }
void DebugState::giveItem(InventoryItem* item) { void DebugState::giveItem(int slot) {
CharacterObject* player = nullptr; CharacterObject* player = nullptr;
if (game->getPlayer()) { if (game->getPlayer()) {
player = game->getPlayer()->getCharacter(); player = game->getPlayer()->getCharacter();
} }
if (player) { if (player) {
player->addToInventory(item); player->addToInventory(slot, 100);
auto& wep = player->getCurrentState().weapons[item->getInventorySlot()];
wep.bulletsTotal = 100;
wep.bulletsClip = 0;
} }
} }

View File

@ -33,7 +33,7 @@ public:
void spawnVehicle(unsigned int id); void spawnVehicle(unsigned int id);
void spawnFollower(unsigned int id); void spawnFollower(unsigned int id);
void giveItem(InventoryItem* item); void giveItem(int slot);
const ViewCamera& getCamera(); const ViewCamera& getCamera();
}; };

View File

@ -6,11 +6,11 @@
#include <ai/PlayerController.hpp> #include <ai/PlayerController.hpp>
#include <data/Model.hpp> #include <data/Model.hpp>
#include <data/WeaponData.hpp>
#include <dynamics/CollisionInstance.hpp> #include <dynamics/CollisionInstance.hpp>
#include <dynamics/RaycastCallbacks.hpp> #include <dynamics/RaycastCallbacks.hpp>
#include <engine/GameState.hpp> #include <engine/GameState.hpp>
#include <engine/GameWorld.hpp> #include <engine/GameWorld.hpp>
#include <items/WeaponItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/ItemPickup.hpp> #include <objects/ItemPickup.hpp>
#include <objects/VehicleObject.hpp> #include <objects/VehicleObject.hpp>
@ -105,9 +105,9 @@ void IngameState::startTest() {
getWorld()->state->playerObject = playerChar->getGameObjectID(); getWorld()->state->playerObject = playerChar->getGameObjectID();
glm::vec3 itemspawn(276.5f, -609.f, 36.5f); glm::vec3 itemspawn(276.5f, -609.f, 36.5f);
for (int i = 1; i < maxInventorySlots; ++i) { for (int i = 1; i < getWorld()->data->weaponData.size(); ++i) {
auto item = getWorld()->getInventoryItem(i); auto& item = getWorld()->data->weaponData[i];
getWorld()->createPickup(itemspawn, item->getModelID(), getWorld()->createPickup(itemspawn, item->modelID,
PickupObject::OnStreet); PickupObject::OnStreet);
itemspawn.x += 2.5f; itemspawn.x += 2.5f;
} }

View File

@ -1,5 +1,4 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <items/WeaponItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include "test_globals.hpp" #include "test_globals.hpp"
@ -11,24 +10,17 @@ BOOST_AUTO_TEST_CASE(test_character_inventory) {
auto character = Global::get().e->createPedestrian(1, {0.f, 0.f, 0.f}); auto character = Global::get().e->createPedestrian(1, {0.f, 0.f, 0.f});
BOOST_REQUIRE(character != nullptr); BOOST_REQUIRE(character != nullptr);
auto item = Global::get().e->getInventoryItem(4); character->addToInventory(1, 10);
auto fist = Global::get().e->getInventoryItem(0);
BOOST_REQUIRE(item != nullptr); BOOST_CHECK_EQUAL(character->getActiveItem(), 0);
BOOST_REQUIRE(fist != nullptr);
BOOST_CHECK_NE(fist, item);
character->addToInventory(item); character->setActiveItem(1);
BOOST_CHECK_EQUAL(character->getActiveItem(), fist); BOOST_CHECK_EQUAL(character->getActiveItem(), 1);
character->setActiveItem(item->getInventorySlot()); character->removeFromInventory(1);
BOOST_CHECK_EQUAL(character->getActiveItem(), item); BOOST_CHECK_EQUAL(character->getActiveItem(), 0);
character->removeFromInventory(item->getInventorySlot());
BOOST_CHECK_EQUAL(character->getActiveItem(), fist);
Global::get().e->destroyObject(character); Global::get().e->destroyObject(character);
} }

View File

@ -1,6 +1,5 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <data/WeaponData.hpp> #include <data/WeaponData.hpp>
#include <items/InventoryItem.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/ItemPickup.hpp> #include <objects/ItemPickup.hpp>
#include <objects/PickupObject.hpp> #include <objects/PickupObject.hpp>
@ -65,16 +64,16 @@ BOOST_AUTO_TEST_CASE(test_item_pickup) {
Global::get().e->createPedestrian(1, {30.1f, 0.f, 0.f}); Global::get().e->createPedestrian(1, {30.1f, 0.f, 0.f});
BOOST_REQUIRE(character != nullptr); BOOST_REQUIRE(character != nullptr);
auto item = Global::get().e->getInventoryItem(3); auto pistol = Global::get().d->weaponData[1].get();
BOOST_REQUIRE(item != nullptr); auto model = Global::get().d->modelinfo[pistol->modelID].get();
ItemPickup* p = new ItemPickup(Global::get().e, {30.f, 0.f, 0.f}, ItemPickup* p = new ItemPickup(Global::get().e, {30.f, 0.f, 0.f}, model,
nullptr, PickupObject::OnStreet, item); PickupObject::OnStreet, pistol);
Global::get().e->allObjects.push_back(p); Global::get().e->allObjects.push_back(p);
// Check the characters inventory is empty. // Check the characters inventory is empty.
for (int i = 0; i < maxInventorySlots; ++i) { for (int i = 0; i < kMaxInventorySlots; ++i) {
BOOST_CHECK(character->getCurrentState().weapons[i].weaponId == 0); BOOST_CHECK(character->getCurrentState().weapons[i].weaponId == 0);
} }
@ -84,8 +83,7 @@ BOOST_AUTO_TEST_CASE(test_item_pickup) {
auto& inventory = character->getCurrentState().weapons; auto& inventory = character->getCurrentState().weapons;
BOOST_CHECK(std::any_of(std::begin(inventory), std::end(inventory), BOOST_CHECK(std::any_of(std::begin(inventory), std::end(inventory),
[&](const CharacterWeaponSlot& i) { [&](const CharacterWeaponSlot& i) {
return i.weaponId == return i.weaponId == pistol->inventorySlot;
item->getInventorySlot();
})); }));
Global::get().e->destroyObject(p); Global::get().e->destroyObject(p);

View File

@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(TestProjectile) {
auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f}); auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f});
BOOST_REQUIRE(character != nullptr); BOOST_REQUIRE(character != nullptr);
auto wepdata = Global::get().e->data->weaponData[5]; auto wepdata = Global::get().e->data->weaponData[5].get();
auto projectile = new ProjectileObject( auto projectile = new ProjectileObject(
Global::get().e, {26.f, 1.f, 10.f}, Global::get().e, {26.f, 1.f, 10.f},
@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(TestProjectile) {
auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f}); auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f});
BOOST_REQUIRE(character != nullptr); BOOST_REQUIRE(character != nullptr);
auto wepdata = Global::get().e->data->weaponData[6]; auto wepdata = Global::get().e->data->weaponData[6].get();
auto projectile = new ProjectileObject( auto projectile = new ProjectileObject(
Global::get().e, {26.f, 1.f, 10.f}, Global::get().e, {26.f, 1.f, 10.f},
@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(TestProjectile) {
auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f}); auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f});
BOOST_REQUIRE(character != nullptr); BOOST_REQUIRE(character != nullptr);
auto wepdata = Global::get().e->data->weaponData[7]; auto wepdata = Global::get().e->data->weaponData[7].get();
auto projectile = new ProjectileObject( auto projectile = new ProjectileObject(
Global::get().e, {26.f, 1.f, 10.f}, Global::get().e, {26.f, 1.f, 10.f},