mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-19 17:01:44 +02:00
Merge pull request #448 from husho/vehiclehealth
[Ready] Vehicle health
This commit is contained in:
commit
c6f5b5406b
@ -42,7 +42,6 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos,
|
|||||||
, physObject(nullptr)
|
, physObject(nullptr)
|
||||||
, physShape(nullptr)
|
, physShape(nullptr)
|
||||||
, controller(controller) {
|
, controller(controller) {
|
||||||
|
|
||||||
auto info = getModelInfo<PedModelInfo>();
|
auto info = getModelInfo<PedModelInfo>();
|
||||||
setClump(ClumpPtr(info->getModel()->clone()));
|
setClump(ClumpPtr(info->getModel()->clone()));
|
||||||
if (info->getModel()) {
|
if (info->getModel()) {
|
||||||
@ -130,8 +129,9 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt) {
|
|||||||
|
|
||||||
// Things are simpler if we're in a vehicle
|
// Things are simpler if we're in a vehicle
|
||||||
if (getCurrentVehicle()) {
|
if (getCurrentVehicle()) {
|
||||||
animator->playAnimation(AnimIndexMovement, animations->animation(AnimCycle::CarSit),
|
animator->playAnimation(AnimIndexMovement,
|
||||||
1.f, true);
|
animations->animation(AnimCycle::CarSit), 1.f,
|
||||||
|
true);
|
||||||
return glm::vec3();
|
return glm::vec3();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +209,9 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt) {
|
|||||||
if (it != movementAnimation->bones.end()) {
|
if (it != movementAnimation->bones.end()) {
|
||||||
auto rootBone = it->second;
|
auto rootBone = it->second;
|
||||||
float step = dt;
|
float step = dt;
|
||||||
RW_CHECK(animator->getAnimation(AnimIndexMovement), "Failed to read animation using index " << AnimIndexMovement);
|
RW_CHECK(
|
||||||
|
animator->getAnimation(AnimIndexMovement),
|
||||||
|
"Failed to read animation using index " << AnimIndexMovement);
|
||||||
const float duration =
|
const float duration =
|
||||||
animator->getAnimation(AnimIndexMovement)->duration;
|
animator->getAnimation(AnimIndexMovement)->duration;
|
||||||
float animTime =
|
float animTime =
|
||||||
@ -266,8 +268,7 @@ void CharacterObject::tick(float dt) {
|
|||||||
void CharacterObject::tickPhysics(float dt) {
|
void CharacterObject::tickPhysics(float dt) {
|
||||||
if (physCharacter) {
|
if (physCharacter) {
|
||||||
auto s = currenteMovementStep * dt;
|
auto s = currenteMovementStep * dt;
|
||||||
physCharacter->setWalkDirection(
|
physCharacter->setWalkDirection(btVector3(s.x, s.y, s.z));
|
||||||
btVector3(s.x, s.y, s.z));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,6 +473,11 @@ void CharacterObject::setCurrentVehicle(VehicleObject* value, size_t seat) {
|
|||||||
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
|
// Right now there's no state that determines immunity to any kind of damage
|
||||||
float dmgPoints = dmg.hitpoints;
|
float dmgPoints = dmg.hitpoints;
|
||||||
|
|
||||||
|
if (getCurrentVehicle()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (currentState.armour > 0.f) {
|
if (currentState.armour > 0.f) {
|
||||||
dmgPoints -= currentState.armour;
|
dmgPoints -= currentState.armour;
|
||||||
currentState.armour =
|
currentState.armour =
|
||||||
@ -522,7 +528,7 @@ void CharacterObject::resetToAINode() {
|
|||||||
bool vehicleNode = !!getCurrentVehicle();
|
bool vehicleNode = !!getCurrentVehicle();
|
||||||
AIGraphNode* nearest = nullptr;
|
AIGraphNode* nearest = nullptr;
|
||||||
float d = std::numeric_limits<float>::max();
|
float d = std::numeric_limits<float>::max();
|
||||||
for (const auto &node : nodes) {
|
for (const auto& node : nodes) {
|
||||||
if (vehicleNode) {
|
if (vehicleNode) {
|
||||||
if (node->type == AIGraphNode::Pedestrian) continue;
|
if (node->type == AIGraphNode::Pedestrian) continue;
|
||||||
} else {
|
} else {
|
||||||
@ -567,7 +573,8 @@ void CharacterObject::playCycle(AnimCycle cycle) {
|
|||||||
flags & AnimCycleInfo::Repeat);
|
flags & AnimCycleInfo::Repeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterObject::playCycleAnimOverride(AnimCycle cycle, AnimationPtr anim) {
|
void CharacterObject::playCycleAnimOverride(AnimCycle cycle,
|
||||||
|
AnimationPtr anim) {
|
||||||
auto flags = animations->flags(cycle);
|
auto flags = animations->flags(cycle);
|
||||||
|
|
||||||
cycle_ = cycle;
|
cycle_ = cycle;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#include "objects/VehicleObject.hpp"
|
#include "objects/VehicleObject.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include <btBulletDynamicsCommon.h>
|
|
||||||
#include <BulletDynamics/Vehicle/btRaycastVehicle.h>
|
#include <BulletDynamics/Vehicle/btRaycastVehicle.h>
|
||||||
|
#include <btBulletDynamicsCommon.h>
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
#include <data/Clump.hpp>
|
#include <data/Clump.hpp>
|
||||||
@ -96,6 +96,7 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos,
|
|||||||
, throttle(0.f)
|
, throttle(0.f)
|
||||||
, brake(0.f)
|
, brake(0.f)
|
||||||
, handbrake(true)
|
, handbrake(true)
|
||||||
|
, health(1000.f)
|
||||||
, info(info)
|
, info(info)
|
||||||
, colourPrimary(prim)
|
, colourPrimary(prim)
|
||||||
, colourSecondary(sec)
|
, colourSecondary(sec)
|
||||||
@ -175,16 +176,16 @@ VehicleObject::~VehicleObject() {
|
|||||||
void VehicleObject::setupModel() {
|
void VehicleObject::setupModel() {
|
||||||
const auto vehicleInfo = getModelInfo<VehicleModelInfo>();
|
const auto vehicleInfo = getModelInfo<VehicleModelInfo>();
|
||||||
const auto isBoat = (vehicleInfo->vehicletype_ == VehicleModelInfo::BOAT);
|
const auto isBoat = (vehicleInfo->vehicletype_ == VehicleModelInfo::BOAT);
|
||||||
const std::string baseName = isBoat? "boat":"chassis";
|
const std::string baseName = isBoat ? "boat" : "chassis";
|
||||||
const auto dummy = getClump()->findFrame("chassis_dummy");
|
const auto dummy = getClump()->findFrame("chassis_dummy");
|
||||||
|
|
||||||
for (const auto& atomic : getClump()->getAtomics()) {
|
for (const auto& atomic : getClump()->getAtomics()) {
|
||||||
auto frame = atomic->getFrame().get();
|
auto frame = atomic->getFrame().get();
|
||||||
const auto& name = frame->getName();
|
const auto& name = frame->getName();
|
||||||
if (name == baseName+"_vlo") {
|
if (name == baseName + "_vlo") {
|
||||||
chassislow_ = atomic.get();
|
chassislow_ = atomic.get();
|
||||||
}
|
}
|
||||||
if (name == baseName+"_hi") {
|
if (name == baseName + "_hi") {
|
||||||
chassishigh_ = atomic.get();
|
chassishigh_ = atomic.get();
|
||||||
}
|
}
|
||||||
if (name.find("extra") == 0) {
|
if (name.find("extra") == 0) {
|
||||||
@ -192,11 +193,10 @@ void VehicleObject::setupModel() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto partNumber = (std::stoul(name.c_str()+5)-1);
|
auto partNumber = (std::stoul(name.c_str() + 5) - 1);
|
||||||
extras_.at(partNumber) = atomic.get();
|
extras_.at(partNumber) = atomic.get();
|
||||||
setExtraEnabled(partNumber, false);
|
setExtraEnabled(partNumber, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dummy) {
|
if (!dummy) {
|
||||||
@ -445,7 +445,8 @@ void VehicleObject::tickPhysics(float dt) {
|
|||||||
|
|
||||||
float bbZ = info->handling.dimensions.z / 2.f;
|
float bbZ = info->handling.dimensions.z / 2.f;
|
||||||
|
|
||||||
float oZ = -bbZ / 2.f + (bbZ * (info->handling.percentSubmerged / 120.f));
|
float oZ =
|
||||||
|
-bbZ / 2.f + (bbZ * (info->handling.percentSubmerged / 120.f));
|
||||||
|
|
||||||
if (isBoat) {
|
if (isBoat) {
|
||||||
oZ = 0.f;
|
oZ = 0.f;
|
||||||
@ -529,6 +530,18 @@ float VehicleObject::getVelocity() const {
|
|||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VehicleObject::isWrecked() const {
|
||||||
|
return health < 250.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VehicleObject::setHealth(float h) {
|
||||||
|
health = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
float VehicleObject::getHealth() const {
|
||||||
|
return health;
|
||||||
|
}
|
||||||
|
|
||||||
void VehicleObject::setSteeringAngle(float a) {
|
void VehicleObject::setSteeringAngle(float a) {
|
||||||
steerAngle = a;
|
steerAngle = a;
|
||||||
}
|
}
|
||||||
@ -641,6 +654,8 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg) {
|
|||||||
}
|
}
|
||||||
/// @todo determine when doors etc. should un-latch
|
/// @todo determine when doors etc. should un-latch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
health -= dmg.hitpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -738,9 +753,9 @@ void VehicleObject::registerPart(ModelFrame* mf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamicParts.insert(
|
dynamicParts.insert({mf->getName(),
|
||||||
{mf->getName(),
|
{mf, normal, damage, nullptr, nullptr, nullptr, false,
|
||||||
{mf, normal, damage, nullptr, nullptr, nullptr, false, 0.f, 0.f, 0.f}});
|
0.f, 0.f, 0.f}});
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehicleObject::createObjectHinge(Part* part) {
|
void VehicleObject::createObjectHinge(Part* part) {
|
||||||
@ -860,9 +875,9 @@ bool VehicleObject::collectSpecial() {
|
|||||||
|
|
||||||
void VehicleObject::grantOccupantRewards(CharacterObject* character) {
|
void VehicleObject::grantOccupantRewards(CharacterObject* character) {
|
||||||
if (character->isPlayer() && collectSpecial()) {
|
if (character->isPlayer() && collectSpecial()) {
|
||||||
if (getVehicle()->vehiclename_ == "TAXI"
|
if (getVehicle()->vehiclename_ == "TAXI" ||
|
||||||
|| getVehicle()->vehiclename_ == "CABBIE"
|
getVehicle()->vehiclename_ == "CABBIE" ||
|
||||||
|| getVehicle()->vehiclename_ == "BORGNINE") {
|
getVehicle()->vehiclename_ == "BORGNINE") {
|
||||||
// Earn $25 from taxi cabs
|
// Earn $25 from taxi cabs
|
||||||
engine->state->playerInfo.money += 25;
|
engine->state->playerInfo.money += 25;
|
||||||
} else if (getVehicle()->vehiclename_ == "POLICAR") {
|
} else if (getVehicle()->vehiclename_ == "POLICAR") {
|
||||||
|
@ -41,7 +41,10 @@ private:
|
|||||||
Atomic* chassislow_ = nullptr;
|
Atomic* chassislow_ = nullptr;
|
||||||
|
|
||||||
std::array<Atomic*, 6> extras_;
|
std::array<Atomic*, 6> extras_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
float health;
|
||||||
|
|
||||||
VehicleInfoHandle info;
|
VehicleInfoHandle info;
|
||||||
glm::u8vec3 colourPrimary;
|
glm::u8vec3 colourPrimary;
|
||||||
glm::u8vec3 colourSecondary;
|
glm::u8vec3 colourSecondary;
|
||||||
@ -57,7 +60,7 @@ public:
|
|||||||
ModelFrame* dummy;
|
ModelFrame* dummy;
|
||||||
Atomic* normal;
|
Atomic* normal;
|
||||||
Atomic* damaged;
|
Atomic* damaged;
|
||||||
btCollisionShape *cs;
|
btCollisionShape* cs;
|
||||||
btRigidBody* body;
|
btRigidBody* body;
|
||||||
btHingeConstraint* constraint;
|
btHingeConstraint* constraint;
|
||||||
bool moveToAngle;
|
bool moveToAngle;
|
||||||
@ -84,13 +87,23 @@ public:
|
|||||||
return getModelInfo<VehicleModelInfo>();
|
return getModelInfo<VehicleModelInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Atomic* getHighLOD() const { return chassishigh_; }
|
Atomic* getHighLOD() const {
|
||||||
Atomic* getLowLOD() const { return chassislow_; }
|
return chassishigh_;
|
||||||
|
}
|
||||||
|
Atomic* getLowLOD() const {
|
||||||
|
return chassislow_;
|
||||||
|
}
|
||||||
|
|
||||||
Type type() const override {
|
Type type() const override {
|
||||||
return Vehicle;
|
return Vehicle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isWrecked() const;
|
||||||
|
|
||||||
|
void setHealth(float);
|
||||||
|
|
||||||
|
float getHealth() const;
|
||||||
|
|
||||||
void setExtraEnabled(size_t extra, bool enabled);
|
void setExtraEnabled(size_t extra, bool enabled);
|
||||||
|
|
||||||
void setSteeringAngle(float);
|
void setSteeringAngle(float);
|
||||||
@ -166,15 +179,15 @@ public:
|
|||||||
void setSecondaryColour(uint8_t color);
|
void setSecondaryColour(uint8_t color);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief isStopped
|
* @brief isStopped
|
||||||
* @return True if the vehicle isn't moving
|
* @return True if the vehicle isn't moving
|
||||||
*/
|
*/
|
||||||
bool isStopped() const;
|
bool isStopped() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief collectSpecial
|
* @brief collectSpecial
|
||||||
* @return True if mHasSpecial was true opon calling
|
* @return True if mHasSpecial was true opon calling
|
||||||
*/
|
*/
|
||||||
bool collectSpecial();
|
bool collectSpecial();
|
||||||
|
|
||||||
void grantOccupantRewards(CharacterObject* character);
|
void grantOccupantRewards(CharacterObject* character);
|
||||||
|
@ -2018,9 +2018,10 @@ void opcode_00ab(const ScriptArguments& args, const ScriptVehicle vehicle, Scrip
|
|||||||
@arg vehicle
|
@arg vehicle
|
||||||
*/
|
*/
|
||||||
bool opcode_00ac(const ScriptArguments& args, const ScriptVehicle vehicle) {
|
bool opcode_00ac(const ScriptArguments& args, const ScriptVehicle vehicle) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x00ac);
|
|
||||||
RW_UNUSED(vehicle);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
if (vehicle) {
|
||||||
|
return !vehicle->isWrecked();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3201,10 +3202,11 @@ bool opcode_0118(const ScriptArguments& args, const ScriptCharacter character) {
|
|||||||
@arg vehicle Car/vehicle
|
@arg vehicle Car/vehicle
|
||||||
*/
|
*/
|
||||||
bool opcode_0119(const ScriptArguments& args, const ScriptVehicle vehicle) {
|
bool opcode_0119(const ScriptArguments& args, const ScriptVehicle vehicle) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x0119);
|
|
||||||
RW_UNUSED(vehicle);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
return false;
|
if (vehicle) {
|
||||||
|
return vehicle->isWrecked();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4191,11 +4193,8 @@ bool opcode_0184(const ScriptArguments& args, const ScriptCharacter character, c
|
|||||||
@arg arg2
|
@arg arg2
|
||||||
*/
|
*/
|
||||||
bool opcode_0185(const ScriptArguments& args, const ScriptVehicle vehicle, const ScriptInt arg2) {
|
bool opcode_0185(const ScriptArguments& args, const ScriptVehicle vehicle, const ScriptInt arg2) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x0185);
|
|
||||||
RW_UNUSED(vehicle);
|
|
||||||
RW_UNUSED(arg2);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
return true;
|
return vehicle->getHealth() > arg2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6263,10 +6262,8 @@ void opcode_0223(const ScriptArguments& args, const ScriptCharacter character, c
|
|||||||
@arg arg2
|
@arg arg2
|
||||||
*/
|
*/
|
||||||
void opcode_0224(const ScriptArguments& args, const ScriptVehicle vehicle, const ScriptInt arg2) {
|
void opcode_0224(const ScriptArguments& args, const ScriptVehicle vehicle, const ScriptInt arg2) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x0224);
|
|
||||||
RW_UNUSED(vehicle);
|
|
||||||
RW_UNUSED(arg2);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
vehicle->setHealth(static_cast<float> (arg2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6305,11 +6302,8 @@ void opcode_0226(const ScriptArguments& args, const ScriptCharacter character, S
|
|||||||
@arg arg2
|
@arg arg2
|
||||||
*/
|
*/
|
||||||
void opcode_0227(const ScriptArguments& args, const ScriptVehicle vehicle, ScriptInt& arg2) {
|
void opcode_0227(const ScriptArguments& args, const ScriptVehicle vehicle, ScriptInt& arg2) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x0227);
|
|
||||||
RW_UNUSED(vehicle);
|
|
||||||
RW_UNUSED(arg2);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
arg2 = 1000.f;
|
arg2 = static_cast<int> (vehicle->getHealth());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user