From 3145af75a6a6496d56aec640d492b854d8fcab54 Mon Sep 17 00:00:00 2001 From: Lila Hioh Date: Sat, 30 Jul 2022 15:37:39 +0000 Subject: [PATCH] Vinesweeper improvements Added missing animations NPCs perform their animations and chatlines in proper sequence and timing Added in the 2 other colors of bunnies, so now all 3 colors of bunnies are present Added in 3 new use-with item interactions: spade on hole, flag on hole, ogleroot on bunny Prevent bunnies from being double dipped for hunter XP Planting a flag now locks the player for the duration of the animation --- Server/data/configs/npc_configs.json | 182 +--------- Server/data/configs/npc_spawns.json | 10 +- .../activity/vinesweeper/Vinesweeper.kt | 333 ++++++++++++------ .../vinesweeper/VinesweeperDialogues.kt | 57 +-- 4 files changed, 266 insertions(+), 316 deletions(-) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index e4290d0bd..f7a2c44dc 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -63096,6 +63096,7 @@ "examine": "A hungry-looking rabbit.", "melee_animation": "0", "range_animation": "0", + "respawn_delay": "50", "defence_animation": "0", "magic_animation": "0", "death_animation": "0", @@ -63126,23 +63127,6 @@ "range_level": "1", "attack_level": "1" }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7129", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, { "examine": "A gnome farmer.", "melee_animation": "0", @@ -113532,6 +113516,7 @@ "examine": "A hungry-looking rabbit.", "melee_animation": "0", "range_animation": "0", + "respawn_delay": "50", "defence_animation": "0", "magic_animation": "0", "death_animation": "0", @@ -113540,24 +113525,7 @@ "safespot": null, "lifepoints": "10", "strength_level": "1", - "id": "7125", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7128", + "id": "7126", "aggressive": "true", "range_level": "1", "attack_level": "1" @@ -113579,23 +113547,6 @@ "range_level": "1", "attack_level": "1" }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7130", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, { "agg_radius": "64", "examine": "That's one big Ork... ", @@ -163399,6 +163350,7 @@ "examine": "A hungry-looking rabbit.", "melee_animation": "0", "range_animation": "0", + "respawn_delay": "50", "defence_animation": "0", "magic_animation": "0", "death_animation": "0", @@ -163407,58 +163359,7 @@ "safespot": null, "lifepoints": "10", "strength_level": "1", - "id": "7125", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7128", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7129", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7130", + "id": "7127", "aggressive": "true", "range_level": "1", "attack_level": "1" @@ -212255,74 +212156,6 @@ "range_level": "1", "attack_level": "1" }, - { - "examine": "A hungry-looking rabbit.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Rabbit", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7125", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7128", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7129", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, - { - "examine": "A gnome farmer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Farmer", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "7130", - "aggressive": "true", - "range_level": "1", - "attack_level": "1" - }, { "agg_radius": "64", "examine": "That's one big Ork... ", @@ -220454,11 +220287,6 @@ "name": "Farmer Blinkin", "id": "7131" }, - { - "examine": "Owner of this homestead.", - "name": "Mrs. Winkin", - "id": "7132" - }, { "examine": "The lady of the pet shop.", "name": "Pet shop owner", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 925d69d7d..73a4f36ca 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -10985,7 +10985,15 @@ }, { "npc_id": "7125", - "loc_data": "{1605,4702,0,1,0}-{1605,4720,0,1,0}-{1631,4730,0,1,0}-{1649,4730,0,1,0}-{1658,4705,0,1,0}-{1658,4687,0,1,0}-{1633,4678,0,1,0}-{1615,4678,0,1,0}" + "loc_data": "{1605,4702,0,1,0}-{1649,4730,0,1,0}" + }, + { + "npc_id": "7126", + "loc_data": "{1605,4720,0,1,0}-{1658,4705,0,1,0}-{1633,4678,0,1,0}" + }, + { + "npc_id": "7127", + "loc_data": "{1631,4730,0,1,0}-{1658,4687,0,1,0}-{1615,4678,0,1,0}" }, { "npc_id": "7128", diff --git a/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/Vinesweeper.kt b/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/Vinesweeper.kt index 086b5f32c..0fdd5f82c 100644 --- a/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/Vinesweeper.kt +++ b/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/Vinesweeper.kt @@ -1,25 +1,19 @@ package rs09.game.content.activity.vinesweeper import BlinkinDialogue +import FarmerDialogue.Companion.FARMER_FLAG_LINES import WinkinDialogue -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.DEAD_PLANT_OBJ -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.FARMERS -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.FARMER_CLEAR_RADIUS -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.HOLES -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.NUMBERS -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.RABBIT -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.SEED_LOCS -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.populateSeeds -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.scheduleNPCs -import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.sendUpdatedPoints import api.* import core.game.component.Component +import core.game.interaction.DestinationFlag +import core.game.interaction.MovementPulse import core.game.node.entity.Entity +import core.game.node.entity.combat.DeathTask import core.game.node.entity.impl.Projectile import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills; +import core.game.node.entity.skill.Skills import core.game.node.item.GroundItemManager import core.game.node.item.Item import core.game.node.scenery.Scenery @@ -27,16 +21,32 @@ import core.game.node.scenery.SceneryBuilder import core.game.system.task.Pulse import core.game.world.map.Location import core.game.world.map.RegionManager +import core.game.world.map.path.Pathfinder import core.game.world.map.zone.ZoneBorders -import core.game.world.update.flag.context.Animation; -import core.game.world.update.flag.context.Graphics; +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.game.world.update.flag.player.FaceLocationFlag import core.plugin.Initializable import core.tools.RandomFunction +import org.rs09.consts.Animations import org.rs09.consts.Components import org.rs09.consts.Items +import org.rs09.consts.NPCs +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.FARMERS +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.FARMER_CLEAR_RADIUS +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.HOLES +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.NUMBERS +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.RABBITS +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.SEED_LOCS +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.populateSeeds +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.scheduleNPCs +import rs09.game.content.activity.vinesweeper.Vinesweeper.Companion.sendPoints import rs09.game.interaction.InteractionListener import rs09.game.interaction.InterfaceListener -import rs09.game.world.GameWorld; +import rs09.game.world.GameWorld +import rs09.game.world.GameWorld.ticks +import org.rs09.consts.Graphics as Gfx +import org.rs09.consts.Scenery as Sceneries class Vinesweeper : InteractionListener, InterfaceListener, MapArea { override fun defineAreaBorders(): Array { @@ -74,7 +84,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { override fun defineListeners() { populateSeeds() - on(PORTAL, SCENERY, "enter") { player, _ -> + on(Sceneries.PORTAL_29534, SCENERY, "enter") { player, _ -> val x = player.getAttribute("vinesweeper:return-tele:x", 3052) val y = player.getAttribute("vinesweeper:return-tele:y", 3304) teleport(player, Location(x, y)) @@ -89,25 +99,47 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { // TODO (crash): authenticity player.sendMessage("You need a spade to dig here.") } else { - player.visualize(Animation(8709), Graphics(1543)) + player.visualize(Animation(Animations.HUMAN_VINESWEEPER_DIG_8709), Graphics(Gfx.VINESWEEPER_DIRT_DIG_1543)) dig(player, node.location) } return@on true } + onUseWith(SCENERY,Items.SPADE_952,*HOLES) { player, _, with -> + player.visualize(Animation(Animations.HUMAN_VINESWEEPER_DIG_8709), Graphics(Gfx.VINESWEEPER_DIRT_DIG_1543)) + dig(player, with.location) + return@onUseWith true + } on(HOLES, SCENERY, "flag") { player, node -> - if(player.inventory.remove(Item(Items.FLAG_12625, 1))) { - player.sendMessage("You add a flag to the patch.") - val scenery = node as Scenery - SceneryBuilder.replace(scenery, scenery.transform(FLAG_OBJ)) - scheduleNPCs(player, scenery.location, true, true) - } else { - // TODO (crash): authenticity - player.sendMessage("You do not have a flag to place in the patch.") + val hole = node as Scenery + var count = 0 + if(player.location != node.location) { + plantFlag(player,hole) + return@on true } + GameWorld.Pulser.submit(object : MovementPulse(player, hole, hole.destinationFlag) { + override fun pulse(): Boolean { + when(count++) { + 0 -> { + player.faceLocation(hole.location) + return false + } + 1 -> { + plantFlag(player,hole) + return true + } + } + return true + } + }) return@on true } + onUseWith(SCENERY,Items.FLAG_12625,*HOLES) { player, _, with -> + val hole = with as Scenery + plantFlag(player,hole) + return@onUseWith true + } on(HOLES, SCENERY, "inspect") { player, node -> - player.animate(Animation(8710)) + player.animate(Animation(Animations.HUMAN_INSPECT_HOLE_8710)) player.lock(5) GameWorld.Pulser.submit(object : Pulse(5) { override fun pulse(): Boolean { @@ -128,54 +160,42 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { }) return@on true } - on(MRS_WINKIN, NPC, "talk-to") { player, npc -> + on(NPCs.MRS_WINKIN_7132, NPC, "talk-to") { player, npc -> openDialogue(player, WinkinDialogue(), npc) return@on true } - on(MRS_WINKIN, NPC, "trade") { player, _ -> + on(NPCs.MRS_WINKIN_7132, NPC, "trade") { player, _ -> player.interfaceManager.open(Component(686)) return@on true } - on(MRS_WINKIN, NPC, "buy flags") { player, npc -> + on(NPCs.MRS_WINKIN_7132, NPC, "buy flags") { player, npc -> val dialogue = WinkinDialogue() dialogue.stage = 20 openDialogue(player, dialogue, npc) return@on true } - on(RABBIT, NPC, "feed") { player, node -> - if(player.inventory.remove(Item(Items.OGLEROOT_12624, 1))) { - val npc = node as NPC - // TODO: find burrow animation id - //npc.animate(9603) - npc.sendChat("Squeak!") - npc.lock(3) - GameWorld.Pulser.submit(object : Pulse(3) { - override fun pulse(): Boolean { - //npc.setInvisible(true) - player.skills.addExperience(Skills.HUNTER, 30.0) - npc.respawnTick = GameWorld.ticks + 50 - npc.location = npc.properties.spawnLocation - return true - } - }) - } else { - // TODO (crash): authenticity - player.sendMessage("You don't have any ogleroots to feed the rabbit.") - } + on(RABBITS, NPC, "feed") { player, node -> + val rabbit = node as NPC + feedRabbit(player,rabbit) return@on true } - on(FARMER_BLINKIN, NPC, "talk-to") { player, npc -> + onUseWith(NPC,Items.OGLEROOT_12624,*RABBITS) { player, _, with -> + val rabbit = with as NPC + feedRabbit(player,rabbit) + return@onUseWith true + } + on(NPCs.FARMER_BLINKIN_7131, NPC, "talk-to") { player, npc -> //player.interfaceManager.open(Component(TUTORIAL)) openDialogue(player, BlinkinDialogue(), npc) return@on true } - on(FARMER_BLINKIN, NPC, "buy-flags") { player, npc -> + on(NPCs.FARMER_BLINKIN_7131, NPC, "buy-flags") { player, npc -> val dialogue = BlinkinDialogue() dialogue.stage = 21 openDialogue(player, dialogue, npc) return@on true } - on(FARMER_BLINKIN, NPC, "buy-roots") { player, npc -> + on(NPCs.FARMER_BLINKIN_7131, NPC, "buy-roots") { player, npc -> val dialogue = BlinkinDialogue() dialogue.stage = 40 openDialogue(player, dialogue, npc) @@ -254,12 +274,9 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { companion object { val AVACH_NIMPORTO_LOC = Location.create(1637, 4709) - val PORTAL = 29534 - val SIGNS = intArrayOf(29461, 29462, 29463, 29464) - val HOLES = intArrayOf(29476, 29477, 29478) + val SIGNS = intArrayOf(Sceneries.INSTRUCTION_SIGN_29461, Sceneries.INSTRUCTION_SIGN_29462, Sceneries.INSTRUCTION_SIGN_29463, Sceneries.INSTRUCTION_SIGN_29464) + val HOLES = intArrayOf(Sceneries.HOLE_29476, Sceneries.HOLE_29477, Sceneries.HOLE_29478) val NUMBERS = intArrayOf(29447, 29448, 29449, 29450, 29451, 29452, 29453, 29454, 29455) - val DEAD_PLANT_OBJ = 29456 - val FLAG_OBJ = 29457 val IFACE = 686 val TRADE_FOR_XP_BUTTON = 53 @@ -337,10 +354,8 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { 29461 to 690 ) - val RABBIT = 7125 - val FARMERS = intArrayOf(7128, 7129, 7130) - val FARMER_BLINKIN = 7131 - val MRS_WINKIN = 7132 + val RABBITS = intArrayOf(NPCs.RABBIT_7125, NPCs.RABBIT_7126, NPCs.RABBIT_7127) + val FARMERS = intArrayOf(NPCs.FARMER_7128, NPCs.FARMER_7129, NPCs.FARMER_7130) val MAX_SEEDS = 300 val FARMER_CLEAR_RADIUS = 3 @@ -368,6 +383,51 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { } } + fun faceHole(player: Player, hole: Scenery) { + + } + fun plantFlag(player: Player, hole: Scenery) { + if(player.inventory.remove(Item(Items.FLAG_12625, 1))) { + player.lock() + player.visualize(Animation(Animations.HUMAN_PLANT_FLAG_8711),Graphics(Gfx.VINESWEEPER_PLANT_FLAG_1541)) + player.sendMessage("You add a flag to the patch.") + GameWorld.Pulser.submit(object : Pulse(2, player) { + override fun pulse(): Boolean { + SceneryBuilder.replace(hole, hole.transform(Sceneries.FLAG_29457)) + scheduleNPCs(player, hole.location, true, true) + player.unlock() + return true + } + }) + } else { + // TODO (crash): authenticity + player.sendMessage("You do not have a flag to place in the patch.") + } + } + + fun feedRabbit(player: Player, rabbit: NPC) { + val respawnDelay = 50 + if(rabbit.isInvisible || DeathTask.isDead(rabbit)) { return } + if(rabbit.getAttribute("dead", 0) > ticks) { return } + if(player.inventory.remove(Item(Items.OGLEROOT_12624, 1))) { + rabbit.setAttribute("dead",ticks + respawnDelay) + player.skills.addExperience(Skills.HUNTER, 30.0) + rabbit.sendChat("Squeak!") + rabbit.animate(Animation(Animations.RABBIT_EAT_OGLEROOT_8734)) + rabbit.lock(3) + GameWorld.Pulser.submit(object : Pulse(3, player) { + override fun pulse(): Boolean { + rabbit.finalizeDeath(player) + rabbit.properties.teleportLocation = rabbit.properties.spawnLocation + return true + } + }) + } else { + // TODO (crash): authenticity + player.sendMessage("You don't have any ogleroots to feed the rabbit.") + } + } + fun dig(player: Player, loc: Location) { if(isSeed(loc)) { val oldPoints = player.getAttribute("vinesweeper:points", 0) @@ -377,7 +437,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { scheduleNPCs(player, loc, false, false) val scenery = getScenery(loc) if(scenery != null) { - SceneryBuilder.replace(scenery, scenery.transform(DEAD_PLANT_OBJ)) + SceneryBuilder.replace(scenery, scenery.transform(Sceneries.DEAD_PLANT_29456)) } } else { player.incrementAttribute("/save:vinesweeper:points", 1) @@ -406,6 +466,20 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { } } + fun sendPoints(npc: NPC, dest: SeedDestination) { + val level = dest.player.skills.getStaticLevel(Skills.FARMING) + val points = RandomFunction.random(level, 4 * level) + dest.player.incrementAttribute("/save:vinesweeper:points", points) + dest.player.inventory.add(Item(Items.FLAG_12625, 1)) + sendUpdatedPoints(dest.player) + for (neighbor in RegionManager.getLocalPlayers(npc)) { + if (neighbor != dest.player) { + neighbor.incrementAttribute("/save:vinesweeper:points", points / 2) + sendUpdatedPoints(neighbor) + } + } + } + fun isHole(loc: Location): Boolean { val scenery = getScenery(loc) return scenery != null && HOLES.contains(scenery.id) @@ -413,7 +487,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { fun scheduleNPCs(player: Player, loc: Location, alive: Boolean, rabbit: Boolean) { val dest = SeedDestination(player, loc, alive) - val ids = if(rabbit) { intArrayOf(RABBIT, *FARMERS) } else { FARMERS } + val ids = if(rabbit) { RABBITS + FARMERS } else { FARMERS } for(npc in findLocalNPCs(player, ids, 30)) { if(npc is VinesweeperNPC) { npc.seedDestinations.add(dest) @@ -432,7 +506,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { player.audioManager.send(125) Projectile.create(npc, player, 109).send() npc.sendChat("Avach nimporto!") - GameWorld.Pulser.submit(object : Pulse(1) { + GameWorld.Pulser.submit(object : Pulse(1, player) { var counter = 0 override fun pulse(): Boolean { when (counter++) { @@ -459,7 +533,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { @Initializable class VinesweeperNPC : AbstractNPC { var seedDestinations: ArrayList = ArrayList(); - constructor() : super(RABBIT, null, true) {} + constructor() : super(RABBITS[0], null, true) {} private constructor(id: Int, location: Location) : super(id, location) {} override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC { return VinesweeperNPC(id, location) @@ -470,9 +544,8 @@ class VinesweeperNPC : AbstractNPC { } override fun getIds(): IntArray { - return intArrayOf(RABBIT, *FARMERS) + return RABBITS + FARMERS } - override fun handleTickActions() { val dest = seedDestinations.find { sd -> sd.loc == location } if(dest != null) { @@ -484,24 +557,13 @@ class VinesweeperNPC : AbstractNPC { } val scenery = getScenery(dest.loc) if(scenery != null) { - if(id == RABBIT) { - val replacement = if(SEED_LOCS.contains(dest.loc)) { DEAD_PLANT_OBJ } else { HOLES[0] } - SceneryBuilder.replace(scenery, scenery.transform(replacement)) - scheduleNPCs(dest.player, dest.loc, alive = false, rabbit = false) + if(id in RABBITS) { + handleRabbitSeed(scenery, dest) } else { if(dest.alive) { handleFarmerFlag(scenery, dest) } else { - sendChat("Hmm. Looks like there's a plant here.") - lock(3) - GameWorld.Pulser.submit(object : Pulse(3) { - override fun pulse(): Boolean { - sendChat("Gracious me! This one's dead") - SceneryBuilder.replace(scenery, scenery.transform(HOLES[0])) - farmerClear(dest) - return true - } - }) + handleFarmerSeed(scenery, dest) } } } @@ -519,48 +581,91 @@ class VinesweeperNPC : AbstractNPC { } } - fun handleFarmerFlag(scenery: Scenery, dest: Vinesweeper.SeedDestination) { - sendChat("Ah, another flag to clear. Let's see what's there.") - lock(3) - animate(Animation(451)) + fun handleRabbitSeed(scenery: Scenery, dest: Vinesweeper.SeedDestination) { if(SEED_LOCS.contains(dest.loc)) { - val npc = this - GameWorld.Pulser.submit(object : Pulse(3) { - override fun pulse(): Boolean { - sendChat("Ah! A seed. Points for everyone near me!") - val level = dest.player.skills.getStaticLevel(Skills.FARMING) - val points = RandomFunction.random(level, 4 * level) - dest.player.incrementAttribute("/save:vinesweeper:points", points) - dest.player.inventory.add(Item(Items.FLAG_12625, 1)) - sendUpdatedPoints(dest.player) - for(neighbor in RegionManager.getLocalPlayers(npc)) { - if(neighbor != dest.player) { - neighbor.incrementAttribute("/save:vinesweeper:points", points / 2) - sendUpdatedPoints(neighbor) - } - } - SceneryBuilder.replace(scenery, scenery.transform(HOLES[0])) - farmerClear(dest) - return true - } - }) + val replacement = Sceneries.DEAD_PLANT_29456 + lock(4) + animate(Animation(Animations.RABBIT_EAT_SEED_8718)) + SceneryBuilder.replace(scenery, scenery.transform(replacement)) + scheduleNPCs(dest.player, dest.loc, alive = false, rabbit = false) } else { - SceneryBuilder.replace(scenery, scenery.transform(HOLES[0])) - var i = 0 - val lines = arrayOf("Hmm, no seeds planted here, I'm afraid.", "I'll have to keep this 'ere flag. Sorry.") - GameWorld.Pulser.submit(object : Pulse(3) { - override fun pulse(): Boolean { - sendChat(lines[i++]) - return i >= lines.size - } - }) + scheduleNPCs(dest.player, dest.loc, alive = true, rabbit = false) } } + fun handleFarmerSeed(scenery: Scenery, dest: Vinesweeper.SeedDestination) { + lock() + var i = 0 + animate(Animation(Animations.GNOME_FARMER_DIG_SEED_8730)) + GameWorld.Pulser.submit(object: Pulse(3) { + override fun pulse(): Boolean { + when(i++) { + 0 -> { + sendChat(FARMER_FLAG_LINES.FIND_PLANT.line) + } + 1 -> { + animate(Animation(Animations.GNOME_FARMER_SPADE_SMACK_8732)) + sendChat(FARMER_FLAG_LINES.DEAD_PLANT.line) + SceneryBuilder.replace(scenery, scenery.transform(HOLES[0])) + } + 2 -> { + animate(Animation(Animations.GNOME_FARMER_CLEAR_HOLES_8724)) + farmerClear(dest) + } + 3 -> { + unlock() + return true + } + } + return false + } + }) + } + fun handleFarmerFlag(scenery: Scenery, dest: Vinesweeper.SeedDestination) { + val npc = this + lock() + var i = 0 + animate(Animation(Animations.GNOME_FARMER_DIG_FLAG_8725)) + GameWorld.Pulser.submit(object: Pulse(3) { + override fun pulse(): Boolean { + when(i++) { + 0 -> { + sendChat(FARMER_FLAG_LINES.FIND_FLAG.line) + } + 1 -> { + SceneryBuilder.replace(scenery, scenery.transform(HOLES[0])) + if(SEED_LOCS.contains(dest.loc)) { + sendChat(FARMER_FLAG_LINES.FIND_SEED.line) + animate(Animation(Animations.GNOME_FARMER_HOORAY_8731)) + sendPoints(npc,dest) + i++ + } else { + sendChat(FARMER_FLAG_LINES.NO_SEED.line) + } + } + 2 -> { + sendChat(FARMER_FLAG_LINES.KEEP_FLAG.line) + i++ + } + 3 -> { + animate(Animation(Animations.GNOME_FARMER_CLEAR_HOLES_8724)) + farmerClear(dest) + + } + 4 -> { + unlock() + return true + } + } + return false + } + }) + } + fun farmerClear(dest: Vinesweeper.SeedDestination) { for(dx in -FARMER_CLEAR_RADIUS..FARMER_CLEAR_RADIUS) { for(dy in -FARMER_CLEAR_RADIUS..FARMER_CLEAR_RADIUS) { val toClear = getScenery(dest.loc.transform(dx, dy, 0)) - if(toClear != null && intArrayOf(DEAD_PLANT_OBJ, *NUMBERS).contains(toClear.id)) { + if(toClear != null && intArrayOf(Sceneries.DEAD_PLANT_29456, *NUMBERS).contains(toClear.id)) { SceneryBuilder.replace(toClear, toClear.transform(HOLES[0])) } } diff --git a/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/VinesweeperDialogues.kt b/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/VinesweeperDialogues.kt index f6a89460f..dfb8443ee 100644 --- a/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/VinesweeperDialogues.kt +++ b/Server/src/main/kotlin/rs09/game/content/activity/vinesweeper/VinesweeperDialogues.kt @@ -7,31 +7,40 @@ import org.rs09.consts.Items import rs09.game.content.dialogue.DialogueFile import rs09.tools.END_DIALOGUE -val BLINKIN_FLAG_LINES = arrayOf( - "Let me check for ya.", - "Flags? It appears ya don't have enough room for 'em. Make some space and talk to me again.", - "Ah! First things first. One of the farm lads dropped off some flags for ya. Ya can have them back. Here ya go.", - "Righty-ho! Ya can have a total of 10 flags. To get yerself a full set of flags'll cost ya %d gold pieces. Would ya like to buy these flags?", - "Here ya go, then.", - "Flags? It appears ya don't have enough room for 'em. Make some space and talk to me again.", - "Ya don't have the coins fer these, I'm afraid! Come back when yer a little bit richer p'raps?", - "Right y'are then! See ya.", - "It looks like ya got all the flags ya need right now. Ya don't need to buy any more." - ) - -val WINKIN_FLAG_LINES = arrayOf( - "Let me check for you.", - "I'm sorry dear, you don't appear to have enough room. Make some space and talk to me again.", - "Ah! First things first. One of the farmers dropped off some flags for you. You can have them back. Here you go.", - "Alright. You can have a total of 10 flags. To obtain a full set of flags will cost you %d coins. Would you like to buy these flags?", - "Here you are then, dear.", - "I'm sorry dear, you don't appear to have enough room. Make some space and talk to me again.", - "I'm afraid it looks like you don't have enough money, dear. Come back and see me again when you have a bit more.", - "Ok, dear. Goodbye.", - "It looks like you have all the flags you need. You don't need to buy any more." - ) - abstract class FarmerDialogue : DialogueFile() { + + companion object { + val BLINKIN_FLAG_LINES = arrayOf( + "Let me check for ya.", + "Flags? It appears ya don't have enough room for 'em. Make some space and talk to me again.", + "Ah! First things first. One of the farm lads dropped off some flags for ya. Ya can have them back. Here ya go.", + "Righty-ho! Ya can have a total of 10 flags. To get yerself a full set of flags'll cost ya %d gold pieces. Would ya like to buy these flags?", + "Here ya go, then.", + "Flags? It appears ya don't have enough room for 'em. Make some space and talk to me again.", + "Ya don't have the coins fer these, I'm afraid! Come back when yer a little bit richer p'raps?", + "Right y'are then! See ya.", + "It looks like ya got all the flags ya need right now. Ya don't need to buy any more." + ) + val WINKIN_FLAG_LINES = arrayOf( + "Let me check for you.", + "I'm sorry dear, you don't appear to have enough room. Make some space and talk to me again.", + "Ah! First things first. One of the farmers dropped off some flags for you. You can have them back. Here you go.", + "Alright. You can have a total of 10 flags. To obtain a full set of flags will cost you %d coins. Would you like to buy these flags?", + "Here you are then, dear.", + "I'm sorry dear, you don't appear to have enough room. Make some space and talk to me again.", + "I'm afraid it looks like you don't have enough money, dear. Come back and see me again when you have a bit more.", + "Ok, dear. Goodbye.", + "It looks like you have all the flags you need. You don't need to buy any more." + ) + enum class FARMER_FLAG_LINES(val line: String) { + FIND_FLAG("Ah, another flag to clear. Let's see what's there."), + FIND_SEED("Ah! A seed. Points for everyone near me!"), + NO_SEED("Hmm, no seeds planted here, I'm afraid."), + KEEP_FLAG("I'll have to keep this 'ere flag. Sorry."), + FIND_PLANT("Hmm. Looks like there's a plant here."), + DEAD_PLANT("Gracious me! This one's dead") + } + } fun handleFlags(componentID: Int, buttonID: Int, lines: Array) { when(stage) { 20 -> npcl(lines[0]).also { stage++ }