diff --git a/data/area/misthalin/varrock/varrock.item-spawns.toml b/data/area/misthalin/varrock/varrock.item-spawns.toml index 28167e836f..15b7fc879c 100644 --- a/data/area/misthalin/varrock/varrock.item-spawns.toml +++ b/data/area/misthalin/varrock/varrock.item-spawns.toml @@ -24,4 +24,10 @@ spawns = [ { id = "empty_pot", x = 3144, y = 3449, level = 2, delay = 100 }, { id = "empty_jug", x = 3142, y = 3447, level = 2, delay = 100 }, { id = "cooking_apple", x = 3141, y = 3447, level = 2, delay = 100 }, + # Gertrude's Cat https://youtu.be/_pZcnvI1l_Q?t=195 + { id = "doogle_leaves", x = 3152, y = 3399, delay = 100 }, + { id = "doogle_leaves", x = 3152, y = 3400, delay = 100 }, + { id = "doogle_leaves", x = 3151, y = 3399, delay = 100 }, + { id = "doogle_leaves", x = 3157, y = 3400, delay = 100 }, + { id = "doogle_leaves", x = 3156, y = 3401, delay = 100 }, ] \ No newline at end of file diff --git a/data/area/misthalin/varrock/varrock.npcs.toml b/data/area/misthalin/varrock/varrock.npcs.toml index 8304f07f43..63f250108e 100644 --- a/data/area/misthalin/varrock/varrock.npcs.toml +++ b/data/area/misthalin/varrock/varrock.npcs.toml @@ -273,6 +273,8 @@ examine = "He tries to keep order around here." [sawmill_operator] id = 4250 +shop = "construction_supplies" +examine = "He changes the shape of wood." [assistant_serf] id = 5066 @@ -429,10 +431,12 @@ examine = "A busy housewife." [philop] id = 782 +dialogue = "child" examine = "One of Gertrude's sons." [kanel] id = 784 +dialogue = "child" examine = "One of Gertrude's sons." [rogue] @@ -608,10 +612,12 @@ examine = "A retired vampyre hunter." [shilop] id = 781 +dialogue = "child" examine = "One of Gertrude's sons." [wilough] id = 783 +dialogue = "child" examine = "One of Gertrude's sons." [treznor] diff --git a/data/area/misthalin/varrock/varrock.objs.toml b/data/area/misthalin/varrock/varrock.objs.toml index 354ce08659..44276c5fa2 100644 --- a/data/area/misthalin/varrock/varrock.objs.toml +++ b/data/area/misthalin/varrock/varrock.objs.toml @@ -44,3 +44,7 @@ examine = "Ideal for cooking on." [cooking_range_varrock_palace_oven] id = 24313 examine = "For cooking food." + +[fence_varrock_lumbermill] +id = 31149 +examine = "A damaged wooden fence" # Source: https://classic.runescape.wiki/w/Low_Fence_%28Lumber_Mill%29 \ No newline at end of file diff --git a/data/entity/player/human.anims.toml b/data/entity/player/human.anims.toml index 9b309e5bf1..45fef598a4 100644 --- a/data/entity/player/human.anims.toml +++ b/data/entity/player/human.anims.toml @@ -95,4 +95,10 @@ id = 2096 id = 2097 [human_pick_wall_end] -id = 2098 \ No newline at end of file +id = 2098 + +[human_squeeze_under] # Appears to be identical with human_squeeze_under_2 +id = 9220 + +[human_squeeze_under_2] +id = 9221 \ No newline at end of file diff --git a/data/quest/members/gertrudes_cat/gertrudes_cat.areas.toml b/data/quest/members/gertrudes_cat/gertrudes_cat.areas.toml new file mode 100644 index 0000000000..c2522bdfeb --- /dev/null +++ b/data/quest/members/gertrudes_cat/gertrudes_cat.areas.toml @@ -0,0 +1,4 @@ +[kitten_search_area] +x = [3313, 3298] +y = [3497, 3517] +level = 0 \ No newline at end of file diff --git a/data/quest/members/gertrudes_cat/gertrudes_cat.npcs.toml b/data/quest/members/gertrudes_cat/gertrudes_cat.npcs.toml new file mode 100644 index 0000000000..ebf45a68b1 --- /dev/null +++ b/data/quest/members/gertrudes_cat/gertrudes_cat.npcs.toml @@ -0,0 +1,6 @@ +[three_little_kittens] +id = 7741 +examine = "Three little kittens." + +[fluffs_cutscene] +id = 7743 \ No newline at end of file diff --git a/data/quest/members/gertrudes_cat/gertrudes_cat.varps.toml b/data/quest/members/gertrudes_cat/gertrudes_cat.varps.toml index 5ccb00e46e..b845eca6a0 100644 --- a/data/quest/members/gertrudes_cat/gertrudes_cat.varps.toml +++ b/data/quest/members/gertrudes_cat/gertrudes_cat.varps.toml @@ -3,4 +3,12 @@ id = 180 persist = true format = "map" default = "unstarted" -values = { unstarted = 0, completed = 6 } +values = { + unstarted = 0, + spoke_to_gertrude = 1, + found_the_boys = 2, + found_fluffs = 3, + attempt_fluffs_pickup = 4, + fluffs_returned = 5, + completed = 6, +} diff --git a/data/quest/members/gertrudes_cat/gertrudes_cat.vars.toml b/data/quest/members/gertrudes_cat/gertrudes_cat.vars.toml new file mode 100644 index 0000000000..abc13a17ba --- /dev/null +++ b/data/quest/members/gertrudes_cat/gertrudes_cat.vars.toml @@ -0,0 +1,23 @@ +[gertrudes_cat_know_where_fluffs_is] +persist = true +format = "boolean" + +[gertrudes_cat_fluffs_fed] +persist = true +format = "boolean" + +[gertrudes_cat_fluffs_milk] +persist = true +format = "boolean" + +[kittens_hiding_here] +persist = true +format = "int" + +[three_little_kittens_found] +persist = true +format = "boolean" + +[gertrudes_cat_talked_about_reward] +persist = true +format = "boolean" \ No newline at end of file diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/BrokenFenceSawmill.kt b/game/src/main/kotlin/content/area/misthalin/varrock/BrokenFenceSawmill.kt new file mode 100644 index 0000000000..e17bb88009 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/varrock/BrokenFenceSawmill.kt @@ -0,0 +1,33 @@ +package content.area.misthalin.varrock + +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.character.player.chat.ChatType +import world.gregs.voidps.type.Tile + +private val EAST_TILE = Tile(3296, 3498) +private val WEST_TILE = Tile(3295, 3498) + +class BrokenFenceSawmill : Script { + init { + objectOperate("Squeeze-under", "fence_varrock_lumbermill") { + when (tile) { + EAST_TILE -> { + anim("human_squeeze_under", delay = 40) + message("You squeeze underneath the fence", ChatType.Filter) + walkOverDelay(WEST_TILE) + clearAnim() + } + WEST_TILE -> { + anim("human_squeeze_under_2", delay = 40) + message("You squeeze underneath the fence", ChatType.Filter) + walkOverDelay(EAST_TILE) + clearAnim() + } + else -> { + message("You need to get closer to use that!") + } + } + } + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/Fluffs.kt b/game/src/main/kotlin/content/area/misthalin/varrock/Fluffs.kt new file mode 100644 index 0000000000..bdda7d75c0 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/varrock/Fluffs.kt @@ -0,0 +1,294 @@ +package content.area.misthalin.varrock + +import content.entity.player.dialogue.Angry +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Idle +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.entity.player.dialogue.type.statement +import content.quest.member.gertrudes_cat.GERTRUDES_CAT_STRING_NAME +import content.quest.quest +import content.quest.setInstanceLogout +import content.quest.startCutscene +import content.skill.summoning.pet.hasCatspeakAmulet +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.clearCamera +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.client.moveCamera +import world.gregs.voidps.engine.client.turnCamera +import world.gregs.voidps.engine.client.ui.open +import world.gregs.voidps.engine.data.definition.Areas +import world.gregs.voidps.engine.entity.character.mode.PauseMode +import world.gregs.voidps.engine.entity.character.move.tele +import world.gregs.voidps.engine.entity.character.npc.NPC +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.name +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.engine.inv.remove +import world.gregs.voidps.type.Direction +import world.gregs.voidps.type.Region +import world.gregs.voidps.type.Tile + +private const val FLUFFS_STRING_ID = "fluffs_normal" +const val FLUFFS_FED_VAR = "gertrudes_cat_fluffs_fed" +const val FLUFFS_MILK_VAR = "gertrudes_cat_fluffs_milk" +const val KITTENS_HIDING_SPOT = "kittens_hiding_here" + +class Fluffs : Script { + private var kittenCrates = mutableSetOf() + + init { + + itemOnNPCOperate("doogle_sardine", FLUFFS_STRING_ID) { + foundCatCheck() + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "attempt_fluffs_pickup" -> checkCanFeed() + else -> message("Fluffs doesn't seem to be hungry right now.") + } + return@itemOnNPCOperate + } + itemOnNPCOperate("bucket_of_milk", FLUFFS_STRING_ID) { + foundCatCheck() + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "attempt_fluffs_pickup" -> milkFluffs() + else -> message("Fluffs doesn't seem to be thirsty right now.") + } + return@itemOnNPCOperate + } + itemOnNPCOperate("*", FLUFFS_STRING_ID) { interact -> + val item = interact.item.id + + foundCatCheck() + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "completed" -> dontBotherCat() + "attempt_fluffs_pickup" -> checkItem(item) + else -> message("Fluffs regards you with disdain.") + } + } + npcOperate("Talk-to", FLUFFS_STRING_ID) { interact -> + foundCatCheck() + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "completed" -> talkPostQuest(interact.target, interact.player.name) + "found_fluffs" -> talkCatFoundFluffs(interact.target) + "attempt_fluffs_pickup" -> talkCatFoundFluffs(interact.target) + else -> dontBotherCat() + } + } + npcOperate("Pick-up", FLUFFS_STRING_ID) { interact -> + foundCatCheck() + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "found_fluffs" -> yoinkCatFoundFluffs(interact.target) + "attempt_fluffs_pickup" -> yoinkCatFoundFluffs(interact.target) + else -> dontBotherCat() + } + } + npcOperate("Stroke", FLUFFS_STRING_ID) { interact -> + foundCatCheck() + if (get(FLUFFS_MILK_VAR, false) && get(FLUFFS_FED_VAR, false)) { + strokeCatFedFluffs(interact.target) + return@npcOperate + } + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "found_fluffs" -> strokeCatFoundFluffs(interact.target) + "attempt_fluffs_pickup" -> strokeCatFoundFluffs(interact.target) + else -> dontBotherCat() + } + } + } + + private fun discoverKittenCrates() { + kittenCrates += Areas["kitten_search_area"] + .flatMap { tile -> + GameObjects.at(tile) + .filter { it.id == "crate_17" } + .map { it.tile } + } + } + + private suspend fun Player.checkCanFeed() { + // check player variable if you already fed the cat + if (get(FLUFFS_FED_VAR, false)) { + dontBotherCat() + } else { + feedFluffs() + } + } + private suspend fun Player.feedFluffs() { + inventory.remove("doogle_sardine") + set(FLUFFS_FED_VAR, true) + npc("Mew!") + player("Progress, at least.") + statement("Fluffs devours the doogle sardine greedily. Then she mews at you again.") + } + + private suspend fun Player.checkItem(item: String) { + val doogleSardineItems = setOf("doogle_leaves", "raw_sardine", "sardine") + + when (item) { + in doogleSardineItems -> { + mildInterest(item) + } + "three_little_kittens" -> { + fluffsGoesHome() + } + else -> { + message("Fluffs doesn't seem to be interested in that.") + } + } + } + + private suspend fun Player.fluffsGoesHome() { + val region = Region(13110) + val custceneStartTile = Tile(3309, 3509, 1) + + inventory.remove("three_little_kittens") + set(GERTRUDES_CAT_STRING_NAME, "fluffs_returned") + + open("fade_out") + val cutscene = startCutscene("fluffs_kittens_reunite", region) + setInstanceLogout(custceneStartTile) + + cutscene.onEnd { + open("fade_out") + delay(3) + tele(custceneStartTile) + clearCamera() + clearAnim() + } + + delay(4) + tele(cutscene.tile(3309, 3509, 1), clearInterfaces = false) + face(Direction.NORTH) + val fluffs = NPCs.add("fluffs_cutscene", cutscene.tile(3309, 3512, 1), Direction.SOUTH) + val kittens = NPCs.add("three_little_kittens", cutscene.tile(3309, 3510, 1), Direction.NORTH) + kittens.mode = PauseMode + fluffs.mode = PauseMode + + // TODO: Get that proper camera angle. This is "good enough" + moveCamera(cutscene.tile(3304, 3505, 1), 500) + turnCamera(cutscene.tile(3309, 3510, 1), 100) + + // Scene start + open("fade_in") + anim("climb_down") + npc("Purr...") + kittens.walkToDelay(cutscene.tile(3309, 3511, 1)) + kittens.mode = PauseMode // They just wanna zoom around! + kittens.animDelay("9207") + delay(15) + fluffs.animDelay("9205") + kittens.say("Purr...") + delay(6) + kittens.walkToDelay(cutscene.tile(3310, 3510, 1), true) + kittens.despawn(1) // Added small delay to let the kittens get to the final tile + fluffs.walkToDelay(cutscene.tile(3309, 3510, 1), true) + fluffs.despawn() + statement("Fluffs has run off home with her offspring.") + + cutscene.end() + } + + private suspend fun Player.mildInterest(item: String) { + var itemName = item + if (item == "doogle_leaves") { + itemName = "doogle leaves" + } + if (item == "raw_sardine") { + itemName = "raw sardine" + } + npc("Hiss!") + player("She seems to be a very fussy cat.") + statement("Fluffs looks vaguely interested at the $itemName but doesn't want it. A similar type of food or drink might be worth a try.") + } + + private suspend fun Player.milkFluffs() { + npc("Mew!") + player("Progress, at least.") + inventory.remove("bucket_of_milk") + inventory.add("bucket") + set(FLUFFS_MILK_VAR, true) + statement("Fluffs laps up the milk greedily. Then she mews at you again.") + } + + private fun Player.foundCatCheck() { + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "found_the_boys" -> set(GERTRUDES_CAT_STRING_NAME, "found_fluffs") + } + } + + private fun Player.dontBotherCat() { + message("You decide it best to not bother the cat.") // Going off of memory here. + } + + private suspend fun Player.talkPostQuest(cat: NPC, playerName: String) { + // TODO: Dialogue when the player has a kitten either following or in the player's inventory + if (hasCatspeakAmulet()) { + player("Hello Fluffs.") + npc("Purrrrr! So you can talk to cats now?") + player("Yes, I got this amulet from a Sphinx.") + npc("Well, I should thank you for finding my kitten that time. I have a terrible time keeping track of them, and I never know how many Gertrude has managed to sell.") + player("They're cute little creatures, aren't they?") + npc("Purrrrr!") + statement("Fluffs looks proud.") + npc("My children have always been popular with adventurers. They inherit their father's adventurous spirit. He's always travelling the world, when he can find some kind person to help him open doors!") + player("Look after yourself, Fluffs.") + npc("You too, $playerName.") + } + cat.say("Miaoww") + } + private fun talkCatFoundFluffs(cat: NPC) { + cat.say("Miaoww") + } + + private suspend fun Player.yoinkCatFoundFluffs(cat: NPC) { + if (inventory.contains("three_little_kittens")) { + doNotTheCat(cat) + + statement("Fluffs looks pitifully towards your backpack.") + return + } + if (get(FLUFFS_FED_VAR, false) && get(FLUFFS_MILK_VAR, false)) { + doNotTheCat(cat) + + discoverKittenCrates() + val crate = kittenCrates.random() + set(KITTENS_HIDING_SPOT, crate.id) + println("Your cat is hiding at $crate") + + statement("Fluffs seems afraid to leave. \nIn the Lumber Yard below you can hear kittens mewing.") + return + } + doNotTheCat(cat) + statement("Fluffs hisses but clearly wants something - maybe she is thirsty?") + } + + // Based off of memory + private suspend fun Player.strokeCatFedFluffs(cat: NPC) { + animDelay("climb_down") + delay(1) + cat.say("Prr...") + delay(1) + statement("Seems like Fluffs doesn't hate you anymore.") + } + + private suspend fun Player.strokeCatFoundFluffs(cat: NPC) { + doNotTheCat(cat) + statement("Perhaps Fluffs wants something - food or drink, maybe?") + } + + private suspend fun Player.doNotTheCat(cat: NPC) { + set(GERTRUDES_CAT_STRING_NAME, "attempt_fluffs_pickup") + animDelay("climb_down") + delay(1) + cat.say("Hiss!") + cat.face(this) + cat.animDelay("pet_pounce_kitten") + delay(1) + say("Ouch!") + delay(1) + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/Gertrude.kt b/game/src/main/kotlin/content/area/misthalin/varrock/Gertrude.kt index adc40323ef..3027c724f4 100644 --- a/game/src/main/kotlin/content/area/misthalin/varrock/Gertrude.kt +++ b/game/src/main/kotlin/content/area/misthalin/varrock/Gertrude.kt @@ -1,16 +1,33 @@ package content.area.misthalin.varrock +import content.entity.player.AdventurersLogs +import content.entity.player.bank.bank +import content.entity.player.dialogue.Angry +import content.entity.player.dialogue.Confused +import content.entity.player.dialogue.Disheartened import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Idle +import content.entity.player.dialogue.Laugh +import content.entity.player.dialogue.Neutral import content.entity.player.dialogue.Quiz import content.entity.player.dialogue.Sad import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc import content.entity.player.dialogue.type.player +import content.entity.player.dialogue.type.statement +import content.quest.member.gertrudes_cat.GERTRUDES_CAT_STRING_NAME import content.quest.quest +import content.quest.questComplete +import content.quest.refreshQuestJournal import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.entity.character.jingle import world.gregs.voidps.engine.entity.character.player.Player +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.event.AuditLog import world.gregs.voidps.engine.inv.add import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.queue.longQueue /** * Minimal Gertrude dialogue. Once Gertrude's Cat quest is completed, lets the @@ -22,13 +39,102 @@ class Gertrude : Script { init { npcOperate("Talk-to", "gertrude") { + if (get(FLUFFS_MILK_VAR, false) && get(FLUFFS_FED_VAR, false) && quest("gertrudes_cat") == "attempt_fluffs_pickup") { + mustBeAReason() + return@npcOperate + } when (quest("gertrudes_cat")) { "completed" -> postQuest() + "spoke_to_gertrude" -> lookingForInformation() + "found_the_boys" -> findingFluffs() + "found_fluffs" -> hungryAndThirsty() + "attempt_fluffs_pickup" -> hungryAndThirsty() + "fluffs_returned" -> finishQuest() else -> unstarted() } } } + private suspend fun Player.finishQuest() { + if (!get("gertrudes_cat_talked_about_reward", false)) { + player("Hello, Gertrude. Fluffs had run off with her kittens, lost them and I have now returned them to her.") + statement("Gertrude thanks you heartily.") + npc("Thank you! If you hadn't found her kittens then they would have died out there. I've got some presents for you in thanks for your help.") + player("That's okay, I like to do my bit.") + set("gertrudes_cat_talked_about_reward", true) + } else { + player("Hello again. You said something about presents...") + } + if (inventory.spaces < 3) { + npc("You don't have space to hold all three of my presents. Come back and talk to me again when you do.") + return + } + npc("I have no real material possessions but I do have kittens. I've cooked you some food too.") + player("Well if one needs a home.") + npc("I would sell one to my cousin in West Ardougne. I hear there's a rat epidemic there but it's too far for me to travel, what with my boys and all.") + npc("Here you go. Look after her and thank you again.") + npc("Oh, by the way, the kitten can live in your backpack but, to ensure it grows, you must take it out, feed it and stroke it often.") + statement("Gertrude gives you a kitten.") + questComplete() + } + + suspend fun Player.questComplete() { + AuditLog.event(this, "quest_completed", "gertrudes_cat") + AdventurersLogs.questCompleted(this, "gertrudes_cat", points = 1) + set(GERTRUDES_CAT_STRING_NAME, "completed") + jingle("quest_complete_1") + exp(Skill.Cooking, 1525.0) + giveKitten() + inventory.add("chocolate_cake") + inventory.add("stew") + refreshQuestJournal() + inc("quest_points") + longQueue("quest_complete", 1) { + questComplete( + "Gertrude's Cat", + "1 Quest Point", + "A kitten!", + "1,525 Cooking XP", + "A chocolate cake", + "A bowl of stew", + "The ability to raise cats", + item = "pet_cat", // TODO: Find cat id + ) + } + } + + private suspend fun Player.mustBeAReason() { + player("Hi!") + npc("Hey traveller, did Fluffs eat the sardines?") + player("Yeah, she loved them, but she still won't leave.") + npc("Well that is strange, there must be a reason.") + } + + private suspend fun Player.hungryAndThirsty() { + findShilopQ() + player("Yes, I've found Fluffs!") + npc("That's great; where is she?") + player("She's still in Varrock. I think she may be hungry, thirsty or both.") + npc("Oh dear, oh dear! Maybe she's just hungry. She loves doogle sardines but I'm all out.") + player("Doogle sardines?") + npc("Yes, raw sardines seasoned with doogle leaves. Unfortunately, I've used all my doogles leaves, but you may find some on the bush out back.") + player("What if she is thirsty?") + npc("In that case, she'd probably like some milk. A bucketful would tempt her, I'm sure.") + player("It seems a rather large amount of milk for one small cat, but I'll give it a try.") + } + + private suspend fun Player.findingFluffs() { + findShilopQ() + player("I think so. I'm just going to look now.") + npc("Thanks again, adventurer.") + } + + private suspend fun Player.findShilopQ() { + player("Hello Gertrude.") + npc("Hello again, did you manage to find Shilop? I can't keep an eye on him for the life of me.") + player("He does seem quite a handful.") + npc("You have no idea! Did he help at all?") + } private suspend fun Player.postQuest() { npc("Hello dear. How are my kittens treating you?") choice { @@ -42,7 +148,7 @@ class Gertrude : Script { } private suspend fun Player.giveKitten() { - if (inventory.contains("pet_kitten")) { + if (inventory.contains("pet_kitten") || bank.contains("pet_kitten")) { npc("It looks like you've already got a kitten with you. Come back when you'd like another.") return } @@ -58,8 +164,56 @@ class Gertrude : Script { } private suspend fun Player.unstarted() { - npc("Oh dear, oh dear. Whatever shall I do...") - player("What's wrong?") - npc("My poor little kitten has wandered off. Come back another time, dear, I haven't got the heart to chat.") + player("Hello, are you okay?") + npc("Do I look okay? Those kids drive me crazy.") + npc("I'm sorry. It's just that I've lost her.") + player("Lost whom?") + npc("Fluffs, poor Fluffs. She never hurt anyone.") + player("Who's Fluffs?") + npc("My beloved feline friend, Fluffs. She's been purring by my side for almost a decade. Please, could you go and search for her while I take care of the children?") + choice { + option("Well, I suppose I could, though I'd need more details.") { + questAccepted() + } + option("What's in it for me?") { + npc("I'm sorry, I'm too poor to pay you anything, the best I could offer is a warm meal.") + npc("So, can you help?") + player("Just a meal? It's not the best offer I've had, but I suppose I can help.") + npc("I suppose I could give you some nice, yummy chocolate cake; maybe even a kitten too, if you seem like a nice sort.") + npc("Is that something you could be persuaded with?") + choice { + option("Well, I suppose I could, though I'd need more details.") { + questAccepted() + } + option("Sorry, I'm too busy to play pet rescue.") { + questRejected() + } + } + } + option("Sorry, I'm too busy to play pet rescue.") { + questRejected() + } + } + } + private suspend fun Player.questRejected() { + npc("Well, okay then. I'll have to find someone else; someone less heartless. It will be on your conscience if a poor kitty is lost in the wilds, though.") + } + private suspend fun Player.questAccepted() { + set(GERTRUDES_CAT_STRING_NAME, "spoke_to_gertrude") + npc("Really? Thank you so much! I really have no idea where she could be!") + npc("I think my sons, Shilop and Wilough, saw the cat last. They'll be out in the marketplace.") + player("The marketplace? Which one would that be? It would help to know what they get up to, as well.") + npc("Really? Well, I generally let them do what they want, so I've no idea exactly what they would be doing. They are good lads, though. I'm sure they are just watching the passers-by in Varrock Marketplace.") + npc("Oh, to be young and carefree again!") + player("Alright then. I'll see what I can do. Two young lads in Varrock Marketplace; I can only hope that there's no school trip passing through when I arrive.") + } + + private suspend fun Player.lookingForInformation() { + player("Hello Gertrude.") + npc("Have you seen my poor Fluffs?") + player("I'm afraid not.") + npc("What about Shilop?") + player("No sign of him either.") + npc("Hmm, strange; he should be in Varrock Marketplace.") } } diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/Kanel.kt b/game/src/main/kotlin/content/area/misthalin/varrock/Kanel.kt new file mode 100644 index 0000000000..7bf604c4d1 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/varrock/Kanel.kt @@ -0,0 +1,43 @@ +package content.area.misthalin.varrock + +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Idle +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.quest.quest +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.entity.character.player.Player + +private const val KANEL_STRING_NAME = "kanel" + +// Source: https://runescape.wiki/w/Transcript:Kanel + +class Kanel : Script { + init { + npcOperate("Talk-to", KANEL_STRING_NAME) { + when (quest("gertrudes_cat")) { + "spoke_to_gertrude" -> lookingForInformation() + else -> unstarted() + } + } + } + + private suspend fun Player.unstarted() { + player("Hello there.") + npc("Hel-lo?") + player("Right. Goodbye.") + npc("Bye?") + } + + private suspend fun Player.lookingForInformation() { + player("Hello there.") + npc("Hel-lo?") + player("Have you seen Fluffs?") + npc("F-wuffs?") + player("She's your mummy's cat.") + npc("Cat?") + player("Right. Bye Kanel.") + npc("Me?") + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/Philop.kt b/game/src/main/kotlin/content/area/misthalin/varrock/Philop.kt new file mode 100644 index 0000000000..a53a81f492 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/varrock/Philop.kt @@ -0,0 +1,43 @@ +package content.area.misthalin.varrock + +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Idle +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.quest.quest +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.entity.character.player.Player + +private const val PHILOP_STRING_NAME = "philop" + +// Source: https://runescape.wiki/w/Transcript:Philop +class Philop : Script { + init { + npcOperate("Talk-to", PHILOP_STRING_NAME) { + when (quest("gertrudes_cat")) { + "spoke_to_gertrude" -> lookingForInformation() + else -> unstarted() + } + } + } + private suspend fun Player.unstarted() { + greetChild() + player("Enjoy playing with your dragon, then.") + npc("Gwwwrrr!") + } + private suspend fun Player.greetChild() { + player("Hello, what's your name?") + npc("Gwwrr!") + player("Err, hello there. What's that you have there?") + npc("Gwwwrrr! Dwa-gon Gwwwwrrrr!") + } + + private suspend fun Player.lookingForInformation() { + greetChild() + player("What a nice dragon, have you seen Fluffs little boy?") + npc("Dwa-gon nasty, dwa-gon eat Fwuffs, gwwwrrr, hungwy chomp chomp!") + player("I see. I don't think this is the most helpful clue I have ever been given.") + npc("Gwwrr!") + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/SawmillOperatorVarrock.kt b/game/src/main/kotlin/content/area/misthalin/varrock/SawmillOperatorVarrock.kt new file mode 100644 index 0000000000..8aeb7045c5 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/varrock/SawmillOperatorVarrock.kt @@ -0,0 +1,39 @@ +package content.area.misthalin.varrock + +import content.entity.npc.shop.openShop +import content.entity.player.dialogue.Confused +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 content.quest.member.gertrudes_cat.GERTRUDES_CAT_STRING_NAME +import content.quest.questStage +import world.gregs.voidps.engine.Script + +class SawmillOperatorVarrock : Script { + // Free to play message: "The sawmill operator pays you no attention, it doesn't seem like he'll help you." + init { + npcApproach("Talk-to", "sawmill_operator") { (target) -> + approachRange(2) + npc("Hello there. Do you want me to make some planks for you? I can make planks from wood, oak, teak and mahogany logs. Or would you like to buy some other housing supplies?") + choice { + option("Yes, please make me some planks.") { + TODO("Plank-making interface not finished") + } + option("Can I buy some housing supplies?") { + npc("Of course!") + openShop(target.def["shop"]) + } + if (questStage(GERTRUDES_CAT_STRING_NAME) == 2 && get("gertrudes_cat_know_where_fluffs_is", false)) { + option("I have some questions about a cat.") { + npc("A cat? What makes you ask about that?") + player("I'm looking for a cat named Fluffs and my sources tell me she may be in your sawmill.") + npc("Your sources? Who's been talking about my sawmill behind my back? This is a business. We don't have animals on the premises.") + } + } + } + } + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/Shilop.kt b/game/src/main/kotlin/content/area/misthalin/varrock/Shilop.kt new file mode 100644 index 0000000000..b189accee1 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/varrock/Shilop.kt @@ -0,0 +1,56 @@ +package content.area.misthalin.varrock + +import content.entity.player.dialogue.Angry +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Idle +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.Scared +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.entity.player.dialogue.type.statement +import content.quest.member.gertrudes_cat.GERTRUDES_CAT_STRING_NAME +import content.quest.quest +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.entity.character.player.Player + +const val SHILOP_STRING_NAME = "shilop" + +class Shilop : Script { + init { + npcOperate("Talk-to", SHILOP_STRING_NAME) { + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "completed" -> gertrudePostQuest() + "spoke_to_gertrude" -> lookingForInformationBranch() + "found_the_boys" -> gertrudeWhereFluffs() + "attempt_fluffs_pickup" -> gertrudeFluffsNotComeBack() + else -> gertrudeUnstarted() + } + } + } +} + +suspend fun Player.gertrudeFluffsNotComeBack() { + player("I've found Fluffs but she won't come back home with me. Any ideas?") + npc("None at all. Not that I want that boring thing back, anyway. I prefer dogs to a fat cat, any day.") +} + +private suspend fun Player.lookingForInformationBranch() { + gertrudeLookingForInformation() + choice { + option("Tell me sonny, or I will inform your mum you are a pair of criminals.") { + npc("W..wh..what?! Y..you wouldn't! Anyway, I'll deny it all and she'll be sure to believe me over some wandering killer like you.", largeHead = true) + player("I'm an upstanding citizen!") + npc("I'm her darling boy and you'd have to forget about her rewarding you. Hop it snitch.") + npc(npcId = WILOUGH_STRING_NAME, "And I'm even more her favourite than he is!") + statement("You decide it's best not to aggravate the repulsive boys any more.") + } + option("What will make you tell me?") { + gertrudeFluffsCost() + } + option("Well never mind, it's Fluffs loss.") { + gertrudeFluffsLoss() + } + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/varrock/Wilough.kt b/game/src/main/kotlin/content/area/misthalin/varrock/Wilough.kt new file mode 100644 index 0000000000..41ce218d9a --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/varrock/Wilough.kt @@ -0,0 +1,141 @@ +package content.area.misthalin.varrock + +import content.entity.player.dialogue.Angry +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Idle +import content.entity.player.dialogue.Laugh +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.Sad +import content.entity.player.dialogue.Scared +import content.entity.player.dialogue.Shock +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.entity.player.dialogue.type.statement +import content.quest.member.gertrudes_cat.GERTRUDES_CAT_STRING_NAME +import content.quest.quest +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.character.player.Player +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.inv.remove + +const val WILOUGH_STRING_NAME = "wilough" + +// Source: https://runescape.wiki/w/Transcript:Wilough +// For some reason his face is small in dialogue. + +class Wilough : Script { + init { + npcOperate("Talk-to", WILOUGH_STRING_NAME) { + when (quest(GERTRUDES_CAT_STRING_NAME)) { + "completed" -> gertrudePostQuest() + "spoke_to_gertrude" -> lookingForInformationBranch() + "found_the_boys" -> gertrudeWhereFluffs() + "attempt_fluffs_pickup" -> gertrudeFluffsNotComeBack() + else -> gertrudeUnstarted() + } + } + } +} + +suspend fun Player.gertrudeUnstarted() { + player("Hello youngster!") + npc("I don't talk to strange old people.") + player("Hey who you calling old?! And strange?!") + npc("You obviously. Old, strange and stupid.") + player("Whatever.") +} + +private suspend fun Player.lookingForInformationBranch() { + gertrudeLookingForInformation() + choice { + option("Tell me sonny, or I will inform your mum you are a pair of criminals.") { + npc("W..wh..what?! Y..you wouldn't! Anyway, I'll deny it all and she'll be sure to believe me over some wandering killer like you.", largeHead = true) + player("I'm an upstanding citizen!") + npc("I'm her darling boy and you'd have to forget about her rewarding you. Hop it snitch.") + npc(npcId = SHILOP_STRING_NAME, "And I'm even more her favourite than he is!") + statement("You decide it's best not to aggravate the repulsive boys any more.") + } + option("What will make you tell me?") { + gertrudeFluffsCost() + } + option("Well never mind, it's Fluffs loss.") { + gertrudeFluffsLoss() + } + } +} + +suspend fun Player.gertrudeFluffsCost() { + npc("Well... Now you ask, I'm a bit short on cash.") + player("How much?") + npc("100 coins should cover it.") + player("100 coins! What sort of expensive things do you need that badly?") + npc("Well I Don't like chocolate and have you seen how much sweets cost to buy?") + player("Why should I pay you then, can you answer that as easily?") + npc("Obviously you shouldn't pay that much, but I won't help otherwise. I never liked that cat anyway, fussy scratchy thing it is, so what do you say?") + choice { + option("I'm not paying you a thing.") { + gertrudeLifeOfCrime() + } + option("Okay then, I'll pay.") { + gertrudePayChildren() + } + } +} + +suspend fun Player.gertrudePayChildren() { + player("Okay then, I'll pay, but I'll want you to tell your mother what a nice person I am.") + npc("What?") + player("I'll want you to tell your mother what a nice person I am so she rewards me for this search.") + npc("It's a deal.") + if (inventory.contains("coins", 100)) { + inventory.remove("coins", 100) + set(GERTRUDES_CAT_STRING_NAME, "found_the_boys") + set("gertrudes_cat_know_where_fluffs_is", true) + statement("You give the lad 100 coins.") + player("There you go, now where did you see Fluffs?") + npc(npcId = WILOUGH_STRING_NAME, "I play at an abandoned lumber mill to the north east. Just beyond the Jolly Boar Inn. I saw Fluffs running around in there.") + player("Anything else?") + npc(npcId = SHILOP_STRING_NAME, "Well, you'll have to find the broken fence to get in. I'm sure you can manage that.") + } else { + player("This is a bit embarrassing - I'll have to get some money first.") + npc("I'll be waiting.") + message("You can not afford that.") + } +} + +suspend fun Player.gertrudeLifeOfCrime() { + npc("Okay then, I'll find another way to make money. You only have yourself to blame if I'm forced into a life of crime.") +} + +suspend fun Player.gertrudeFluffsLoss() { + npc("I'm sure our mum will get over it.") +} + +suspend fun Player.gertrudeLookingForInformation() { + player("Hello there, I've been looking for you and it's important.") + npc("I didn't mean to take it! I just forgot to pay.") + player("What? I'm trying to help your mum find some cat called Fluffs.") + npc("Ohh...well, in that case I might be able to help. Fluffs followed me to my super secret hideout, I haven't seen her since. She's probably off eating small creatures somewhere.") + player("Where is this secret hideout? I really need to find that cat for your mum.") + npc("If I told you that, it wouldn't be a secret. What if I need to escape from the law? I need a hideout.") + player("From my limited knowledge of the law, they are not usually involved in manhunts for children.") + npc("Well it's still mine anyway, we need a place to relax sometimes. Those two little brothers at the house are just such babies.") +} + +suspend fun Player.gertrudePostQuest() { + player("Hello again.") + npc("You think you're tough do you?") + player("Pardon?") + npc("I can beat anyone up.") + player("Really?") + statement("The boy starts jumping around with his fists up. You decide it's best not to kill him yet.") // Source - Under "Trivia" last point: https://runescape.wiki/w/Wilough +} + +// Source: https://oldschool.runescape.wiki/w/Transcript:Gertrude%27s_Cat +suspend fun Player.gertrudeWhereFluffs() { + player("Where did you say you saw Fluffs?") + npc("Weren't you listening? I saw the flea bag in the old lumber mill just north east of here. Just walk past the Jolly Boar Inn and you should find it.") +} diff --git a/game/src/main/kotlin/content/quest/member/gertrudes_cat/DoogleSardineRecipe.kt b/game/src/main/kotlin/content/quest/member/gertrudes_cat/DoogleSardineRecipe.kt new file mode 100644 index 0000000000..dfa4688d1c --- /dev/null +++ b/game/src/main/kotlin/content/quest/member/gertrudes_cat/DoogleSardineRecipe.kt @@ -0,0 +1,29 @@ +package content.quest.member.gertrudes_cat + +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.inv.add +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.inv.remove + +class DoogleSardineRecipe : Script { + init { + /** + * Source: https://runescape.wiki/w/Transcript:Gertrude%27s_Cat + * "Use doogle leaves, raw sardine or sardine on Fluffs" + * Implies the recipe also permits cooked sardine + */ + itemOnItem("doogle_leaves", "raw_sardine") { _, _ -> + inventory.remove("doogle_leaves") + inventory.remove("raw_sardine") + message("You rub the doogle leaves over the sardine.") + inventory.add("doogle_sardine") + } + itemOnItem("doogle_leaves", "sardine") { _, _ -> + inventory.remove("doogle_leaves") + inventory.remove("sardine") + message("You rub the doogle leaves over the sardine.") + inventory.add("doogle_sardine") + } + } +} diff --git a/game/src/main/kotlin/content/quest/member/gertrudes_cat/GertrudesCat.kt b/game/src/main/kotlin/content/quest/member/gertrudes_cat/GertrudesCat.kt new file mode 100644 index 0000000000..ca6ed188b3 --- /dev/null +++ b/game/src/main/kotlin/content/quest/member/gertrudes_cat/GertrudesCat.kt @@ -0,0 +1,114 @@ +package content.quest.member.gertrudes_cat + +import content.quest.questJournal +import content.quest.questStage +import world.gregs.voidps.engine.Script + +// Source: https://runescape.wiki/w/Transcript:Gertrude%27s_Cat/Journal +// https://www.youtube.com/watch?v=_pZcnvI1l_Q from 2011 using a mix of RS3 and OSRS transcript and going as best as I can off of memory and videos. +const val GERTRUDES_CAT_STRING_NAME = "gertrudes_cat" +class GertrudesCat : Script { + init { + questJournalOpen(GERTRUDES_CAT_STRING_NAME) { + val progress = questStage(GERTRUDES_CAT_STRING_NAME) + val lines = mutableListOf() + + // Unstarted + if (progress == 0) { + lines += "I can start this quest by speaking to Gertrude." + lines += "She can be found in a house south of the road leading west" + lines += "out of Varrock." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + // Couldn't find anything official, this is just extrapolating. + lines += "I helped Gertrude to find her lost cat," + + // spoke_to_gertrude + if (progress == 1) { + lines += "I need to speak to Gertrude's sons," + lines += "Shilop and Wilough, in Varrock Marketplace." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + + lines += "I spoke with Gertrude's sons," + lines += "Shilop and Wilough, in Varrock Marketplace." + + // found_the_boys + if (progress == 2) { + lines += "I need to go to Shilop and Wilough's secret hideout" + lines += "in an abandoned Lumber Mill, to the north-east and find" + lines += "Fluffs, then return her to Gertrude." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + + // found_fluffs + if (progress == 3) { + lines += "I had a poke round the abandoned Lumber Mill and found" + lines += "Fluffs up a ladder. I now need to return Fluffs to Gertrude." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + + /** + * attempt_fluffs_pickup + */ + if (progress == 4) { + if (!get("gertrudes_cat_fluffs_milk", false)) { + lines += "I found Fluffs and fed her some milk but she still won't come back." + lines += "Now I should feed her some doogle sardines." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + if (!get("gertrudes_cat_fluffs_fed", false)) { + lines += "I found Fluffs and fed her some doogle sardines but she still won't come back." + lines += "Now I should feed her some milk." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + if (get("three_little_kittens_found", false)) { + lines += "I have found some kittens. " + lines += "I think I should see whether Fluffs is looking for them." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + if (get("gertrudes_cat_fluffs_milk", false) && get("gertrudes_cat_fluffs_fed", false)) { + lines += "I found Fluffs and fed her some milk and doogle sardine," + lines += "but she still won't come back. I should look around the Lumbermill Yard" + lines += "for a reason for this behaviour." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + lines += "I had a poke round the abandoned Lumber Mill and found" + lines += "Fluffs up a ladder. I now need to return Fluffs to" + lines += "Gertrude. " + lines += "I think Fluffs may be hungry or thirsty but I am not sure what" + lines += "she wants; perhaps Gertrude can help?" + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + /** + * End of attempt_fluffs_pickup + */ + + lines += "I fed her and returned her missing kitten," + + // fluffs_returned + if (progress == 5) { + lines += "I returned the kittens to Fluffs who then ran away." + lines += "I think I should see Gertrude in her house, west of Varrock," + lines += "and explain what has happened." + questJournal("Gertrude's Cat", lines) + return@questJournalOpen + } + + // completed + lines += "Gertrude gave me my very own pet for a reward." + lines += "" + lines += "QUEST COMPLETE!" + questJournal("Gertrude's Cat", lines) + } + } +} diff --git a/game/src/main/kotlin/content/quest/member/gertrudes_cat/KittenCrates.kt b/game/src/main/kotlin/content/quest/member/gertrudes_cat/KittenCrates.kt new file mode 100644 index 0000000000..2a1226bf08 --- /dev/null +++ b/game/src/main/kotlin/content/quest/member/gertrudes_cat/KittenCrates.kt @@ -0,0 +1,47 @@ +package content.quest.member.gertrudes_cat + +import content.area.misthalin.varrock.KITTENS_HIDING_SPOT +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.data.definition.Areas +import world.gregs.voidps.engine.inv.add +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.type.Tile + +const val KITTENS_FOUND = "three_little_kittens_found" + +class KittenCrates : Script { + init { + objectOperate("Search", "crate_17") { interact -> + val player = interact.player + val crate = interact.target + + if (interact.target.tile !in Areas["kitten_search_area"]) { + return@objectOperate + } + if (get(KITTENS_FOUND, false)) { + message("You search the crate.") + pause(1) + message("You find nothing.") + return@objectOperate + } + + val kittenCoords = get(KITTENS_HIDING_SPOT, -1) + var kittenCrate = Tile(kittenCoords) + if (crate.tile == kittenCrate) { + if (player.inventory.isFull()) { + message("You find three little kittens but you have no space for them in your backpack.") + return@objectOperate + } + set(KITTENS_FOUND, true) + player.inventory.add("three_little_kittens") + statement("You find three little kittens! You carefully place them in your backpack. This explains why Fluffs is so agitated.") + } else { + message("You search the crate.") + pause(1) + message("You find nothing. You can hear kittens mewing close by...") + } + } + } +} diff --git a/game/src/main/kotlin/content/quest/member/gertrudes_cat/ThreeLittleKittens.kt b/game/src/main/kotlin/content/quest/member/gertrudes_cat/ThreeLittleKittens.kt new file mode 100644 index 0000000000..a86bfe002f --- /dev/null +++ b/game/src/main/kotlin/content/quest/member/gertrudes_cat/ThreeLittleKittens.kt @@ -0,0 +1,35 @@ +package content.quest.member.gertrudes_cat + +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.character.npc.NPC +import world.gregs.voidps.engine.entity.character.npc.NPCs +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.inv.remove +import world.gregs.voidps.type.Tile + +private const val THREE_LITTLE_KITTENS_STRING_NAME = "three_little_kittens" + +class ThreeLittleKittens : Script { + init { + // This works, but if the player moves then the kittens aren't shown properly running away. + // Putting it in a queue does not fix it. + // If you drop the kittens up the ladder by Fluffs then the kittens will stick around. Or perhaps I delayed in doing something so the kittens spawned in, but performed the action before they despawned. + itemOption("Drop", THREE_LITTLE_KITTENS_STRING_NAME) { + val playerLoc = this.tile + inventory.remove(THREE_LITTLE_KITTENS_STRING_NAME) + set(KITTENS_FOUND, false) + message("You place the kittens on the floor.") + + pause(2) + val threeLittleKittens: NPC = NPCs.add(THREE_LITTLE_KITTENS_STRING_NAME, playerLoc) + threeLittleKittens.walkTo(Tile(3294, 3507)) + threeLittleKittens.say("Mew!") + + pause(2) + threeLittleKittens.despawn(0) + message("The kittens have run off.") + return@itemOption + } + } +}