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()){