diff --git a/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt b/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt index 61ac1b029..ee6e3f1b8 100644 --- a/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt +++ b/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt @@ -5,24 +5,34 @@ import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.node.entity.player.link.TeleportManager import core.game.node.item.Item +import core.game.node.entity.player.Player +import core.game.world.repository.Repository class HouseTeleTabOptionListener : InteractionListener { override fun defineListeners() { val homeTabID = 8013 on(homeTabID, IntType.ITEM, "break") {player, node -> - var hasHouse = player.houseManager.location.exitLocation != null - if (!hasHouse) { - sendMessage( player, "You must have a house to teleport to before attempting that.") - return@on false + //Snowscape: teleport to the last house you entered, if possible + var owner: Player + val lastHouseOwner = Repository.getPlayerByName(player.getAttribute("lasthouseentered", null)) + if (lastHouseOwner != null && !lastHouseOwner.getHouseManager().isLocked()) { + owner = lastHouseOwner + } else { + var hasHouse = player.houseManager.location.exitLocation != null + if (!hasHouse) { + sendMessage( player, "You must have a house to teleport to before attempting that.") + return@on false + } + owner = player } closeInterface(player) lock(player, 5) if (inInventory(player, node.id)) { - player.houseManager.preEnter(player, false) - val location = player.houseManager.getEnterLocation() + owner.houseManager.preEnter(player, false) + val location = owner.houseManager.getEnterLocation() if (teleport(player, location, TeleportManager.TeleportType.TELETABS)) { removeItem(player, Item(node.id, 1)) - player.houseManager.postEnter(player, false) + owner.houseManager.postEnter(player, false) } } return@on true diff --git a/Server/src/main/content/global/skill/construction/HouseManager.java b/Server/src/main/content/global/skill/construction/HouseManager.java index 01a37f377..65ee6c3d9 100644 --- a/Server/src/main/content/global/skill/construction/HouseManager.java +++ b/Server/src/main/content/global/skill/construction/HouseManager.java @@ -101,6 +101,9 @@ public final class HouseManager { public void parse(JSONObject data){ location = HouseLocation.values()[Integer.parseInt( data.get("location").toString())]; style = HousingStyle.values()[Integer.parseInt( data.get("style").toString())]; + if (data.get("locked") != null) { + locked = true; + } Object servRaw = data.get("servant"); if(servRaw != null){ servant = Servant.parse((JSONObject) servRaw); @@ -225,7 +228,9 @@ public final class HouseManager { */ public void toggleBuildingMode(Player player, boolean enable) { if (!isInHouse(player)) { - player.getPacketDispatch().sendMessage("Building mode really only helps if you're in a house."); + //player.getPacketDispatch().sendMessage("Building mode really only helps if you're in a house."); + setLocked(enable); + player.sendMessage("Your house is now "+(player.getHouseManager().isLocked() ? "locked." : "unlocked." )); return; } if (buildingMode != enable) { diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index ccd426c19..33f875362 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -92,7 +92,9 @@ public final class HouseZone extends MapZone { if (e instanceof Player) { Player p = (Player) e; // The below tears down the house if the owner was the one who left - if (house == p.getHouseManager()) { + //if (house == p.getHouseManager()) { + // Snowscape: tear down the house when the last person leaves, allowing guests to stay in the house without the owner. + if (!house.getHouseRegion().isViewed() && (!house.hasDungeon() || !house.getDungeonRegion().isViewed())) { house.expelGuests(p); int toRemove = previousRegion; int dungRemove = previousDungeon; diff --git a/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java b/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java index 23d951dac..23d9621a2 100644 --- a/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java +++ b/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java @@ -8,6 +8,7 @@ import core.game.dialogue.DialoguePlugin; import core.game.interaction.OptionHandler; import core.game.node.Node; import core.game.node.entity.player.Player; +import core.game.node.entity.skill.Skills; import core.game.node.scenery.Scenery; import core.plugin.Initializable; import core.plugin.Plugin; @@ -33,6 +34,7 @@ public final class PortalOptionPlugin extends OptionHandler { SceneryDefinition.forId(13405).getHandlers().put("option:lock", this); SceneryDefinition.forId(13405).getHandlers().put("option:enter", this); ClassScanner.definePlugin(new PortalDialogue()); + ClassScanner.definePlugin(new PortalExitDialogue()); return this; } @@ -40,7 +42,8 @@ public final class PortalOptionPlugin extends OptionHandler { public boolean handle(Player player, Node node, String option) { Scenery object = node.asScenery(); if (object.getId() == 13405 && option.equals("enter")) { - HouseManager.leave(player); + player.getDialogueInterpreter().open("houseExitDialogue"); + //HouseManager.leave(player); return true; } if (option.equals("lock")) { @@ -111,11 +114,14 @@ public final class PortalOptionPlugin extends OptionHandler { break; } //If the Player has a house, but does not have their house moved to the portal they are interacting with + /* Snowscape: allow entering house from anywhere if (player.getHouseManager().getLocation().getPortalId() != player.getAttribute("con:portal", -1)) { player.getPacketDispatch().sendMessage("Your house is in " + player.getHouseManager().getLocation().getName() + "."); player.sendMessage("Speak with an estate agent to change your house location."); break; } + */ + player.removeAttribute("lasthouseentered"); player.getHouseManager().enter(player, buttonId == 2); break; case 3: @@ -134,10 +140,12 @@ public final class PortalOptionPlugin extends OptionHandler { player.getPacketDispatch().sendMessage("You aren't a friend of yourself!"); return Unit.INSTANCE; } + /* Snowscape: allow entering house if host is not home. if (!p.getHouseManager().isLoaded()) { player.getPacketDispatch().sendMessage("This player is not at home right now."); return Unit.INSTANCE; } + */ if (p.getHouseManager().isBuildingMode()) { player.getPacketDispatch().sendMessage("This player is in building mode."); return Unit.INSTANCE; @@ -146,6 +154,7 @@ public final class PortalOptionPlugin extends OptionHandler { player.getPacketDispatch().sendMessage("The other player has locked their house."); return Unit.INSTANCE; } + player.setAttribute("/save:lasthouseentered", (String) value); p.setAttribute("poh_owner", (String) value); p.getHouseManager().enter(player, false); return Unit.INSTANCE; @@ -162,4 +171,114 @@ public final class PortalOptionPlugin extends OptionHandler { return new int[] { DialogueInterpreter.getDialogueKey("con:portal") }; } } + + + + /** + * Snowscape: select destination via dialogue when leaving the house + * + */ + @PluginManifest(type= PluginType.DIALOGUE) + private class PortalExitDialogue extends DialoguePlugin { + + /** + * Constructs a new {@code PortalExitDialogue} {@code Object} + */ + public PortalExitDialogue() { + + } + + /** + * Constructs a new {@code PortalExitDialogue} {@code Object} + * @param player The player. + */ + public PortalExitDialogue(Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new PortalExitDialogue(player); + } + + @Override + public boolean open(Object... args) { + options("Leave house (home location)", "Rimmington", "Taverly", "Pollnivneach", "Next Page"); + stage = 1; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 1: + switch (buttonId) { + case 1: + HouseManager.leave(player); + end(); + break; + case 2: + attemptHouseExit(HouseLocation.RIMMINGTON); + end(); + break; + case 3: + attemptHouseExit(HouseLocation.TAVERLY); + end(); + break; + case 4: + attemptHouseExit(HouseLocation.POLLNIVNEACH); + end(); + break; + case 5: + options("Rellekka", "Brimhaven","Yanille", "Cancel"); + stage = 2; + break; + } + break; + case 2: + switch (buttonId) { + case 1: + attemptHouseExit(HouseLocation.RELLEKKA); + end(); + break; + case 2: + attemptHouseExit(HouseLocation.BRIMHAVEN); + end(); + break; + case 3: + attemptHouseExit(HouseLocation.YANILLE); + end(); + break; + case 4: + end(); + break; + } + } + return true; + } + + @Override + public int[] getIds() { + return new int[] { DialogueInterpreter.getDialogueKey("houseExitDialogue") }; + } + + public void attemptHouseExit(HouseLocation targetLocation){ + int level = 0; + String message = null; + if (player.getHouseManager().isInHouse(player)) { + level = getStatLevel(player, Skills.CONSTRUCTION); + message = "You need "; + } else { + level = getStatLevel(Repository.getPlayerByName(player.getAttribute("lasthouseentered", null)), Skills.CONSTRUCTION); + message = "The house owner needs "; + } + + if (targetLocation.getLevelRequirement() <= level){ + //player.animate(Animation.RESET); + player.getProperties().setTeleportLocation(targetLocation.getExitLocation()); + } else { + player.sendMessage(message + targetLocation.getLevelRequirement() + " Construction to for you to teleport to " + targetLocation.getName() + "."); + } + } + } } \ No newline at end of file diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 16c7f8fbe..6b96e386a 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -33,6 +33,7 @@ import org.rs09.consts.Scenery import org.rs09.consts.Sounds import core.game.system.task.Pulse +import core.game.world.repository.Repository class ModernListeners : SpellListener("modern"){ override fun defineListeners() { @@ -370,17 +371,26 @@ class ModernListeners : SpellListener("modern"){ player.sendMessage("A magical force prevents you from teleporting.") return } - val hasHouse = player.houseManager.location.exitLocation != null - if(!hasHouse){ - player.sendMessage("You do not have a house you can teleport to.") - return + + //Snowscape: teleport to the last house you entered, if possible + var houseOwner: Player + val lastHouseOwner = Repository.getPlayerByName(player.getAttribute("lasthouseentered", null)) + if (lastHouseOwner != null && !lastHouseOwner.getHouseManager().isLocked()) { + houseOwner = lastHouseOwner + } else { + val hasHouse = player.houseManager.location.exitLocation != null + if(!hasHouse){ + player.sendMessage("You do not have a house you can teleport to.") + return + } + houseOwner = player } - player.houseManager.preEnter(player, false) + houseOwner.houseManager.preEnter(player, false) val teleType = TeleportManager.TeleportType.NORMAL - val loc = player.houseManager.getEnterLocation() + val loc = houseOwner.houseManager.getEnterLocation() player.teleporter.send(loc, teleType) - player.houseManager.postEnter(player, false) //this actually runs when the teleport is SUBMITTED rather than EXECUTED, but this is fine + houseOwner.houseManager.postEnter(player, false) //this actually runs when the teleport is SUBMITTED rather than EXECUTED, but this is fine removeRunes(player) addXP(player,30.0) setDelay(player,true) diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 52c286223..436e83475 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -378,6 +378,7 @@ public class Player extends Entity { interfaceManager.closeSingleTab(); super.clear(); getZoneMonitor().clear(); + houseManager.expelGuests(this); HouseManager.leave(this); UpdateSequence.getRenderablePlayers().remove(this); sendLogoutEvents(); diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 2709ae12a..56d018d9a 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -191,6 +191,7 @@ class PlayerSaver (val player: Player){ fun saveHouseData(root: JSONObject){ val manager = player.houseManager val houseData = JSONObject() + if (manager.isLocked) houseData.put("locked", true) houseData.put("location",manager.location.ordinal.toString()) houseData.put("style",manager.style.ordinal.toString()) if(manager.hasServant()){