1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-02 16:49:46 +02:00

Make DamageInfo construction more explicit

This commit is contained in:
Daniel Evans 2019-01-05 02:22:38 +00:00
parent bdacc1137a
commit f59653eeea
5 changed files with 61 additions and 43 deletions

View File

@ -570,41 +570,39 @@ void GameWorld::destroyEffect(VisualFX& effect) {
void GameWorld::doWeaponScan(const WeaponScan& scan) { void GameWorld::doWeaponScan(const WeaponScan& scan) {
if (scan.type == ScanType::Radius) { if (scan.type == ScanType::Radius) {
HitTest test {*dynamicsWorld}; 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) { for(const auto& target : result) {
if (!scan.doesDamage(target.object)) { if (!scan.doesDamage(target.object)) {
continue; continue;
} }
GameObject::DamageInfo di; target.object->takeDamage(
di.damageSource = scan.center; {
di.type = GameObject::DamageInfo::Melee; GameObject::DamageInfo::DamageType::Melee,
di.hitpoints = scan.damage; {}, scan.center, scan.damage
target.object->takeDamage(di); });
} }
} else if (scan.type == ScanType::HitScan) { } else if (scan.type == ScanType::HitScan) {
btVector3 from(scan.center.x, scan.center.y, scan.center.z), btVector3 from(scan.center.x, scan.center.y, scan.center.z),
to(scan.end.x, scan.end.y, scan.end.z); to(scan.end.x, scan.end.y, scan.end.z);
glm::vec3 hitEnd = scan.end;
btCollisionWorld::ClosestRayResultCallback cb(from, to); btCollisionWorld::ClosestRayResultCallback cb(from, to);
cb.m_collisionFilterGroup = btBroadphaseProxy::AllFilter; cb.m_collisionFilterGroup = btBroadphaseProxy::AllFilter;
dynamicsWorld->rayTest(from, to, cb); dynamicsWorld->rayTest(from, to, cb);
// TODO: did any weapons penetrate? if (!cb.hasHit()) {
return;
if (cb.hasHit()) {
GameObject* go = static_cast<GameObject*>(
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);
} }
auto go = static_cast<GameObject *>(
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(); dmg = mp.getPositionWorldOnB();
} }
object->takeDamage({{dmg.x(), dmg.y(), dmg.z()}, object->takeDamage({
{src.x(), src.y(), src.z()}, GameObject::DamageInfo::DamageType::Physics,
0.f, {dmg.x(), dmg.y(), dmg.z()},
GameObject::DamageInfo::Physics, {src.x(), src.y(), src.z()},
mp.getAppliedImpulse()}); 0.f,
mp.getAppliedImpulse()
});
} }
void handleInstanceResponse(InstanceObject* instance, const btManifoldPoint& mp, 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 dmg = isA ? mp.m_positionWorldOnA : mp.m_positionWorldOnB;
auto impulse = mp.getAppliedImpulse(); auto impulse = mp.getAppliedImpulse();
if (impulse > 0.0f) { if (impulse <= 0.0f) {
///@ todo Correctness: object damage calculation return;
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});
} }
///@ 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 } // namespace

View File

@ -164,7 +164,9 @@ public:
} }
struct DamageInfo { struct DamageInfo {
enum DamageType { Explosion, Burning, Bullet, Physics, Melee }; enum class DamageType {
Explosion, Burning, Bullet, Physics, Melee
};
/** /**
* World position of damage * World position of damage
@ -190,6 +192,11 @@ public:
* Physics impulse. * Physics impulse.
*/ */
float 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) { virtual bool takeDamage(const DamageInfo& damage) {

View File

@ -78,8 +78,9 @@ void ProjectileObject::explode() {
float d = glm::distance(getPosition(), o->getPosition()); float d = glm::distance(getPosition(), o->getPosition());
if (d > damageSize) continue; if (d > damageSize) continue;
o->takeDamage({getPosition(), getPosition(), o->takeDamage({DamageInfo::DamageType::Explosion,
damage / glm::max(d, 1.f), DamageInfo::Explosion, getPosition(), getPosition(),
damage / glm::max(d, 1.f),
0.f}); 0.f});
} }

View File

@ -207,9 +207,13 @@ Menu DebugState::createAIMenu() {
if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) { if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) {
continue; continue;
} }
pedestrianPtr->takeDamage({pedestrianPtr->getPosition(), pedestrianPtr->takeDamage(
pedestrianPtr->getPosition(), 100.f, {
GameObject::DamageInfo::Explosion, 0.f}); GameObject::DamageInfo::DamageType::Explosion,
pedestrianPtr->getPosition(),
pedestrianPtr->getPosition(), 100.f,
0.f
});
} }
}); });

View File

@ -129,9 +129,11 @@ BOOST_AUTO_TEST_CASE(test_death) {
BOOST_CHECK_EQUAL(character->getCurrentState().health, 100.f); BOOST_CHECK_EQUAL(character->getCurrentState().health, 100.f);
BOOST_CHECK(character->isAlive()); BOOST_CHECK(character->isAlive());
GameObject::DamageInfo dmg; GameObject::DamageInfo dmg {
dmg.type = GameObject::DamageInfo::Bullet; GameObject::DamageInfo::DamageType::Bullet,
dmg.hitpoints = character->getCurrentState().health + 1.f; {}, {},
character->getCurrentState().health + 1.f
};
// Do some damage // Do some damage
BOOST_CHECK(character->takeDamage(dmg)); BOOST_CHECK(character->takeDamage(dmg));