diff --git a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java index 73d02232e..cd48aff49 100644 --- a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java +++ b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java @@ -203,7 +203,7 @@ public final class ZoneMonitor { * @return {@code True} if so. */ public boolean teleport(int type, Node node) { - if (type != -1 && entity.isTeleBlocked()) { + if (type != -1 && entity.isTeleBlocked() && !canTeleportByGlory(type, node)) { if (entity.isPlayer()) { entity.asPlayer().sendMessage("A magical force has stopped you from teleporting."); } @@ -217,6 +217,34 @@ public final class ZoneMonitor { return true; } + /** + * Checks if a player can teleport with a glory in >= 1 <= 30 wilderness level + * @return {@code True} if so. + */ + private boolean canTeleportByGlory(int type, Node node) { + if (type != 1 || !node.asItem().getName().contains("Amulet of glory")) { + return false; + } + + if (entity.timers.getTimer("teleblock") != null) + return false; + + if (entity.getZoneMonitor().isRestricted(ZoneRestriction.TELEPORT)) { + return false; + } + + if (entity.getLocks().isTeleportLocked()) { + if (entity.isPlayer()) { + Player p = entity.asPlayer(); + if (p.getSkullManager().getLevel() >= 1 && p.getSkullManager().getLevel() <= 30) { + return true; + } + } + } + + return false; + } + /** * Checks if the death should start for an entity. * @param entity the entity. diff --git a/Server/src/test/kotlin/core/game/world/map/zone/ZoneMonitorTests.kt b/Server/src/test/kotlin/core/game/world/map/zone/ZoneMonitorTests.kt new file mode 100644 index 000000000..f0b99839c --- /dev/null +++ b/Server/src/test/kotlin/core/game/world/map/zone/ZoneMonitorTests.kt @@ -0,0 +1,94 @@ +package core.game.world.map.zone + +import MockPlayer +import core.api.hasTimerActive +import core.api.registerTimer +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.system.timer.impl.Teleblock +import core.game.world.map.Location +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class ZoneMonitorTests { + + val GLORIES = intArrayOf(1710, 1708, 1706, 1712) + + init { + TestUtils.preTestSetup() + } + + /** + * Evalutes success of glory teleport using all glory charged items + */ + fun teleportWithGlory(expected : Boolean, p : Player) { + for (id in GLORIES) { + val glory = Item(id, 1) + Assertions.assertEquals(expected, p.zoneMonitor.teleport(1, glory)) + } + } + + @Nested + inner class GloryTeleportSuccess { + + @Test + fun successOnLevel21Wilderness() { + TestUtils.getMockPlayer("").use {p -> + // level 21 wilderness + p.skullManager.level = 21; + p.location = (Location.create(3067, 3683, 0)) + Assertions.assertTrue(p.locks.isTeleportLocked) + teleportWithGlory(true, p) + } + } + + @Test + fun successOnLevel30Wilderness() { + TestUtils.getMockPlayer("").use {p -> + // level 30 wilderness + p.location = (Location.create(3069, 3755, 0)) + p.skullManager.level = 30; + Assertions.assertTrue(p.locks.isTeleportLocked) + teleportWithGlory(true, p) + } + } + + @Test + fun successOnNoRestrictions() { + TestUtils.getMockPlayer("").use {p -> + // lumbridge + p.location = (Location.create(3222, 3218, 0)) + Assertions.assertFalse(p.locks.isTeleportLocked) + Assertions.assertFalse(hasTimerActive(p, "teleblock")) + Assertions.assertFalse(p.zoneMonitor.isRestricted(ZoneRestriction.TELEPORT)) + teleportWithGlory(true, p) + } + } + + } + + @Nested + inner class GloryTeleportFailure { + + @Test + fun failOnTeleBlock() { + TestUtils.getMockPlayer("").use { p -> + registerTimer(p, Teleblock()) + Assertions.assertTrue(hasTimerActive(p, "teleblock")) + teleportWithGlory(false, p) + } + } + + @Test + fun failOnLock() { + TestUtils.getMockPlayer("").use { p -> + p.locks.lockTeleport(100000) + Assertions.assertTrue(p.locks.isTeleportLocked) + teleportWithGlory(false, p) + } + } + + } + +} \ No newline at end of file