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