diff --git a/game/plugin/entity/pathing/src/org/apollo/plugin/entity/pathing/Pathing.kt b/game/plugin/entity/pathing/src/org/apollo/plugin/entity/pathing/Pathing.kt index 93adb699..963bb48a 100644 --- a/game/plugin/entity/pathing/src/org/apollo/plugin/entity/pathing/Pathing.kt +++ b/game/plugin/entity/pathing/src/org/apollo/plugin/entity/pathing/Pathing.kt @@ -63,21 +63,4 @@ fun Mob.walkTo(target: Position, positionPredicate: ((Position) -> Boolean)? = n /** * Returns the bounding size of the specified [Entity], in [x-size, y-size] format. */ -private fun bounds(target: Entity): Pair { - return when (target) { - is GameObject -> { - val orientation = Direction.WNES[target.orientation] - val rotated = (orientation == Direction.WEST || orientation == Direction.EAST) - - val definition = target.definition - - val width = if (rotated) definition.length else definition.width - val height = if (rotated) definition.width else definition.length - - Pair(width, height) - } - is Npc -> Pair(target.definition.size, target.definition.size) - is Player -> Pair(1, 1) - else -> error("Invalid entity type") - } -} \ No newline at end of file +private fun bounds(target: Entity): Pair = Pair(target.width, target.length) \ No newline at end of file diff --git a/game/src/main/java/org/apollo/game/model/area/collision/CollisionUpdate.java b/game/src/main/java/org/apollo/game/model/area/collision/CollisionUpdate.java index cd8fb73a..1c404784 100644 --- a/game/src/main/java/org/apollo/game/model/area/collision/CollisionUpdate.java +++ b/game/src/main/java/org/apollo/game/model/area/collision/CollisionUpdate.java @@ -195,23 +195,16 @@ public final class CollisionUpdate { } int x = position.getX(), y = position.getY(), height = position.getHeight(); - int width = definition.getWidth(), length = definition.getLength(); boolean impenetrable = definition.isImpenetrable(); int orientation = object.getOrientation(); - // north / south for walls, north east / south west for corners - if (orientation == 1 || orientation == 3) { - width = definition.getLength(); - length = definition.getWidth(); - } - if (type == FLOOR_DECORATION.getValue()) { if (definition.isInteractive() && definition.isSolid()) { tile(new Position(x, y, height), impenetrable, Direction.NESW); } } else if (type >= DIAGONAL_WALL.getValue() && type < FLOOR_DECORATION.getValue()) { - for (int dx = 0; dx < width; dx++) { - for (int dy = 0; dy < length; dy++) { + for (int dx = 0; dx < object.getWidth(); dx++) { + for (int dy = 0; dy < object.getLength(); dy++) { tile(new Position(x + dx, y + dy, height), impenetrable, Direction.NESW); } } diff --git a/game/src/main/java/org/apollo/game/model/entity/obj/GameObject.java b/game/src/main/java/org/apollo/game/model/entity/obj/GameObject.java index 0d8391bf..1ceb7689 100644 --- a/game/src/main/java/org/apollo/game/model/entity/obj/GameObject.java +++ b/game/src/main/java/org/apollo/game/model/entity/obj/GameObject.java @@ -13,6 +13,9 @@ import org.apollo.game.model.entity.Player; import com.google.common.base.MoreObjects; +import static org.apollo.game.model.entity.obj.ObjectType.RECTANGULAR_CORNER; +import static org.apollo.game.model.entity.obj.ObjectType.TRIANGULAR_CORNER; + /** * Represents an object in the game world. * @@ -86,21 +89,32 @@ public abstract class GameObject extends Entity implements GroupableEntity { return packed >> 2 & 0x3F; } - @Override public int getLength() { - Direction direction = Direction.WNES[getOrientation()]; - - return direction == Direction.WEST || direction == Direction.EAST ? - getDefinition().getWidth() : getDefinition().getLength(); + return isRotated() ? getDefinition().getWidth() : getDefinition().getLength(); } @Override public int getWidth() { - Direction direction = Direction.WNES[getOrientation()]; + return isRotated() ? getDefinition().getLength() : getDefinition().getWidth(); + } - return direction == Direction.WEST || direction == Direction.EAST ? - getDefinition().getLength() : getDefinition().getWidth(); + /** + * Returns whether or not this GameObject's orientation is rotated {@link Direction#WEST} or {@link Direction#EAST}. + * + * @return {@code true} iff this GameObject's orientation is rotated. + */ + public boolean isRotated() { + int orientation = getOrientation(); + int type = getType(); + Direction direction = Direction.WNES[orientation]; + + if (type == TRIANGULAR_CORNER.getValue() || type == RECTANGULAR_CORNER.getValue()) { + direction = Direction.WNES_DIAGONAL[orientation]; + } + + return direction == Direction.NORTH || direction == Direction.SOUTH + || direction == Direction.NORTH_WEST || direction == Direction.SOUTH_EAST; } @Override diff --git a/game/src/test/java/org/apollo/game/model/area/collision/CollisionManagerTests.java b/game/src/test/java/org/apollo/game/model/area/collision/CollisionManagerTests.java index d0f52897..056793e4 100644 --- a/game/src/test/java/org/apollo/game/model/area/collision/CollisionManagerTests.java +++ b/game/src/test/java/org/apollo/game/model/area/collision/CollisionManagerTests.java @@ -85,9 +85,10 @@ public final class CollisionManagerTests { assertUntraversable(collisionManager, back, Direction.SOUTH_EAST); } + /** - * Tests that a corner wall is untraversable from the sides that it blocks. Corners are much like walls, with - * the only difference being their orientation. Instead of {@link Direction#WNES}, they have diagonal directions. + * Tests that a corner triangular wall is untraversable from the sides that it blocks. Corners are much like walls, + * with the only difference being their orientation. Instead of {@link Direction#WNES}, they have diagonal directions. * With a corner wall at (0, 1) facing to the north-east we end up with a grid looking like this: *

*

@@ -121,6 +122,42 @@ public final class CollisionManagerTests {
 		assertUntraversable(collisionManager, back, Direction.SOUTH_WEST);
 	}
 
+	/**
+	 * Tests that a corner rectangle wall is untraversable from the sides that it blocks.  Corners are much like walls,
+	 * with the only difference being their orientation.  Instead of {@link Direction#WNES}, they have diagonal directions.
+	 * With a corner wall at (0, 1) facing to the north-east we end up with a grid looking like this:
+	 * 

+ *

+	 * (0,2) |---------|---------|
+	 *       |         |         |
+	 *       |         |         |
+	 *       |         |xxx      |
+	 * (0,1) |---------|---------|
+	 *       |      xxx|         |
+	 *       |         |         |
+	 *       |         |         |
+	 * (0,0) |---------|---------|
+	 * 	   (1,0)     (2,0)     (3,0)
+	 * 
+ *

+ * Where you can walk north and east through the tile the corner occupies, as well as south and west through the + * adjacent tile, but not north-east or south-west. + */ + @Test + public void rectangleWall() { + Position front = new Position(0, 1, 0); + Position back = front.step(1, Direction.NORTH_EAST); + + CollisionManager collisionManager = createCollisionManager( + createMapObject(WALL, front, ObjectType.RECTANGULAR_CORNER, Direction.NORTH_EAST) + ); + + assertTraversable(collisionManager, front, Direction.NORTH, Direction.EAST); + assertUntraversable(collisionManager, front, Direction.NORTH_EAST); + assertTraversable(collisionManager, back, Direction.SOUTH, Direction.WEST); + assertUntraversable(collisionManager, back, Direction.SOUTH_WEST); + } + /** * Tests that the tiles occupied by a 2x2 square object are not traversable. When an interactable object is added * to a collision update, all tiles spanning its with and length from its origin position will be marked as completely