diff --git a/rwengine/src/engine/GameWorld.cpp b/rwengine/src/engine/GameWorld.cpp index e512145a..11d01968 100644 --- a/rwengine/src/engine/GameWorld.cpp +++ b/rwengine/src/engine/GameWorld.cpp @@ -570,41 +570,39 @@ void GameWorld::destroyEffect(VisualFX& effect) { void GameWorld::doWeaponScan(const WeaponScan& scan) { if (scan.type == ScanType::Radius) { HitTest test {*dynamicsWorld}; - const auto result = test.sphereTest(scan.center, scan.radius); + const auto& result = test.sphereTest(scan.center, scan.radius); for(const auto& target : result) { if (!scan.doesDamage(target.object)) { continue; } - GameObject::DamageInfo di; - di.damageSource = scan.center; - di.type = GameObject::DamageInfo::Melee; - di.hitpoints = scan.damage; - target.object->takeDamage(di); + target.object->takeDamage( + { + GameObject::DamageInfo::DamageType::Melee, + {}, scan.center, scan.damage + }); } } else if (scan.type == ScanType::HitScan) { btVector3 from(scan.center.x, scan.center.y, scan.center.z), to(scan.end.x, scan.end.y, scan.end.z); - glm::vec3 hitEnd = scan.end; btCollisionWorld::ClosestRayResultCallback cb(from, to); cb.m_collisionFilterGroup = btBroadphaseProxy::AllFilter; dynamicsWorld->rayTest(from, to, cb); - // TODO: did any weapons penetrate? - - if (cb.hasHit()) { - GameObject* go = static_cast( - cb.m_collisionObject->getUserPointer()); - GameObject::DamageInfo di; - hitEnd = di.damageLocation = - glm::vec3(cb.m_hitPointWorld.x(), cb.m_hitPointWorld.y(), - cb.m_hitPointWorld.z()); - di.damageSource = scan.center; - di.type = GameObject::DamageInfo::Bullet; - di.hitpoints = scan.damage; - go->takeDamage(di); + if (!cb.hasHit()) { + return; } + + auto go = static_cast( + cb.m_collisionObject->getUserPointer()); + go->takeDamage( + { + GameObject::DamageInfo::DamageType::Bullet, + {cb.m_hitPointWorld.x(), cb.m_hitPointWorld.y(), + cb.m_hitPointWorld.z()}, + scan.center, scan.damage + }); } } @@ -671,11 +669,13 @@ void handleVehicleResponse(GameObject* object, btManifoldPoint& mp, bool isA) { dmg = mp.getPositionWorldOnB(); } - object->takeDamage({{dmg.x(), dmg.y(), dmg.z()}, - {src.x(), src.y(), src.z()}, - 0.f, - GameObject::DamageInfo::Physics, - mp.getAppliedImpulse()}); + object->takeDamage({ + GameObject::DamageInfo::DamageType::Physics, + {dmg.x(), dmg.y(), dmg.z()}, + {src.x(), src.y(), src.z()}, + 0.f, + mp.getAppliedImpulse() + }); } void handleInstanceResponse(InstanceObject* instance, const btManifoldPoint& mp, @@ -687,16 +687,20 @@ void handleInstanceResponse(InstanceObject* instance, const btManifoldPoint& mp, auto dmg = isA ? mp.m_positionWorldOnA : mp.m_positionWorldOnB; auto impulse = mp.getAppliedImpulse(); - 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()}, - {dmg.x(), dmg.y(), dmg.z()}, - hp, - GameObject::DamageInfo::Physics, - impulse}); + if (impulse <= 0.0f) { + return; } + + ///@ todo Correctness: object damage calculation + constexpr auto kMinimumDamageImpulse = 500.f; + const auto hp = std::max(0.f, impulse - kMinimumDamageImpulse); + instance->takeDamage({ + GameObject::DamageInfo::DamageType::Physics, + {dmg.x(), dmg.y(), dmg.z()}, + {dmg.x(), dmg.y(), dmg.z()}, + hp, + impulse + }); } } // namespace diff --git a/rwengine/src/objects/GameObject.hpp b/rwengine/src/objects/GameObject.hpp index f9ada284..74910f46 100644 --- a/rwengine/src/objects/GameObject.hpp +++ b/rwengine/src/objects/GameObject.hpp @@ -164,7 +164,9 @@ public: } struct DamageInfo { - enum DamageType { Explosion, Burning, Bullet, Physics, Melee }; + enum class DamageType { + Explosion, Burning, Bullet, Physics, Melee + }; /** * World position of damage @@ -190,6 +192,11 @@ public: * Physics impulse. */ float impulse; + + DamageInfo(DamageType type, const glm::vec3 &location, + const glm::vec3 &source, float damage, float impulse = 0.f) + : damageLocation(location), damageSource(source), hitpoints(damage), + type(type), impulse(impulse) {} }; virtual bool takeDamage(const DamageInfo& damage) { diff --git a/rwengine/src/objects/ProjectileObject.cpp b/rwengine/src/objects/ProjectileObject.cpp index e14627e5..a26dc552 100644 --- a/rwengine/src/objects/ProjectileObject.cpp +++ b/rwengine/src/objects/ProjectileObject.cpp @@ -78,8 +78,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, + o->takeDamage({DamageInfo::DamageType::Explosion, + getPosition(), getPosition(), + damage / glm::max(d, 1.f), 0.f}); } diff --git a/rwgame/states/DebugState.cpp b/rwgame/states/DebugState.cpp index a9b29d16..1165a209 100644 --- a/rwgame/states/DebugState.cpp +++ b/rwgame/states/DebugState.cpp @@ -207,9 +207,13 @@ Menu DebugState::createAIMenu() { if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) { continue; } - pedestrianPtr->takeDamage({pedestrianPtr->getPosition(), - pedestrianPtr->getPosition(), 100.f, - GameObject::DamageInfo::Explosion, 0.f}); + pedestrianPtr->takeDamage( + { + GameObject::DamageInfo::DamageType::Explosion, + pedestrianPtr->getPosition(), + pedestrianPtr->getPosition(), 100.f, + 0.f + }); } }); diff --git a/tests/test_Character.cpp b/tests/test_Character.cpp index d52eafb6..65726e59 100644 --- a/tests/test_Character.cpp +++ b/tests/test_Character.cpp @@ -129,9 +129,11 @@ BOOST_AUTO_TEST_CASE(test_death) { BOOST_CHECK_EQUAL(character->getCurrentState().health, 100.f); BOOST_CHECK(character->isAlive()); - GameObject::DamageInfo dmg; - dmg.type = GameObject::DamageInfo::Bullet; - dmg.hitpoints = character->getCurrentState().health + 1.f; + GameObject::DamageInfo dmg { + GameObject::DamageInfo::DamageType::Bullet, + {}, {}, + character->getCurrentState().health + 1.f + }; // Do some damage BOOST_CHECK(character->takeDamage(dmg));