aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/collision/DynamicTree.cpp48
-rw-r--r--src/server/collision/DynamicTree.h2
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp15
-rwxr-xr-xsrc/server/game/Maps/Map.cpp20
-rwxr-xr-xsrc/server/game/Maps/Map.h11
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp5
6 files changed, 90 insertions, 11 deletions
diff --git a/src/server/collision/DynamicTree.cpp b/src/server/collision/DynamicTree.cpp
index 1d6877d1209..89e76d426fe 100644
--- a/src/server/collision/DynamicTree.cpp
+++ b/src/server/collision/DynamicTree.cpp
@@ -176,6 +176,54 @@ struct DynamicTreeIntersectionCallback_WithLogger
bool didHit() const { return did_hit;}
};
+bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, const Vector3& endPos, float& maxDist) const
+{
+ float distance = maxDist;
+ DynamicTreeIntersectionCallback callback(phasemask);
+ impl.intersectRay(ray, callback, distance, endPos);
+ if (callback.didHit())
+ maxDist = distance;
+ return callback.didHit();
+}
+
+bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const Vector3& startPos, const Vector3& endPos, Vector3& resultHit, float modifyDist) const
+{
+ bool result = false;
+ float maxDist = (endPos - startPos).magnitude();
+ // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
+ ASSERT(maxDist < std::numeric_limits<float>::max());
+ // prevent NaN values which can cause BIH intersection to enter infinite loop
+ if (maxDist < 1e-10f)
+ {
+ resultHit = endPos;
+ return false;
+ }
+ Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1
+ G3D::Ray ray(startPos, dir);
+ float dist = maxDist;
+ if (getIntersectionTime(phasemask, ray, endPos, dist))
+ {
+ resultHit = startPos + dir * dist;
+ if (modifyDist < 0)
+ {
+ if ((resultHit - startPos).magnitude() > -modifyDist)
+ resultHit = resultHit + dir*modifyDist;
+ else
+ resultHit = startPos;
+ }
+ else
+ resultHit = resultHit + dir*modifyDist;
+
+ result = true;
+ }
+ else
+ {
+ resultHit = endPos;
+ result = false;
+ }
+ return result;
+}
+
bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
{
Vector3 v1(x1,y1,z1), v2(x2,y2,z2);
diff --git a/src/server/collision/DynamicTree.h b/src/server/collision/DynamicTree.h
index ab28641b6ad..0b4f5908c04 100644
--- a/src/server/collision/DynamicTree.h
+++ b/src/server/collision/DynamicTree.h
@@ -46,6 +46,8 @@ public:
~DynamicMapTree();
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const;
+ bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, const Vector3& endPos, float& maxDist) const;
+ bool getObjectHitPos(uint32 phasemask, const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const;
float getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const;
void insert(const GameObjectModel&);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 3ab91e9582f..aadf9f44b0b 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -2671,7 +2671,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
{
angle += m_orientation;
float destx, desty, destz, ground, floor;
-
+ pos.m_positionZ += 2.0f;
destx = pos.m_positionX + dist * cos(angle);
desty = pos.m_positionY + dist * sin(angle);
ground = GetMap()->GetHeight(GetPhaseMask(), destx, desty, MAX_HEIGHT, true);
@@ -2689,6 +2689,17 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
dist = sqrt((pos.m_positionX - destx)*(pos.m_positionX - destx) + (pos.m_positionY - desty)*(pos.m_positionY - desty));
}
+ // check dynamic collision
+ col = GetMap()->getObjectHitPos(GetPhaseMask(), pos.m_positionX, pos.m_positionY, pos.m_positionZ+0.5f, destx, desty, destz+0.5f, destx, desty, destz, -0.5f);
+
+ // Collided with a gameobject
+ if (col)
+ {
+ destx -= CONTACT_DISTANCE * cos(angle);
+ desty -= CONTACT_DISTANCE * sin(angle);
+ dist = sqrt((pos.m_positionX - destx)*(pos.m_positionX - destx) + (pos.m_positionY - desty)*(pos.m_positionY - desty));
+ }
+
float step = dist/10.0f;
for (uint8 j = 0; j < 10; ++j)
@@ -2712,7 +2723,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
Trinity::NormalizeMapCoord(pos.m_positionX);
Trinity::NormalizeMapCoord(pos.m_positionY);
- UpdateGroundPositionZ(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
+ UpdateAllowedPositionZ(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
pos.m_orientation = m_orientation;
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 6e13e70d1cd..b8c35d45e98 100755
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -500,7 +500,7 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Trinity::Obj
void Map::Update(const uint32 t_diff)
{
- m_dyn_tree.update(t_diff);
+ _dynamicTree.update(t_diff);
/// update worldsessions for existing players
for (m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter)
{
@@ -1800,12 +1800,26 @@ void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 area
bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
{
return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
- && m_dyn_tree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask);
+ && _dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask);
+}
+
+bool Map::getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
+{
+ Vector3 startPos = Vector3(x1, y1, z1);
+ Vector3 dstPos = Vector3(x2, y2, z2);
+
+ Vector3 resultPos;
+ bool result = _dynamicTree.getObjectHitPos(phasemask, startPos, dstPos, resultPos, modifyDist);
+
+ rx = resultPos.x;
+ ry = resultPos.y;
+ rz = resultPos.z;
+ return result;
}
float Map::GetHeight(uint32 phasemask, float x, float y, float z, bool vmap/*=true*/, float maxSearchDist/*=DEFAULT_HEIGHT_SEARCH*/) const
{
- return std::max<float>(GetHeight(x, y, z, vmap, maxSearchDist), m_dyn_tree.getHeight(x, y, z, maxSearchDist, phasemask));
+ return std::max<float>(GetHeight(x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phasemask));
}
bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 7d234d5f75a..148a55d4691 100755
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -429,10 +429,11 @@ class Map : public GridRefManager<NGridType>
float GetWaterOrGroundLevel(float x, float y, float z, float* ground = NULL, bool swim = false) const;
float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const;
- void Balance() { m_dyn_tree.balance(); }
- void Remove(const GameObjectModel& mdl) { m_dyn_tree.remove(mdl); }
- void Insert(const GameObjectModel& mdl) { m_dyn_tree.insert(mdl); }
- bool Contains(const GameObjectModel& mdl) const { return m_dyn_tree.contains(mdl);}
+ void Balance() { _dynamicTree.balance(); }
+ void Remove(const GameObjectModel& mdl) { _dynamicTree.remove(mdl); }
+ void Insert(const GameObjectModel& mdl) { _dynamicTree.insert(mdl); }
+ bool Contains(const GameObjectModel& mdl) const { return _dynamicTree.contains(mdl);}
+ bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist);
private:
void LoadMapAndVMap(int gx, int gy);
void LoadVMap(int gx, int gy);
@@ -488,7 +489,7 @@ class Map : public GridRefManager<NGridType>
uint32 i_InstanceId;
uint32 m_unloadTimer;
float m_VisibleDistance;
- DynamicMapTree m_dyn_tree;
+ DynamicMapTree _dynamicTree;
MapRefManager m_mapRefManager;
MapRefManager::iterator m_mapRefIter;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 6802cbdd90d..ef5f32b5575 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -6076,7 +6076,10 @@ void Spell::EffectLeap(SpellEffIndex /*effIndex*/)
if (!m_targets.HasDst())
return;
- unitTarget->NearTeleportTo(m_targets.GetDst()->GetPositionX(), m_targets.GetDst()->GetPositionY(), m_targets.GetDst()->GetPositionZ(), m_targets.GetDst()->GetOrientation(), unitTarget == m_caster);
+ Position pos;
+ m_targets.GetDst()->GetPosition(&pos);
+ unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetDistance(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + 2.0f), 0.0f);
+ unitTarget->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), unitTarget == m_caster);
}
void Spell::EffectReputation(SpellEffIndex effIndex)