1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 18:32:44 +01:00

clang-format files in rwengine/src/objects

This commit is contained in:
Daniel Evans 2016-09-09 21:13:19 +01:00
parent 305737cc3d
commit f2eede5301
17 changed files with 2297 additions and 2360 deletions

View File

@ -1,11 +1,11 @@
#include <objects/CharacterObject.hpp>
#include <ai/CharacterController.hpp>
#include <engine/GameWorld.hpp>
#include <data/Skeleton.hpp>
#include <engine/Animator.hpp>
#include <engine/GameData.hpp>
#include <objects/VehicleObject.hpp>
#include <engine/GameWorld.hpp>
#include <items/InventoryItem.hpp>
#include <data/Skeleton.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
#include <rw/defines.hpp>
// TODO: make this not hardcoded
@ -13,7 +13,9 @@ 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, const ModelRef& model, std::shared_ptr<CharacterData> data)
CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model,
std::shared_ptr<CharacterData> data)
: GameObject(engine, pos, rot, model)
, currentState({})
, currentVehicle(nullptr)
@ -26,8 +28,7 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, const
, physCharacter(nullptr)
, physObject(nullptr)
, physShape(nullptr)
, controller(nullptr)
{
, controller(nullptr) {
// TODO move AnimationGroup creation somewhere else.
animations.idle = engine->data->animations["idle_stance"];
animations.walk = engine->data->animations["walk_player"];
@ -73,17 +74,14 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, const
}
}
CharacterObject::~CharacterObject()
{
CharacterObject::~CharacterObject() {
destroyActor();
if( currentVehicle )
{
if (currentVehicle) {
currentVehicle->setOccupant(getCurrentSeat(), nullptr);
}
}
void CharacterObject::createActor(const glm::vec2& size)
{
void CharacterObject::createActor(const glm::vec2& size) {
if (physCharacter) {
destroyActor();
}
@ -100,21 +98,23 @@ void CharacterObject::createActor(const glm::vec2& size)
physShape = new btCapsuleShapeZ(size.x, size.y);
physObject->setCollisionShape(physShape);
physObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
physCharacter = new btKinematicCharacterController(physObject, physShape, 0.30f, 2);
physCharacter =
new btKinematicCharacterController(physObject, physShape, 0.30f, 2);
physCharacter->setFallSpeed(20.f);
physCharacter->setUseGhostSweepTest(true);
physCharacter->setVelocityForTimeInterval(btVector3(1.f, 1.f, 1.f), 1.f);
physCharacter->setVelocityForTimeInterval(btVector3(1.f, 1.f, 1.f),
1.f);
physCharacter->setGravity(engine->dynamicsWorld->getGravity().length());
physCharacter->setJumpSpeed(5.f);
engine->dynamicsWorld->addCollisionObject(physObject, btBroadphaseProxy::KinematicFilter,
engine->dynamicsWorld->addCollisionObject(
physObject, btBroadphaseProxy::KinematicFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::SensorTrigger);
engine->dynamicsWorld->addAction(physCharacter);
}
}
void CharacterObject::destroyActor()
{
void CharacterObject::destroyActor() {
if (physCharacter) {
engine->dynamicsWorld->removeCollisionObject(physObject);
engine->dynamicsWorld->removeAction(physCharacter);
@ -126,27 +126,25 @@ void CharacterObject::destroyActor()
}
}
glm::vec3 CharacterObject::updateMovementAnimation(float dt)
{
glm::vec3 CharacterObject::updateMovementAnimation(float dt) {
glm::vec3 animTranslate;
if (motionBlockedByActivity)
{
if (motionBlockedByActivity) {
// Clear any residual motion animation
animator->playAnimation(AnimIndexMovement, nullptr, 1.f, false);
return glm::vec3();
}
// Things are simpler if we're in a vehicle
if (getCurrentVehicle())
{
if (getCurrentVehicle()) {
animator->playAnimation(0, animations.car_sit, 1.f, true);
return glm::vec3();
}
Animation* movementAnimation = animations.idle;
Animation* currentAnim = animator->getAnimation(AnimIndexMovement);
bool isActionHappening = (animator->getAnimation(AnimIndexAction) != nullptr);
bool isActionHappening =
(animator->getAnimation(AnimIndexAction) != nullptr);
float animationSpeed = 1.f;
bool repeat = true;
constexpr float movementEpsilon = 0.1f;
@ -155,54 +153,42 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt)
if (!isAlive()) {
movementAnimation = animations.ko_shot_front;
repeat = false;
}
else if (jumped) {
} else if (jumped) {
repeat = false;
if (currentAnim == animations.jump_start &&
animator->isCompleted(AnimIndexMovement)) {
movementAnimation = animations.jump_start;
}
if (isOnGround()) {
if (currentAnim != animations.jump_land
|| !animator->isCompleted(AnimIndexMovement)) {
if (currentAnim != animations.jump_land ||
!animator->isCompleted(AnimIndexMovement)) {
movementAnimation = animations.jump_land;
}
else {
} else {
// We are done jumping
jumped = false;
}
}
else {
} else {
movementAnimation = animations.jump_glide;
}
}
else if (movementLength > movementEpsilon)
{
} else if (movementLength > movementEpsilon) {
if (running && !isActionHappening) {
if (movementLength > 1.f) {
movementAnimation = animations.sprint;
}
else {
} else {
movementAnimation = animations.run;
}
animationSpeed = 1.f;
}
else {
} else {
animationSpeed = 1.f / movementLength;
// Determine if we need to play the walk start animation
if (currentAnim != animations.walk)
{
if (currentAnim != animations.walk_start || !animator->isCompleted(AnimIndexMovement))
{
if (currentAnim != animations.walk) {
if (currentAnim != animations.walk_start ||
!animator->isCompleted(AnimIndexMovement)) {
movementAnimation = animations.walk_start;
}
else
{
} else {
movementAnimation = animations.walk;
}
}
else
{
} else {
// Keep walkin
movementAnimation = animations.walk;
}
@ -210,42 +196,43 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt)
}
// Check if we need to change the animation or change speed
if (animator->getAnimation(AnimIndexMovement) != movementAnimation)
{
animator->playAnimation(AnimIndexMovement, movementAnimation, animationSpeed, repeat);
}
else
{
if (animator->getAnimation(AnimIndexMovement) != movementAnimation) {
animator->playAnimation(AnimIndexMovement, movementAnimation,
animationSpeed, repeat);
} else {
animator->setAnimationSpeed(AnimIndexMovement, animationSpeed);
}
// If we have to, interrogate the movement animation
if (movementAnimation != animations.idle)
{
if(! model->resource->frames[0]->getChildren().empty() )
{
if (movementAnimation != animations.idle) {
if (!model->resource->frames[0]->getChildren().empty()) {
ModelFrame* root = model->resource->frames[0]->getChildren()[0];
auto it = movementAnimation->bones.find(root->getName());
if (it != movementAnimation->bones.end())
{
if (it != movementAnimation->bones.end()) {
AnimationBone* rootBone = it->second;
float step = dt;
const float duration = animator->getAnimation(AnimIndexMovement)->duration;
float animTime = fmod(animator->getAnimationTime(AnimIndexMovement), duration);
const float duration =
animator->getAnimation(AnimIndexMovement)->duration;
float animTime = fmod(
animator->getAnimationTime(AnimIndexMovement), duration);
// Handle any remaining transformation before the end of the keyframes
if ((animTime+step) > duration)
{
glm::vec3 a = rootBone->getInterpolatedKeyframe(animTime).position;
glm::vec3 b = rootBone->getInterpolatedKeyframe(duration).position;
// Handle any remaining transformation before the end of the
// keyframes
if ((animTime + step) > duration) {
glm::vec3 a =
rootBone->getInterpolatedKeyframe(animTime).position;
glm::vec3 b =
rootBone->getInterpolatedKeyframe(duration).position;
glm::vec3 d = (b - a);
animTranslate.y += d.y;
step -= (duration - animTime);
animTime = 0.f;
}
glm::vec3 a = rootBone->getInterpolatedKeyframe(animTime).position;
glm::vec3 b = rootBone->getInterpolatedKeyframe(animTime+step).position;
glm::vec3 a =
rootBone->getInterpolatedKeyframe(animTime).position;
glm::vec3 b =
rootBone->getInterpolatedKeyframe(animTime + step).position;
glm::vec3 d = (b - a);
animTranslate.y += d.y;
@ -259,8 +246,7 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt)
return animTranslate;
}
void CharacterObject::tick(float dt)
{
void CharacterObject::tick(float dt) {
if (controller) {
controller->update(dt);
}
@ -275,10 +261,10 @@ void CharacterObject::tick(float dt)
}
#include <algorithm>
void CharacterObject::changeCharacterModel(const std::string &name)
{
void CharacterObject::changeCharacterModel(const std::string& name) {
auto modelName = std::string(name);
std::transform(modelName.begin(), modelName.end(), modelName.begin(), ::tolower);
std::transform(modelName.begin(), modelName.end(), modelName.begin(),
::tolower);
engine->data->loadDFF(modelName + ".dff");
engine->data->loadTXD(modelName + ".txd");
@ -289,8 +275,7 @@ void CharacterObject::changeCharacterModel(const std::string &name)
model = mfind->second;
}
if( skeleton )
{
if (skeleton) {
delete animator;
delete skeleton;
}
@ -299,8 +284,7 @@ void CharacterObject::changeCharacterModel(const std::string &name)
animator = new Animator(model->resource, skeleton);
}
void CharacterObject::updateCharacter(float dt)
{
void CharacterObject::updateCharacter(float dt) {
/*
* You can fire weapons while moving
*
@ -327,24 +311,21 @@ void CharacterObject::updateCharacter(float dt)
walkDir = rotation * walkDir;
if( jumped )
{
if( !isOnGround() )
{
if (jumped) {
if (!isOnGround()) {
walkDir = rotation * glm::vec3(0.f, jumpSpeed * dt, 0.f);
}
}
if (isAlive())
{
physCharacter->setWalkDirection(btVector3(walkDir.x, walkDir.y, walkDir.z));
}
else
{
if (isAlive()) {
physCharacter->setWalkDirection(
btVector3(walkDir.x, walkDir.y, walkDir.z));
} else {
physCharacter->setWalkDirection(btVector3(0.f, 0.f, 0.f));
}
auto Pos = physCharacter->getGhostObject()->getWorldTransform().getOrigin();
auto Pos =
physCharacter->getGhostObject()->getWorldTransform().getOrigin();
position = glm::vec3(Pos.x(), Pos.y(), Pos.z());
// Handle above waist height water.
@ -372,27 +353,21 @@ void CharacterObject::updateCharacter(float dt)
physCharacter->setGravity(0.f);
inWater = true;
}
else {
} else {
physCharacter->setGravity(9.81f);
inWater = false;
}
}
_lastHeight = getPosition().z;
}
else
{
} else {
updateMovementAnimation(dt);
}
}
void CharacterObject::setPosition(const glm::vec3& pos)
{
if( physCharacter )
{
void CharacterObject::setPosition(const glm::vec3& pos) {
if (physCharacter) {
btVector3 bpos(pos.x, pos.y, pos.z);
if( std::abs(-100.f - pos.z) < 0.01f )
{
if (std::abs(-100.f - pos.z) < 0.01f) {
// Find the ground position
auto gpos = engine->getGroundAtPosition(pos);
bpos.setZ(gpos.z + 1.f);
@ -402,19 +377,16 @@ void CharacterObject::setPosition(const glm::vec3& pos)
position = pos;
}
bool CharacterObject::isAlive() const
{
bool CharacterObject::isAlive() const {
return currentState.health > 0.f;
}
bool CharacterObject::enterVehicle(VehicleObject* vehicle, size_t seat)
{
bool CharacterObject::enterVehicle(VehicleObject* vehicle, size_t seat) {
if (vehicle) {
// Check that the seat is free
if (vehicle->getOccupant(seat)) {
return false;
}
else {
} else {
// Make sure we leave any vehicle we're inside
enterVehicle(nullptr, 0);
vehicle->setOccupant(seat, this);
@ -422,8 +394,7 @@ bool CharacterObject::enterVehicle(VehicleObject* vehicle, size_t seat)
// enterAction(VehicleSit);
return true;
}
}
else {
} else {
if (currentVehicle) {
currentVehicle->setOccupant(seat, nullptr);
// Disabled due to crashing.
@ -435,17 +406,13 @@ bool CharacterObject::enterVehicle(VehicleObject* vehicle, size_t seat)
return false;
}
bool CharacterObject::isEnteringOrExitingVehicle() const
{
bool CharacterObject::isEnteringOrExitingVehicle() const {
auto a = animator->getAnimation(AnimIndexAction);
return a == animations.car_getout_lhs ||
a == animations.car_getin_lhs ||
a == animations.car_getout_rhs ||
a == animations.car_getin_rhs;
return a == animations.car_getout_lhs || a == animations.car_getin_lhs ||
a == animations.car_getout_rhs || a == animations.car_getin_rhs;
}
bool CharacterObject::isStopped() const
{
bool CharacterObject::isStopped() const {
if (currentVehicle != nullptr) {
return currentVehicle->isStopped();
}
@ -453,35 +420,31 @@ bool CharacterObject::isStopped() const
return controller->getCurrentActivity() == nullptr;
}
VehicleObject *CharacterObject::getCurrentVehicle() const
{
VehicleObject* CharacterObject::getCurrentVehicle() const {
return currentVehicle;
}
size_t CharacterObject::getCurrentSeat() const
{
size_t CharacterObject::getCurrentSeat() const {
return currentSeat;
}
void CharacterObject::setCurrentVehicle(VehicleObject *value, size_t seat)
{
void CharacterObject::setCurrentVehicle(VehicleObject* value, size_t seat) {
currentVehicle = value;
currentSeat = seat;
if (currentVehicle == nullptr && physCharacter == nullptr) {
createActor();
}
else if(currentVehicle) {
} else if (currentVehicle) {
destroyActor();
}
}
bool CharacterObject::takeDamage(const GameObject::DamageInfo& dmg)
{
bool CharacterObject::takeDamage(const GameObject::DamageInfo& dmg) {
// Right now there's no state that determines immunity to any kind of damage
float dmgPoints = dmg.hitpoints;
if (currentState.armour > 0.f) {
dmgPoints -= currentState.armour;
currentState.armour = std::max(0.f, currentState.armour - dmg.hitpoints);
currentState.armour =
std::max(0.f, currentState.armour - dmg.hitpoints);
}
if (dmgPoints > 0.f) {
currentState.health = std::max(0.f, currentState.health - dmgPoints);
@ -489,48 +452,44 @@ bool CharacterObject::takeDamage(const GameObject::DamageInfo& dmg)
return true;
}
void CharacterObject::jump()
{
void CharacterObject::jump() {
if (physCharacter) {
physCharacter->jump();
jumped = true;
animator->playAnimation(AnimIndexMovement, animations.jump_start, 1.f, false);
animator->playAnimation(AnimIndexMovement, animations.jump_start, 1.f,
false);
}
}
float CharacterObject::getJumpSpeed() const
{
float CharacterObject::getJumpSpeed() const {
return jumpSpeed;
}
bool CharacterObject::isOnGround() const
{
bool CharacterObject::isOnGround() const {
if (physCharacter) {
return physCharacter->onGround();
}
return true;
}
bool CharacterObject::canTurn() const
{
return isOnGround() && !jumped && isAlive() && controller->getCurrentActivity() == nullptr;
bool CharacterObject::canTurn() const {
return isOnGround() && !jumped && isAlive() &&
controller->getCurrentActivity() == nullptr;
}
void CharacterObject::setJumpSpeed(float speed)
{
void CharacterObject::setJumpSpeed(float speed) {
jumpSpeed = speed;
}
void CharacterObject::resetToAINode()
{
void CharacterObject::resetToAINode() {
auto nodes = engine->aigraph.nodes;
bool vehicleNode = !!getCurrentVehicle();
AIGraphNode* nearest = nullptr; float d = std::numeric_limits<float>::max();
AIGraphNode* nearest = nullptr;
float d = std::numeric_limits<float>::max();
for (auto it = nodes.begin(); it != nodes.end(); ++it) {
if (vehicleNode) {
if ((*it)->type == AIGraphNode::Pedestrian) continue;
}
else {
} else {
if ((*it)->type == AIGraphNode::Vehicle) continue;
}
@ -543,56 +502,53 @@ void CharacterObject::resetToAINode()
if (nearest) {
if (vehicleNode) {
getCurrentVehicle()->setPosition(nearest->position + glm::vec3(0.f, 0.f, 2.5f));
}
else {
getCurrentVehicle()->setPosition(nearest->position +
glm::vec3(0.f, 0.f, 2.5f));
} else {
setPosition(nearest->position + glm::vec3(0.f, 0.f, 2.5f));
}
}
}
void CharacterObject::playActivityAnimation(Animation* animation, bool repeat, bool blocked)
{
void CharacterObject::playActivityAnimation(Animation* animation, bool repeat,
bool blocked) {
RW_CHECK(animator != nullptr, "No Animator");
animator->playAnimation(AnimIndexAction, animation, 1.f, repeat);
motionBlockedByActivity = blocked;
}
void CharacterObject::activityFinished()
{
void CharacterObject::activityFinished() {
animator->playAnimation(AnimIndexAction, nullptr, 1.f, false);
motionBlockedByActivity = false;
}
void CharacterObject::addToInventory(InventoryItem *item)
{
RW_CHECK(item->getInventorySlot() < maxInventorySlots, "Inventory Slot greater than maxInventorySlots");
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();
currentState.weapons[item->getInventorySlot()].weaponId =
item->getItemID();
}
}
void CharacterObject::setActiveItem(int slot)
{
void CharacterObject::setActiveItem(int slot) {
currentState.currentWeapon = slot;
}
InventoryItem *CharacterObject::getActiveItem()
{
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;
}
void CharacterObject::cycleInventory(bool up)
{
void CharacterObject::cycleInventory(bool up) {
if (up) {
for(int j = currentState.currentWeapon+1; j < maxInventorySlots; ++j) {
for (int j = currentState.currentWeapon + 1; j < maxInventorySlots;
++j) {
if (currentState.weapons[j].weaponId != 0) {
currentState.currentWeapon = j;
return;
@ -601,8 +557,7 @@ void CharacterObject::cycleInventory(bool up)
// if there's no higher slot, set the first item.
currentState.currentWeapon = 0;
}
else {
} else {
for (int j = currentState.currentWeapon - 1; j >= 0; --j) {
if (currentState.weapons[j].weaponId != 0) {
currentState.currentWeapon = j;
@ -620,8 +575,7 @@ void CharacterObject::cycleInventory(bool up)
}
}
void CharacterObject::useItem(bool active, bool primary)
{
void CharacterObject::useItem(bool active, bool primary) {
if (getActiveItem()) {
if (primary) {
if (active)
@ -630,8 +584,7 @@ void CharacterObject::useItem(bool active, bool primary)
currentState.primaryEndTime = engine->getGameTime() * 1000.f;
currentState.primaryActive = active;
getActiveItem()->primary(this);
}
else {
} else {
currentState.secondaryActive = active;
getActiveItem()->secondary(this);
}

View File

@ -1,12 +1,12 @@
#pragma once
#ifndef _CHARACTEROBJECT_HPP_
#define _CHARACTEROBJECT_HPP_
#include <objects/GameObject.hpp>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <BulletDynamics/Character/btKinematicCharacterController.h>
#include <btBulletCollisionCommon.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <glm/glm.hpp>
#include <array>
#include <glm/glm.hpp>
#include <objects/GameObject.hpp>
constexpr int maxInventorySlots = 13;
@ -14,16 +14,14 @@ constexpr int maxInventorySlots = 13;
constexpr unsigned int AnimIndexMovement = 0;
constexpr unsigned int AnimIndexAction = 1;
struct CharacterWeaponSlot
{
struct CharacterWeaponSlot {
// Assuming these match the entries in weapon.dat
uint32_t weaponId;
uint32_t bulletsClip;
uint32_t bulletsTotal;
};
struct CharacterState
{
struct CharacterState {
glm::vec3 position;
float rotation;
float health = 100.f;
@ -41,8 +39,7 @@ class VehicleObject;
class GameWorld;
class InventoryItem;
struct AnimationGroup
{
struct AnimationGroup {
Animation* idle;
Animation* walk;
Animation* walk_start;
@ -80,23 +77,31 @@ struct AnimationGroup
Animation* ko_shot_front;
AnimationGroup()
: idle(nullptr), walk(nullptr), walk_start(nullptr), run(nullptr),
jump_start(nullptr), jump_glide(nullptr), jump_land(nullptr),
car_sit(nullptr), car_sit_low(nullptr), car_open_lhs(nullptr),
car_getin_lhs(nullptr), car_getout_lhs(nullptr), car_open_rhs(nullptr),
car_getin_rhs(nullptr)
: idle(nullptr)
, walk(nullptr)
, walk_start(nullptr)
, run(nullptr)
, jump_start(nullptr)
, jump_glide(nullptr)
, jump_land(nullptr)
, car_sit(nullptr)
, car_sit_low(nullptr)
, car_open_lhs(nullptr)
, car_getin_lhs(nullptr)
, car_getout_lhs(nullptr)
, car_open_rhs(nullptr)
, car_getin_rhs(nullptr)
, car_getout_rhs(nullptr)
, kd_front(nullptr)
, ko_shot_front(nullptr)
{}
, ko_shot_front(nullptr) {
}
};
/**
* @brief The CharacterObject struct
* Implements Character object behaviours.
*/
class CharacterObject : public GameObject
{
class CharacterObject : public GameObject {
private:
CharacterState currentState;
@ -116,8 +121,8 @@ private:
bool motionBlockedByActivity;
glm::vec3 updateMovementAnimation(float dt);
public:
public:
static const float DefaultJumpSpeed;
std::shared_ptr<CharacterData> ped;
@ -136,16 +141,24 @@ public:
* @param model
* @param ped PEDS_t struct to use.
*/
CharacterObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, std::shared_ptr< CharacterData > data);
CharacterObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model,
std::shared_ptr<CharacterData> data);
~CharacterObject();
Type type() { return Character; }
Type type() {
return Character;
}
void tick(float dt);
const CharacterState& getCurrentState() const { return currentState; }
CharacterState& getCurrentState(){ return currentState; }
const CharacterState& getCurrentState() const {
return currentState;
}
CharacterState& getCurrentState() {
return currentState;
}
/**
* @brief Loads the model and texture for a character skin.
@ -182,8 +195,12 @@ public:
bool isOnGround() const;
bool canTurn() const;
void setRunning(bool run) { running = run; }
bool isRunning() const { return running; }
void setRunning(bool run) {
running = run;
}
bool isRunning() const {
return running;
}
/**
* Resets the Actor to the nearest AI Graph node
@ -191,10 +208,18 @@ public:
*/
void resetToAINode();
void setMovement(const glm::vec3& _m) { movement = _m; }
const glm::vec3& getMovement() const { return movement; }
void setLook(const glm::vec2& look) { m_look = look; }
const glm::vec2& getLook() const { return m_look; }
void setMovement(const glm::vec3& _m) {
movement = _m;
}
const glm::vec3& getMovement() const {
return movement;
}
void setLook(const glm::vec2& look) {
m_look = look;
}
const glm::vec2& getLook() const {
return m_look;
}
/**
* @brief playActivityAnimation Plays an animation for an activity.
@ -205,7 +230,8 @@ public:
* This allows controller activities to play their own animations and
* controll blending with movement.
*/
void playActivityAnimation(Animation* animation, bool repeat, bool blocking);
void playActivityAnimation(Animation* animation, bool repeat,
bool blocking);
/**
* @brief activityFinished removes activity animation
*/

View File

@ -1,27 +1,22 @@
#include <objects/CutsceneObject.hpp>
#include <engine/Animator.hpp>
#include <data/Skeleton.hpp>
#include <engine/Animator.hpp>
#include <objects/CutsceneObject.hpp>
CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos, const glm::quat& rot, const ModelRef& model)
: GameObject(engine, pos, rot, model)
, _parent(nullptr)
, _bone(nullptr)
{
CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos,
const glm::quat &rot, const ModelRef &model)
: GameObject(engine, pos, rot, model), _parent(nullptr), _bone(nullptr) {
skeleton = new Skeleton;
animator = new Animator(model->resource, skeleton);
}
CutsceneObject::~CutsceneObject()
{
CutsceneObject::~CutsceneObject() {
}
void CutsceneObject::tick(float dt)
{
void CutsceneObject::tick(float dt) {
animator->tick(dt);
}
void CutsceneObject::setParentActor(GameObject *parent, ModelFrame *bone)
{
void CutsceneObject::setParentActor(GameObject *parent, ModelFrame *bone) {
_parent = parent;
_bone = bone;
}

View File

@ -6,29 +6,28 @@
/**
* @brief Object type used for cutscene animations.
*/
class CutsceneObject : public GameObject
{
class CutsceneObject : public GameObject {
GameObject* _parent;
ModelFrame* _bone;
public:
CutsceneObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model);
CutsceneObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model);
~CutsceneObject();
Type type() { return Cutscene; }
Type type() {
return Cutscene;
}
void tick(float dt);
void setParentActor(GameObject* parent, ModelFrame* bone);
GameObject* getParentActor() const
{
GameObject* getParentActor() const {
return _parent;
}
ModelFrame* getParentFrame() const
{
ModelFrame* getParentFrame() const {
return _bone;
}
};

View File

@ -1,41 +1,33 @@
#include <objects/GameObject.hpp>
#include <loaders/LoaderIFP.hpp>
#include <loaders/LoaderDFF.hpp>
#include <engine/Animator.hpp>
#include <data/Skeleton.hpp>
#include <engine/Animator.hpp>
#include <glm/gtc/quaternion.hpp>
#include <loaders/LoaderDFF.hpp>
#include <loaders/LoaderIFP.hpp>
#include <objects/GameObject.hpp>
GameObject::~GameObject()
{
if(animator)
{
GameObject::~GameObject() {
if (animator) {
delete animator;
}
if(skeleton)
{
if (skeleton) {
delete skeleton;
}
}
void GameObject::setPosition(const glm::vec3& pos)
{
void GameObject::setPosition(const glm::vec3& pos) {
_lastPosition = position = pos;
}
void GameObject::setRotation(const glm::quat& orientation)
{
void GameObject::setRotation(const glm::quat& orientation) {
rotation = orientation;
}
float GameObject::getHeading() const
{
float GameObject::getHeading() const {
auto hdg = glm::roll(getRotation());
return hdg / glm::pi<float>() * 180.f;
}
void GameObject::setHeading(float heading)
{
void GameObject::setHeading(float heading) {
auto hdg = (heading / 180.f) * glm::pi<float>();
auto quat = glm::normalize(glm::quat(glm::vec3(0.f, 0.f, hdg)));
setRotation(quat);

View File

@ -2,14 +2,14 @@
#ifndef _GAMEOBJECT_HPP_
#define _GAMEOBJECT_HPP_
#include <rw/types.hpp>
#include <objects/ObjectTypes.hpp>
#include <data/Model.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderIPL.hpp>
#include <data/Model.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <memory>
#include <objects/ObjectTypes.hpp>
#include <rw/types.hpp>
class Skeleton;
class CharacterController;
@ -23,11 +23,11 @@ class GameWorld;
* Contains handle to the world, and other useful properties like water level
* tracking used to make tunnels work.
*/
class GameObject
{
class GameObject {
glm::vec3 _lastPosition;
glm::quat _lastRotation;
GameObjectID objectID;
public:
glm::vec3 position;
glm::quat rotation;
@ -52,7 +52,8 @@ public:
*/
bool visible;
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelRef model)
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot,
ModelRef model)
: _lastPosition(pos)
, _lastRotation(rot)
, objectID(0)
@ -65,24 +66,29 @@ public:
, inWater(false)
, _lastHeight(std::numeric_limits<float>::max())
, visible(true)
, lifetime(GameObject::UnknownLifetime)
{}
, lifetime(GameObject::UnknownLifetime) {
}
virtual ~GameObject();
GameObjectID getGameObjectID() const { return objectID; }
GameObjectID getGameObjectID() const {
return objectID;
}
/**
* Do not call this, use GameWorld::insertObject
*/
void setGameObjectID(GameObjectID id) { objectID = id; }
void setGameObjectID(GameObjectID id) {
objectID = id;
}
int getScriptObjectID() const { return getGameObjectID(); }
int getScriptObjectID() const {
return getGameObjectID();
}
/**
* @brief Enumeration of possible object types.
*/
enum Type
{
enum Type {
Instance,
Character,
Vehicle,
@ -96,14 +102,22 @@ public:
* @brief determines what type of object this is.
* @return one of Type
*/
virtual Type type() { return Unknown; }
virtual Type type() {
return Unknown;
}
virtual void setPosition(const glm::vec3& pos);
const glm::vec3& getPosition() const { return position; }
const glm::vec3& getLastPosition() const { return _lastPosition; }
const glm::vec3& getPosition() const {
return position;
}
const glm::vec3& getLastPosition() const {
return _lastPosition;
}
const glm::quat& getRotation() const { return rotation; }
const glm::quat& getRotation() const {
return rotation;
}
virtual void setRotation(const glm::quat& orientation);
float getHeading() const;
@ -112,15 +126,8 @@ public:
*/
void setHeading(float heading);
struct DamageInfo
{
enum DamageType
{
Explosion,
Burning,
Bullet,
Physics
};
struct DamageInfo {
enum DamageType { Explosion, Burning, Bullet, Physics };
/**
* World position of damage
@ -148,11 +155,17 @@ public:
float impulse;
};
virtual bool takeDamage(const DamageInfo& /*damage*/) { return false; }
virtual bool takeDamage(const DamageInfo& /*damage*/) {
return false;
}
virtual bool isAnimationFixed() const { return true; }
virtual bool isAnimationFixed() const {
return true;
}
virtual bool isInWater() const { return inWater; }
virtual bool isInWater() const {
return inWater;
}
virtual void tick(float dt) = 0;
@ -160,8 +173,7 @@ public:
* @brief Function used to modify the last transform
* @param newPos
*/
void _updateLastTransform()
{
void _updateLastTransform() {
_lastPosition = getPosition();
_lastRotation = getRotation();
}
@ -173,8 +185,7 @@ public:
return t;
}
enum ObjectLifetime
{
enum ObjectLifetime {
/// lifetime has not been set
UnknownLifetime,
/// Generic background pedestrians
@ -185,11 +196,14 @@ public:
PlayerLifetime
};
void setLifetime(ObjectLifetime ol) { lifetime = ol; }
ObjectLifetime getLifetime() const { return lifetime; }
void setLifetime(ObjectLifetime ol) {
lifetime = ol;
}
ObjectLifetime getLifetime() const {
return lifetime;
}
void updateTransform(const glm::vec3& pos, const glm::quat& rot)
{
void updateTransform(const glm::vec3& pos, const glm::quat& rot) {
_lastPosition = position;
_lastRotation = rotation;
position = pos;

View File

@ -1,14 +1,12 @@
#include <objects/InstanceObject.hpp>
#include <engine/GameWorld.hpp>
#include <data/CollisionModel.hpp>
#include <dynamics/CollisionInstance.hpp>
#include <engine/Animator.hpp>
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
#include <objects/InstanceObject.hpp>
InstanceObject::InstanceObject(GameWorld* engine,
const glm::vec3& pos,
const glm::quat& rot,
const ModelRef& model,
InstanceObject::InstanceObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model,
const glm::vec3& scale,
std::shared_ptr<ObjectData> obj,
InstanceObject* lod,
@ -20,43 +18,42 @@ InstanceObject::InstanceObject(GameWorld* engine,
, object(obj)
, LODinstance(lod)
, dynamics(dyn)
, _enablePhysics(false)
{
, _enablePhysics(false) {
if (obj) {
changeModel(obj);
for( auto& path : obj->paths )
{
for (auto& path : obj->paths) {
engine->aigraph.createPathNodes(position, rot, path);
}
}
}
InstanceObject::~InstanceObject()
{
InstanceObject::~InstanceObject() {
if (body) {
delete body;
}
}
void InstanceObject::tick(float dt)
{
void InstanceObject::tick(float dt) {
if (dynamics && body) {
if (_enablePhysics) {
if (body->getBulletBody()->isStaticObject()) {
// Apparently bodies must be removed and re-added if their mass changes.
// Apparently bodies must be removed and re-added if their mass
// changes.
body->changeMass(dynamics->mass);
}
}
const glm::vec3& ws = getPosition();
auto wX = (int) ((ws.x + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
auto wY = (int) ((ws.y + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
auto wX = (int)((ws.x + WATER_WORLD_SIZE / 2.f) /
(WATER_WORLD_SIZE / WATER_HQ_DATA_SIZE));
auto wY = (int)((ws.y + WATER_WORLD_SIZE / 2.f) /
(WATER_WORLD_SIZE / WATER_HQ_DATA_SIZE));
float vH = ws.z; // - _collisionHeight/2.f;
float wH = 0.f;
if( wX >= 0 && wX < WATER_HQ_DATA_SIZE && wY >= 0 && wY < WATER_HQ_DATA_SIZE ) {
if (wX >= 0 && wX < WATER_HQ_DATA_SIZE && wY >= 0 &&
wY < WATER_HQ_DATA_SIZE) {
int i = (wX * WATER_HQ_DATA_SIZE) + wY;
int hI = engine->data->realWater[i];
if (hI < NO_WATER_INDEX) {
@ -64,19 +61,18 @@ void InstanceObject::tick(float dt)
wH += engine->data->getWaveHeightAt(ws);
if (vH <= wH) {
inWater = true;
}
else {
} else {
inWater = false;
}
}
else {
} else {
inWater = false;
}
}
_lastHeight = ws.z;
if (inWater) {
float oZ = -(body->getBoundingHeight() * (dynamics->bouancy/100.f));
float oZ =
-(body->getBoundingHeight() * (dynamics->bouancy / 100.f));
body->getBulletBody()->activate(true);
// Damper motion
body->getBulletBody()->setDamping(0.95f, 0.9f);
@ -89,19 +85,31 @@ void InstanceObject::tick(float dt)
h += engine->data->getWaveHeightAt(ws);
if (ws.z <= h) {
/*if( dynamics->uprootForce > 0.f && (body->body->getCollisionFlags() & btRigidBody::CF_STATIC_OBJECT) != 0 ) {
// Apparently bodies must be removed and re-added if their mass changes.
/*if( dynamics->uprootForce > 0.f &&
(body->body->getCollisionFlags() &
btRigidBody::CF_STATIC_OBJECT) != 0 ) {
// Apparently bodies must be removed and re-added if
their mass changes.
engine->dynamicsWorld->removeRigidBody(body->body);
btVector3 inert;
body->getCollisionShape()->calculateLocalInertia(dynamics->mass, inert);
body->getCollisionShape()->calculateLocalInertia(dynamics->mass,
inert);
body->setMassProps(dynamics->mass, inert);
engine->dynamicsWorld->addRigidBody(body);
}*/
float x = (h - ws.z);
float F = WATER_BUOYANCY_K * x + -WATER_BUOYANCY_C * body->getBulletBody()->getLinearVelocity().z();
btVector3 forcePos = btVector3(0.f, 0.f, 2.f).rotate(
body->getBulletBody()->getOrientation().getAxis(), body->getBulletBody()->getOrientation().getAngle());
float F =
WATER_BUOYANCY_K * x +
-WATER_BUOYANCY_C *
body->getBulletBody()->getLinearVelocity().z();
btVector3 forcePos = btVector3(0.f, 0.f, 2.f)
.rotate(body->getBulletBody()
->getOrientation()
.getAxis(),
body->getBulletBody()
->getOrientation()
.getAngle());
body->getBulletBody()->applyForce(btVector3(0.f, 0.f, F),
forcePos);
}
@ -112,8 +120,7 @@ void InstanceObject::tick(float dt)
if (animator) animator->tick(dt);
}
void InstanceObject::changeModel(std::shared_ptr<ObjectData> incoming)
{
void InstanceObject::changeModel(std::shared_ptr<ObjectData> incoming) {
if (body) {
delete body;
body = nullptr;
@ -124,16 +131,14 @@ void InstanceObject::changeModel(std::shared_ptr<ObjectData> incoming)
if (incoming) {
auto bod = new CollisionInstance;
if( bod->createPhysicsBody(this, object->modelName, dynamics.get()) )
{
if (bod->createPhysicsBody(this, object->modelName, dynamics.get())) {
bod->getBulletBody()->setActivationState(ISLAND_SLEEPING);
body = bod;
}
}
}
void InstanceObject::setRotation(const glm::quat &r)
{
void InstanceObject::setRotation(const glm::quat& r) {
if (body) {
auto& wtr = body->getBulletBody()->getWorldTransform();
wtr.setRotation(btQuaternion(r.x, r.y, r.z, r.w));
@ -141,13 +146,14 @@ void InstanceObject::setRotation(const glm::quat &r)
GameObject::setRotation(r);
}
bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg)
{
bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) {
bool smash = false;
if (dynamics) {
smash = dynamics->collDamageFlags == 80;
if( dmg.impulse >= dynamics->uprootForce && (body->getBulletBody()->getCollisionFlags() & btRigidBody::CF_STATIC_OBJECT) != 0 ) {
if (dmg.impulse >= dynamics->uprootForce &&
(body->getBulletBody()->getCollisionFlags() &
btRigidBody::CF_STATIC_OBJECT) != 0) {
_enablePhysics = true;
}
}
@ -158,8 +164,7 @@ bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg)
return false;
}
void InstanceObject::setSolid(bool solid)
{
void InstanceObject::setSolid(bool solid) {
// Early out in case we don't have a collision body
if (body == nullptr || body->getBulletBody() == nullptr) {
return;
@ -173,5 +178,3 @@ void InstanceObject::setSolid(bool solid)
}
body->getBulletBody()->setCollisionFlags(flags);
}

View File

@ -1,8 +1,8 @@
#pragma once
#ifndef _OBJECTINSTANCE_HPP_
#define _OBJECTINSTANCE_HPP_
#include <objects/GameObject.hpp>
#include <btBulletDynamicsCommon.h>
#include <objects/GameObject.hpp>
class CollisionInstance;
@ -10,10 +10,10 @@ class CollisionInstance;
* @struct InstanceObject
* A simple object instance
*/
class InstanceObject : public GameObject
{
class InstanceObject : public GameObject {
float health;
bool visible = true;
public:
glm::vec3 scale;
CollisionInstance* body;
@ -22,11 +22,15 @@ public:
std::shared_ptr<DynamicObjectData> dynamics;
bool _enablePhysics;
InstanceObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, const glm::vec3& scale, std::shared_ptr< ObjectData > obj, InstanceObject* lod, std::shared_ptr< DynamicObjectData > dyn
);
InstanceObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model,
const glm::vec3& scale, std::shared_ptr<ObjectData> obj,
InstanceObject* lod, std::shared_ptr<DynamicObjectData> dyn);
~InstanceObject();
Type type() { return Instance; }
Type type() {
return Instance;
}
void tick(float dt);
@ -41,10 +45,13 @@ public:
void setVisible(bool visible) {
this->visible = visible;
}
float getVisible() const { return visible; }
float getVisible() const {
return visible;
}
float getHealth() const { return health; }
float getHealth() const {
return health;
}
};
#endif

View File

@ -1,18 +1,16 @@
#include <objects/ItemPickup.hpp>
#include <objects/CharacterObject.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, PickupType type, InventoryItem* item)
: PickupObject(world, position, item->getModelID(), type)
, item(item)
{
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");
}
bool ItemPickup::onCharacterTouch(CharacterObject *character)
{
bool ItemPickup::onCharacterTouch(CharacterObject *character) {
character->addToInventory(item);
auto &wep = character->getCurrentState().weapons[item->getInventorySlot()];
auto totalRounds = 0, clipRounds = 0;
@ -47,8 +45,7 @@ bool ItemPickup::onCharacterTouch(CharacterObject *character)
break;
}
if (getPickupType() == OnStreet || getPickupType() == OnStreetSlow)
{
if (getPickupType() == OnStreet || getPickupType() == OnStreetSlow) {
totalRounds /= 5;
}

View File

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

View File

@ -1,10 +1,9 @@
#include <objects/PickupObject.hpp>
#include <objects/CharacterObject.hpp>
#include <engine/GameWorld.hpp>
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/PickupObject.hpp>
bool PickupObject::doesRespawn(PickupType type)
{
bool PickupObject::doesRespawn(PickupType type) {
switch (type) {
case Once:
case OnceTimeout:
@ -23,8 +22,7 @@ bool PickupObject::doesRespawn(PickupType type)
}
}
float PickupObject::respawnTime(PickupType type)
{
float PickupObject::respawnTime(PickupType type) {
switch (type) {
case InShop:
return 5.f;
@ -36,8 +34,7 @@ float PickupObject::respawnTime(PickupType type)
}
}
uint32_t PickupObject::behaviourFlags(PickupType type)
{
uint32_t PickupObject::behaviourFlags(PickupType type) {
switch (type) {
case InShop:
case OnStreet:
@ -61,15 +58,15 @@ uint32_t PickupObject::behaviourFlags(PickupType type)
}
}
PickupObject::PickupObject(GameWorld *world, const glm::vec3 &position, int modelID, PickupType type)
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)
{
, m_type(type) {
btTransform tf;
tf.setIdentity();
tf.setOrigin(btVector3(position.x, position.y, position.z));
@ -79,7 +76,8 @@ PickupObject::PickupObject(GameWorld *world, const glm::vec3 &position, int mode
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);
m_ghost->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT |
btCollisionObject::CF_NO_CONTACT_RESPONSE);
m_corona = world->createEffect(VisualFX::Particle);
m_corona->particle.position = getPosition();
@ -91,13 +89,13 @@ PickupObject::PickupObject(GameWorld *world, const glm::vec3 &position, int mode
auto flags = behaviourFlags(m_type);
RW_UNUSED(flags);
RW_CHECK((flags & PickupInVehicle)==0, "In Vehicle pickup not implemented yet");
RW_CHECK((flags & PickupInVehicle) == 0,
"In Vehicle pickup not implemented yet");
setEnabled(true);
}
PickupObject::~PickupObject()
{
PickupObject::~PickupObject() {
if (m_ghost) {
setEnabled(false);
engine->destroyEffect(m_corona);
@ -106,8 +104,7 @@ PickupObject::~PickupObject()
}
}
void PickupObject::tick(float dt)
{
void PickupObject::tick(float dt) {
if (!m_enabled) {
// Check if our type of pickup respawns
if (doesRespawn(m_type)) {
@ -122,23 +119,26 @@ void PickupObject::tick(float dt)
if (m_enabled) {
// Sort out interactions with things that may or may not be players.
btManifoldArray manifoldArray;
btBroadphasePairArray& pairArray = m_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++)
{
for (int i = 0; i < numPairs; i++) {
manifoldArray.clear();
const btBroadphasePair& pair = pairArray[i];
auto otherObject = static_cast<const btCollisionObject*>(
pair.m_pProxy0->m_clientObject == m_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((flags & PickupOnFoot) == PickupOnFoot
&& object->type() == Character)
{
CharacterObject* character = static_cast<CharacterObject*>(object);
GameObject* object =
static_cast<GameObject*>(otherObject->getUserPointer());
if ((flags & PickupOnFoot) == PickupOnFoot &&
object->type() == Character) {
CharacterObject* character =
static_cast<CharacterObject*>(object);
m_collected = onCharacterTouch(character);
setEnabled(!m_collected);
@ -151,13 +151,12 @@ void PickupObject::tick(float dt)
}
}
void PickupObject::setEnabled(bool enabled)
{
void PickupObject::setEnabled(bool enabled) {
if (!m_enabled && enabled) {
engine->dynamicsWorld->addCollisionObject(m_ghost, btBroadphaseProxy::SensorTrigger);
engine->dynamicsWorld->addCollisionObject(
m_ghost, btBroadphaseProxy::SensorTrigger);
m_corona->particle.size = glm::vec2(1.5f, 1.5f);
}
else if( m_enabled && ! enabled ) {
} else if (m_enabled && !enabled) {
engine->dynamicsWorld->removeCollisionObject(m_ghost);
m_corona->particle.size = glm::vec2(0.f, 0.f);
}

View File

@ -1,10 +1,10 @@
#pragma once
#ifndef _PICKUPOBJECT_HPP_
#define _PICKUPOBJECT_HPP_
#include <objects/GameObject.hpp>
#include <btBulletCollisionCommon.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <btBulletCollisionCommon.h>
#include <glm/glm.hpp>
#include <objects/GameObject.hpp>
class VisualFX;
class CharacterObject;
@ -13,8 +13,7 @@ class CharacterObject;
* @brief The PickupObject class
* Implements interface and base behaviour for pickups
*/
class PickupObject : public GameObject
{
class PickupObject : public GameObject {
public:
enum PickupType {
InShop = 1,
@ -32,37 +31,44 @@ public:
FloatingPackageFloating = 13,
OnStreetSlow = 14
};
enum /*BehaviourFlags*/ {
PickupOnFoot = 1,
PickupInVehicle = 2
};
enum /*BehaviourFlags*/ { PickupOnFoot = 1, PickupInVehicle = 2 };
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(GameWorld* world, const glm::vec3& position, int modelID,
PickupType type);
~PickupObject();
int getModelID() const { return m_model; }
int getModelID() const {
return m_model;
}
Type type() { return Pickup; }
Type type() {
return Pickup;
}
void tick(float dt);
virtual bool onCharacterTouch(CharacterObject* character)
{
virtual bool onCharacterTouch(CharacterObject* character) {
RW_UNUSED(character);
return false;
}
bool isEnabled() const { return m_enabled; }
bool isEnabled() const {
return m_enabled;
}
void setEnabled(bool enabled);
bool isCollected() const { return m_collected; }
bool isCollected() const {
return m_collected;
}
PickupType getPickupType() const { return m_type; }
PickupType getPickupType() const {
return m_type;
}
private:
btPairCachingGhostObject* m_ghost;

View File

@ -1,12 +1,12 @@
#include <objects/ProjectileObject.hpp>
#include <engine/GameWorld.hpp>
#include <engine/GameData.hpp>
#include <data/WeaponData.hpp>
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
#include <objects/ProjectileObject.hpp>
void ProjectileObject::checkPhysicsContact()
{
void ProjectileObject::checkPhysicsContact() {
btManifoldArray manifoldArray;
btBroadphasePairArray& pairArray = _ghostBody->getOverlappingPairCache()->getOverlappingPairArray();
btBroadphasePairArray& pairArray =
_ghostBody->getOverlappingPairCache()->getOverlappingPairArray();
int numPairs = pairArray.size();
for (int i = 0; i < numPairs; i++) {
@ -14,8 +14,11 @@ void ProjectileObject::checkPhysicsContact()
const btBroadphasePair& pair = pairArray[i];
//unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
btBroadphasePair* collisionPair = engine->dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
// unless we manually perform collision detection on this pair, the
// contacts are in the dynamics world paircache:
btBroadphasePair* collisionPair =
engine->dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,
pair.m_pProxy1);
if (!collisionPair) {
continue;
}
@ -26,10 +29,12 @@ void ProjectileObject::checkPhysicsContact()
for (int j = 0; j < manifoldArray.size(); j++) {
// btPersistentManifold* manifold = manifoldArray[j];
//const btCollisionObject* B = manifold->getBody0() == _ghostBody ? manifold->getBody1() : manifold->getBody0();
// const btCollisionObject* B = manifold->getBody0() == _ghostBody ?
// manifold->getBody1() : manifold->getBody0();
// GameObject* go = static_cast<GameObject*>(B->getUserPointer());
/// @todo check if this is a suitable level to check c.f btManifoldPoint
/// @todo check if this is a suitable level to check c.f
/// btManifoldPoint
// It's happening
explode();
@ -38,8 +43,7 @@ void ProjectileObject::checkPhysicsContact()
}
}
void ProjectileObject::explode()
{
void ProjectileObject::explode() {
if (!_exploded) {
// Remove our physics objects
cleanup();
@ -62,13 +66,9 @@ void ProjectileObject::explode()
float d = glm::distance(getPosition(), o->getPosition());
if (d > damageSize) continue;
o->takeDamage({
getPosition(),
getPosition(),
damage / glm::max(d, 1.f),
DamageInfo::Explosion,
0.f
});
o->takeDamage({getPosition(), getPosition(),
damage / glm::max(d, 1.f), DamageInfo::Explosion,
0.f});
}
auto tex = engine->data->findTexture("explo02");
@ -88,8 +88,7 @@ void ProjectileObject::explode()
}
}
void ProjectileObject::cleanup()
{
void ProjectileObject::cleanup() {
if (_body) {
engine->dynamicsWorld->removeRigidBody(_body);
delete _body;
@ -106,15 +105,18 @@ void ProjectileObject::cleanup()
}
}
ProjectileObject::ProjectileObject(GameWorld *world, const glm::vec3 &position, const ProjectileObject::ProjectileInfo &info)
: GameObject(world, position, glm::quat(), nullptr),
_info(info), _body(nullptr), _ghostBody(nullptr),
_exploded(false)
{
ProjectileObject::ProjectileObject(GameWorld* world, const glm::vec3& position,
const ProjectileObject::ProjectileInfo& info)
: GameObject(world, position, glm::quat(), nullptr)
, _info(info)
, _body(nullptr)
, _ghostBody(nullptr)
, _exploded(false) {
_shape = new btSphereShape(0.45f);
btVector3 inertia(0.f, 0.f, 0.f);
_shape->calculateLocalInertia(1.f, inertia);
btRigidBody::btRigidBodyConstructionInfo riginfo(1.f, nullptr, _shape, inertia);
btRigidBody::btRigidBodyConstructionInfo riginfo(1.f, nullptr, _shape,
inertia);
btTransform ws;
ws.setIdentity();
@ -124,8 +126,11 @@ ProjectileObject::ProjectileObject(GameWorld *world, const glm::vec3 &position,
_body = new btRigidBody(riginfo);
_body->setUserPointer(this);
_body->setLinearVelocity(btVector3(_info.direction.x, _info.direction.y, _info.direction.z) * _info.velocity);
engine->dynamicsWorld->addRigidBody(_body, btBroadphaseProxy::DefaultFilter,
_body->setLinearVelocity(
btVector3(_info.direction.x, _info.direction.y, _info.direction.z) *
_info.velocity);
engine->dynamicsWorld->addRigidBody(
_body, btBroadphaseProxy::DefaultFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
if (_info.type == RPG) {
@ -139,22 +144,25 @@ ProjectileObject::ProjectileObject(GameWorld *world, const glm::vec3 &position,
_ghostBody->setWorldTransform(_body->getWorldTransform());
_ghostBody->setCollisionShape(_shape);
_ghostBody->setUserPointer(this);
_ghostBody->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT|btCollisionObject::CF_NO_CONTACT_RESPONSE);
engine->dynamicsWorld->addCollisionObject(_ghostBody, btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::AllFilter);
_ghostBody->setCollisionFlags(
btCollisionObject::CF_KINEMATIC_OBJECT |
btCollisionObject::CF_NO_CONTACT_RESPONSE);
engine->dynamicsWorld->addCollisionObject(
_ghostBody, btBroadphaseProxy::SensorTrigger,
btBroadphaseProxy::AllFilter);
}
}
ProjectileObject::~ProjectileObject()
{
ProjectileObject::~ProjectileObject() {
cleanup();
}
void ProjectileObject::tick(float dt)
{
void ProjectileObject::tick(float dt) {
if (_body == nullptr) return;
auto& bttr = _body->getWorldTransform();
position = { bttr.getOrigin().x(), bttr.getOrigin().y(), bttr.getOrigin().z() };
position = {bttr.getOrigin().x(), bttr.getOrigin().y(),
bttr.getOrigin().z()};
auto r = bttr.getRotation();
rotation = {r.x(), r.y(), r.z(), r.w()};

View File

@ -1,18 +1,16 @@
#pragma once
#ifndef _PROJECTILEOBJECT_HPP_
#define _PROJECTILEOBJECT_HPP_
#include <objects/GameObject.hpp>
#include <data/WeaponData.hpp>
#include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <btBulletDynamicsCommon.h>
#include <data/WeaponData.hpp>
#include <objects/GameObject.hpp>
/**
* @brief Implements weapon projectile (e.g. molotovs, RPGs etc.)
*/
class ProjectileObject : public GameObject
{
class ProjectileObject : public GameObject {
public:
enum ProjectileType {
Grenade,
Molotov,
@ -31,7 +29,6 @@ public:
};
private:
ProjectileInfo _info;
btSphereShape* _shape;
@ -48,19 +45,23 @@ private:
void cleanup();
public:
/**
* @brief ProjectileObject constructor
*/
ProjectileObject(GameWorld* world, const glm::vec3& position, const ProjectileInfo& info);
ProjectileObject(GameWorld* world, const glm::vec3& position,
const ProjectileInfo& info);
~ProjectileObject();
void tick(float dt);
Type type() { return Projectile; }
Type type() {
return Projectile;
}
const ProjectileInfo& getProjectileInfo() const { return _info; }
const ProjectileInfo& getProjectileInfo() const {
return _info;
}
};
#endif

View File

@ -1,31 +1,20 @@
#pragma once
#ifndef _VEHICLE_INFO_HPP_
#define _VEHICLE_INFO_HPP_
#include <glm/glm.hpp>
#include <memory>
#include <string>
#include <vector>
#include <memory>
#include <glm/glm.hpp>
struct VehicleData;
/**
* @brief Stores data loaded from handling.cfg
*/
struct VehicleHandlingInfo
{
enum EngineType
{
Diesel = 'D',
Petrol = 'P',
Electric = 'E'
};
struct VehicleHandlingInfo {
enum EngineType { Diesel = 'D', Petrol = 'P', Electric = 'E' };
enum DriveType
{
Forward = 'F',
Rear = 'R',
All = '4'
};
enum DriveType { Forward = 'F', Rear = 'R', All = '4' };
std::string ID;
float mass;
@ -74,8 +63,7 @@ struct VehicleHandlingInfo
};
};
struct WheelInfo
{
struct WheelInfo {
glm::vec3 position;
};
@ -84,7 +72,8 @@ struct SeatInfo {
};
/**
* @brief Vehicle Handling and runtime-derrived information about wheel and seat positions.
* @brief Vehicle Handling and runtime-derrived information about wheel and seat
* positions.
*/
struct VehicleInfo {
/** Handling data */

View File

@ -1,14 +1,14 @@
#include <objects/VehicleObject.hpp>
#include <objects/CharacterObject.hpp>
#include <engine/GameWorld.hpp>
#include <dynamics/CollisionInstance.hpp>
#include <BulletDynamics/Vehicle/btRaycastVehicle.h>
#include <dynamics/RaycastCallbacks.hpp>
#include <data/CollisionModel.hpp>
#include <data/Skeleton.hpp>
#include <data/Model.hpp>
#include <data/Skeleton.hpp>
#include <dynamics/CollisionInstance.hpp>
#include <dynamics/RaycastCallbacks.hpp>
#include <engine/Animator.hpp>
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
#define PART_CLOSE_VELOCITY 0.25f
constexpr float kVehicleMaxExitVelocity = 0.15f;
@ -16,23 +16,26 @@ constexpr float kVehicleMaxExitVelocity = 0.15f;
/**
* A raycaster that will ignore the body of the vehicle when casting rays
*/
class VehicleRaycaster : public btVehicleRaycaster
{
class VehicleRaycaster : public btVehicleRaycaster {
btDynamicsWorld* _world;
VehicleObject* _vehicle;
public:
VehicleRaycaster(VehicleObject* vehicle, btDynamicsWorld* world)
: _world(world), _vehicle(vehicle) {}
: _world(world), _vehicle(vehicle) {
}
void* castRay(const btVector3 &from, const btVector3 &to, btVehicleRaycasterResult &result)
{
ClosestNotMeRayResultCallback rayCallback( _vehicle->collision->getBulletBody(), from, to );
void* castRay(const btVector3& from, const btVector3& to,
btVehicleRaycasterResult& result) {
ClosestNotMeRayResultCallback rayCallback(
_vehicle->collision->getBulletBody(), from, to);
const void* res = 0;
_world->rayTest(from, to, rayCallback);
if (rayCallback.hasHit()) {
const btRigidBody* body = btRigidBody::upcast( rayCallback.m_collisionObject );
const btRigidBody* body =
btRigidBody::upcast(rayCallback.m_collisionObject);
if (body && body->hasContactResponse()) {
result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
@ -47,25 +50,22 @@ public:
}
};
class VehiclePartMotionState : public btMotionState
{
class VehiclePartMotionState : public btMotionState {
public:
VehiclePartMotionState(VehicleObject* object, VehicleObject::Part* part)
: m_object(object)
, m_part(part)
{ }
: m_object(object), m_part(part) {
}
virtual void getWorldTransform(btTransform& tform) const
{
virtual void getWorldTransform(btTransform& tform) const {
const auto& p = m_part->dummy->getDefaultTranslation();
const auto& o = glm::toQuat(m_part->dummy->getDefaultRotation());
tform.setOrigin(btVector3(p.x, p.y, p.z));
tform.setRotation(btQuaternion(o.x, o.y, o.z, o.w));
tform = m_object->collision->getBulletBody()->getWorldTransform() * tform;
tform =
m_object->collision->getBulletBody()->getWorldTransform() * tform;
}
virtual void setWorldTransform(const btTransform& tform)
{
virtual void setWorldTransform(const btTransform& tform) {
auto inv = glm::inverse(m_object->getRotation());
const auto& rot = tform.getRotation();
auto r2 = inv * glm::quat(rot.w(), rot.x(), rot.y(), rot.z());
@ -82,7 +82,10 @@ private:
VehicleObject::Part* m_part;
};
VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec)
VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model,
VehicleDataHandle data, VehicleInfoHandle info,
const glm::u8vec3& prim, const glm::u8vec3& sec)
: GameObject(engine, pos, rot, model)
, steerAngle(0.f)
, throttle(0.f)
@ -94,19 +97,20 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
, colourSecondary(sec)
, collision(nullptr)
, physRaycaster(nullptr)
, physVehicle(nullptr)
{
, physVehicle(nullptr) {
collision = new CollisionInstance;
if( collision->createPhysicsBody(this, data->modelName, nullptr, &info->handling) ) {
if (collision->createPhysicsBody(this, data->modelName, nullptr,
&info->handling)) {
physRaycaster = new VehicleRaycaster(this, engine->dynamicsWorld);
btRaycastVehicle::btVehicleTuning tuning;
float travel = fabs(info->handling.suspensionUpperLimit - info->handling.suspensionLowerLimit);
float travel = fabs(info->handling.suspensionUpperLimit -
info->handling.suspensionLowerLimit);
tuning.m_frictionSlip = 3.f;
tuning.m_maxSuspensionTravelCm = travel * 100.f;
physVehicle = new btRaycastVehicle(tuning, collision->getBulletBody(), physRaycaster);
physVehicle = new btRaycastVehicle(tuning, collision->getBulletBody(),
physRaycaster);
physVehicle->setCoordinateSystem(0, 2, 1);
// physBody->setActivationState(DISABLE_DEACTIVATION);
engine->dynamicsWorld->addAction(physVehicle);
@ -117,12 +121,13 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
for (size_t w = 0; w < info->wheels.size(); ++w) {
auto restLength = travel;
auto heightOffset = info->handling.suspensionUpperLimit;
btVector3 connection(
info->wheels[w].position.x,
btVector3 connection(info->wheels[w].position.x,
info->wheels[w].position.y,
info->wheels[w].position.z + heightOffset);
bool front = connection.y() > 0;
btWheelInfo& wi = physVehicle->addWheel(connection, btVector3(0.f, 0.f, -1.f), btVector3(1.f, 0.f, 0.f), restLength, data->wheelScale / 2.f, tuning, front);
btWheelInfo& wi = physVehicle->addWheel(
connection, btVector3(0.f, 0.f, -1.f), btVector3(1.f, 0.f, 0.f),
restLength, data->wheelScale / 2.f, tuning, front);
wi.m_suspensionRestLength1 = restLength;
wi.m_raycastInfo.m_suspensionLength = 0.f;
@ -130,20 +135,25 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
wi.m_suspensionStiffness = (info->handling.suspensionForce * 50.f);
// float dampEffect = (info->handling.suspensionDamping) / travel;
//wi.m_wheelsDampingCompression = wi.m_wheelsDampingRelaxation = dampEffect;
// wi.m_wheelsDampingCompression = wi.m_wheelsDampingRelaxation =
// dampEffect;
wi.m_wheelsDampingCompression = kC * 2.f * btSqrt(wi.m_suspensionStiffness);
wi.m_wheelsDampingRelaxation = kR * 2.f * btSqrt(wi.m_suspensionStiffness);
wi.m_wheelsDampingCompression =
kC * 2.f * btSqrt(wi.m_suspensionStiffness);
wi.m_wheelsDampingRelaxation =
kR * 2.f * btSqrt(wi.m_suspensionStiffness);
wi.m_rollInfluence = 0.30f;
float halfFriction = tuning.m_frictionSlip * 0.5f;
wi.m_frictionSlip = halfFriction + halfFriction * (front ? info->handling.tractionBias : 1.f - info->handling.tractionBias);
wi.m_frictionSlip =
halfFriction +
halfFriction * (front ? info->handling.tractionBias
: 1.f - info->handling.tractionBias);
}
// Hide all LOD and damage frames.
skeleton = new Skeleton;
for(ModelFrame* frame : model->resource->frames)
{
for (ModelFrame* frame : model->resource->frames) {
auto& name = frame->getName();
bool isDam = name.find("_dam") != name.npos;
bool isLod = name.find("lo") != name.npos;
@ -160,14 +170,12 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
}
}
VehicleObject::~VehicleObject()
{
VehicleObject::~VehicleObject() {
ejectAll();
engine->dynamicsWorld->removeAction(physVehicle);
for(auto& p : dynamicParts)
{
for (auto& p : dynamicParts) {
destroyObjectHinge(&p.second);
}
@ -177,17 +185,14 @@ VehicleObject::~VehicleObject()
delete physRaycaster;
}
void VehicleObject::setPosition(const glm::vec3& pos)
{
void VehicleObject::setPosition(const glm::vec3& pos) {
GameObject::setPosition(pos);
if (collision->getBulletBody()) {
auto bodyOrigin = btVector3(position.x, position.y, position.z);
for(auto& part : dynamicParts)
{
for (auto& part : dynamicParts) {
if (part.second.body == nullptr) continue;
auto body = part.second.body;
auto rel = body->getWorldTransform().getOrigin() -
bodyOrigin;
auto rel = body->getWorldTransform().getOrigin() - bodyOrigin;
body->getWorldTransform().setOrigin(
btVector3(pos.x + rel.x(), pos.y + rel.y(), pos.z + rel.z()));
}
@ -198,31 +203,27 @@ void VehicleObject::setPosition(const glm::vec3& pos)
}
}
void VehicleObject::setRotation(const glm::quat &orientation)
{
void VehicleObject::setRotation(const glm::quat& orientation) {
if (collision->getBulletBody()) {
auto t = collision->getBulletBody()->getWorldTransform();
t.setRotation(btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w));
t.setRotation(btQuaternion(orientation.x, orientation.y, orientation.z,
orientation.w));
collision->getBulletBody()->setWorldTransform(t);
}
GameObject::setRotation(orientation);
}
#include <glm/gtc/type_ptr.hpp>
void VehicleObject::tick(float dt)
{
void VehicleObject::tick(float dt) {
RW_UNUSED(dt);
// Moved to tickPhysics
}
void VehicleObject::tickPhysics(float dt)
{
void VehicleObject::tickPhysics(float dt) {
RW_UNUSED(dt);
if( physVehicle )
{
if (physVehicle) {
// todo: a real engine function
float velFac = info->handling.maxVelocity;
float engineForce = info->handling.acceleration * throttle * velFac;
@ -232,45 +233,50 @@ void VehicleObject::tickPhysics(float dt)
float brakeF = getBraking();
if( handbrake )
{
if (handbrake) {
brakeF = 5.f;
}
for (int w = 0; w < physVehicle->getNumWheels(); ++w) {
btWheelInfo& wi = physVehicle->getWheelInfo(w);
if (info->handling.driveType == VehicleHandlingInfo::All ||
(info->handling.driveType == VehicleHandlingInfo::Forward && wi.m_bIsFrontWheel) ||
(info->handling.driveType == VehicleHandlingInfo::Rear && !wi.m_bIsFrontWheel))
{
(info->handling.driveType == VehicleHandlingInfo::Forward &&
wi.m_bIsFrontWheel) ||
(info->handling.driveType == VehicleHandlingInfo::Rear &&
!wi.m_bIsFrontWheel)) {
physVehicle->applyEngineForce(engineForce, w);
}
float brakeReal = 5.f * info->handling.brakeDeceleration * (wi.m_bIsFrontWheel? info->handling.brakeBias : 1.f - info->handling.brakeBias);
float brakeReal =
5.f * info->handling.brakeDeceleration *
(wi.m_bIsFrontWheel ? info->handling.brakeBias
: 1.f - info->handling.brakeBias);
physVehicle->setBrake(brakeReal * brakeF, w);
if (wi.m_bIsFrontWheel) {
float sign = std::signbit(steerAngle) ? -1.f : 1.f;
physVehicle->setSteeringValue(std::min(info->handling.steeringLock*(3.141f/180.f), std::abs(steerAngle)) * sign, w);
//physVehicle->setSteeringValue(std::min(3.141f/2.f, std::abs(steerAngle)) * sign, w);
physVehicle->setSteeringValue(
std::min(info->handling.steeringLock * (3.141f / 180.f),
std::abs(steerAngle)) *
sign,
w);
// physVehicle->setSteeringValue(std::min(3.141f/2.f,
// std::abs(steerAngle)) * sign, w);
}
}
// Update passenger positions
for (auto& seat : seatOccupants)
{
for (auto& seat : seatOccupants) {
auto character = static_cast<CharacterObject*>(seat.second);
glm::vec3 passPosition;
if (character->isEnteringOrExitingVehicle())
{
if (character->isEnteringOrExitingVehicle()) {
passPosition = getSeatEntryPositionWorld(seat.first);
}
else
{
} else {
passPosition = getPosition();
if (seat.first < info->seats.size()) {
passPosition += getRotation() * (info->seats[seat.first].offset);
passPosition +=
getRotation() * (info->seats[seat.first].offset);
}
}
seat.second->updateTransform(passPosition, getRotation());
@ -279,46 +285,53 @@ void VehicleObject::tickPhysics(float dt)
if (vehicle->type == VehicleData::BOAT) {
if (isInWater()) {
float sign = std::signbit(steerAngle) ? -1.f : 1.f;
float steer = std::min(info->handling.steeringLock*(3.141f/180.f), std::abs(steerAngle)) * sign;
float steer =
std::min(info->handling.steeringLock * (3.141f / 180.f),
std::abs(steerAngle)) *
sign;
auto orient = collision->getBulletBody()->getOrientation();
// Find the local-space velocity
auto velocity = collision->getBulletBody()->getLinearVelocity();
velocity = velocity.rotate(-orient.getAxis(), orient.getAngle());
velocity =
velocity.rotate(-orient.getAxis(), orient.getAngle());
// Rudder force is proportional to velocity.
float rAngle = steer * (velFac * 0.5f + 0.5f);
btVector3 rForce = btVector3(1000.f * velocity.y() * rAngle, 0.f, 0.f)
btVector3 rForce =
btVector3(1000.f * velocity.y() * rAngle, 0.f, 0.f)
.rotate(orient.getAxis(), orient.getAngle());
btVector3 rudderPoint = btVector3(0.f, -info->handling.dimensions.y/2.f, 0.f)
btVector3 rudderPoint =
btVector3(0.f, -info->handling.dimensions.y / 2.f, 0.f)
.rotate(orient.getAxis(), orient.getAngle());
collision->getBulletBody()->applyForce(rForce, rudderPoint);
btVector3 rudderVector =
btVector3(0.f, 1.f, 0.f)
.rotate(orient.getAxis(), orient.getAngle());
collision->getBulletBody()->applyForce(
rForce,
rudderPoint);
rudderVector * engineForce * 100.f, rudderPoint);
btVector3 rudderVector = btVector3(0.f, 1.f, 0.f)
.rotate(orient.getAxis(), orient.getAngle());
collision->getBulletBody()->applyForce(
rudderVector * engineForce * 100.f,
rudderPoint);
btVector3 dampforce( 10000.f * velocity.x(), velocity.y() * 100.f, 0.f );
collision->getBulletBody()->applyCentralForce(-dampforce.rotate(orient.getAxis(), orient.getAngle()));
btVector3 dampforce(10000.f * velocity.x(),
velocity.y() * 100.f, 0.f);
collision->getBulletBody()->applyCentralForce(
-dampforce.rotate(orient.getAxis(), orient.getAngle()));
}
}
const auto& ws = getPosition();
auto wX = (int) ((ws.x + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
auto wY = (int) ((ws.y + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
auto wX = (int)((ws.x + WATER_WORLD_SIZE / 2.f) /
(WATER_WORLD_SIZE / WATER_HQ_DATA_SIZE));
auto wY = (int)((ws.y + WATER_WORLD_SIZE / 2.f) /
(WATER_WORLD_SIZE / WATER_HQ_DATA_SIZE));
btVector3 bbmin, bbmax;
// This is in world space.
collision->getBulletBody()->getAabb(bbmin, bbmax);
float vH = bbmin.z();
float wH = 0.f;
if( wX >= 0 && wX < WATER_HQ_DATA_SIZE && wY >= 0 && wY < WATER_HQ_DATA_SIZE ) {
if (wX >= 0 && wX < WATER_HQ_DATA_SIZE && wY >= 0 &&
wY < WATER_HQ_DATA_SIZE) {
int i = (wX * WATER_HQ_DATA_SIZE) + wY;
int hI = engine->data->realWater[i];
if (hI < NO_WATER_INDEX) {
@ -330,26 +343,22 @@ void VehicleObject::tickPhysics(float dt)
if (_lastHeight >= wH) {
// we are for real, underwater
inWater = true;
}
else if( inWater == false ) {
} else if (inWater == false) {
// It's just a tunnel or something, we good.
inWater = false;
}
}
else {
} else {
// The water is beneath us
inWater = false;
}
}
else {
} else {
inWater = false;
}
}
if (inWater) {
// Ensure that vehicles don't fall asleep at the top of a wave.
if(! collision->getBulletBody()->isActive() )
{
if (!collision->getBulletBody()->isActive()) {
collision->getBulletBody()->activate(true);
}
@ -367,12 +376,17 @@ void VehicleObject::tickPhysics(float dt)
oZ = 0.f;
}
// Boats, Buoyancy offset is affected by the orientation of the chassis.
// Boats, Buoyancy offset is affected by the orientation of the
// chassis.
// Vehicles, it isn't.
glm::vec3 vFwd = glm::vec3(0.f, info->handling.dimensions.y/2.f, oZ),
vBack = glm::vec3(0.f, -info->handling.dimensions.y/2.f, oZ);
glm::vec3 vRt = glm::vec3( info->handling.dimensions.x/2.f, 0.f, oZ),
vLeft = glm::vec3(-info->handling.dimensions.x/2.f, 0.f, oZ);
glm::vec3 vFwd =
glm::vec3(0.f, info->handling.dimensions.y / 2.f, oZ),
vBack = glm::vec3(0.f, -info->handling.dimensions.y / 2.f,
oZ);
glm::vec3 vRt =
glm::vec3(info->handling.dimensions.x / 2.f, 0.f, oZ),
vLeft = glm::vec3(-info->handling.dimensions.x / 2.f, 0.f,
oZ);
vFwd = getRotation() * vFwd;
vBack = getRotation() * vBack;
@ -384,12 +398,10 @@ void VehicleObject::tickPhysics(float dt)
applyWaterFloat(vBack);
applyWaterFloat(vRt);
applyWaterFloat(vLeft);
}
else {
} else {
if (vehicle->type == VehicleData::BOAT) {
collision->getBulletBody()->setDamping(0.1f, 0.8f);
}
else {
} else {
collision->getBulletBody()->setDamping(0.05f, 0.0f);
}
}
@ -399,17 +411,15 @@ void VehicleObject::tickPhysics(float dt)
// Update hinge object rotations
for (auto& it : dynamicParts) {
if (it.second.body == nullptr) continue;
if( it.second.moveToAngle )
{
auto angledelta = it.second.targetAngle - it.second.constraint->getHingeAngle();
if( glm::abs(angledelta) <= 0.01f )
{
if (it.second.moveToAngle) {
auto angledelta = it.second.targetAngle -
it.second.constraint->getHingeAngle();
if (glm::abs(angledelta) <= 0.01f) {
it.second.constraint->enableAngularMotor(false, 1.f, 1.f);
dynamicParts[it.first].moveToAngle = false;
}
else
{
it.second.constraint->enableAngularMotor(true, glm::sign(angledelta) * 5.f, 1.f);
} else {
it.second.constraint->enableAngularMotor(
true, glm::sign(angledelta) * 5.f, 1.f);
}
}
@ -417,11 +427,10 @@ void VehicleObject::tickPhysics(float dt)
/// @TODO not all parts rotate in the z axis.
float zspeed = it.second.body->getAngularVelocity().getZ();
if (it.second.openAngle < 0.f) zspeed = -zspeed;
if(zspeed >= PART_CLOSE_VELOCITY)
{
auto d = it.second.constraint->getHingeAngle() - it.second.closedAngle;
if( glm::abs(d) < 0.05f )
{
if (zspeed >= PART_CLOSE_VELOCITY) {
auto d = it.second.constraint->getHingeAngle() -
it.second.closedAngle;
if (glm::abs(d) < 0.05f) {
dynamicParts[it.first].moveToAngle = false;
setPartLocked(&(it.second), true);
}
@ -430,65 +439,53 @@ void VehicleObject::tickPhysics(float dt)
}
}
bool VehicleObject::isFlipped() const
{
bool VehicleObject::isFlipped() const {
auto up = getRotation() * glm::vec3(0.f, 0.f, 1.f);
return up.z <= -0.1f;
}
float VehicleObject::getVelocity() const
{
float VehicleObject::getVelocity() const {
if (physVehicle) {
return (physVehicle->getCurrentSpeedKmHour() * 1000.f) / (60.f * 60.f);
}
return 0.f;
}
void VehicleObject::setSteeringAngle(float a)
{
void VehicleObject::setSteeringAngle(float a) {
steerAngle = a;
}
float VehicleObject::getSteeringAngle() const
{
float VehicleObject::getSteeringAngle() const {
return steerAngle;
}
void VehicleObject::setThrottle(float t)
{
void VehicleObject::setThrottle(float t) {
throttle = t;
}
float VehicleObject::getThrottle() const
{
float VehicleObject::getThrottle() const {
return throttle;
}
void VehicleObject::setBraking(float b)
{
void VehicleObject::setBraking(float b) {
brake = b;
}
float VehicleObject::getBraking() const
{
float VehicleObject::getBraking() const {
return brake;
}
void VehicleObject::setHandbraking(bool hb)
{
void VehicleObject::setHandbraking(bool hb) {
handbrake = hb;
}
bool VehicleObject::getHandbraking() const
{
bool VehicleObject::getHandbraking() const {
return handbrake;
}
void VehicleObject::ejectAll()
{
void VehicleObject::ejectAll() {
for (std::map<size_t, GameObject*>::iterator it = seatOccupants.begin();
it != seatOccupants.end();
) {
it != seatOccupants.end();) {
if (it->second->type() == GameObject::Character) {
CharacterObject* c = static_cast<CharacterObject*>(it->second);
c->setCurrentVehicle(nullptr, 0);
@ -498,8 +495,7 @@ void VehicleObject::ejectAll()
}
}
GameObject* VehicleObject::getOccupant(size_t seat)
{
GameObject* VehicleObject::getOccupant(size_t seat) {
auto it = seatOccupants.find(seat);
if (it != seatOccupants.end()) {
return it->second;
@ -507,40 +503,34 @@ GameObject* VehicleObject::getOccupant(size_t seat)
return nullptr;
}
void VehicleObject::setOccupant(size_t seat, GameObject* occupant)
{
void VehicleObject::setOccupant(size_t seat, GameObject* occupant) {
auto it = seatOccupants.find(seat);
if (occupant == nullptr) {
if (it != seatOccupants.end()) {
seatOccupants.erase(it);
}
}
else {
} else {
seatOccupants[seat] = occupant;
}
}
bool VehicleObject::canOccupantExit() const
{
bool VehicleObject::canOccupantExit() const {
return getVelocity() <= kVehicleMaxExitVelocity;
}
bool VehicleObject::isOccupantDriver(size_t seat) const
{
bool VehicleObject::isOccupantDriver(size_t seat) const {
// This isn't true for all vehicles, but it'll do until we figure it out
return seat == 0;
}
VehicleObject::Part* VehicleObject::getSeatEntryDoor(size_t seat)
{
VehicleObject::Part* VehicleObject::getSeatEntryDoor(size_t seat) {
auto pos = info->seats[seat].offset + glm::vec3(0.f, 0.5f, 0.f);
Part* nearestDoor = nullptr;
float d = std::numeric_limits<float>::max();
for(auto& p : dynamicParts)
{
float partDist = glm::distance(p.second.dummy->getDefaultTranslation(), pos);
if( partDist < d && p.second.dummy->getName().substr(0, 5) == "door_" )
{
for (auto& p : dynamicParts) {
float partDist =
glm::distance(p.second.dummy->getDefaultTranslation(), pos);
if (partDist < d && p.second.dummy->getName().substr(0, 5) == "door_") {
d = partDist;
nearestDoor = &p.second;
}
@ -548,8 +538,7 @@ VehicleObject::Part* VehicleObject::getSeatEntryDoor(size_t seat)
return nearestDoor;
}
bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg)
{
bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg) {
RW_CHECK(dmg.hitpoints == 0, "Vehicle Damage not implemented yet");
const float frameDamageThreshold = 1500.f;
@ -560,18 +549,18 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg)
dpoint = glm::inverse(getRotation()) * dpoint;
// Set any parts within range to damaged state.
for(auto d : dynamicParts)
{
for (auto d : dynamicParts) {
auto p = &d.second;
if (p->normal == nullptr) continue;
if( skeleton->getData(p->normal->getIndex()).enabled )
{
auto& geom = model->resource->geometries[p->normal->getGeometries()[0]];
auto pp = p->normal->getMatrix() * glm::vec4(0.f, 0.f, 0.f, 1.f);
float td = glm::distance(glm::vec3(pp)+geom->geometryBounds.center
, dpoint);
if (skeleton->getData(p->normal->getIndex()).enabled) {
auto& geom =
model->resource->geometries[p->normal->getGeometries()[0]];
auto pp =
p->normal->getMatrix() * glm::vec4(0.f, 0.f, 0.f, 1.f);
float td = glm::distance(
glm::vec3(pp) + geom->geometryBounds.center, dpoint);
if (td < geom->geometryBounds.radius * 1.2f) {
setPartState(p, DAM);
}
@ -583,22 +572,18 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg)
return true;
}
void VehicleObject::setPartState(VehicleObject::Part* part, VehicleObject::FrameState state)
{
if( state == VehicleObject::OK )
{
void VehicleObject::setPartState(VehicleObject::Part* part,
VehicleObject::FrameState state) {
if (state == VehicleObject::OK) {
if (part->normal) skeleton->setEnabled(part->normal, true);
if (part->damaged) skeleton->setEnabled(part->damaged, false);
}
else if( state == VehicleObject::DAM )
{
} else if (state == VehicleObject::DAM) {
if (part->normal) skeleton->setEnabled(part->normal, false);
if (part->damaged) skeleton->setEnabled(part->damaged, true);
}
}
void VehicleObject::applyWaterFloat(const glm::vec3 &relPt)
{
void VehicleObject::applyWaterFloat(const glm::vec3& relPt) {
auto ws = getPosition() + relPt;
auto wi = engine->data->getWaterIndexAt(ws);
if (wi != NO_WATER_INDEX) {
@ -610,21 +595,18 @@ void VehicleObject::applyWaterFloat(const glm::vec3 &relPt)
if (ws.z <= h) {
float x = (h - ws.z);
float F = WATER_BUOYANCY_K * x +
-WATER_BUOYANCY_C * collision->getBulletBody()->getLinearVelocity().z();
collision->getBulletBody()->applyImpulse(btVector3(0.f, 0.f, F),
btVector3(relPt.x, relPt.y, relPt.z));
-WATER_BUOYANCY_C *
collision->getBulletBody()->getLinearVelocity().z();
collision->getBulletBody()->applyImpulse(
btVector3(0.f, 0.f, F), btVector3(relPt.x, relPt.y, relPt.z));
}
}
}
void VehicleObject::setPartLocked(VehicleObject::Part* part, bool locked)
{
if( part->body == nullptr && locked == false )
{
void VehicleObject::setPartLocked(VehicleObject::Part* part, bool locked) {
if (part->body == nullptr && locked == false) {
createObjectHinge(part);
}
else if( part->body != nullptr && locked == true )
{
} else if (part->body != nullptr && locked == true) {
destroyObjectHinge(part);
// Restore default bone transform
@ -635,12 +617,10 @@ void VehicleObject::setPartLocked(VehicleObject::Part* part, bool locked)
}
}
void VehicleObject::setPartTarget(VehicleObject::Part* part, bool enable, float target)
{
if( enable )
{
if( part->body == nullptr )
{
void VehicleObject::setPartTarget(VehicleObject::Part* part, bool enable,
float target) {
if (enable) {
if (part->body == nullptr) {
setPartLocked(part, false);
}
@ -648,71 +628,49 @@ void VehicleObject::setPartTarget(VehicleObject::Part* part, bool enable, float
part->moveToAngle = true;
part->body->activate(true);
}
else
{
} else {
part->targetAngle = target;
part->moveToAngle = false;
}
}
VehicleObject::Part* VehicleObject::getPart(const std::string& name)
{
VehicleObject::Part* VehicleObject::getPart(const std::string& name) {
auto f = dynamicParts.find(name);
if( f != dynamicParts.end() )
{
if (f != dynamicParts.end()) {
return &f->second;
}
return nullptr;
}
ModelFrame* findStateFrame(ModelFrame* f, const std::string& state)
{
ModelFrame* findStateFrame(ModelFrame* f, const std::string& state) {
auto it = std::find_if(
f->getChildren().begin(),
f->getChildren().end(),
[&](ModelFrame* c){ return c->getName().find(state) != std::string::npos; }
);
if( it != f->getChildren().end() )
{
f->getChildren().begin(), f->getChildren().end(), [&](ModelFrame* c) {
return c->getName().find(state) != std::string::npos;
});
if (it != f->getChildren().end()) {
return *it;
}
return nullptr;
}
void VehicleObject::registerPart(ModelFrame* mf)
{
void VehicleObject::registerPart(ModelFrame* mf) {
auto normal = findStateFrame(mf, "_ok");
auto damage = findStateFrame(mf, "_dam");
if( normal == nullptr && damage == nullptr )
{
if (normal == nullptr && damage == nullptr) {
// Not actually a useful part, just a dummy.
return;
}
dynamicParts.insert(
{mf->getName(),
{
mf,
normal,
damage,
nullptr, nullptr,
false,
0.f,
0.f,
0.f
}
});
{mf, normal, damage, nullptr, nullptr, false, 0.f, 0.f, 0.f}});
}
void VehicleObject::createObjectHinge(Part *part)
{
void VehicleObject::createObjectHinge(Part* part) {
float sign = glm::sign(part->dummy->getDefaultTranslation().x);
btVector3 hingeAxis,
hingePosition;
btVector3 boxSize,
boxOffset;
btVector3 hingeAxis, hingePosition;
btVector3 boxSize, boxOffset;
float hingeMax = 1.f;
float hingeMin = 0.f;
@ -739,24 +697,20 @@ void VehicleObject::createObjectHinge(Part *part)
hingeMin = 0.f;
part->openAngle = hingeMax;
part->closedAngle = hingeMin;
}
else
{
} else {
hingeMin = glm::quarter_pi<float>() * -1.5f;
hingeMax = 0.f;
part->openAngle = hingeMin;
part->closedAngle = hingeMax;
}
}
else if( fn.find("bonnet") != fn.npos ) {
} else if (fn.find("bonnet") != fn.npos) {
hingeAxis = {1.f, 0.f, 0.f};
hingePosition = {0.f, -0.2f, 0.f};
hingeMax = 0.f;
hingeMin = -glm::quarter_pi<float>() * 1.5f;
boxSize = {0.4f, 0.4f, 0.1f};
boxOffset = {0.f, 0.2f, 0.f};
}
else {
} else {
// TODO: boot, bumper
return;
}
@ -770,7 +724,8 @@ void VehicleObject::createObjectHinge(Part *part)
tr.setRotation(btQuaternion(o.x, o.y, o.z, o.w));
btCollisionShape* cs = new btBoxShape(boxSize);
btTransform t; t.setIdentity();
btTransform t;
t.setIdentity();
t.setOrigin(boxOffset);
btVector3 inertia;
@ -780,11 +735,9 @@ void VehicleObject::createObjectHinge(Part *part)
btRigidBody* subObject = new btRigidBody(rginfo);
subObject->setUserPointer(this);
auto hinge = new btHingeConstraint(
*collision->getBulletBody(),
*subObject,
tr.getOrigin(), hingePosition,
hingeAxis, hingeAxis);
auto hinge = new btHingeConstraint(*collision->getBulletBody(), *subObject,
tr.getOrigin(), hingePosition, hingeAxis,
hingeAxis);
hinge->setLimit(hingeMin, hingeMax);
hinge->setBreakingImpulseThreshold(250.f);
@ -795,8 +748,7 @@ void VehicleObject::createObjectHinge(Part *part)
engine->dynamicsWorld->addConstraint(part->constraint, true);
}
void VehicleObject::destroyObjectHinge(Part* part)
{
void VehicleObject::destroyObjectHinge(Part* part) {
if (part->constraint != nullptr) {
engine->dynamicsWorld->removeConstraint(part->constraint);
delete part->constraint;
@ -815,17 +767,14 @@ void VehicleObject::destroyObjectHinge(Part* part)
part->moveToAngle = false;
}
void VehicleObject::setPrimaryColour(uint8_t color)
{
void VehicleObject::setPrimaryColour(uint8_t color) {
colourPrimary = engine->data->vehicleColours[color];
}
void VehicleObject::setSecondaryColour(uint8_t color)
{
void VehicleObject::setSecondaryColour(uint8_t color) {
colourSecondary = engine->data->vehicleColours[color];
}
bool VehicleObject::isStopped() const
{
bool VehicleObject::isStopped() const {
return fabsf(physVehicle->getCurrentSpeedKmHour()) < 0.75f;
}

View File

@ -1,8 +1,8 @@
#pragma once
#ifndef _VEHICLEOBJECT_HPP_
#define _VEHICLEOBJECT_HPP_
#include <objects/GameObject.hpp>
#include <map>
#include <objects/GameObject.hpp>
#include <objects/VehicleInfo.hpp>
class CollisionInstance;
@ -16,15 +16,14 @@ class btTransform;
* @class VehicleObject
* Implements Vehicle behaviours.
*/
class VehicleObject : public GameObject
{
class VehicleObject : public GameObject {
private:
float steerAngle;
float throttle;
float brake;
bool handbrake;
public:
public:
VehicleDataHandle vehicle;
VehicleInfoHandle info;
glm::u8vec3 colourPrimary;
@ -36,8 +35,7 @@ public:
btVehicleRaycaster* physRaycaster;
btRaycastVehicle* physVehicle;
struct Part
{
struct Part {
ModelFrame* dummy;
ModelFrame* normal;
ModelFrame* damaged;
@ -51,7 +49,10 @@ public:
std::map<std::string, Part> dynamicParts;
VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec);
VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot,
const ModelRef& model, VehicleDataHandle data,
VehicleInfoHandle info, const glm::u8vec3& prim,
const glm::u8vec3& sec);
virtual ~VehicleObject();
@ -59,7 +60,9 @@ public:
void setRotation(const glm::quat& orientation);
Type type() { return Vehicle; }
Type type() {
return Vehicle;
}
void setSteeringAngle(float);
@ -106,7 +109,8 @@ public:
glm::vec3 getSeatEntryPosition(size_t seat) const {
auto pos = info->seats[seat].offset;
pos -= glm::vec3(glm::sign(pos.x) * -0.81756252f, 0.34800607f, -0.486281008f);
pos -= glm::vec3(glm::sign(pos.x) * -0.81756252f, 0.34800607f,
-0.486281008f);
return pos;
}
glm::vec3 getSeatEntryPositionWorld(size_t seat) const {
@ -117,11 +121,7 @@ public:
virtual bool takeDamage(const DamageInfo& damage);
enum FrameState {
OK,
DAM,
BROKEN
};
enum FrameState { OK, DAM, BROKEN };
void setPartState(Part* part, FrameState state);
@ -143,7 +143,6 @@ public:
bool isStopped() const;
private:
void registerPart(ModelFrame* mf);
void createObjectHinge(Part* part);
void destroyObjectHinge(Part* part);