2018-07-06 15:30:00 +02:00
|
|
|
package com.eu.habbo.habbohotel.rooms;
|
|
|
|
|
|
|
|
import com.eu.habbo.Emulator;
|
2019-05-04 12:43:41 +02:00
|
|
|
import com.eu.habbo.habbohotel.bots.Bot;
|
|
|
|
import com.eu.habbo.habbohotel.pets.Pet;
|
|
|
|
import com.eu.habbo.habbohotel.users.Habbo;
|
2018-07-06 15:30:00 +02:00
|
|
|
import gnu.trove.set.hash.THashSet;
|
|
|
|
|
|
|
|
import java.awt.*;
|
|
|
|
import java.sql.ResultSet;
|
|
|
|
import java.sql.SQLException;
|
2019-03-18 02:22:00 +01:00
|
|
|
import java.util.*;
|
2018-07-06 15:30:00 +02:00
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
public class RoomLayout
|
|
|
|
{
|
|
|
|
public static double MAXIMUM_STEP_HEIGHT = 1.1;
|
|
|
|
public static boolean ALLOW_FALLING = true;
|
|
|
|
protected static final int BASICMOVEMENTCOST = 10;
|
|
|
|
protected static final int DIAGONALMOVEMENTCOST = 14;
|
|
|
|
|
|
|
|
public boolean CANMOVEDIAGONALY = true;
|
|
|
|
private String name;
|
|
|
|
private short doorX;
|
|
|
|
private short doorY;
|
|
|
|
private short doorZ;
|
|
|
|
private int doorDirection;
|
|
|
|
private String heightmap;
|
|
|
|
private int mapSize;
|
|
|
|
private int mapSizeX;
|
|
|
|
private int mapSizeY;
|
|
|
|
private RoomTile[][] roomTiles;
|
|
|
|
private RoomTile doorTile;
|
|
|
|
private Room room;
|
|
|
|
|
|
|
|
public RoomLayout(ResultSet set, Room room) throws SQLException
|
|
|
|
{
|
|
|
|
this.room = room;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
this.name = set.getString("name");
|
|
|
|
this.doorX = set.getShort("door_x");
|
|
|
|
this.doorY = set.getShort("door_y");
|
|
|
|
|
|
|
|
this.doorDirection = set.getInt("door_dir");
|
|
|
|
this.heightmap = set.getString("heightmap");
|
|
|
|
|
|
|
|
this.parse();
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
Emulator.getLogging().logErrorLine(e);
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void parse()
|
|
|
|
{
|
|
|
|
String[] modelTemp = this.heightmap.replace("\n", "").split(Character.toString('\r'));
|
|
|
|
|
|
|
|
this.mapSize = 0;
|
|
|
|
this.mapSizeX = modelTemp[0].length();
|
|
|
|
this.mapSizeY = modelTemp.length;
|
|
|
|
this.roomTiles = new RoomTile[this.mapSizeX][this.mapSizeY];
|
|
|
|
|
|
|
|
for (short y = 0; y < this.mapSizeY; y++)
|
|
|
|
{
|
|
|
|
if(modelTemp[y].isEmpty() || modelTemp[y].equalsIgnoreCase("\r"))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (short x = 0; x < this.mapSizeX; x++)
|
|
|
|
{
|
|
|
|
if(modelTemp[y].length() != this.mapSizeX)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
String square = modelTemp[y].substring(x, x + 1).trim().toLowerCase();
|
|
|
|
RoomTileState state = RoomTileState.OPEN;
|
|
|
|
short height = 0;
|
|
|
|
if (square.equalsIgnoreCase("x"))
|
|
|
|
{
|
2018-11-17 14:28:00 +01:00
|
|
|
state = RoomTileState.INVALID;
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (square.isEmpty()) {
|
|
|
|
height = 0;
|
|
|
|
}
|
|
|
|
else if (Emulator.isNumeric(square))
|
|
|
|
{
|
|
|
|
height = Short.parseShort(square);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
height = (short) (10 + "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(square.toUpperCase()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.mapSize += 1;
|
|
|
|
|
2018-11-17 14:28:00 +01:00
|
|
|
this.roomTiles[x][y] = new RoomTile(x, y, height, state, true);
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.doorTile = this.roomTiles[this.doorX][this.doorY];
|
|
|
|
|
|
|
|
if (this.doorTile != null)
|
|
|
|
{
|
2018-11-17 14:28:00 +01:00
|
|
|
this.doorTile.setAllowStack(false);
|
2018-07-06 15:30:00 +02:00
|
|
|
RoomTile doorFrontTile = this.getTileInFront(this.doorTile, this.doorDirection);
|
|
|
|
|
|
|
|
if (doorFrontTile != null && this.tileExists(doorFrontTile.x, doorFrontTile.y))
|
|
|
|
{
|
2018-11-17 14:28:00 +01:00
|
|
|
if (this.roomTiles[doorFrontTile.x][doorFrontTile.y].state != RoomTileState.INVALID)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
|
|
|
if (this.doorZ != this.roomTiles[doorFrontTile.x][doorFrontTile.y].z || this.roomTiles[this.doorX][this.doorY].state != this.roomTiles[doorFrontTile.x][doorFrontTile.y].state)
|
|
|
|
{
|
|
|
|
this.doorZ = this.roomTiles[doorFrontTile.x][doorFrontTile.y].z;
|
|
|
|
this.roomTiles[this.doorX][this.doorY].state = RoomTileState.OPEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getName()
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
return this.name;
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public short getDoorX()
|
|
|
|
{
|
|
|
|
return this.doorX;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDoorX(short doorX)
|
|
|
|
{
|
|
|
|
this.doorX = doorX;
|
|
|
|
}
|
|
|
|
|
|
|
|
public short getDoorY()
|
|
|
|
{
|
|
|
|
return this.doorY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDoorY(short doorY)
|
|
|
|
{
|
|
|
|
this.doorY = doorY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getDoorZ()
|
|
|
|
{
|
|
|
|
return this.doorZ;
|
|
|
|
}
|
|
|
|
|
|
|
|
public RoomTile getDoorTile()
|
|
|
|
{
|
|
|
|
return this.doorTile;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getDoorDirection()
|
|
|
|
{
|
|
|
|
return this.doorDirection;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDoorDirection(int doorDirection)
|
|
|
|
{
|
|
|
|
this.doorDirection = doorDirection;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setHeightmap(String heightMap)
|
|
|
|
{
|
|
|
|
this.heightmap = heightMap;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getHeightmap()
|
|
|
|
{
|
|
|
|
return this.heightmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getMapSize()
|
|
|
|
{
|
|
|
|
return this.mapSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getMapSizeX()
|
|
|
|
{
|
|
|
|
return this.mapSizeX;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getMapSizeY()
|
|
|
|
{
|
|
|
|
return this.mapSizeY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public short getHeightAtSquare(int x, int y)
|
|
|
|
{
|
|
|
|
if(x < 0 ||
|
|
|
|
y < 0 ||
|
|
|
|
x >= this.getMapSizeX() ||
|
|
|
|
y >= this.getMapSizeY())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return this.roomTiles[x][y].z;
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getStackHeightAtSquare(int x, int y)
|
|
|
|
{
|
|
|
|
if(x < 0 ||
|
|
|
|
y < 0 ||
|
|
|
|
x >= this.getMapSizeX() ||
|
|
|
|
y >= this.getMapSizeY())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return this.roomTiles[x][y].getStackHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getRelativeHeightAtSquare(int x, int y)
|
|
|
|
{
|
|
|
|
if(x < 0 ||
|
|
|
|
y < 0 ||
|
|
|
|
x >= this.getMapSizeX() ||
|
|
|
|
y >= this.getMapSizeY())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return this.roomTiles[x][y].relativeHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
public RoomTile getTile(short x, short y)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
if (this.tileExists(x, y))
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
|
|
|
return this.roomTiles[x][y];
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean tileExists(short x, short y)
|
|
|
|
{
|
|
|
|
return !(x < 0 || y < 0 || x >= this.getMapSizeX() || y >= this.getMapSizeY());
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean tileWalkable(short x, short y)
|
|
|
|
{
|
|
|
|
return this.tileExists(x, y) && this.roomTiles[x][y].state == RoomTileState.OPEN && this.roomTiles[x][y].isWalkable();
|
|
|
|
}
|
|
|
|
|
2018-12-22 11:39:00 +01:00
|
|
|
public boolean isVoidTile(short x, short y)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
if (!this.tileExists(x, y)) return true;
|
2018-12-22 11:39:00 +01:00
|
|
|
return this.roomTiles[x][y].state == RoomTileState.INVALID;
|
|
|
|
}
|
|
|
|
|
2018-07-06 15:30:00 +02:00
|
|
|
public RoomTileState getStateAt(short x, short y)
|
|
|
|
{
|
|
|
|
return this.roomTiles[x][y].state;
|
|
|
|
}
|
|
|
|
public String getRelativeMap()
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
return this.heightmap.replace("\r\n", "\r");
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
|
2018-11-17 14:28:00 +01:00
|
|
|
public final Deque<RoomTile> findPath(RoomTile oldTile, RoomTile newTile, RoomTile goalLocation)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
LinkedList<RoomTile> openList = new LinkedList<>();
|
2018-07-06 15:30:00 +02:00
|
|
|
try
|
|
|
|
{
|
2018-11-17 14:28:00 +01:00
|
|
|
if (this.room == null || !this.room.isLoaded() || oldTile == null || newTile == null || oldTile.equals(newTile) || newTile.state == RoomTileState.INVALID)
|
2018-07-06 15:30:00 +02:00
|
|
|
return openList;
|
|
|
|
|
2019-03-18 02:22:00 +01:00
|
|
|
List<RoomTile> closedList = new LinkedList<>();
|
2018-07-06 15:30:00 +02:00
|
|
|
|
|
|
|
openList.add(oldTile.copy());
|
|
|
|
|
2019-05-04 12:43:41 +02:00
|
|
|
List<RoomTile> unitsAt = new ArrayList<>();
|
|
|
|
|
|
|
|
for(Bot b : this.room.getCurrentBots().valueCollection()) {
|
|
|
|
unitsAt.add(b.getRoomUnit().getCurrentLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
for(Habbo b : this.room.getCurrentHabbos().values()) {
|
|
|
|
unitsAt.add(b.getRoomUnit().getCurrentLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
for(Pet b : this.room.getCurrentPets().valueCollection()) {
|
|
|
|
unitsAt.add(b.getRoomUnit().getCurrentLocation());
|
|
|
|
}
|
|
|
|
|
2018-07-06 15:30:00 +02:00
|
|
|
long startMillis = System.currentTimeMillis();
|
|
|
|
while (true)
|
|
|
|
{
|
2019-05-04 12:43:41 +02:00
|
|
|
if (System.currentTimeMillis() - startMillis > 50)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
|
|
|
return new LinkedList<>();
|
|
|
|
}
|
|
|
|
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile current = this.lowestFInOpen(openList);
|
2018-07-06 15:30:00 +02:00
|
|
|
openList.remove(current);
|
|
|
|
|
|
|
|
if ((current.x == newTile.x) && (current.y == newTile.y))
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
return this.calcPath(this.findTile(openList, oldTile.x, oldTile.y), current);
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
|
2019-03-18 02:22:00 +01:00
|
|
|
List<RoomTile> adjacentNodes = this.getAdjacent(openList, current, newTile);
|
2018-07-06 15:30:00 +02:00
|
|
|
|
|
|
|
for (RoomTile currentAdj : adjacentNodes)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
if (closedList.contains(currentAdj)) continue;
|
2018-07-06 15:30:00 +02:00
|
|
|
|
2018-11-17 14:28:00 +01:00
|
|
|
//If the tile is sitable or layable and its not our goal tile, we cannot walk over it.
|
2019-05-04 12:43:41 +02:00
|
|
|
if (!currentAdj.equals(goalLocation) && (currentAdj.state == RoomTileState.BLOCKED || currentAdj.state == RoomTileState.SIT || currentAdj.state == RoomTileState.LAY))
|
2018-11-17 14:28:00 +01:00
|
|
|
{
|
2019-04-22 01:42:00 +02:00
|
|
|
closedList.add(currentAdj);
|
|
|
|
openList.remove(currentAdj);
|
2018-07-06 15:30:00 +02:00
|
|
|
continue;
|
2018-11-17 14:28:00 +01:00
|
|
|
}
|
|
|
|
////if (!room.getLayout().tileWalkable((short) currentAdj.x, (short) currentAdj.y)) continue;
|
|
|
|
|
|
|
|
//Height difference.
|
|
|
|
double height = currentAdj.getStackHeight() - current.getStackHeight();
|
|
|
|
|
|
|
|
//If we are not allowed to fall and the height difference is bigger than the maximum stepheight, continue.
|
|
|
|
if (!ALLOW_FALLING && height < - MAXIMUM_STEP_HEIGHT) continue;
|
|
|
|
|
|
|
|
//If the step difference is bigger than the maximum step height, continue.
|
2019-05-04 12:43:41 +02:00
|
|
|
if (currentAdj.state == RoomTileState.OPEN && height > MAXIMUM_STEP_HEIGHT) continue;
|
2018-07-06 15:30:00 +02:00
|
|
|
|
2018-11-17 14:28:00 +01:00
|
|
|
//Check if the tile has habbos.
|
2019-05-04 12:43:41 +02:00
|
|
|
if (unitsAt.contains(currentAdj) && (!this.room.isAllowWalkthrough() || currentAdj.equals(goalLocation)))
|
2019-03-18 02:22:00 +01:00
|
|
|
{
|
|
|
|
closedList.add(currentAdj);
|
|
|
|
openList.remove(currentAdj);
|
|
|
|
continue;
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
|
|
|
|
//if (room.hasPetsAt(currentAdj.x, currentAdj.y)) continue;
|
|
|
|
|
2018-11-17 14:28:00 +01:00
|
|
|
if (!openList.contains(currentAdj))
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
|
|
|
currentAdj.setPrevious(current);
|
2019-03-18 02:22:00 +01:00
|
|
|
currentAdj.sethCosts(this.findTile(openList, newTile.x, newTile.y));
|
2018-07-06 15:30:00 +02:00
|
|
|
currentAdj.setgCosts(current);
|
|
|
|
openList.add(currentAdj);
|
|
|
|
}
|
|
|
|
else if (currentAdj.getgCosts() > currentAdj.calculategCosts(current))
|
|
|
|
{
|
|
|
|
currentAdj.setPrevious(current);
|
|
|
|
currentAdj.setgCosts(current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (openList.isEmpty())
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
return new LinkedList<>();
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(Exception e)
|
|
|
|
{
|
|
|
|
Emulator.getLogging().logErrorLine(e);
|
|
|
|
}
|
|
|
|
return new LinkedList<>();
|
|
|
|
}
|
|
|
|
|
|
|
|
private RoomTile findTile(List<RoomTile> tiles, short x, short y)
|
|
|
|
{
|
|
|
|
for (RoomTile tile : tiles)
|
|
|
|
{
|
|
|
|
if (x == tile.x && y == tile.y)
|
|
|
|
{
|
|
|
|
return tile;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RoomTile tile = this.getTile(x, y);
|
|
|
|
|
|
|
|
if (tile != null)
|
|
|
|
{
|
|
|
|
return tile.copy();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Deque<RoomTile> calcPath(RoomTile start, RoomTile goal)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
LinkedList<RoomTile> path = new LinkedList<>();
|
2018-07-06 15:30:00 +02:00
|
|
|
if (start == null)
|
|
|
|
return path;
|
|
|
|
|
|
|
|
RoomTile curr = goal;
|
|
|
|
while (curr != null)
|
|
|
|
{
|
2019-04-22 01:42:00 +02:00
|
|
|
path.addFirst(this.getTile(curr.x, curr.y));
|
2018-07-06 15:30:00 +02:00
|
|
|
curr = curr.getPrevious();
|
2019-03-18 02:22:00 +01:00
|
|
|
if ((curr != null) && (curr.equals(start))) {
|
2018-07-06 15:30:00 +02:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
private RoomTile lowestFInOpen(List<RoomTile> openList)
|
|
|
|
{
|
|
|
|
if(openList == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
RoomTile cheapest = openList.get(0);
|
|
|
|
for (RoomTile anOpenList : openList)
|
|
|
|
{
|
2019-05-05 06:21:02 +02:00
|
|
|
if (anOpenList.getfCosts() < cheapest.getfCosts())
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
|
|
|
cheapest = anOpenList;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return cheapest;
|
|
|
|
}
|
|
|
|
|
2018-12-22 11:39:00 +01:00
|
|
|
private List<RoomTile> getAdjacent(List<RoomTile> openList, RoomTile node, RoomTile nextTile)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
|
|
|
short x = node.x;
|
|
|
|
short y = node.y;
|
2018-09-28 21:25:00 +02:00
|
|
|
List<RoomTile> adj = new LinkedList<>();
|
2018-07-06 15:30:00 +02:00
|
|
|
if (x > 0)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, (short) (x - 1), y);
|
2018-11-17 14:28:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(false);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (x < this.mapSizeX)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, (short) (x + 1), y);
|
2018-11-17 14:28:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(false);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (y > 0)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, x, (short) (y - 1));
|
2018-11-17 14:28:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(false);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (y < this.mapSizeY)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, x, (short) (y + 1));
|
2018-11-17 14:28:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(false);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
2019-03-18 02:22:00 +01:00
|
|
|
if (this.CANMOVEDIAGONALY)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
|
|
|
if ((x < this.mapSizeX) && (y < this.mapSizeY))
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile offX = this.findTile(openList, (short) (x + 1), y);
|
|
|
|
RoomTile offY = this.findTile(openList, x, (short) (y+1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (offX != null && offY != null && (offX.isWalkable() || offY.isWalkable()))
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, (short) (x + 1), (short) (y + 1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
|
|
|
{
|
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(true);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((x > 0) && (y > 0))
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile offX = this.findTile(openList, (short) (x - 1), y);
|
|
|
|
RoomTile offY = this.findTile(openList, x, (short) (y - 1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (offX != null && offY != null && (offX.isWalkable() || offY.isWalkable()))
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, (short) (x - 1), (short) (y - 1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
|
|
|
{
|
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(true);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((x > 0) && (y < this.mapSizeY))
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile offX = this.findTile(openList, (short) (x - 1), y);
|
|
|
|
RoomTile offY = this.findTile(openList, x, (short) (y+1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (offX != null && offY != null && (offX.isWalkable() || offY.isWalkable()))
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, (short) (x - 1), (short) (y + 1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
|
|
|
{
|
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(true);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((x < this.mapSizeX) && (y > 0))
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile offX = this.findTile(openList, (short) (x + 1), y);
|
|
|
|
RoomTile offY = this.findTile(openList, x, (short) (y - 1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (offX != null && offY != null && (offX.isWalkable() || offY.isWalkable()))
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile temp = this.findTile(openList, (short) (x + 1), (short) (y - 1));
|
2018-12-22 11:39:00 +01:00
|
|
|
if (temp != null && temp.state != RoomTileState.BLOCKED && temp.state != RoomTileState.INVALID)
|
|
|
|
{
|
|
|
|
if (temp.state != RoomTileState.SIT || nextTile.getStackHeight() - node.getStackHeight() <= 2.0)
|
|
|
|
{
|
|
|
|
temp.isDiagonally(true);
|
|
|
|
if (!adj.contains(temp))
|
|
|
|
adj.add(temp);
|
|
|
|
}
|
|
|
|
}
|
2018-07-06 15:30:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return adj;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void moveDiagonally(boolean value)
|
|
|
|
{
|
|
|
|
this.CANMOVEDIAGONALY = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean squareInSquare(Rectangle outerSquare, Rectangle innerSquare)
|
|
|
|
{
|
|
|
|
if(outerSquare.x > innerSquare.x)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(outerSquare.y > innerSquare.y)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(outerSquare.x + outerSquare.width < innerSquare.x + innerSquare.width)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(outerSquare.y + outerSquare.height < innerSquare.y + innerSquare.height)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-09-28 21:25:00 +02:00
|
|
|
public static boolean tileInSquare(Rectangle square, RoomTile tile)
|
|
|
|
{
|
|
|
|
return (square.contains(tile.x, tile.y));
|
|
|
|
}
|
|
|
|
|
2018-07-06 15:30:00 +02:00
|
|
|
public static boolean pointInSquare(int x1, int y1, int x2, int y2, int pointX, int pointY)
|
|
|
|
{
|
|
|
|
return (pointX >= x1 && pointY >= y1) && (pointX <= x2 && pointY <= y2);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean tilesAdjecent(RoomTile one, RoomTile two)
|
|
|
|
{
|
|
|
|
return !(one == null || two == null) && !(Math.abs(one.x - two.x) > 1) && !(Math.abs(one.y - two.y) > 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
public RoomTile getTileInFront(RoomTile tile, int rotation)
|
|
|
|
{
|
|
|
|
return this.getTileInFront(tile, rotation, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public RoomTile getTileInFront(RoomTile tile, int rotation, int offset)
|
|
|
|
{
|
|
|
|
int offsetX = 0;
|
|
|
|
int offsetY = 0;
|
|
|
|
|
|
|
|
rotation = rotation % 8;
|
|
|
|
switch (rotation)
|
|
|
|
{
|
|
|
|
case 0: offsetY--; break;
|
|
|
|
case 1: offsetX++; offsetY--; break;
|
|
|
|
case 2: offsetX++; break;
|
|
|
|
case 3: offsetX++; offsetY++; break;
|
|
|
|
case 4: offsetY++; break;
|
|
|
|
case 5: offsetX--; offsetY++; break;
|
|
|
|
case 6: offsetX--; break;
|
|
|
|
case 7: offsetX--; offsetY--; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
short x = tile.x;
|
|
|
|
short y = tile.y;
|
|
|
|
|
|
|
|
for (int i = 0; i <= offset; i++)
|
|
|
|
{
|
|
|
|
x += offsetX;
|
|
|
|
y += offsetY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.getTile(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<RoomTile> getTilesInFront(RoomTile tile, int rotation, int amount)
|
|
|
|
{
|
|
|
|
List<RoomTile> tiles = new ArrayList<>(amount);
|
|
|
|
RoomTile previous = tile;
|
|
|
|
for (int i = 0; i < amount; i++)
|
|
|
|
{
|
2019-04-22 01:42:00 +02:00
|
|
|
RoomTile t = this.getTileInFront(previous, rotation, i);
|
2018-07-06 15:30:00 +02:00
|
|
|
|
|
|
|
if (t != null)
|
|
|
|
{
|
|
|
|
tiles.add(t);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<RoomTile> getTilesAround(RoomTile tile)
|
2019-03-18 02:22:00 +01:00
|
|
|
{
|
|
|
|
return getTilesAround(tile, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<RoomTile> getTilesAround(RoomTile tile, int directionOffset)
|
2018-07-06 15:30:00 +02:00
|
|
|
{
|
2018-09-28 21:25:00 +02:00
|
|
|
List<RoomTile> tiles = new ArrayList<>(8);
|
2018-07-06 15:30:00 +02:00
|
|
|
|
|
|
|
if (tile != null)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
2019-03-18 02:22:00 +01:00
|
|
|
RoomTile t = this.getTileInFront(tile, (i + directionOffset) % 8);
|
2018-07-06 15:30:00 +02:00
|
|
|
if (t != null)
|
|
|
|
{
|
|
|
|
tiles.add(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tiles;
|
|
|
|
}
|
|
|
|
|
2019-05-04 08:21:43 +02:00
|
|
|
public List<RoomTile> getWalkableTilesAround(RoomTile tile) {
|
|
|
|
return getWalkableTilesAround(tile, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<RoomTile> getWalkableTilesAround(RoomTile tile, int directionOffset) {
|
|
|
|
List<RoomTile> availableTiles = new ArrayList<>(this.getTilesAround(tile, directionOffset));
|
|
|
|
|
|
|
|
List<RoomTile> toRemove = new ArrayList<>();
|
|
|
|
|
|
|
|
for(RoomTile t : availableTiles) {
|
|
|
|
if(t == null || t.state != RoomTileState.OPEN || !t.isWalkable()) {
|
|
|
|
toRemove.add(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(RoomTile t : toRemove) {
|
|
|
|
availableTiles.remove(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
return availableTiles;
|
|
|
|
}
|
|
|
|
|
2018-07-06 15:30:00 +02:00
|
|
|
public static Rectangle getRectangle(int x, int y, int width, int length, int rotation)
|
|
|
|
{
|
|
|
|
rotation = (rotation % 8);
|
|
|
|
|
|
|
|
if(rotation == 2 || rotation == 6)
|
|
|
|
{
|
|
|
|
return new Rectangle(x, y, length, width);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Rectangle(x, y, width, length);
|
|
|
|
}
|
|
|
|
|
2019-05-03 05:08:27 +02:00
|
|
|
public boolean fitsOnMap(RoomTile tile, int width, int length, int rotation)
|
|
|
|
{
|
|
|
|
THashSet<RoomTile> pointList = new THashSet<>(width * length, 0.1f);
|
|
|
|
|
|
|
|
if (tile != null)
|
|
|
|
{
|
|
|
|
if (rotation == 0 || rotation == 4)
|
|
|
|
{
|
|
|
|
for (short i = tile.x; i <= (tile.x + (width - 1)); i++)
|
|
|
|
{
|
|
|
|
for (short j = tile.y; j <= (tile.y + (length - 1)); j++)
|
|
|
|
{
|
|
|
|
RoomTile t = this.getTile(i, j);
|
|
|
|
|
|
|
|
if (t == null || t.state == RoomTileState.INVALID)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rotation == 2 || rotation == 6)
|
|
|
|
{
|
|
|
|
for (short i = tile.x; i <= (tile.x + (length - 1)); i++)
|
|
|
|
{
|
|
|
|
for (short j = tile.y; j <= (tile.y + (width - 1)); j++)
|
|
|
|
{
|
|
|
|
RoomTile t = this.getTile(i, j);
|
|
|
|
|
|
|
|
if (t == null || t.state == RoomTileState.INVALID)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-07-06 15:30:00 +02:00
|
|
|
public THashSet<RoomTile> getTilesAt(RoomTile tile, int width, int length, int rotation)
|
|
|
|
{
|
2018-09-28 21:25:00 +02:00
|
|
|
THashSet<RoomTile> pointList = new THashSet<>(width * length, 0.1f);
|
2018-07-06 15:30:00 +02:00
|
|
|
|
|
|
|
if (tile != null)
|
|
|
|
{
|
|
|
|
if (rotation == 0 || rotation == 4)
|
|
|
|
{
|
|
|
|
for (short i = tile.x; i <= (tile.x + (width - 1)); i++)
|
|
|
|
{
|
|
|
|
for (short j = tile.y; j <= (tile.y + (length - 1)); j++)
|
|
|
|
{
|
|
|
|
RoomTile t = this.getTile(i, j);
|
|
|
|
|
|
|
|
if (t != null)
|
|
|
|
{
|
|
|
|
pointList.add(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rotation == 2 || rotation == 6)
|
|
|
|
{
|
|
|
|
for (short i = tile.x; i <= (tile.x + (length - 1)); i++)
|
|
|
|
{
|
|
|
|
for (short j = tile.y; j <= (tile.y + (width - 1)); j++)
|
|
|
|
{
|
|
|
|
RoomTile t = this.getTile(i, j);
|
|
|
|
|
|
|
|
if (t != null)
|
|
|
|
{
|
|
|
|
pointList.add(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pointList;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean tilesAdjecent(RoomTile tile, RoomTile comparator, int width, int length, int rotation)
|
|
|
|
{
|
|
|
|
Rectangle rectangle = getRectangle(comparator.x, comparator.y, width, length, rotation);
|
|
|
|
rectangle = new Rectangle(rectangle.x - 1, rectangle.y -1, rectangle.width + 2, rectangle.height + 2);
|
|
|
|
|
|
|
|
return rectangle.contains(tile.x, tile.y);
|
|
|
|
}
|
|
|
|
}
|