From 020a3681da0aec8a1dbe06deb53a58d0727bfdc0 Mon Sep 17 00:00:00 2001 From: Daniel Scharrer Date: Thu, 14 Sep 2017 16:25:36 +0200 Subject: [PATCH] Physics: Prevent entities from escaping the world This should not be required with perfect entity-world collisions, but having this sanity check is a good idea even after we fix the physics. Partially reverts commit 8768128 "Remove first check if falling physics object is above ground". Fixes: issue #1042 --- src/physics/Physics.cpp | 40 +++++++++++++++++++++++++++++++++++++--- src/physics/Physics.h | 2 ++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/physics/Physics.cpp b/src/physics/Physics.cpp index 2e3fa3f587..eb69164fb2 100644 --- a/src/physics/Physics.cpp +++ b/src/physics/Physics.cpp @@ -58,11 +58,13 @@ ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. #include "game/EntityManager.h" #include "game/magic/spells/SpellsLvl06.h" -#include "scene/GameSound.h" -#include "scene/Interactive.h" +#include "io/log/Logger.h" #include "physics/Collisions.h" +#include "scene/GameSound.h" +#include "scene/Interactive.h" + // Creation of the physics box... quite cabalistic and extensive func... // Need to put a (really) smarter algorithm in there... @@ -795,6 +797,27 @@ static void ARX_TEMPORARY_TrySound(Entity * source, Material collisionMaterial, } } +bool EERIE_PHYSICS_BOX_IsValidPosition(const Vec3f & pos) { + + BackgroundTileData * tile = getFastBackgroundData(pos.x, pos.z); + if(!tile) { + // Position is outside the world grid + return false; + } + + if(tile->nbpolyin <= 0) { + // Position is in an empty tile + return false; + } + + if(pos.y > tile->maxy) { + // Position is below the lowest part of the tile + return false; + } + + return true; +} + static void ARX_EERIE_PHYSICS_BOX_Compute(PHYSICS_BOX_DATA * pbox, float framediff, Entity * source) { Vec3f oldpos[32]; @@ -809,11 +832,22 @@ static void ARX_EERIE_PHYSICS_BOX_Compute(PHYSICS_BOX_DATA * pbox, float framedi } RK4Integrate(pbox->vert, framediff); - + EERIEPOLY * collisionPoly = NULL; + bool invalidPosition = false; + for(size_t i = 0; i < pbox->vert.size(); i += 2) { + if(!EERIE_PHYSICS_BOX_IsValidPosition(pbox->vert[i].pos - Vec3f(0.f, 10.f, 0.f))) { + // This indicaties that entity-world collisions are broken + LogWarning << "Entity " << source->idString() << " escaped the world"; + invalidPosition = true; + break; + } + } + if( !IsFULLObjectVertexInValidPosition(*pbox, collisionPoly) || ARX_INTERACTIVE_CheckFULLCollision(*pbox, source) + || invalidPosition || IsObjectInField(*pbox) ) { diff --git a/src/physics/Physics.h b/src/physics/Physics.h index c51356c397..59ae71efbc 100644 --- a/src/physics/Physics.h +++ b/src/physics/Physics.h @@ -88,6 +88,8 @@ struct PHYSICS_BOX_DATA {} }; +bool EERIE_PHYSICS_BOX_IsValidPosition(const Vec3f & pos); + void EERIE_PHYSICS_BOX_Create(EERIE_3DOBJ * obj); void EERIE_PHYSICS_BOX_Release(EERIE_3DOBJ * obj); void EERIE_PHYSICS_BOX_Launch(EERIE_3DOBJ * obj, const Vec3f & pos, const Anglef & angle, const Vec3f & vect);