1
0
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:
Daniel Evans 2018-05-15 13:13:19 +01:00 committed by GitHub
commit c6f5b5406b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 47 deletions

View File

@ -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;

View File

@ -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") {

View File

@ -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);

View File

@ -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());
} }
/** /**