From c0f23136607375035d0468ba0a981d06fc90b589 Mon Sep 17 00:00:00 2001 From: aka MrSlayerGod <31116755+MrSlayerGod@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:43:18 +0100 Subject: [PATCH 1/9] wip adding shilo npc dialogue and shops etc --- .../area/karamja/shilo_village/Fernahei.kt | 26 ++++++++ .../area/karamja/shilo_village/Yohnus.kt | 65 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt create mode 100644 game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt new file mode 100644 index 0000000000..bcb1a99770 --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt @@ -0,0 +1,26 @@ +package content.area.karamja.shilo_village + +import content.entity.npc.shop.openShop +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import world.gregs.voidps.engine.Script + + +class Fernahei : Script { + + init { + npcOperate("Talk-to", "fernahei_shilo_village") { + npc("Welcome to Fernahei's Fishing Shop Bwana! Would you like to see my items?") + choice { + option("Yes please!") { + openShop("fernaheis_fishing_hut") + } + option("No, but thanks for the offer.") { + npc("That's fine and thanks for your interest.") + } + } + } + } +} \ No newline at end of file diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt new file mode 100644 index 0000000000..7ea3a1d3f0 --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -0,0 +1,65 @@ +package content.area.karamja.shilo_village + +import content.entity.obj.door.enterDoor +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.inv.transact.TransactionError +import world.gregs.voidps.engine.inv.transact.operation.RemoveItem.remove + +class Yohnus : Script { + + init { + + npcOperate("Talk-to", "yohnus_shilo_village") { + npc("Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces.") + choice { + option("Use Furnace - 20 Gold") { + inventory.transaction { + remove("coins", 20) + } + when (inventory.transaction.error) { + TransactionError.None -> { + npc("Thanks Bwana! Enjoy the facilities!") + } + else -> npc("Sorry, you don't have enough coins.") + } + } + option("No thanks!") { + player("No thanks!") + npc("Very well Bwana, have a nice day.") + } + } + } + objectOperate("Open", "blacksmiths_door_closed") { (target) -> + if (tile.y >= target.tile.y) { + enterDoor(target) + return@objectOperate + } + if (!inventory.contains("coins", 20)) { + npc( + "yohnus_shilo_village", + "Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces." + ) + return@objectOperate + } + inventory.transaction { + remove("coins", 20) + } + when (inventory.transaction.error) { + TransactionError.None -> { + npc("yohnus_shilo_village", "Thanks Bwana! Enjoy the facilities!") + enterDoor(target) + } + else -> { + npc("yohnus_shilo_village", "Sorry, you don't have enough coins.") + } + } + } + } +} \ No newline at end of file From 6b88cbd92e940230c57de7e8c56a696984732250 Mon Sep 17 00:00:00 2001 From: aka MrSlayerGod <31116755+MrSlayerGod@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:14:11 +0100 Subject: [PATCH 2/9] updated dialogues --- .../content/area/karamja/shilo_village/Fernahei.kt | 11 +++++++++++ .../content/area/karamja/shilo_village/Yohnus.kt | 3 +-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt index bcb1a99770..26e3c0326e 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt @@ -3,9 +3,12 @@ package content.area.karamja.shilo_village import content.entity.npc.shop.openShop import content.entity.player.dialogue.Happy import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.Shifty import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.entity.character.player.equip.equipped +import world.gregs.voidps.network.login.protocol.visual.update.player.EquipSlot class Fernahei : Script { @@ -21,6 +24,14 @@ class Fernahei : Script { npc("That's fine and thanks for your interest.") } } + npcOperate("Trade", "fernahei_shilo_village") { + val amulet = equipped(EquipSlot.Amulet) + if (amulet.id == "monkeyspeak_amulet") { + openShop("dagas_scimitar_smithy") + } else { + npc("Ook! Ah Uh Ah! Ook Ook! Ah!") + } + } } } } \ No newline at end of file diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt index 7ea3a1d3f0..ee3c33ff81 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -15,7 +15,6 @@ import world.gregs.voidps.engine.inv.transact.operation.RemoveItem.remove class Yohnus : Script { init { - npcOperate("Talk-to", "yohnus_shilo_village") { npc("Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces.") choice { @@ -37,7 +36,7 @@ class Yohnus : Script { } } objectOperate("Open", "blacksmiths_door_closed") { (target) -> - if (tile.y >= target.tile.y) { + if (tile.y > target.tile.y) { enterDoor(target) return@objectOperate } From ffed7092efccd2b15d9ec42357032fac9ced2396 Mon Sep 17 00:00:00 2001 From: aka MrSlayerGod <31116755+MrSlayerGod@users.noreply.github.com> Date: Mon, 8 Jun 2026 00:52:12 +0100 Subject: [PATCH 3/9] updated dialogues and codes --- .../area/karamja/shilo_village/Fernahei.kt | 17 ++++------------- .../area/karamja/shilo_village/Yohnus.kt | 8 +++++++- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt index 26e3c0326e..ce332fae77 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt @@ -3,16 +3,12 @@ package content.area.karamja.shilo_village import content.entity.npc.shop.openShop import content.entity.player.dialogue.Happy import content.entity.player.dialogue.Neutral -import content.entity.player.dialogue.Shifty import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc import world.gregs.voidps.engine.Script -import world.gregs.voidps.engine.entity.character.player.equip.equipped -import world.gregs.voidps.network.login.protocol.visual.update.player.EquipSlot class Fernahei : Script { - init { npcOperate("Talk-to", "fernahei_shilo_village") { npc("Welcome to Fernahei's Fishing Shop Bwana! Would you like to see my items?") @@ -20,18 +16,13 @@ class Fernahei : Script { option("Yes please!") { openShop("fernaheis_fishing_hut") } - option("No, but thanks for the offer.") { + option("No, but thanks for the offer.") { npc("That's fine and thanks for your interest.") } } - npcOperate("Trade", "fernahei_shilo_village") { - val amulet = equipped(EquipSlot.Amulet) - if (amulet.id == "monkeyspeak_amulet") { - openShop("dagas_scimitar_smithy") - } else { - npc("Ook! Ah Uh Ah! Ook Ook! Ah!") - } - } + } + npcOperate("Trade", "fernahei_shilo_village") { + openShop("fernaheis_fishing_hut") } } } \ No newline at end of file diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt index ee3c33ff81..4700dd4668 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -24,6 +24,7 @@ class Yohnus : Script { } when (inventory.transaction.error) { TransactionError.None -> { + this["yohnus_paid"] = true npc("Thanks Bwana! Enjoy the facilities!") } else -> npc("Sorry, you don't have enough coins.") @@ -40,13 +41,18 @@ class Yohnus : Script { enterDoor(target) return@objectOperate } - if (!inventory.contains("coins", 20)) { + if (!inventory.contains("coins", 20) && !this["yohnus_paid", false]) { npc( "yohnus_shilo_village", "Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces." ) return@objectOperate } + if (this["yohnus_paid", false]) { + clear("yohnus_paid") + enterDoor(target) + return@objectOperate + } inventory.transaction { remove("coins", 20) } From f7aa07b24466092a34374ea38c892c47cf079b0a Mon Sep 17 00:00:00 2001 From: aka MrSlayerGod <31116755+MrSlayerGod@users.noreply.github.com> Date: Sun, 12 Jul 2026 20:20:16 +0100 Subject: [PATCH 4/9] update files --- .../area/karamja/shilo_village/Fernahei.kt | 3 +- .../area/karamja/shilo_village/Obli.kt | 27 ++++++ .../area/karamja/shilo_village/Vigroy.kt | 85 +++++++++++++++++++ .../area/karamja/shilo_village/Yohnus.kt | 58 ++++++------- 4 files changed, 138 insertions(+), 35 deletions(-) create mode 100644 game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt create mode 100644 game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt index ce332fae77..41323b5864 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt @@ -7,7 +7,6 @@ import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc import world.gregs.voidps.engine.Script - class Fernahei : Script { init { npcOperate("Talk-to", "fernahei_shilo_village") { @@ -25,4 +24,4 @@ class Fernahei : Script { openShop("fernaheis_fishing_hut") } } -} \ No newline at end of file +} diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt new file mode 100644 index 0000000000..c68d22bbc7 --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt @@ -0,0 +1,27 @@ +package content.area.karamja.shilo_village + +import content.entity.npc.shop.openShop +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import world.gregs.voidps.engine.Script + +class Obli : Script { + init { + npcOperate("Talk-to", "obli_shilo_village") { + npc("Welcome to Obli's General Store Bwana! Would you like to see my items?") + choice { + option("Yes please!") { + openShop("oblis_general_store") + } + option("No, but thanks for the offer.") { + npc("That's fine and thanks for your interest.") + } + } + } + npcOperate("Trade", "obli_shilo_village") { + openShop("oblis_general_store") + } + } +} diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt new file mode 100644 index 0000000000..a87f68a9d9 --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt @@ -0,0 +1,85 @@ +package content.area.karamja.shilo_village + +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.ui.dialogue.talkWith +import world.gregs.voidps.engine.client.ui.open +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.Player +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.inv.transact.TransactionError +import world.gregs.voidps.engine.inv.transact.operation.RemoveItem.remove +import world.gregs.voidps.type.Tile + +class Vigroy : Script { + init { + npcOperate("Talk-to", "hajedy_shilo_village") { + offerCartRide() + } + + npcOperate("Pay-fare", "hajedy_shilo_village") { + payFare() + } + + objectOperate("Board", "travel_cart_shilo_village") { + talkWith(NPCs.findBySpawn(HAJEDY_SPAWN, "hajedy_shilo_village")) + offerCartRide() + } + + objectOperate("Pay-fare", "travel_cart_shilo_village") { + talkWith(NPCs.findBySpawn(HAJEDY_SPAWN, "hajedy_shilo_village")) + payFare() + } + } +} + +private val HAJEDY_SPAWN = Tile(2812, 3095) // placeholder, swap for Hajedy's actual spawn tile +private const val CART_FARE = 30 // adjust to actual RS cart fare +private const val ARRIVAL_X = 2762 // placeholder Brimhaven coords, swap for actual arrival tile +private const val ARRIVAL_Z = 3187 + +/** + * Talk-to/Board: full dialogue asking whether the player wants to travel. + */ +private suspend fun Player.offerCartRide() { + npc("I am offering a cart ride to Brimhaven, if you're interested. It will cost $CART_FARE coins. Is that okay?") + choice { + option("Yes please, I'd like to go to Brimhaven.") { + attemptPayment() + } + option("No thanks.") { + npc("Okay, Bwana, let me know if you change your mind.") + } + } +} + +/** + * Pay-fare: skips the dialogue and attempts payment immediately. + */ +private suspend fun Player.payFare() { + attemptPayment() +} + +private suspend fun Player.attemptPayment() { + inventory.transaction { + remove("coins", CART_FARE) + } + when (inventory.transaction.error) { + TransactionError.None -> { + npc("You hop into the cart and the driver urges the horses on.") + npc("You take a taxing journey through the jungle to Brimhaven.") + npc("You feel tired from the journey, but at least you didn't have to walk all that distance.") + + open("fade_out") + delay(3) + tele(ARRIVAL_X, ARRIVAL_Z) + open("fade_in") + } + else -> { + npc("Sorry, but it looks as if you don't have enough money. Come and see me when you have enough for the ride.") + } + } +} \ No newline at end of file diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt index 4700dd4668..aa59f41257 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -3,68 +3,60 @@ package content.area.karamja.shilo_village import content.entity.obj.door.enterDoor import content.entity.player.dialogue.Happy import content.entity.player.dialogue.Neutral -import content.entity.player.dialogue.Quiz import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc -import content.entity.player.dialogue.type.player import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.ui.dialogue.talkWith +import world.gregs.voidps.engine.entity.character.npc.NPCs +import world.gregs.voidps.engine.entity.character.player.Player import world.gregs.voidps.engine.inv.inventory import world.gregs.voidps.engine.inv.transact.TransactionError import world.gregs.voidps.engine.inv.transact.operation.RemoveItem.remove +import world.gregs.voidps.type.Tile class Yohnus : Script { init { npcOperate("Talk-to", "yohnus_shilo_village") { - npc("Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces.") - choice { - option("Use Furnace - 20 Gold") { - inventory.transaction { - remove("coins", 20) - } - when (inventory.transaction.error) { - TransactionError.None -> { - this["yohnus_paid"] = true - npc("Thanks Bwana! Enjoy the facilities!") - } - else -> npc("Sorry, you don't have enough coins.") - } - } - option("No thanks!") { - player("No thanks!") - npc("Very well Bwana, have a nice day.") - } - } + furnace() } objectOperate("Open", "blacksmiths_door_closed") { (target) -> if (tile.y > target.tile.y) { enterDoor(target) return@objectOperate } - if (!inventory.contains("coins", 20) && !this["yohnus_paid", false]) { - npc( - "yohnus_shilo_village", - "Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces." - ) + if (this["yohnus_paid", false]) { + clear("yohnus_paid") + enterDoor(target) return@objectOperate } + talkWith(NPCs.findBySpawn(Tile(2857, 2963), "yohnus_shilo_village")) + furnace() if (this["yohnus_paid", false]) { clear("yohnus_paid") enterDoor(target) - return@objectOperate } + } + } +} + +private suspend fun Player.furnace() { + npc("Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces.") + choice { + option("Use Furnace - 20 Gold") { inventory.transaction { remove("coins", 20) } when (inventory.transaction.error) { TransactionError.None -> { - npc("yohnus_shilo_village", "Thanks Bwana! Enjoy the facilities!") - enterDoor(target) - } - else -> { - npc("yohnus_shilo_village", "Sorry, you don't have enough coins.") + this["yohnus_paid"] = true + npc("Thanks Bwana! Enjoy the facilities!") } + else -> npc("Sorry, you don't have enough coins.") } } + option("No thanks!") { + npc("Very well Bwana, have a nice day.") + } } -} \ No newline at end of file +} From 0e747422c975ba7838f3c1e7e45219d635efef31 Mon Sep 17 00:00:00 2001 From: GregHib Date: Thu, 13 Aug 2026 09:50:48 +0100 Subject: [PATCH 5/9] Code formatting --- .../shilo_village/shilo_village.npcs.toml | 2 ++ .../area/karamja/shilo_village/Fernahei.kt | 7 ++-- .../area/karamja/shilo_village/Obli.kt | 7 ++-- .../area/karamja/shilo_village/Vigroy.kt | 34 +++++++------------ .../area/karamja/shilo_village/Yohnus.kt | 18 ++++------ 5 files changed, 26 insertions(+), 42 deletions(-) diff --git a/data/area/karamja/shilo_village/shilo_village.npcs.toml b/data/area/karamja/shilo_village/shilo_village.npcs.toml index 219263b03e..481ccb009e 100644 --- a/data/area/karamja/shilo_village/shilo_village.npcs.toml +++ b/data/area/karamja/shilo_village/shilo_village.npcs.toml @@ -60,10 +60,12 @@ examine = "Yanni Salika; he buys and sells antiques." [obli_shilo_village] id = 516 +shop = "oblis_general_store" examine = "An intelligent-looking shop owner." [fernahei_shilo_village] id = 517 +shop = "fernaheis_fishing_hut" examine = "This is Fernahei; he owns the local fishing tackle shop." [undead_one_shilo_village_3] diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt index 41323b5864..d8ba5153b8 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt @@ -9,19 +9,16 @@ import world.gregs.voidps.engine.Script class Fernahei : Script { init { - npcOperate("Talk-to", "fernahei_shilo_village") { + npcOperate("Talk-to", "fernahei_shilo_village") { (target) -> npc("Welcome to Fernahei's Fishing Shop Bwana! Would you like to see my items?") choice { option("Yes please!") { - openShop("fernaheis_fishing_hut") + openShop(target.def["shop"]) } option("No, but thanks for the offer.") { npc("That's fine and thanks for your interest.") } } } - npcOperate("Trade", "fernahei_shilo_village") { - openShop("fernaheis_fishing_hut") - } } } diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt index c68d22bbc7..5572fc2e7b 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt @@ -9,19 +9,16 @@ import world.gregs.voidps.engine.Script class Obli : Script { init { - npcOperate("Talk-to", "obli_shilo_village") { + npcOperate("Talk-to", "obli_shilo_village") { (target) -> npc("Welcome to Obli's General Store Bwana! Would you like to see my items?") choice { option("Yes please!") { - openShop("oblis_general_store") + openShop(target.def["shop"]) } option("No, but thanks for the offer.") { npc("That's fine and thanks for your interest.") } } } - npcOperate("Trade", "obli_shilo_village") { - openShop("oblis_general_store") - } } } diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt index a87f68a9d9..ba3d46f77d 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt @@ -10,8 +10,7 @@ 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.Player import world.gregs.voidps.engine.inv.inventory -import world.gregs.voidps.engine.inv.transact.TransactionError -import world.gregs.voidps.engine.inv.transact.operation.RemoveItem.remove +import world.gregs.voidps.engine.inv.remove import world.gregs.voidps.type.Tile class Vigroy : Script { @@ -39,7 +38,7 @@ class Vigroy : Script { private val HAJEDY_SPAWN = Tile(2812, 3095) // placeholder, swap for Hajedy's actual spawn tile private const val CART_FARE = 30 // adjust to actual RS cart fare private const val ARRIVAL_X = 2762 // placeholder Brimhaven coords, swap for actual arrival tile -private const val ARRIVAL_Z = 3187 +private const val ARRIVAL_Y = 3187 /** * Talk-to/Board: full dialogue asking whether the player wants to travel. @@ -64,22 +63,15 @@ private suspend fun Player.payFare() { } private suspend fun Player.attemptPayment() { - inventory.transaction { - remove("coins", CART_FARE) + if (!inventory.remove("coins", CART_FARE)) { + npc("Sorry, but it looks as if you don't have enough money. Come and see me when you have enough for the ride.") + return } - when (inventory.transaction.error) { - TransactionError.None -> { - npc("You hop into the cart and the driver urges the horses on.") - npc("You take a taxing journey through the jungle to Brimhaven.") - npc("You feel tired from the journey, but at least you didn't have to walk all that distance.") - - open("fade_out") - delay(3) - tele(ARRIVAL_X, ARRIVAL_Z) - open("fade_in") - } - else -> { - npc("Sorry, but it looks as if you don't have enough money. Come and see me when you have enough for the ride.") - } - } -} \ No newline at end of file + npc("You hop into the cart and the driver urges the horses on.") + npc("You take a taxing journey through the jungle to Brimhaven.") + npc("You feel tired from the journey, but at least you didn't have to walk all that distance.") + open("fade_out") + delay(3) + tele(ARRIVAL_X, ARRIVAL_Y) + open("fade_in") +} diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt index aa59f41257..c95325c0d4 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -10,16 +10,16 @@ import world.gregs.voidps.engine.client.ui.dialogue.talkWith import world.gregs.voidps.engine.entity.character.npc.NPCs import world.gregs.voidps.engine.entity.character.player.Player import world.gregs.voidps.engine.inv.inventory -import world.gregs.voidps.engine.inv.transact.TransactionError +import world.gregs.voidps.engine.inv.remove import world.gregs.voidps.engine.inv.transact.operation.RemoveItem.remove import world.gregs.voidps.type.Tile class Yohnus : Script { - init { npcOperate("Talk-to", "yohnus_shilo_village") { furnace() } + objectOperate("Open", "blacksmiths_door_closed") { (target) -> if (tile.y > target.tile.y) { enterDoor(target) @@ -44,16 +44,12 @@ private suspend fun Player.furnace() { npc("Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces.") choice { option("Use Furnace - 20 Gold") { - inventory.transaction { - remove("coins", 20) - } - when (inventory.transaction.error) { - TransactionError.None -> { - this["yohnus_paid"] = true - npc("Thanks Bwana! Enjoy the facilities!") - } - else -> npc("Sorry, you don't have enough coins.") + if (!inventory.remove("coins", 20)) { + npc("Sorry, you don't have enough coins.") + return@option } + this["yohnus_paid"] = true + npc("Thanks Bwana! Enjoy the facilities!") } option("No thanks!") { npc("Very well Bwana, have a nice day.") From 2445792168b8cfa59ffc0e37238d532ae3db75e4 Mon Sep 17 00:00:00 2001 From: GregHib Date: Thu, 13 Aug 2026 10:43:43 +0100 Subject: [PATCH 6/9] Add missing cart object defs --- data/area/karamja/brimhaven/brimhaven.objs.toml | 6 +++++- data/area/karamja/shilo_village/shilo_village.objs.toml | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/data/area/karamja/brimhaven/brimhaven.objs.toml b/data/area/karamja/brimhaven/brimhaven.objs.toml index 611596070f..eda5770643 100644 --- a/data/area/karamja/brimhaven/brimhaven.objs.toml +++ b/data/area/karamja/brimhaven/brimhaven.objs.toml @@ -68,4 +68,8 @@ examine = "Handy for boarding the ship." [gangplank_brimhaven_exit] id = 2088 -examine = "Handy for boarding the ship." \ No newline at end of file +examine = "Handy for boarding the ship." + +[travel_cart_brimhaven] +id = 2230 +examine = "A sturdy cart for travelling in." diff --git a/data/area/karamja/shilo_village/shilo_village.objs.toml b/data/area/karamja/shilo_village/shilo_village.objs.toml index b4caaf7a27..e889a247fa 100644 --- a/data/area/karamja/shilo_village/shilo_village.objs.toml +++ b/data/area/karamja/shilo_village/shilo_village.objs.toml @@ -13,3 +13,7 @@ examine = "A rocky outcrop from the running water." [shilo_river_stepping_stone] id = 10536 examine = "Handy for crossing rivers." + +[travel_cart_shilo_village] +id = 2265 +examine = "A sturdy cart for travelling in." From 3a30e5430597f8382c3671343c262184e4e90e31 Mon Sep 17 00:00:00 2001 From: GregHib Date: Thu, 13 Aug 2026 10:44:00 +0100 Subject: [PATCH 7/9] Add Hajedy and entering shilo village by cart --- .../content/area/karamja/brimhaven/Hajedy.kt | 45 ++++++++++ .../area/karamja/shilo_village/Vigroy.kt | 89 ++++++++++--------- .../shilo_village/ShiloVillageCartTest.kt | 40 +++++++++ 3 files changed, 133 insertions(+), 41 deletions(-) create mode 100644 game/src/main/kotlin/content/area/karamja/brimhaven/Hajedy.kt create mode 100644 game/src/test/kotlin/content/area/karamja/shilo_village/ShiloVillageCartTest.kt diff --git a/game/src/main/kotlin/content/area/karamja/brimhaven/Hajedy.kt b/game/src/main/kotlin/content/area/karamja/brimhaven/Hajedy.kt new file mode 100644 index 0000000000..28ea81b783 --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/brimhaven/Hajedy.kt @@ -0,0 +1,45 @@ +package content.area.karamja.brimhaven + +import content.area.karamja.shilo_village.Vigroy +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.ui.dialogue.talkWith +import world.gregs.voidps.engine.entity.character.npc.NPCs +import world.gregs.voidps.engine.entity.character.player.Player +import world.gregs.voidps.type.Tile + +class Hajedy : Script { + init { + npcOperate("Talk-to", "hajedy_brimhaven") { + offerCartRide() + } + + npcOperate("Pay-fare", "hajedy_brimhaven") { + Vigroy.payFare(this, Tile(2834, 2951)) + } + + objectOperate("Board", "travel_cart_brimhaven") { + talkWith(NPCs.findBySpawn(Tile(2779, 3211), "hajedy_brimhaven")) + offerCartRide() + } + + objectOperate("Pay-fare", "travel_cart_brimhaven") { + talkWith(NPCs.findBySpawn(Tile(2779, 3211), "hajedy_brimhaven")) + Vigroy.payFare(this, Tile(2834, 2951)) + } + } + + private suspend fun Player.offerCartRide() { + npc("I am offering a cart ride to Shilo Village, if you're interested. It will cost ${Vigroy.CART_FARE} coins. Is that okay?") + choice { + option("Yes please, I'd like to go to Shilo Village.") { + Vigroy.attemptPayment(this, "Shilo Village", Tile(2834, 2951)) + } + option("No thanks.") { + npc("Okay, Bwana, let me know if you change your mind.") + } + } + } +} diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt index ba3d46f77d..70fb649143 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt @@ -3,75 +3,82 @@ package content.area.karamja.shilo_village import content.entity.player.dialogue.Neutral import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.statement import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.message import world.gregs.voidps.engine.client.ui.dialogue.talkWith import world.gregs.voidps.engine.client.ui.open 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.Player +import world.gregs.voidps.engine.entity.character.player.chat.ChatType import world.gregs.voidps.engine.inv.inventory import world.gregs.voidps.engine.inv.remove import world.gregs.voidps.type.Tile class Vigroy : Script { init { - npcOperate("Talk-to", "hajedy_shilo_village") { + npcOperate("Talk-to", "vigroy_shilo_village") { offerCartRide() } - npcOperate("Pay-fare", "hajedy_shilo_village") { - payFare() + npcOperate("Pay-fare", "vigroy_shilo_village") { + payFare(this, Tile(2778, 3210)) } objectOperate("Board", "travel_cart_shilo_village") { - talkWith(NPCs.findBySpawn(HAJEDY_SPAWN, "hajedy_shilo_village")) + talkWith(NPCs.findBySpawn(Tile(2834, 2954), "vigroy_shilo_village")) offerCartRide() } objectOperate("Pay-fare", "travel_cart_shilo_village") { - talkWith(NPCs.findBySpawn(HAJEDY_SPAWN, "hajedy_shilo_village")) - payFare() + talkWith(NPCs.findBySpawn(Tile(2834, 2954), "vigroy_shilo_village")) + payFare(this, Tile(2778, 3210)) } } -} - -private val HAJEDY_SPAWN = Tile(2812, 3095) // placeholder, swap for Hajedy's actual spawn tile -private const val CART_FARE = 30 // adjust to actual RS cart fare -private const val ARRIVAL_X = 2762 // placeholder Brimhaven coords, swap for actual arrival tile -private const val ARRIVAL_Y = 3187 -/** - * Talk-to/Board: full dialogue asking whether the player wants to travel. - */ -private suspend fun Player.offerCartRide() { - npc("I am offering a cart ride to Brimhaven, if you're interested. It will cost $CART_FARE coins. Is that okay?") - choice { - option("Yes please, I'd like to go to Brimhaven.") { - attemptPayment() - } - option("No thanks.") { - npc("Okay, Bwana, let me know if you change your mind.") + /** + * Talk-to/Board: full dialogue asking whether the player wants to travel. + */ + private suspend fun Player.offerCartRide() { + npc("I am offering a cart ride to Brimhaven, if you're interested. It will cost $CART_FARE coins. Is that okay?") + choice { + option("Yes please, I'd like to go to Brimhaven.") { + attemptPayment(this, "Brimhaven", Tile(2778, 3210)) + } + option("No thanks.") { + npc("Okay, Bwana, let me know if you change your mind.") + } } } -} -/** - * Pay-fare: skips the dialogue and attempts payment immediately. - */ -private suspend fun Player.payFare() { - attemptPayment() -} + companion object { -private suspend fun Player.attemptPayment() { - if (!inventory.remove("coins", CART_FARE)) { - npc("Sorry, but it looks as if you don't have enough money. Come and see me when you have enough for the ride.") - return + const val CART_FARE = 10 + + suspend fun payFare(player: Player, tile: Tile) { + if (!player.inventory.remove("coins", CART_FARE)) { + player.npc("Sorry, but it looks as if you don't have enough money. Come and see me when you have enough for the ride.") + return + } + player.open("fade_out") + player.delay(3) + player.tele(tile) + player.open("fade_in") + player.message("You feel tired from the journey, but at least you didn't have to walk all that distance.", ChatType.Filter) + } + + suspend fun attemptPayment(player: Player, location: String, tile: Tile) { + if (!player.inventory.remove("coins", CART_FARE)) { + player.npc("Sorry, but it looks as if you don't have enough money. Come and see me when you have enough for the ride.") + return + } + player.statement("You hop into the cart and the driver urges the horses on. You take a taxing journey through the jungle to $location.", clickToContinue = false) + player.open("fade_out") + player.delay(3) + player.tele(tile) + player.open("fade_in") + player.statement("You hop into the cart and the driver urges the horses on. You take a taxing journey through the jungle to $location. You feel tired from the journey, but at least you didn't have to walk all that distance.") + } } - npc("You hop into the cart and the driver urges the horses on.") - npc("You take a taxing journey through the jungle to Brimhaven.") - npc("You feel tired from the journey, but at least you didn't have to walk all that distance.") - open("fade_out") - delay(3) - tele(ARRIVAL_X, ARRIVAL_Y) - open("fade_in") } diff --git a/game/src/test/kotlin/content/area/karamja/shilo_village/ShiloVillageCartTest.kt b/game/src/test/kotlin/content/area/karamja/shilo_village/ShiloVillageCartTest.kt new file mode 100644 index 0000000000..10936f28c7 --- /dev/null +++ b/game/src/test/kotlin/content/area/karamja/shilo_village/ShiloVillageCartTest.kt @@ -0,0 +1,40 @@ +package content.area.karamja.shilo_village + +import WorldTest +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import world.gregs.voidps.engine.client.instruction.handle.interactObject +import world.gregs.voidps.engine.entity.obj.GameObjects +import world.gregs.voidps.engine.inv.add +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.type.Tile + +class ShiloVillageCartTest : WorldTest() { + override var loadNpcs: Boolean = true + + @Test + fun `Travel from shilo to brimhaven`() { + val player = createPlayer(Tile(2833, 2954)) + player.inventory.add("coins", 10) + val cart = GameObjects.find(Tile(2831, 2952), "travel_cart_shilo_village") + + player.interactObject(cart, "Pay-fare") + + tick(4) + assertEquals(0, player.inventory.count("coins")) + assertEquals(Tile(2778, 3210), player.tile) + } + + @Test + fun `Travel from brimhaven to shilo village`() { + val player = createPlayer(Tile(2778, 3210)) + player.inventory.add("coins", 10) + val cart = GameObjects.find(Tile(2777, 3211), "travel_cart_brimhaven") + + player.interactObject(cart, "Pay-fare") + + tick(4) + assertEquals(0, player.inventory.count("coins")) + assertEquals(Tile(2834, 2951), player.tile) + } +} From ddd78da5a3c5634c1b13bb4a2920b8f8c0253df3 Mon Sep 17 00:00:00 2001 From: GregHib Date: Thu, 13 Aug 2026 10:48:06 +0100 Subject: [PATCH 8/9] Fix furnace dialogue --- .../main/kotlin/content/area/karamja/shilo_village/Yohnus.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt index c95325c0d4..612a48634c 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -5,6 +5,8 @@ import content.entity.player.dialogue.Happy import content.entity.player.dialogue.Neutral import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.quest.questCompleted import world.gregs.voidps.engine.Script import world.gregs.voidps.engine.client.ui.dialogue.talkWith import world.gregs.voidps.engine.entity.character.npc.NPCs @@ -43,7 +45,7 @@ class Yohnus : Script { private suspend fun Player.furnace() { npc("Sorry but the blacksmiths is closed. But I can let you use the furnace at the cost of 20 gold pieces.") choice { - option("Use Furnace - 20 Gold") { + option("Use Furnace - 20 Gold") { if (!inventory.remove("coins", 20)) { npc("Sorry, you don't have enough coins.") return@option From c06c5cd9def21605ca979ac5b4309453f3ffed0b Mon Sep 17 00:00:00 2001 From: GregHib Date: Thu, 13 Aug 2026 11:07:10 +0100 Subject: [PATCH 9/9] Formatting --- .../main/kotlin/content/area/karamja/shilo_village/Yohnus.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt index 612a48634c..5a2f7a28cc 100644 --- a/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -5,8 +5,6 @@ import content.entity.player.dialogue.Happy import content.entity.player.dialogue.Neutral import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc -import content.entity.player.dialogue.type.player -import content.quest.questCompleted import world.gregs.voidps.engine.Script import world.gregs.voidps.engine.client.ui.dialogue.talkWith import world.gregs.voidps.engine.entity.character.npc.NPCs