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.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/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." 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/Fernahei.kt b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt new file mode 100644 index 0000000000..d8ba5153b8 --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Fernahei.kt @@ -0,0 +1,24 @@ +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") { (target) -> + npc("Welcome to Fernahei's Fishing Shop Bwana! Would you like to see my items?") + choice { + option("Yes please!") { + openShop(target.def["shop"]) + } + option("No, but thanks for the offer.") { + npc("That's fine and thanks for your interest.") + } + } + } + } +} 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..5572fc2e7b --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Obli.kt @@ -0,0 +1,24 @@ +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") { (target) -> + npc("Welcome to Obli's General Store Bwana! Would you like to see my items?") + choice { + option("Yes please!") { + openShop(target.def["shop"]) + } + option("No, but thanks for the offer.") { + npc("That's fine and thanks for your interest.") + } + } + } + } +} 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..70fb649143 --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Vigroy.kt @@ -0,0 +1,84 @@ +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", "vigroy_shilo_village") { + offerCartRide() + } + + npcOperate("Pay-fare", "vigroy_shilo_village") { + payFare(this, Tile(2778, 3210)) + } + + objectOperate("Board", "travel_cart_shilo_village") { + talkWith(NPCs.findBySpawn(Tile(2834, 2954), "vigroy_shilo_village")) + offerCartRide() + } + + objectOperate("Pay-fare", "travel_cart_shilo_village") { + talkWith(NPCs.findBySpawn(Tile(2834, 2954), "vigroy_shilo_village")) + payFare(this, Tile(2778, 3210)) + } + } + + /** + * 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.") + } + } + } + + companion object { + + 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.") + } + } +} 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..5a2f7a28cc --- /dev/null +++ b/game/src/main/kotlin/content/area/karamja/shilo_village/Yohnus.kt @@ -0,0 +1,58 @@ +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.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.engine.inv.inventory +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) + return@objectOperate + } + 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) + } + } + } +} + +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") { + 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.") + } + } +} 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) + } +}