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:
parent
305737cc3d
commit
f2eede5301
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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()};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user