1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00

Skeleton collision effect handling

This commit is contained in:
Daniel Evans 2018-01-13 00:29:21 +00:00
parent 4f0109b17e
commit 65f51bc3c2
6 changed files with 141 additions and 112 deletions

View File

@ -463,24 +463,32 @@ struct DynamicObjectData {
float mass; // Kg float mass; // Kg
float turnMass; // Kg m^3 float turnMass; // Kg m^3
float airRes; // fraction float airRes; // fraction
float elacticity; // " float elasticity; // "
float bouancy; float buoyancy;
float uprootForce; // Force float uprootForce; // Force
float collDamageMulti; float collDamageMulti;
/*
* 1: change model enum {
* 2: split model Damage_ChangeModel = 1,
* 3: smash Damage_SplitModel = 2,
* 4: change and smash Damage_Smash = 3,
*/ Damage_ChangeThenSmash = 4,
uint8_t collDamageFlags; Damage_SmashCardboard = 50,
/* Damage_SmashWoodenBox = 60,
* 1: lampost Damage_SmashTrafficCone = 70,
* 2: smallbox Damage_SmashBarPost = 80,
* 3: bigbox };
* 4: fencepart uint8_t collDamageEffect;
*/
enum {
Response_None = 0,
Response_LampPost = 1,
Response_SmallBox = 2,
Response_BigBox = 3,
Response_FencePart = 4,
};
uint8_t collResponseFlags; uint8_t collResponseFlags;
bool cameraAvoid; bool cameraAvoid;
}; };

View File

@ -587,9 +587,12 @@ void handleInstanceResponse(InstanceObject *instance, const btManifoldPoint &mp,
auto impulse = mp.getAppliedImpulse(); auto impulse = mp.getAppliedImpulse();
if (impulse > 0.0f) { if (impulse > 0.0f) {
///@ todo Correctness: object damage calculation
constexpr auto kMinimumDamageImpulse = 500.f;
const auto hp = std::max(0.f, impulse - kMinimumDamageImpulse);
instance->takeDamage({{dmg.x(), dmg.y(), dmg.z()}, instance->takeDamage({{dmg.x(), dmg.y(), dmg.z()},
{dmg.x(), dmg.y(), dmg.z()}, {dmg.x(), dmg.y(), dmg.z()},
0.f, hp,
GameObject::DamageInfo::Physics, GameObject::DamageInfo::Physics,
impulse}); impulse});
} }

View File

@ -37,9 +37,9 @@ void GenericDATLoader::loadDynamicObjects(const std::string& name,
if (ss.peek() == ',') ss.ignore(1); if (ss.peek() == ',') ss.ignore(1);
ss >> dyndata->airRes; ss >> dyndata->airRes;
if (ss.peek() == ',') ss.ignore(1); if (ss.peek() == ',') ss.ignore(1);
ss >> dyndata->elacticity; ss >> dyndata->elasticity;
if (ss.peek() == ',') ss.ignore(1); if (ss.peek() == ',') ss.ignore(1);
ss >> dyndata->bouancy; ss >> dyndata->buoyancy;
if (ss.peek() == ',') ss.ignore(1); if (ss.peek() == ',') ss.ignore(1);
ss >> dyndata->uprootForce; ss >> dyndata->uprootForce;
if (ss.peek() == ',') ss.ignore(1); if (ss.peek() == ',') ss.ignore(1);
@ -47,7 +47,7 @@ void GenericDATLoader::loadDynamicObjects(const std::string& name,
if (ss.peek() == ',') ss.ignore(1); if (ss.peek() == ',') ss.ignore(1);
int tmp; int tmp;
ss >> tmp; ss >> tmp;
dyndata->collDamageFlags = tmp; dyndata->collDamageEffect = tmp;
if (ss.peek() == ',') ss.ignore(1); if (ss.peek() == ',') ss.ignore(1);
ss >> tmp; ss >> tmp;
dyndata->collResponseFlags = tmp; dyndata->collResponseFlags = tmp;

View File

@ -47,7 +47,18 @@ InstanceObject::~InstanceObject() {
} }
void InstanceObject::tick(float dt) { void InstanceObject::tick(float dt) {
if (dynamics && body) { if (animator) animator->tick(dt);
if (!body || !dynamics) {
return;
}
if (changeAtomic != -1) {
RW_ASSERT(getModelInfo<SimpleModelInfo>()->getNumAtomics() >
changeAtomic);
changeModel(getModelInfo<SimpleModelInfo>(), changeAtomic);
changeAtomic = -1;
}
if (_enablePhysics) { if (_enablePhysics) {
if (body->getBulletBody()->isStaticObject()) { if (body->getBulletBody()->isStaticObject()) {
body->changeMass(dynamics->mass); body->changeMass(dynamics->mass);
@ -78,7 +89,7 @@ void InstanceObject::tick(float dt) {
if (inWater) { if (inWater) {
float oZ = float oZ =
-(body->getBoundingHeight() * (dynamics->bouancy / 100.f)); -(body->getBoundingHeight() * (dynamics->buoyancy / 100.f));
body->getBulletBody()->activate(true); body->getBulletBody()->activate(true);
// Damper motion // Damper motion
body->getBulletBody()->setDamping(0.95f, 0.9f); body->getBulletBody()->setDamping(0.95f, 0.9f);
@ -91,19 +102,6 @@ void InstanceObject::tick(float dt) {
h += engine->data->getWaveHeightAt(ws); h += engine->data->getWaveHeightAt(ws);
if (ws.z <= h) { 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.
engine->dynamicsWorld->removeRigidBody(body->body);
btVector3 inert;
body->getCollisionShape()->calculateLocalInertia(dynamics->mass,
inert);
body->setMassProps(dynamics->mass, inert);
engine->dynamicsWorld->addRigidBody(body);
}*/
float x = (h - ws.z); float x = (h - ws.z);
float F = float F =
WATER_BUOYANCY_K * x + WATER_BUOYANCY_K * x +
@ -121,12 +119,9 @@ void InstanceObject::tick(float dt) {
} }
} }
} }
}
if (animator) animator->tick(dt);
} }
void InstanceObject::changeModel(BaseModelInfo* incoming) { void InstanceObject::changeModel(BaseModelInfo* incoming, int atomicNumber) {
if (body) { if (body) {
body.reset(); body.reset();
} }
@ -141,12 +136,13 @@ void InstanceObject::changeModel(BaseModelInfo* incoming) {
setModel(getModelInfo<SimpleModelInfo>()->getModel()); setModel(getModelInfo<SimpleModelInfo>()->getModel());
auto collision = getModelInfo<SimpleModelInfo>()->getCollision(); auto collision = getModelInfo<SimpleModelInfo>()->getCollision();
auto modelatomic = getModelInfo<SimpleModelInfo>()->getAtomic(0); RW_ASSERT(getModelInfo<SimpleModelInfo>()->getNumAtomics() > atomicNumber);
if (modelatomic) { auto atomic = getModelInfo<SimpleModelInfo>()->getAtomic(atomicNumber);
auto previousatomic = atomic_; if (atomic) {
atomic_ = modelatomic->clone(); auto previous = atomic_;
if (previousatomic) { atomic_ = atomic->clone();
atomic_->setFrame(previousatomic->getFrame()); if (previous) {
atomic_->setFrame(previous->getFrame());
} else { } else {
atomic_->setFrame(std::make_shared<ModelFrame>()); atomic_->setFrame(std::make_shared<ModelFrame>());
} }
@ -182,20 +178,41 @@ void InstanceObject::setRotation(const glm::quat& r) {
} }
bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) { bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) {
bool smash = false; if (!dynamics) {
if (dynamics) { return false;
smash = dynamics->collDamageFlags == 80; }
const auto effect = dynamics->collDamageEffect;
if (dmg.hitpoints > 0.f) {
switch (effect) {
case DynamicObjectData::Damage_ChangeModel:
changeAtomic = 1;
break;
case DynamicObjectData::Damage_ChangeThenSmash:
changeAtomic = 1;
RW_UNIMPLEMENTED("Collision Damage Effect: Changing, then Smashing");
break;
case DynamicObjectData::Damage_Smash:
RW_UNIMPLEMENTED("Collision Damage Effect: Smashing");
break;
case DynamicObjectData::Damage_SmashCardboard:
case DynamicObjectData::Damage_SmashWoodenBox:
case DynamicObjectData::Damage_SmashTrafficCone:
case DynamicObjectData::Damage_SmashBarPost:
RW_UNIMPLEMENTED("Collision Damage Effect");
break;
default:
break;
}
}
if (dmg.impulse >= dynamics->uprootForce && if (dmg.impulse >= dynamics->uprootForce &&
body->getBulletBody()->isStaticObject()) { body->getBulletBody()->isStaticObject()) {
_enablePhysics = true; _enablePhysics = true;
} }
}
if (smash) {
health -= dmg.hitpoints;
return true; return true;
}
return false;
} }
void InstanceObject::setSolid(bool solid) { void InstanceObject::setSolid(bool solid) {

View File

@ -19,6 +19,7 @@ class GameWorld;
class InstanceObject : public GameObject { class InstanceObject : public GameObject {
float health; float health;
bool visible = true; bool visible = true;
int changeAtomic = -1;
/** /**
* The Atomic instance for this object * The Atomic instance for this object
@ -47,7 +48,7 @@ public:
void tick(float dt) override; void tick(float dt) override;
void changeModel(BaseModelInfo* incoming); void changeModel(BaseModelInfo* incoming, int atomicNumber = 0);
void setPosition(const glm::vec3& pos) override; void setPosition(const glm::vec3& pos) override;

View File

@ -59,11 +59,11 @@ BOOST_AUTO_TEST_CASE(test_dynamic_dat_loader) {
BOOST_CHECK_EQUAL(lamp->mass, 600.0); BOOST_CHECK_EQUAL(lamp->mass, 600.0);
BOOST_CHECK_EQUAL(lamp->turnMass, 4000.0); BOOST_CHECK_EQUAL(lamp->turnMass, 4000.0);
BOOST_CHECK_CLOSE(lamp->airRes, 0.99, 1.0); BOOST_CHECK_CLOSE(lamp->airRes, 0.99, 1.0);
BOOST_CHECK_CLOSE(lamp->elacticity, 0.05, 0.01); BOOST_CHECK_CLOSE(lamp->elasticity, 0.05, 0.01);
BOOST_CHECK_EQUAL(lamp->bouancy, 50.0); BOOST_CHECK_EQUAL(lamp->buoyancy, 50.0);
BOOST_CHECK_EQUAL(lamp->uprootForce, 400); BOOST_CHECK_EQUAL(lamp->uprootForce, 400);
BOOST_CHECK_EQUAL(lamp->collDamageMulti, 1.0); BOOST_CHECK_EQUAL(lamp->collDamageMulti, 1.0);
BOOST_CHECK_EQUAL(lamp->collDamageFlags, 1); BOOST_CHECK_EQUAL(lamp->collDamageEffect, 1);
BOOST_CHECK_EQUAL(lamp->collResponseFlags, 1); BOOST_CHECK_EQUAL(lamp->collResponseFlags, 1);
BOOST_CHECK_EQUAL(lamp->cameraAvoid, false); BOOST_CHECK_EQUAL(lamp->cameraAvoid, false);
} }