diff --git a/data/definitions/npcs.yml b/data/definitions/npcs.yml index 34c2666ff..d2f932947 100644 --- a/data/definitions/npcs.yml +++ b/data/definitions/npcs.yml @@ -1855,11 +1855,13 @@ mage_of_zamorak_wilderness: id: 2257 faces: false race: human + wander_radius: 4 examine: "A disciple of Zamorak." mage_of_zamorak_varrock: id: 2260 faces: false race: human + wander_radius: 5 examine: "A disciple of Zamorak." abyssal_leech: id: 2263 diff --git a/data/spawns/npc-spawns.yml b/data/spawns/npc-spawns.yml index ffb6f3c65..dab4df533 100644 --- a/data/spawns/npc-spawns.yml +++ b/data/spawns/npc-spawns.yml @@ -2003,7 +2003,7 @@ - { id: dark_wizard_earth_2, x: 3224, y: 3370 } - { id: goblin_orange_hat_spear, x: 3259, y: 3338 } - { id: tarquin, x: 3203, y: 3344 } -- { id: mage_of_zamorak_varrock, x: 3260, y: 3385, members: true } +- { id: mage_of_zamorak_varrock, x: 3259, y: 3386, members: true } # 12853 - { id: ash_cleaner, x: 3250, y: 3429 } - { id: iffie, x: 3204, y: 3419 } diff --git a/game/src/test/kotlin/world/gregs/voidps/world/activity/quest/EnterTheAbyss.kt b/game/src/test/kotlin/world/gregs/voidps/world/activity/quest/EnterTheAbyss.kt new file mode 100644 index 000000000..06acce605 --- /dev/null +++ b/game/src/test/kotlin/world/gregs/voidps/world/activity/quest/EnterTheAbyss.kt @@ -0,0 +1,102 @@ +package world.gregs.voidps.world.activity.quest + +import org.junit.jupiter.api.Test +import world.gregs.voidps.FakeRandom +import world.gregs.voidps.engine.entity.character.move.tele +import world.gregs.voidps.engine.entity.character.player.Player +import world.gregs.voidps.engine.entity.character.player.skill.Skill +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.type.Tile +import world.gregs.voidps.type.setRandom +import world.gregs.voidps.world.script.WorldTest +import world.gregs.voidps.world.script.dialogueContinue +import world.gregs.voidps.world.script.dialogueOption +import world.gregs.voidps.world.script.npcOption +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +internal class EnterTheAbyss : WorldTest() { + + @Test + fun `Complete the mini-quest`() { + // Talk to the mage of zamorak in the wilderness + val player = createPlayer("quester", Tile(3107, 3556)) + player["rune_mysteries"] = "completed" + assertEquals("unstarted", player["enter_the_abyss", "unstarted"]) + + var mage = findNpc(player, "mage_of_zamorak_wilderness") + player.npcOption(mage, 0) // Talk-to + tick() + player.dialogueOption("continue") + assertEquals("started", player["enter_the_abyss", "unstarted"]) + player.dialogueOption("line2") + + // Talk to the mage of zamorak in varrock + player.tele(3258, 3386) + tick(1) + mage = findNpc(player, "mage_of_zamorak_varrock") + player.npcOption(mage, 0) // Talk-to + tick() + player.dialogueContinue(5) + assertTrue(player["enter_abyss_where_runes", false]) + player.dialogueOption("line1") // Where do you get your runes from + player.dialogueContinue(8) + player.dialogueOption("line2") // But I'm a loyal servant + player.dialogueContinue(8) + player.dialogueOption("line1") // I did it to steal their secrets + player.dialogueContinue(3) + assertTrue(player["enter_abyss_offer", false]) + player.dialogueOption("line1") // Deal + player.dialogueContinue(13) + assertTrue(player["enter_abyss_has_orb", false]) + assertEquals("scrying", player["enter_the_abyss", "unstarted"]) + + // Take the scrying orb to three saradomin wizards + player.tele(3253, 3401) + tick() + var wizard = findNpc(player, "aubury") + player.npcOption(wizard, 3) // Teleport + setRandom(object : FakeRandom() { + override fun nextInt(from: Int, until: Int): Int { + return when (from) { + 2880 -> 2911 + 4800 -> 4832 + else -> from + } + } + }) + tick(4) + assertTrue(player["scrying_orb_aubury", false]) + + player.tele(2681, 3324) + tick() + wizard = findNpc(player, "wizard_cromperty") + player.npcOption(wizard, 2) // Teleport + tick(4) + assertTrue(player["scrying_orb_wizard_cromperty", false]) + + player.tele(2409, 9815) + tick() + wizard = findNpc(player, "brimstail") + player.npcOption(wizard, 2) // Teleport + tick(4) + assertTrue(player["scrying_orb_brimstail", false]) + assertTrue(player.inventory.contains("scrying_orb_full")) + + // Return the scrying orb to the mage of zamorak + player.tele(3258, 3386) + tick(1) + player.npcOption(mage, 0) // Talk-to + tick() + player.dialogueContinue(2) + assertEquals("orb_inspect", player["enter_the_abyss", "unstarted"]) + player.dialogueContinue(3) + assertTrue(player["enter_abyss_taken_orb", false]) + player.dialogueContinue(11) + assertEquals("completed", player["enter_the_abyss", "unstarted"]) + assertEquals(1000.0, player.experience.get(Skill.Runecrafting)) + } + + private fun findNpc(player: Player, id: String) = npcs[player.tile.region.toLevel(player.tile.level)].first { it.id == id } + +} \ No newline at end of file diff --git a/game/src/test/kotlin/world/gregs/voidps/world/script/InstructionCalls.kt b/game/src/test/kotlin/world/gregs/voidps/world/script/InstructionCalls.kt index 05b973b79..f6c1d3d4a 100644 --- a/game/src/test/kotlin/world/gregs/voidps/world/script/InstructionCalls.kt +++ b/game/src/test/kotlin/world/gregs/voidps/world/script/InstructionCalls.kt @@ -119,10 +119,16 @@ fun Player.dialogueOption( component: String, option: Int = -1, id: String = dialogue!! -) { +) = runTest { emit(ContinueDialogue(id, component, option)) } +fun Player.dialogueContinue(repeat: Int = 1) { + repeat(repeat) { + dialogueOption("continue") + } +} + private fun getItemOptionIndex(item: String, option: String): Int? { val definitions: ItemDefinitions = get() val definition = definitions.getOrNull(item) ?: return null @@ -177,8 +183,10 @@ fun Player.itemOnItem( )) } -fun Player.npcOption(npc: NPC, option: String) = runTest { - instructions.send(InteractNPC(npc.index, npc.def.options.indexOf(option) + 1)) +fun Player.npcOption(npc: NPC, option: String) = npcOption(npc, npc.def.options.indexOf(option)) + +fun Player.npcOption(npc: NPC, option: Int) = runTest { + instructions.send(InteractNPC(npc.index, option + 1)) } fun Player.objectOption(gameObject: GameObject, option: String = "", optionIndex: Int? = null) = runTest { @@ -192,4 +200,4 @@ fun Player.floorItemOption(floorItem: FloorItem, option: String) = runTest { fun Inventory.set(index: Int, id: String, amount: Int = 1) = transaction { set(index, Item(id, amount)) } -fun Player.containsMessage(message: String) = get>("messages", emptyList()).any { it.contains(message) } \ No newline at end of file +fun Player.containsMessage(message: String) = get>("messages", emptyList()).any { it.contains(message) }