Fixed construction door and wall placement

Fixed the bug where some hotspots were still visible even in non-building mode
This commit is contained in:
Player Name 2024-07-13 04:37:04 +00:00 committed by Ryan
parent 81495ab8a8
commit 21a07841f6
3 changed files with 104 additions and 80 deletions

View file

@ -1,9 +1,4 @@
package content.global.skill.construction; package content.global.skill.construction;
//import org.arios.game.content.global.DeadmanTimedAction;
//import org.arios.game.node.entity.player.info.login.SavingModule;
import core.api.regionspec.RegionSpecification; import core.api.regionspec.RegionSpecification;
import core.api.regionspec.contracts.FillChunkContract; import core.api.regionspec.contracts.FillChunkContract;
import core.game.dialogue.FacialExpression; import core.game.dialogue.FacialExpression;
@ -17,12 +12,10 @@ import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder; import core.game.world.map.zone.ZoneBuilder;
import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Animation;
import core.tools.Log; import core.tools.Log;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import core.tools.SystemLogger;
import core.game.world.GameWorld; import core.game.world.GameWorld;
import org.rs09.consts.Sounds; import org.rs09.consts.Sounds;

View file

@ -2,9 +2,13 @@ package content.global.skill.construction;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.scenery.Constructed;
import core.game.node.scenery.Scenery; import core.game.node.scenery.Scenery;
import core.game.node.scenery.SceneryBuilder; import core.game.node.scenery.SceneryBuilder;
import core.game.world.map.*; import core.game.world.map.*;
import core.tools.Log;
import static core.api.ContentAPIKt.log;
/** /**
* Represents a room. * Represents a room.
@ -93,7 +97,7 @@ public final class Room {
Region.load(region, true); Region.load(region, true);
chunk = region.getPlanes()[style.getPlane()].getRegionChunk(properties.getChunkX(), properties.getChunkY()); chunk = region.getPlanes()[style.getPlane()].getRegionChunk(properties.getChunkX(), properties.getChunkY());
} }
/** /**
* Gets the hotspot object for the given hotspot type. * Gets the hotspot object for the given hotspot type.
* @param hotspot The hotspot type. * @param hotspot The hotspot type.
@ -154,6 +158,7 @@ public final class Room {
chunk.rotate(rotation); chunk.rotate(rotation);
} }
if (!house.isBuildingMode()) { if (!house.isBuildingMode()) {
placeDoors(housePlane, house, chunk);
removeHotspots(housePlane, house, chunk); removeHotspots(housePlane, house, chunk);
} }
} }
@ -165,17 +170,16 @@ public final class Room {
* @param chunk The region chunk used. * @param chunk The region chunk used.
*/ */
private void removeHotspots(int housePlane, HouseManager house, BuildRegionChunk chunk) { private void removeHotspots(int housePlane, HouseManager house, BuildRegionChunk chunk) {
for (int i = 0; i < BuildRegionChunk.ARRAY_SIZE; i++) { if (properties.isRoof()) return;
for (int x = 0; x < 8; x++) { for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) { for (int y = 0; y < 8; y++) {
for (int i = 0; i < BuildRegionChunk.ARRAY_SIZE; i++) {
Scenery object = chunk.get(x, y, i); Scenery object = chunk.get(x, y, i);
if (object != null && object.getDefinition().hasAction("Build")) { if (object != null) {
if (properties.isChamber() && BuildingUtils.isDoorHotspot(object)) { boolean isBuilt = object instanceof Constructed;
if (!placeDoors(house, chunk, object, housePlane, x, y, rotation)) { boolean isWall = object.getId() == 13065 || object.getId() == house.getStyle().getWallId();
SceneryBuilder.remove(object); boolean isDoor = object.getId() == house.getStyle().getDoorId() || object.getId() == house.getStyle().getSecondDoorId();
chunk.remove(object); if (!isBuilt && !isWall && !isDoor) {
}
} else {
SceneryBuilder.remove(object); SceneryBuilder.remove(object);
chunk.remove(object); chunk.remove(object);
} }
@ -186,65 +190,92 @@ public final class Room {
} }
/** /**
* Places the doors when needed. * Replaces the door hotspots with doors, walls, or passageways as needed.
* @param chunk The chunk. * TODO: it is believed that doors authentically remember their open/closed state for the usual duration (see e.g. https://www.youtube.com/watch?v=nRGux739h8s 1:00 vs 1:55), but this is not possible with the current HouseManager approach, which deallocates the instance as soon as the player leaves.
* @param object The object. * @param housePlane The room's plane in house.
* @param x The x-coordinate of the object. * @param house The house manager.
* @param y The y-coordinate of the object. * @param chunk The region chunk used.
*/ */
private boolean placeDoors(HouseManager house, BuildRegionChunk chunk, Scenery object, int z, int x, int y, Direction rotation) { private void placeDoors(int housePlane, HouseManager house, BuildRegionChunk chunk) {
int doorX; Room[][][] rooms = house.getRooms();
int doorY; int rx = chunk.getCurrentBase().getChunkX();
switch (rotation) { int ry = chunk.getCurrentBase().getChunkY();
case EAST: for (int i = 0; i < BuildRegionChunk.ARRAY_SIZE; i++) {
doorX = y; for (int x = 0; x < 8; x++) {
doorY = 7 - x; for (int y = 0; y < 8; y++) {
break; Scenery object = chunk.get(x, y, i);
case SOUTH: if (object != null && BuildingUtils.isDoorHotspot(object)) {
doorX = 7 - x; boolean edge = false;
doorY = 7 - y; Room otherRoom = null;
break; switch (object.getRotation()) {
case WEST: case 0: //east
doorX = 7 - y; edge = rx == 0;
doorY = x; otherRoom = edge ? null : rooms[housePlane][rx - 1][ry];
break; break;
default: case 1: //south
doorX = x; edge = ry == 7;
doorY = y; otherRoom = edge ? null : rooms[housePlane][rx][ry + 1];
break; break;
} case 2: //west
int chunkX = chunk.getCurrentBase().getChunkX(); edge = rx == 7;
int chunkY = chunk.getCurrentBase().getChunkY(); otherRoom = edge ? null : rooms[housePlane][rx + 1][ry];
boolean houseExit = true; break;
Room r; case 3: //north
if (doorX == 0 && chunkX > 0 && (r = house.getRooms()[z][chunkX - 1][chunkY]) != null && r.getProperties().isChamber()) { edge = ry == 0;
houseExit = false; otherRoom = edge ? null : rooms[housePlane][rx][ry - 1];
} break;
else if (doorX == 7 && chunkX < 7 && (r = house.getRooms()[z][chunkX + 1][chunkY]) != null && r.getProperties().isChamber()) { default:
houseExit = false; log(this.getClass(), Log.ERR, "Impossible rotation when placing doors??");
} }
else if (doorY == 0 && chunkY > 0 && (r = house.getRooms()[z][chunkX][chunkY - 1]) != null && r.getProperties().isChamber()) { int replaceId = getReplaceId(housePlane, house, this, edge, otherRoom, object);
houseExit = false; if (replaceId == -1) {
} continue;
else if (doorY == 7 && chunkY < 7 && (r = house.getRooms()[z][chunkX][chunkY + 1]) != null && r.getProperties().isChamber()) { }
houseExit = false; SceneryBuilder.replace(object, object.transform(replaceId));
} }
int replaceId = object.getId() % 2 != 0 ? house.getStyle().getDoorId() : house.getStyle().getSecondDoorId(); }
houseExit = false;
if (z != 0 && houseExit) {
r = house.getRooms()[z][chunkX][chunkY];
if (r.getProperties().isDungeon()) {
replaceId = 13065;
} else {
replaceId = house.getStyle().getWallId();
} }
} }
else if (!houseExit) {
return false;
}
return SceneryBuilder.replace(object, object.transform(replaceId, object.getRotation(), chunk.getCurrentBase().transform(x, y, 0)), true, true);
} }
/**
* Checks if rooms transition between inside<>outside the house and returns the appropriate door replacement.
* @param housePlane The room's plane in house.
* @param house The house manager.
* @param room The room the door is in.
* @param edge Whether the door is adjacent to an edge.
* @param otherRoom The room the door is adjacent to.
* @param object The door object itself.
*/
private int getReplaceId(int housePlane, HouseManager house, Room room, boolean edge, Room otherRoom, Scenery object) {
boolean thisOutside = !room.getProperties().isChamber();
if (edge && thisOutside) {
// No door or wall
return -1;
}
if (!edge) {
boolean otherOutside = otherRoom == null || !otherRoom.getProperties().isChamber();
if (thisOutside == otherOutside) {
// Free passage, unless the other room has a blind wall here
if (otherRoom == null) {
return -1;
}
boolean exit = otherRoom.getExits()[object.getRotation()];
if (exit) {
return -1;
}
}
if (thisOutside != otherOutside && housePlane == 0) {
// Door if we are the inside room only
if (thisOutside) {
return -1;
}
return object.getId() % 2 != 0 ? house.getStyle().getDoorId() : house.getStyle().getSecondDoorId();
}
}
return room.getProperties().isDungeon() ? 13065 : house.getStyle().getWallId();
}
/** /**
* Sets the decoration index for a group of object ids * Sets the decoration index for a group of object ids
* @param index The index. * @param index The index.
@ -392,4 +423,4 @@ public final class Room {
return rotation; return rotation;
} }
} }

View file

@ -1,13 +1,13 @@
package content.global.skill.construction.decoration package content.global.skill.construction.decoration
import content.global.skill.construction.BuildHotspot
import content.global.skill.construction.HousingStyle
import core.cache.def.impl.SceneryDefinition import core.cache.def.impl.SceneryDefinition
import core.game.global.action.DoorActionHandler import core.game.global.action.DoorActionHandler
import core.game.interaction.OptionHandler import core.game.interaction.OptionHandler
import core.game.node.Node import core.game.node.Node
import core.game.node.scenery.Scenery
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import content.global.skill.construction.BuildHotspot import core.game.node.scenery.Scenery
import content.global.skill.construction.HousingStyle
import core.plugin.Initializable import core.plugin.Initializable
import core.plugin.Plugin import core.plugin.Plugin
@ -38,11 +38,11 @@ class ConstructionDoorPlugin : OptionHandler() {
} }
override fun handle(player: Player, node: Node, option: String): Boolean { override fun handle(player: Player, node: Node, option: String): Boolean {
val `object` = node as Scenery
val second = DoorActionHandler.getSecondDoor(`object`, player)
when (option) { when (option) {
"pick-lock", "force" -> return false //TODO "pick-lock", "force" -> return false //TODO
} }
val `object` = node as Scenery
val second = DoorActionHandler.getSecondDoor(`object`, player)
DoorActionHandler.open(`object`, second, getReplaceId(`object`), getReplaceId(second), true, 500, false) DoorActionHandler.open(`object`, second, getReplaceId(`object`), getReplaceId(second), true, 500, false)
return true return true
} }
@ -80,4 +80,4 @@ class ConstructionDoorPlugin : OptionHandler() {
intArrayOf(13119, 13121) intArrayOf(13119, 13121)
) )
} }
} }