diff --git a/data/definitions/animations.yml b/data/definitions/animations.yml index bfb6d700e..cf6dbd6ee 100644 --- a/data/definitions/animations.yml +++ b/data/definitions/animations.yml @@ -1803,6 +1803,8 @@ restless_ghost_awakens: 4019 restless_ghost_warlock_spawn: 1552 climb_through_pipe: 10580 gnome_wall_run: 2922 +gnome_wall_fail: 11793 +gnome_wall_stand: 11794 gnome_run_up: 11784 gnome_jump: 11785 gnome_swing: 11789 diff --git a/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeAdvanced.kts b/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeAdvanced.kts index b9f935db1..0b134bb09 100644 --- a/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeAdvanced.kts +++ b/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeAdvanced.kts @@ -2,18 +2,17 @@ package world.gregs.voidps.world.activity.skill.agility.course import world.gregs.voidps.engine.client.message import world.gregs.voidps.engine.client.variable.start -import world.gregs.voidps.engine.entity.character.clearAnimation -import world.gregs.voidps.engine.entity.character.exactMove -import world.gregs.voidps.engine.entity.character.face +import world.gregs.voidps.engine.entity.character.* import world.gregs.voidps.engine.entity.character.move.tele import world.gregs.voidps.engine.entity.character.npc.NPCs import world.gregs.voidps.engine.entity.character.player.chat.ChatType import world.gregs.voidps.engine.entity.character.player.skill.Skill import world.gregs.voidps.engine.entity.character.player.skill.exp.exp +import world.gregs.voidps.engine.entity.character.player.skill.level.Level import world.gregs.voidps.engine.entity.character.player.skill.level.Level.has -import world.gregs.voidps.engine.entity.character.setAnimation import world.gregs.voidps.engine.entity.obj.objectApproach import world.gregs.voidps.engine.entity.obj.objectOperate +import world.gregs.voidps.engine.getPropertyOrNull import world.gregs.voidps.engine.inject import world.gregs.voidps.engine.queue.strongQueue import world.gregs.voidps.engine.suspend.approachRange @@ -22,11 +21,15 @@ import world.gregs.voidps.engine.suspend.pause import world.gregs.voidps.type.Direction import world.gregs.voidps.type.Tile import world.gregs.voidps.type.Zone +import world.gregs.voidps.world.interact.dialogue.Happy +import world.gregs.voidps.world.interact.dialogue.type.npc +import world.gregs.voidps.world.interact.entity.combat.hit.damage val npcs: NPCs by inject() objectOperate("Climb-up", "gnome_tree_branch_advanced") { - if (!player.has(Skill.Agility, 85)) { + if (!player.has(Skill.Agility, 85, message = true)) { + npc("gnome_trainer", "Sorry mate, you're not experienced enough to try that route. I suggest you carry on over the balancing rope instead.") return@objectOperate } npcs.gnomeTrainer("Terrorbirds could climb faster than that!", Zone(9263413)) @@ -47,14 +50,34 @@ objectApproach("Run-across", "gnome_sign_post_advanced") { // Pausing for 2 ticks to ensure we're in the correct spot. // arriveDelay() wouldn't work as objectApproach is called before Movement.tick where "last_movement" is set pause(2) + val disable = getPropertyOrNull("disableGnomeAdvancedCourseFailure").toBoolean() + val success = disable || Level.success(player.levels.get(Skill.Agility), -8..286) // failure rate 4.68-1.17% from 85-88 player.face(Direction.EAST) - player.setAnimation("gnome_wall_run") - player.start("input_delay", 4) + player.setAnimation("gnome_wall_${if (success) "run" else "fail"}") + player.start("input_delay", if (success) 4 else 20) player.strongQueue("wall-run", 1) { - player.exactMove(Tile(2484, 3418, 3), 60, Direction.EAST) - pause(2) - player.gnomeStage(5) - player.exp(Skill.Agility, 25.0) + if (!success) { + onCancel = { + player.tele(2484, 3418, 3) + } + player.exactMove(Tile(2480, 3418, 3), 30, Direction.EAST) + pause(6) + } + player.exactMove(Tile(2484, 3418, 3), if (success) 60 else 210, Direction.EAST) + if (success) { + pause(2) + player.exp(Skill.Agility, 25.0) + player.gnomeStage(5) + } else { + pause(10) + player.setAnimation("gnome_wall_stand") + pause(1) + player.damage((player.levels.get(Skill.Constitution) - 1).coerceAtMost(65)) + // Skip stage so lap doesn't count at end + if (getPropertyOrNull("disableGnomeAdvancedCourseFailLapSkip").toBoolean()) { + player.gnomeStage(5) + } + } player.clearAnimation() } } diff --git a/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStronghold.kts b/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStronghold.kts index 52eee92a5..cb9eca612 100644 --- a/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStronghold.kts +++ b/game/src/main/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStronghold.kts @@ -47,7 +47,7 @@ objectOperate("Climb-over", "gnome_obstacle_net") { player.start("input_delay", 2) player.strongQueue("netting", 2) { player.gnomeStage(2) - player.tele(player.tile.add(y = -2, level = 1)) + player.tele(player.tile.x.coerceIn(2471, 2476), 3424, 1) player.exp(Skill.Agility, 7.5) } } @@ -107,7 +107,8 @@ objectOperate("Climb-over", "gnome_obstacle_net_free_standing") { player.start("input_delay", 2) player.strongQueue("netting", 2) { player.gnomeStage(6) - player.tele(player.tile.add(y = 2)) + val direction = target.tile.delta(player.tile).toDirection().vertical() + player.tele(player.tile.add(direction.delta).add(direction.delta)) player.exp(Skill.Agility, 7.5) } } diff --git a/game/src/main/resources/game.properties b/game/src/main/resources/game.properties index 07ee9f8f6..4f95651bb 100644 --- a/game/src/main/resources/game.properties +++ b/game/src/main/resources/game.properties @@ -21,6 +21,9 @@ showSoak=true damageSoak=true # Events shootingStars=true +# Content +disableGnomeAdvancedCourseFailure=false +disableGnomeAdvancedCourseFailLapSkip=false # Files fileServer=true ## Storage diff --git a/game/src/test/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStrongholdTest.kt b/game/src/test/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStrongholdTest.kt index cfb5ae1fa..d07a2c1e2 100644 --- a/game/src/test/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStrongholdTest.kt +++ b/game/src/test/kotlin/world/gregs/voidps/world/activity/skill/agility/course/GnomeStrongholdTest.kt @@ -80,6 +80,18 @@ internal class GnomeStrongholdTest : WorldTest() { assertEquals(7.5, player.experience.get(Skill.Agility)) } + @Test + fun `Climb over netting backwards`() { + val player = createPlayer("agile", Tile(2484, 3427)) + val net = objects[Tile(2483, 3426), "gnome_obstacle_net_free_standing"]!! + + player.objectOption(net, "Climb-over") + tick(3) + + assertEquals(Tile(2484, 3425), player.tile) + assertEquals(7.5, player.experience.get(Skill.Agility)) + } + @Test fun `Climb through pipe`() { val player = createPlayer("agile", Tile(2488, 3431)) diff --git a/game/src/test/resources/test.properties b/game/src/test/resources/test.properties index 92b248e86..cbf0098ae 100644 --- a/game/src/test/resources/test.properties +++ b/game/src/test/resources/test.properties @@ -56,4 +56,6 @@ eventBufferLimit=25 randomWalk=false members=true characterCollision=true -loadUnusedObjects=true \ No newline at end of file +loadUnusedObjects=true +disableGnomeAdvancedCourseFailure=true +disableGnomeAdvancedCourseFailLapSkip=true