diff options
| author | Meji <alvaro.megias@outlook.com> | 2024-05-04 13:20:13 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2024-05-27 18:53:47 +0200 |
| commit | b070e63fa867f7f25e73e9ef3aafbe18902a50e9 (patch) | |
| tree | c3d0151e9b46d30ccb69d57983df431acfb673a3 /src/server/game/Entities/Object | |
| parent | 38e99e1569fcba821211fcd2d7c3a0b2bd00701c (diff) | |
Core/AreaTriggers: Fix triggering of client areatriggers for some shapes
Diffstat (limited to 'src/server/game/Entities/Object')
| -rw-r--r-- | src/server/game/Entities/Object/Position.cpp | 101 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Position.h | 9 |
2 files changed, 92 insertions, 18 deletions
diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index d91c55eb84a..aa391a0d062 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -62,38 +62,109 @@ Position Position::GetPositionWithOffset(Position const& offset) const return ret; } -bool Position::IsWithinBox(Position const& center, float xradius, float yradius, float zradius) const +bool Position::IsWithinBox(Position const& boxOrigin, float length, float width, float height) const { // rotate the WorldObject position instead of rotating the whole cube, that way we can make a simplified // is-in-cube check and we have to calculate only one point instead of 4 // 2PI = 360*, keep in mind that ingame orientation is counter-clockwise - double rotation = 2 * M_PI - center.GetOrientation(); + double rotation = 2 * M_PI - boxOrigin.GetOrientation(); double sinVal = std::sin(rotation); double cosVal = std::cos(rotation); - float BoxDistX = GetPositionX() - center.GetPositionX(); - float BoxDistY = GetPositionY() - center.GetPositionY(); + float BoxDistX = GetPositionX() - boxOrigin.GetPositionX(); + float BoxDistY = GetPositionY() - boxOrigin.GetPositionY(); - float rotX = float(center.GetPositionX() + BoxDistX * cosVal - BoxDistY*sinVal); - float rotY = float(center.GetPositionY() + BoxDistY * cosVal + BoxDistX*sinVal); + float rotX = float(boxOrigin.GetPositionX() + BoxDistX * cosVal - BoxDistY * sinVal); + float rotY = float(boxOrigin.GetPositionY() + BoxDistY * cosVal + BoxDistX * sinVal); // box edges are parallel to coordiante axis, so we can treat every dimension independently :D - float dz = GetPositionZ() - center.GetPositionZ(); - float dx = rotX - center.GetPositionX(); - float dy = rotY - center.GetPositionY(); - if ((std::fabs(dx) > xradius) || - (std::fabs(dy) > yradius) || - (std::fabs(dz) > zradius)) + float dz = GetPositionZ() - boxOrigin.GetPositionZ(); + float dx = rotX - boxOrigin.GetPositionX(); + float dy = rotY - boxOrigin.GetPositionY(); + if ((std::fabs(dx) > length) || + (std::fabs(dy) > width) || + (std::fabs(dz) > height)) return false; return true; } -bool Position::IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const +bool Position::IsWithinVerticalCylinder(Position const& cylinderOrigin, float radius, float height, bool isDoubleVertical) const { - float verticalDelta = GetPositionZ() - center->GetPositionZ(); - return IsInDist2d(center, radius) && std::abs(verticalDelta) <= height; + float verticalDelta = GetPositionZ() - cylinderOrigin.GetPositionZ(); + bool isValidPositionZ = isDoubleVertical ? std::abs(verticalDelta) <= height : 0 <= verticalDelta && verticalDelta <= height; + + return isValidPositionZ && IsInDist2d(cylinderOrigin, radius); +} + +bool Position::IsInPolygon2D(Position const& polygonOrigin, std::span<Position const> vertices) const +{ + float testX = GetPositionX(); + float testY = GetPositionY(); + + //this method uses the ray tracing algorithm to determine if the point is in the polygon + bool locatedInPolygon = false; + + for (std::size_t vertex = 0; vertex < vertices.size(); ++vertex) + { + std::size_t nextVertex; + + //repeat loop for all sets of points + if (vertex == (vertices.size() - 1)) + { + //if i is the last vertex, let j be the first vertex + nextVertex = 0; + } + else + { + //for all-else, let j=(i+1)th vertex + nextVertex = vertex + 1; + } + + float vertX_i = polygonOrigin.GetPositionX() + vertices[vertex].GetPositionX(); + float vertY_i = polygonOrigin.GetPositionY() + vertices[vertex].GetPositionY(); + float vertX_j = polygonOrigin.GetPositionX() + vertices[nextVertex].GetPositionX(); + float vertY_j = polygonOrigin.GetPositionY() + vertices[nextVertex].GetPositionY(); + + // following statement checks if testPoint.Y is below Y-coord of i-th vertex + bool belowLowY = vertY_i > testY; + // following statement checks if testPoint.Y is below Y-coord of i+1-th vertex + bool belowHighY = vertY_j > testY; + + /* following statement is true if testPoint.Y satisfies either (only one is possible) + -->(i).Y < testPoint.Y < (i+1).Y OR + -->(i).Y > testPoint.Y > (i+1).Y + + (Note) + Both of the conditions indicate that a point is located within the edges of the Y-th coordinate + of the (i)-th and the (i+1)- th vertices of the polygon. If neither of the above + conditions is satisfied, then it is assured that a semi-infinite horizontal line draw + to the right from the testpoint will NOT cross the line that connects vertices i and i+1 + of the polygon + */ + bool withinYsEdges = belowLowY != belowHighY; + + if (withinYsEdges) + { + // this is the slope of the line that connects vertices i and i+1 of the polygon + float slopeOfLine = (vertX_j - vertX_i) / (vertY_j - vertY_i); + + // this looks up the x-coord of a point lying on the above line, given its y-coord + float pointOnLine = (slopeOfLine * (testY - vertY_i)) + vertX_i; + + //checks to see if x-coord of testPoint is smaller than the point on the line with the same y-coord + bool isLeftToLine = testX < pointOnLine; + + if (isLeftToLine) + { + //this statement changes true to false (and vice-versa) + locatedInPolygon = !locatedInPolygon; + }//end if (isLeftToLine) + }//end if (withinYsEdges + } + + return locatedInPolygon; } bool Position::HasInArc(float arc, Position const* obj, float border) const diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index 1bd11b69c88..ed4709dadf3 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -19,6 +19,7 @@ #define Trinity_game_Position_h__ #include "Define.h" +#include <span> #include <string> #include <cmath> @@ -138,16 +139,18 @@ public: float GetRelativeAngle(Position const* pos) const { return ToRelativeAngle(GetAbsoluteAngle(pos)); } constexpr bool IsInDist2d(float x, float y, float dist) const { return GetExactDist2dSq(x, y) < dist * dist; } + constexpr bool IsInDist2d(Position const& pos, float dist) const { return GetExactDist2dSq(pos) < dist * dist; } constexpr bool IsInDist2d(Position const* pos, float dist) const { return GetExactDist2dSq(pos) < dist * dist; } constexpr bool IsInDist(float x, float y, float z, float dist) const { return GetExactDistSq(x, y, z) < dist * dist; } constexpr bool IsInDist(Position const& pos, float dist) const { return GetExactDistSq(pos) < dist * dist; } constexpr bool IsInDist(Position const* pos, float dist) const { return GetExactDistSq(pos) < dist * dist; } - bool IsWithinBox(Position const& center, float xradius, float yradius, float zradius) const; + bool IsWithinBox(Position const& boxOrigin, float length, float width, float height) const; - // dist2d < radius && abs(dz) < height - bool IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const; + bool IsWithinVerticalCylinder(Position const& cylinderOrigin, float radius, float height, bool isDoubleVertical = false) const; + + bool IsInPolygon2D(Position const& polygonOrigin, std::span<Position const> vertices) const; bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; bool HasInLine(Position const* pos, float objSize, float width) const; |
