mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-03 17:19:46 +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:
parent
44f73af9e9
commit
5c78930c1b
@ -58,9 +58,8 @@ set(RWENGINE_SOURCES
|
||||
src/engine/SaveGame.hpp
|
||||
src/engine/ScreenText.cpp
|
||||
src/engine/ScreenText.hpp
|
||||
src/items/InventoryItem.hpp
|
||||
src/items/WeaponItem.cpp
|
||||
src/items/WeaponItem.hpp
|
||||
src/items/Weapon.cpp
|
||||
src/items/Weapon.hpp
|
||||
src/loaders/DataLoader.cpp
|
||||
src/loaders/DataLoader.hpp
|
||||
src/loaders/GenericDATLoader.cpp
|
||||
|
@ -1,11 +1,12 @@
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <ai/CharacterController.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
|
||||
#include <data/Model.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>
|
||||
|
||||
constexpr float kCloseDoorIdleTime = 2.f;
|
||||
@ -384,14 +385,20 @@ bool Activities::ExitVehicle::update(CharacterObject *character,
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <data/Model.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
bool Activities::ShootWeapon::update(CharacterObject *character,
|
||||
CharacterController *controller) {
|
||||
bool Activities::UseItem::update(CharacterObject *character,
|
||||
CharacterController *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
|
||||
// Thrown projectiles have lob / throw.
|
||||
@ -400,85 +407,73 @@ bool Activities::ShootWeapon::update(CharacterObject *character,
|
||||
character->setRotation(
|
||||
glm::angleAxis(character->getLook().x, glm::vec3{0.f, 0.f, 1.f}));
|
||||
|
||||
RW_CHECK(wepdata->inventorySlot < maxInventorySlots,
|
||||
"Inventory slot out of bounds");
|
||||
auto &itemState =
|
||||
character->getCurrentState().weapons[wepdata->inventorySlot];
|
||||
if (itemState.bulletsClip == 0 && itemState.bulletsTotal > 0) {
|
||||
itemState.bulletsClip +=
|
||||
std::min(int(itemState.bulletsTotal), wepdata->clipSize);
|
||||
itemState.bulletsTotal -= itemState.bulletsClip;
|
||||
if (state.bulletsClip == 0 && state.bulletsTotal > 0) {
|
||||
state.bulletsClip +=
|
||||
std::min(int(state.bulletsTotal), weapon->clipSize);
|
||||
state.bulletsTotal -= state.bulletsClip;
|
||||
}
|
||||
bool hasammo = itemState.bulletsClip > 0;
|
||||
bool hasammo = state.bulletsClip > 0;
|
||||
|
||||
if (wepdata->fireType == WeaponData::INSTANT_HIT) {
|
||||
if (_item->isFiring(character) && hasammo) {
|
||||
auto shootanim =
|
||||
character->engine->data->animations[wepdata->animation1];
|
||||
if (shootanim) {
|
||||
if (character->animator->getAnimation(AnimIndexAction) !=
|
||||
shootanim) {
|
||||
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;
|
||||
}
|
||||
if (weapon->fireType == WeaponData::INSTANT_HIT) {
|
||||
if (!character->getCurrentState().primaryActive) {
|
||||
// Character is no longer firing
|
||||
return true;
|
||||
}
|
||||
if (hasammo && shootanim) {
|
||||
if (animator->getAnimation(AnimIndexAction) != shootanim) {
|
||||
character->playActivityAnimation(shootanim, false, false);
|
||||
}
|
||||
} else {
|
||||
if (character->animator->isCompleted(AnimIndexAction)) {
|
||||
return true;
|
||||
|
||||
auto loopstart = weapon->animLoopStart / 100.f;
|
||||
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.)
|
||||
else if (wepdata->fireType == WeaponData::PROJECTILE && hasammo) {
|
||||
auto shootanim =
|
||||
character->engine->data->animations[wepdata->animation1];
|
||||
auto throwanim =
|
||||
character->engine->data->animations[wepdata->animation2];
|
||||
|
||||
if (character->animator->getAnimation(AnimIndexAction) == shootanim) {
|
||||
if (character->animator->isCompleted(AnimIndexAction)) {
|
||||
else if (weapon->fireType == WeaponData::PROJECTILE && hasammo) {
|
||||
if (animator->getAnimation(AnimIndexAction) == shootanim) {
|
||||
if (character->getCurrentState().primaryActive) {
|
||||
power = animator->getAnimationTime(AnimIndexAction) / 0.5f;
|
||||
}
|
||||
if (animator->isCompleted(AnimIndexAction)) {
|
||||
character->playActivityAnimation(throwanim, false, false);
|
||||
}
|
||||
} else if (character->animator->getAnimation(AnimIndexAction) ==
|
||||
throwanim) {
|
||||
auto firetime = wepdata->animCrouchFirePoint / 100.f;
|
||||
auto currID =
|
||||
character->animator->getAnimationTime(AnimIndexAction);
|
||||
} else if (animator->getAnimation(AnimIndexAction) == throwanim) {
|
||||
auto firetime = weapon->animCrouchFirePoint / 100.f;
|
||||
auto currID = animator->getAnimationTime(AnimIndexAction);
|
||||
|
||||
if (currID >= firetime && !_fired) {
|
||||
itemState.bulletsClip--;
|
||||
_item->fire(character);
|
||||
_fired = true;
|
||||
if (currID >= firetime && !fired) {
|
||||
state.bulletsClip--;
|
||||
Weapon::fireProjectile(weapon.get(), character, power);
|
||||
fired = true;
|
||||
}
|
||||
if (character->animator->isCompleted(AnimIndexAction)) {
|
||||
if (animator->isCompleted(AnimIndexAction)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
character->playActivityAnimation(throwanim, false, true);
|
||||
character->playActivityAnimation(shootanim, false, true);
|
||||
}
|
||||
} else if (wepdata->fireType == WeaponData::MELEE) {
|
||||
RW_CHECK(wepdata->fireType != WeaponData::MELEE,
|
||||
} else if (weapon->fireType == WeaponData::MELEE) {
|
||||
RW_CHECK(weapon->fireType != WeaponData::MELEE,
|
||||
"Melee attacks not implemented");
|
||||
return true;
|
||||
} else {
|
||||
RW_ERROR("Unrecognized fireType: " << wepdata->fireType);
|
||||
RW_ERROR("Unrecognized fireType: " << weapon->fireType);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,6 @@ public:
|
||||
}
|
||||
|
||||
// TODO: Refactor this with an ugly macro to reduce code dup.
|
||||
class WeaponItem;
|
||||
|
||||
/**
|
||||
* @brief Activities for CharacterController behaviour
|
||||
@ -217,13 +216,14 @@ struct ExitVehicle : public CharacterController::Activity {
|
||||
bool update(CharacterObject* character, CharacterController* controller);
|
||||
};
|
||||
|
||||
struct ShootWeapon : public CharacterController::Activity {
|
||||
DECL_ACTIVITY(ShootWeapon)
|
||||
struct UseItem : public CharacterController::Activity {
|
||||
DECL_ACTIVITY(UseItem)
|
||||
|
||||
WeaponItem* _item;
|
||||
bool _fired;
|
||||
int itemslot;
|
||||
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);
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <ai/TrafficDirector.hpp>
|
||||
#include <data/Model.hpp>
|
||||
#include <data/WeaponData.hpp>
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <job/WorkContext.hpp>
|
||||
#include <loaders/LoaderIDE.hpp>
|
||||
#include <loaders/LoaderIPL.hpp>
|
||||
@ -99,11 +98,6 @@ GameWorld::GameWorld(Logger* log, WorkContext* work, GameData* dat)
|
||||
new btGhostPairCallback());
|
||||
gContactProcessedCallback = ContactProcessedCallback;
|
||||
dynamicsWorld->setInternalTickCallback(PhysicsTickCallback, this);
|
||||
|
||||
// Populate inventory items
|
||||
for (auto& w : data->weaponData) {
|
||||
inventoryItems.push_back(new WeaponItem(inventoryItems.size(), w));
|
||||
}
|
||||
}
|
||||
|
||||
GameWorld::~GameWorld() {
|
||||
@ -433,14 +427,13 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
|
||||
PickupObject* pickup = nullptr;
|
||||
auto pickuptype = (PickupObject::PickupType)type;
|
||||
|
||||
// Attempt to find an InventoryItem associated with this model
|
||||
auto it = std::find_if(
|
||||
inventoryItems.begin(), inventoryItems.end(),
|
||||
[=](InventoryItem* itm) { return itm->getModelID() == id; });
|
||||
data->weaponData.begin(), data->weaponData.end(),
|
||||
[=](const std::shared_ptr<WeaponData>& x) { return x->modelID == id; });
|
||||
|
||||
// If nothing, create a generic pickup instead of an item pickup
|
||||
if (it != inventoryItems.end()) {
|
||||
pickup = new ItemPickup(this, pos, modelInfo, pickuptype, *it);
|
||||
if (it != data->weaponData.end()) {
|
||||
pickup = new ItemPickup(this, pos, modelInfo, pickuptype, it->get());
|
||||
} else {
|
||||
RW_UNIMPLEMENTED("Non-weapon pickups");
|
||||
pickup = new PickupObject(this, pos, modelInfo, pickuptype);
|
||||
@ -640,14 +633,6 @@ float GameWorld::getGameTime() const {
|
||||
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) {
|
||||
bool isVehicle = object->type() == GameObject::Vehicle;
|
||||
if (!isVehicle) return;
|
||||
|
@ -27,7 +27,6 @@ class ViewCamera;
|
||||
#include <render/VisualFX.hpp>
|
||||
|
||||
struct BlipData;
|
||||
class InventoryItem;
|
||||
struct WeaponScan;
|
||||
struct VehicleGenerator;
|
||||
|
||||
@ -179,13 +178,6 @@ public:
|
||||
|
||||
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
|
||||
*/
|
||||
@ -353,11 +345,6 @@ private:
|
||||
|
||||
std::vector<AreaIndicatorInfo> areaIndicators;
|
||||
|
||||
/**
|
||||
* Inventory Item instances
|
||||
*/
|
||||
std::vector<InventoryItem*> inventoryItems;
|
||||
|
||||
/**
|
||||
* Flag for pausing the simulation
|
||||
*/
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <engine/GameState.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <engine/SaveGame.hpp>
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/GameObject.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
|
@ -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
|
48
rwengine/src/items/Weapon.cpp
Normal file
48
rwengine/src/items/Weapon.cpp
Normal 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);
|
||||
}
|
12
rwengine/src/items/Weapon.hpp
Normal file
12
rwengine/src/items/Weapon.hpp
Normal 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
|
@ -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;
|
||||
}
|
@ -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
|
@ -3,7 +3,6 @@
|
||||
#include <engine/Animator.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <items/InventoryItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/VehicleObject.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;
|
||||
|
||||
CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos,
|
||||
const glm::quat& rot,
|
||||
BaseModelInfo *modelinfo)
|
||||
const glm::quat& rot, BaseModelInfo* modelinfo)
|
||||
: GameObject(engine, pos, rot, modelinfo)
|
||||
, currentState({})
|
||||
, currentVehicle(nullptr)
|
||||
@ -521,12 +519,11 @@ void CharacterObject::activityFinished() {
|
||||
motionBlockedByActivity = false;
|
||||
}
|
||||
|
||||
void CharacterObject::addToInventory(InventoryItem* item) {
|
||||
RW_CHECK(item->getInventorySlot() < maxInventorySlots,
|
||||
"Inventory Slot greater than maxInventorySlots");
|
||||
if (item->getInventorySlot() < maxInventorySlots) {
|
||||
currentState.weapons[item->getInventorySlot()].weaponId =
|
||||
item->getItemID();
|
||||
void CharacterObject::addToInventory(int slot, int ammo) {
|
||||
RW_CHECK(slot < kMaxInventorySlots, "Slot greater than kMaxInventorySlots");
|
||||
if (slot < kMaxInventorySlots) {
|
||||
currentState.weapons[slot].weaponId = slot;
|
||||
currentState.weapons[slot].bulletsTotal += ammo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -534,19 +531,16 @@ void CharacterObject::setActiveItem(int 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) {
|
||||
currentState.weapons[slot].weaponId = 0;
|
||||
if (currentState.currentWeapon == slot) {
|
||||
currentState.currentWeapon = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterObject::cycleInventory(bool up) {
|
||||
if (up) {
|
||||
for (int j = currentState.currentWeapon + 1; j < maxInventorySlots;
|
||||
for (int j = currentState.currentWeapon + 1; j < kMaxInventorySlots;
|
||||
++j) {
|
||||
if (currentState.weapons[j].weaponId != 0) {
|
||||
currentState.currentWeapon = j;
|
||||
@ -565,7 +559,7 @@ void CharacterObject::cycleInventory(bool up) {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
currentState.currentWeapon = j;
|
||||
return;
|
||||
@ -575,17 +569,21 @@ void CharacterObject::cycleInventory(bool up) {
|
||||
}
|
||||
|
||||
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 (active)
|
||||
currentState.primaryStartTime = engine->getGameTime() * 1000.f;
|
||||
else
|
||||
currentState.primaryEndTime = engine->getGameTime() * 1000.f;
|
||||
if (!currentState.primaryActive && active) {
|
||||
// If we've just started, activate
|
||||
controller->setNextActivity(new Activities::UseItem(item));
|
||||
}
|
||||
else if (currentState.primaryActive && !active) {
|
||||
// UseItem will cancel itself upon !primaryActive
|
||||
}
|
||||
currentState.primaryActive = active;
|
||||
getActiveItem()->primary(this);
|
||||
} else {
|
||||
currentState.secondaryActive = active;
|
||||
getActiveItem()->secondary(this);
|
||||
/// @todo handle scopes and sights
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <objects/GameObject.hpp>
|
||||
|
||||
constexpr int maxInventorySlots = 13;
|
||||
constexpr int kMaxInventorySlots = 13;
|
||||
|
||||
// Animation slots used for character animation blending
|
||||
constexpr unsigned int AnimIndexMovement = 0;
|
||||
@ -26,18 +26,15 @@ struct CharacterState {
|
||||
float rotation;
|
||||
float health = 100.f;
|
||||
float armour = 0.f;
|
||||
std::array<CharacterWeaponSlot, maxInventorySlots> weapons;
|
||||
std::array<CharacterWeaponSlot, kMaxInventorySlots> weapons;
|
||||
uint16_t currentWeapon = 0;
|
||||
uint32_t lastFireTimeMS = 0;
|
||||
bool primaryActive = false;
|
||||
bool secondaryActive = false;
|
||||
uint32_t primaryStartTime = 0;
|
||||
uint32_t primaryEndTime = 0;
|
||||
};
|
||||
|
||||
class VehicleObject;
|
||||
class GameWorld;
|
||||
class InventoryItem;
|
||||
|
||||
struct AnimationGroup {
|
||||
Animation* idle;
|
||||
@ -234,9 +231,21 @@ public:
|
||||
*/
|
||||
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);
|
||||
InventoryItem* getActiveItem();
|
||||
int getActiveItem() const { return currentState.currentWeapon; }
|
||||
|
||||
/**
|
||||
* @brief removeFromInventory Removes item at slot from inventory
|
||||
*/
|
||||
void removeFromInventory(int slot);
|
||||
|
||||
/**
|
||||
|
@ -1,22 +1,20 @@
|
||||
#include <data/WeaponData.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/ItemPickup.hpp>
|
||||
#include <rw/defines.hpp>
|
||||
|
||||
ItemPickup::ItemPickup(GameWorld *world, const glm::vec3 &position,
|
||||
BaseModelInfo *modelinfo, PickupType type,
|
||||
InventoryItem *item)
|
||||
WeaponData *item)
|
||||
: PickupObject(world, position, modelinfo, type), item(item) {
|
||||
RW_CHECK(item != nullptr, "Pickup created with null item");
|
||||
}
|
||||
|
||||
bool ItemPickup::onCharacterTouch(CharacterObject *character) {
|
||||
character->addToInventory(item);
|
||||
auto &wep = character->getCurrentState().weapons[item->getInventorySlot()];
|
||||
auto totalRounds = 0, clipRounds = 0;
|
||||
auto totalRounds = 0;
|
||||
|
||||
switch (item->getModelID()) {
|
||||
switch (item->modelID) {
|
||||
case 173: /* Pistol */
|
||||
totalRounds = 45;
|
||||
break;
|
||||
@ -50,8 +48,7 @@ bool ItemPickup::onCharacterTouch(CharacterObject *character) {
|
||||
totalRounds /= 5;
|
||||
}
|
||||
|
||||
wep.bulletsTotal = totalRounds;
|
||||
wep.bulletsClip = clipRounds;
|
||||
character->addToInventory(item->inventorySlot, totalRounds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,21 +1,19 @@
|
||||
#pragma once
|
||||
#ifndef _ITEMPICKUP_HPP_
|
||||
#define _ITEMPICKUP_HPP_
|
||||
#include <data/WeaponData.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <objects/PickupObject.hpp>
|
||||
|
||||
class InventoryItem;
|
||||
|
||||
/**
|
||||
* @brief The ItemPickup class
|
||||
* Inserts an item into a characters inventory on pickup.
|
||||
*/
|
||||
class ItemPickup : public PickupObject {
|
||||
InventoryItem* item;
|
||||
|
||||
WeaponData* item;
|
||||
public:
|
||||
ItemPickup(GameWorld* world, const glm::vec3& position, BaseModelInfo *modelinfo, PickupType type,
|
||||
InventoryItem* item);
|
||||
ItemPickup(GameWorld* world, const glm::vec3& position,
|
||||
BaseModelInfo* modelinfo, PickupType type, WeaponData* item);
|
||||
|
||||
bool onCharacterTouch(CharacterObject* character);
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
/** Time to dentonation or removal */
|
||||
float time;
|
||||
|
||||
std::shared_ptr<WeaponData> weapon;
|
||||
WeaponData* weapon;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include <ai/CharacterController.hpp>
|
||||
#include <data/ModelData.hpp>
|
||||
#include <items/InventoryItem.hpp>
|
||||
|
||||
#include <data/CutsceneData.hpp>
|
||||
#include <data/Skeleton.hpp>
|
||||
|
@ -32,7 +32,6 @@ class ProjectileObject;
|
||||
class CutsceneObject;
|
||||
|
||||
class Animator;
|
||||
class InventoryItem;
|
||||
|
||||
class Renderer;
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <render/ObjectRenderer.hpp>
|
||||
|
||||
// Objects that we know how to turn into renderlist entries
|
||||
#include <items/InventoryItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/CutsceneObject.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
@ -302,31 +301,30 @@ void ObjectRenderer::renderCharacter(CharacterObject* pedestrian,
|
||||
renderFrame(pedestrian->getModel(), root->getChildren()[0], matrixModel,
|
||||
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) {
|
||||
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);
|
||||
if (weapon->modelID == -1) {
|
||||
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>(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,
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "DrawUI.hpp"
|
||||
#include <ai/PlayerController.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <data/WeaponData.hpp>
|
||||
#include <render/GameRenderer.hpp>
|
||||
|
||||
#include <glm/gtc/constants.hpp>
|
||||
@ -152,16 +152,14 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world,
|
||||
render->text.renderText(ti);
|
||||
#endif
|
||||
|
||||
InventoryItem* current = player->getCharacter()->getActiveItem();
|
||||
auto item = player->getCharacter()->getActiveItem();
|
||||
auto weapon = world->data->weaponData[item];
|
||||
std::string itemTextureName = "fist";
|
||||
if (current) {
|
||||
uint16_t model = current->getModelID();
|
||||
if (model > 0) {
|
||||
auto weaponData =
|
||||
world->data->findModelInfo<SimpleModelInfo>(model);
|
||||
if (weaponData != nullptr) {
|
||||
itemTextureName = weaponData->name;
|
||||
}
|
||||
if (weapon && weapon->modelID > 0) {
|
||||
auto model =
|
||||
world->data->findModelInfo<SimpleModelInfo>(weapon->modelID);
|
||||
if (model != nullptr) {
|
||||
itemTextureName = model->name;
|
||||
}
|
||||
}
|
||||
// Urgh
|
||||
@ -179,25 +177,20 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world,
|
||||
glm::vec4(iconX, iconY, ui_weaponSize, ui_weaponSize));
|
||||
}
|
||||
|
||||
if (current) {
|
||||
WeaponItem* wep = static_cast<WeaponItem*>(current);
|
||||
if (wep->getWeaponData()->fireType != WeaponData::MELEE) {
|
||||
const CharacterState& cs =
|
||||
player->getCharacter()->getCurrentState();
|
||||
const CharacterWeaponSlot& slotInfo = cs.weapons[cs.currentWeapon];
|
||||
ti.text = GameStringUtil::fromString(
|
||||
std::to_string(slotInfo.bulletsClip) + "-" +
|
||||
std::to_string(slotInfo.bulletsTotal));
|
||||
if (weapon->fireType != WeaponData::MELEE) {
|
||||
const CharacterState& cs = player->getCharacter()->getCurrentState();
|
||||
const CharacterWeaponSlot& slotInfo = cs.weapons[cs.currentWeapon];
|
||||
ti.text = GameStringUtil::fromString(
|
||||
std::to_string(slotInfo.bulletsClip) + "-" +
|
||||
std::to_string(slotInfo.bulletsTotal));
|
||||
|
||||
ti.baseColour = ui_shadowColour;
|
||||
ti.font = 2;
|
||||
ti.size = ui_ammoSize;
|
||||
ti.align = TextRenderer::TextInfo::Center;
|
||||
ti.screenPosition =
|
||||
glm::vec2(iconX + ui_weaponSize / 2.f,
|
||||
iconY + ui_weaponSize - ui_ammoHeight);
|
||||
render->text.renderText(ti);
|
||||
}
|
||||
ti.baseColour = ui_shadowColour;
|
||||
ti.font = 2;
|
||||
ti.size = ui_ammoSize;
|
||||
ti.align = TextRenderer::TextInfo::Center;
|
||||
ti.screenPosition = glm::vec2(iconX + ui_weaponSize / 2.f,
|
||||
iconY + ui_weaponSize - ui_ammoHeight);
|
||||
render->text.renderText(ti);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <engine/GameState.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <items/InventoryItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
@ -279,11 +278,10 @@ Menu* DebugState::createWeaponMenu() {
|
||||
[=] { this->enterMenu(createDebugMenu()); },
|
||||
kDebugEntryHeight));
|
||||
|
||||
for (int i = 1; i < maxInventorySlots; ++i) {
|
||||
auto item = getWorld()->getInventoryItem(i);
|
||||
for (int i = 1; i < kMaxInventorySlots; ++i) {
|
||||
auto& name = getWorld()->data->weaponData[i]->name;
|
||||
m->addEntry(
|
||||
Menu::lambda(name, [=] { giveItem(item); }, kDebugEntryHeight));
|
||||
Menu::lambda(name, [=] { giveItem(i); }, kDebugEntryHeight));
|
||||
}
|
||||
|
||||
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;
|
||||
if (game->getPlayer()) {
|
||||
player = game->getPlayer()->getCharacter();
|
||||
}
|
||||
|
||||
if (player) {
|
||||
player->addToInventory(item);
|
||||
auto& wep = player->getCurrentState().weapons[item->getInventorySlot()];
|
||||
wep.bulletsTotal = 100;
|
||||
wep.bulletsClip = 0;
|
||||
player->addToInventory(slot, 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
|
||||
void spawnVehicle(unsigned int id);
|
||||
void spawnFollower(unsigned int id);
|
||||
void giveItem(InventoryItem* item);
|
||||
void giveItem(int slot);
|
||||
|
||||
const ViewCamera& getCamera();
|
||||
};
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
#include <ai/PlayerController.hpp>
|
||||
#include <data/Model.hpp>
|
||||
#include <data/WeaponData.hpp>
|
||||
#include <dynamics/CollisionInstance.hpp>
|
||||
#include <dynamics/RaycastCallbacks.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/ItemPickup.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
@ -105,9 +105,9 @@ void IngameState::startTest() {
|
||||
getWorld()->state->playerObject = playerChar->getGameObjectID();
|
||||
|
||||
glm::vec3 itemspawn(276.5f, -609.f, 36.5f);
|
||||
for (int i = 1; i < maxInventorySlots; ++i) {
|
||||
auto item = getWorld()->getInventoryItem(i);
|
||||
getWorld()->createPickup(itemspawn, item->getModelID(),
|
||||
for (int i = 1; i < getWorld()->data->weaponData.size(); ++i) {
|
||||
auto& item = getWorld()->data->weaponData[i];
|
||||
getWorld()->createPickup(itemspawn, item->modelID,
|
||||
PickupObject::OnStreet);
|
||||
itemspawn.x += 2.5f;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <objects/CharacterObject.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});
|
||||
BOOST_REQUIRE(character != nullptr);
|
||||
|
||||
auto item = Global::get().e->getInventoryItem(4);
|
||||
auto fist = Global::get().e->getInventoryItem(0);
|
||||
character->addToInventory(1, 10);
|
||||
|
||||
BOOST_REQUIRE(item != nullptr);
|
||||
BOOST_REQUIRE(fist != nullptr);
|
||||
BOOST_CHECK_NE(fist, item);
|
||||
BOOST_CHECK_EQUAL(character->getActiveItem(), 0);
|
||||
|
||||
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);
|
||||
|
||||
character->removeFromInventory(item->getInventorySlot());
|
||||
|
||||
BOOST_CHECK_EQUAL(character->getActiveItem(), fist);
|
||||
BOOST_CHECK_EQUAL(character->getActiveItem(), 0);
|
||||
|
||||
Global::get().e->destroyObject(character);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <data/WeaponData.hpp>
|
||||
#include <items/InventoryItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/ItemPickup.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});
|
||||
BOOST_REQUIRE(character != nullptr);
|
||||
|
||||
auto item = Global::get().e->getInventoryItem(3);
|
||||
BOOST_REQUIRE(item != nullptr);
|
||||
auto pistol = Global::get().d->weaponData[1].get();
|
||||
auto model = Global::get().d->modelinfo[pistol->modelID].get();
|
||||
|
||||
ItemPickup* p = new ItemPickup(Global::get().e, {30.f, 0.f, 0.f},
|
||||
nullptr, PickupObject::OnStreet, item);
|
||||
ItemPickup* p = new ItemPickup(Global::get().e, {30.f, 0.f, 0.f}, model,
|
||||
PickupObject::OnStreet, pistol);
|
||||
|
||||
Global::get().e->allObjects.push_back(p);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -84,8 +83,7 @@ BOOST_AUTO_TEST_CASE(test_item_pickup) {
|
||||
auto& inventory = character->getCurrentState().weapons;
|
||||
BOOST_CHECK(std::any_of(std::begin(inventory), std::end(inventory),
|
||||
[&](const CharacterWeaponSlot& i) {
|
||||
return i.weaponId ==
|
||||
item->getInventorySlot();
|
||||
return i.weaponId == pistol->inventorySlot;
|
||||
}));
|
||||
|
||||
Global::get().e->destroyObject(p);
|
||||
|
@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(TestProjectile) {
|
||||
auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f});
|
||||
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(
|
||||
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});
|
||||
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(
|
||||
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});
|
||||
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(
|
||||
Global::get().e, {26.f, 1.f, 10.f},
|
||||
|
Loading…
Reference in New Issue
Block a user