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
This commit is contained in:
Lila Hioh 2022-07-30 15:37:39 +00:00 committed by Ryan
parent 4ff7d347b5
commit 3145af75a6
4 changed files with 266 additions and 316 deletions

View file

@ -63096,6 +63096,7 @@
"examine": "A hungry-looking rabbit.", "examine": "A hungry-looking rabbit.",
"melee_animation": "0", "melee_animation": "0",
"range_animation": "0", "range_animation": "0",
"respawn_delay": "50",
"defence_animation": "0", "defence_animation": "0",
"magic_animation": "0", "magic_animation": "0",
"death_animation": "0", "death_animation": "0",
@ -63126,23 +63127,6 @@
"range_level": "1", "range_level": "1",
"attack_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.", "examine": "A gnome farmer.",
"melee_animation": "0", "melee_animation": "0",
@ -113532,6 +113516,7 @@
"examine": "A hungry-looking rabbit.", "examine": "A hungry-looking rabbit.",
"melee_animation": "0", "melee_animation": "0",
"range_animation": "0", "range_animation": "0",
"respawn_delay": "50",
"defence_animation": "0", "defence_animation": "0",
"magic_animation": "0", "magic_animation": "0",
"death_animation": "0", "death_animation": "0",
@ -113540,24 +113525,7 @@
"safespot": null, "safespot": null,
"lifepoints": "10", "lifepoints": "10",
"strength_level": "1", "strength_level": "1",
"id": "7125", "id": "7126",
"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", "aggressive": "true",
"range_level": "1", "range_level": "1",
"attack_level": "1" "attack_level": "1"
@ -113579,23 +113547,6 @@
"range_level": "1", "range_level": "1",
"attack_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", "agg_radius": "64",
"examine": "That's one big Ork... ", "examine": "That's one big Ork... ",
@ -163399,6 +163350,7 @@
"examine": "A hungry-looking rabbit.", "examine": "A hungry-looking rabbit.",
"melee_animation": "0", "melee_animation": "0",
"range_animation": "0", "range_animation": "0",
"respawn_delay": "50",
"defence_animation": "0", "defence_animation": "0",
"magic_animation": "0", "magic_animation": "0",
"death_animation": "0", "death_animation": "0",
@ -163407,58 +163359,7 @@
"safespot": null, "safespot": null,
"lifepoints": "10", "lifepoints": "10",
"strength_level": "1", "strength_level": "1",
"id": "7125", "id": "7127",
"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", "aggressive": "true",
"range_level": "1", "range_level": "1",
"attack_level": "1" "attack_level": "1"
@ -212255,74 +212156,6 @@
"range_level": "1", "range_level": "1",
"attack_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", "agg_radius": "64",
"examine": "That's one big Ork... ", "examine": "That's one big Ork... ",
@ -220454,11 +220287,6 @@
"name": "Farmer Blinkin", "name": "Farmer Blinkin",
"id": "7131" "id": "7131"
}, },
{
"examine": "Owner of this homestead.",
"name": "Mrs. Winkin",
"id": "7132"
},
{ {
"examine": "The lady of the pet shop.", "examine": "The lady of the pet shop.",
"name": "Pet shop owner", "name": "Pet shop owner",

View file

@ -10985,7 +10985,15 @@
}, },
{ {
"npc_id": "7125", "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", "npc_id": "7128",

View file

@ -1,25 +1,19 @@
package rs09.game.content.activity.vinesweeper package rs09.game.content.activity.vinesweeper
import BlinkinDialogue import BlinkinDialogue
import FarmerDialogue.Companion.FARMER_FLAG_LINES
import WinkinDialogue 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 api.*
import core.game.component.Component 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.Entity
import core.game.node.entity.combat.DeathTask
import core.game.node.entity.impl.Projectile import core.game.node.entity.impl.Projectile
import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player 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.GroundItemManager
import core.game.node.item.Item import core.game.node.item.Item
import core.game.node.scenery.Scenery 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.system.task.Pulse
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.RegionManager import core.game.world.map.RegionManager
import core.game.world.map.path.Pathfinder
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics; import core.game.world.update.flag.context.Graphics
import core.game.world.update.flag.player.FaceLocationFlag
import core.plugin.Initializable import core.plugin.Initializable
import core.tools.RandomFunction import core.tools.RandomFunction
import org.rs09.consts.Animations
import org.rs09.consts.Components import org.rs09.consts.Components
import org.rs09.consts.Items 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.InteractionListener
import rs09.game.interaction.InterfaceListener 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 { class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
override fun defineAreaBorders(): Array<ZoneBorders> { override fun defineAreaBorders(): Array<ZoneBorders> {
@ -74,7 +84,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
override fun defineListeners() { override fun defineListeners() {
populateSeeds() populateSeeds()
on(PORTAL, SCENERY, "enter") { player, _ -> on(Sceneries.PORTAL_29534, SCENERY, "enter") { player, _ ->
val x = player.getAttribute("vinesweeper:return-tele:x", 3052) val x = player.getAttribute("vinesweeper:return-tele:x", 3052)
val y = player.getAttribute("vinesweeper:return-tele:y", 3304) val y = player.getAttribute("vinesweeper:return-tele:y", 3304)
teleport(player, Location(x, y)) teleport(player, Location(x, y))
@ -89,25 +99,47 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
// TODO (crash): authenticity // TODO (crash): authenticity
player.sendMessage("You need a spade to dig here.") player.sendMessage("You need a spade to dig here.")
} else { } 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) dig(player, node.location)
} }
return@on true 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 -> on(HOLES, SCENERY, "flag") { player, node ->
if(player.inventory.remove(Item(Items.FLAG_12625, 1))) { val hole = node as Scenery
player.sendMessage("You add a flag to the patch.") var count = 0
val scenery = node as Scenery if(player.location != node.location) {
SceneryBuilder.replace(scenery, scenery.transform(FLAG_OBJ)) plantFlag(player,hole)
scheduleNPCs(player, scenery.location, true, true) return@on true
} else {
// TODO (crash): authenticity
player.sendMessage("You do not have a flag to place in the patch.")
} }
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 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 -> on(HOLES, SCENERY, "inspect") { player, node ->
player.animate(Animation(8710)) player.animate(Animation(Animations.HUMAN_INSPECT_HOLE_8710))
player.lock(5) player.lock(5)
GameWorld.Pulser.submit(object : Pulse(5) { GameWorld.Pulser.submit(object : Pulse(5) {
override fun pulse(): Boolean { override fun pulse(): Boolean {
@ -128,54 +160,42 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
}) })
return@on true 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) openDialogue(player, WinkinDialogue(), npc)
return@on true return@on true
} }
on(MRS_WINKIN, NPC, "trade") { player, _ -> on(NPCs.MRS_WINKIN_7132, NPC, "trade") { player, _ ->
player.interfaceManager.open(Component(686)) player.interfaceManager.open(Component(686))
return@on true return@on true
} }
on(MRS_WINKIN, NPC, "buy flags") { player, npc -> on(NPCs.MRS_WINKIN_7132, NPC, "buy flags") { player, npc ->
val dialogue = WinkinDialogue() val dialogue = WinkinDialogue()
dialogue.stage = 20 dialogue.stage = 20
openDialogue(player, dialogue, npc) openDialogue(player, dialogue, npc)
return@on true return@on true
} }
on(RABBIT, NPC, "feed") { player, node -> on(RABBITS, NPC, "feed") { player, node ->
if(player.inventory.remove(Item(Items.OGLEROOT_12624, 1))) { val rabbit = node as NPC
val npc = node as NPC feedRabbit(player,rabbit)
// 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.")
}
return@on true 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)) //player.interfaceManager.open(Component(TUTORIAL))
openDialogue(player, BlinkinDialogue(), npc) openDialogue(player, BlinkinDialogue(), npc)
return@on true return@on true
} }
on(FARMER_BLINKIN, NPC, "buy-flags") { player, npc -> on(NPCs.FARMER_BLINKIN_7131, NPC, "buy-flags") { player, npc ->
val dialogue = BlinkinDialogue() val dialogue = BlinkinDialogue()
dialogue.stage = 21 dialogue.stage = 21
openDialogue(player, dialogue, npc) openDialogue(player, dialogue, npc)
return@on true return@on true
} }
on(FARMER_BLINKIN, NPC, "buy-roots") { player, npc -> on(NPCs.FARMER_BLINKIN_7131, NPC, "buy-roots") { player, npc ->
val dialogue = BlinkinDialogue() val dialogue = BlinkinDialogue()
dialogue.stage = 40 dialogue.stage = 40
openDialogue(player, dialogue, npc) openDialogue(player, dialogue, npc)
@ -254,12 +274,9 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
companion object companion object
{ {
val AVACH_NIMPORTO_LOC = Location.create(1637, 4709) val AVACH_NIMPORTO_LOC = Location.create(1637, 4709)
val PORTAL = 29534 val SIGNS = intArrayOf(Sceneries.INSTRUCTION_SIGN_29461, Sceneries.INSTRUCTION_SIGN_29462, Sceneries.INSTRUCTION_SIGN_29463, Sceneries.INSTRUCTION_SIGN_29464)
val SIGNS = intArrayOf(29461, 29462, 29463, 29464) val HOLES = intArrayOf(Sceneries.HOLE_29476, Sceneries.HOLE_29477, Sceneries.HOLE_29478)
val HOLES = intArrayOf(29476, 29477, 29478)
val NUMBERS = intArrayOf(29447, 29448, 29449, 29450, 29451, 29452, 29453, 29454, 29455) 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 IFACE = 686
val TRADE_FOR_XP_BUTTON = 53 val TRADE_FOR_XP_BUTTON = 53
@ -337,10 +354,8 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
29461 to 690 29461 to 690
) )
val RABBIT = 7125 val RABBITS = intArrayOf(NPCs.RABBIT_7125, NPCs.RABBIT_7126, NPCs.RABBIT_7127)
val FARMERS = intArrayOf(7128, 7129, 7130) val FARMERS = intArrayOf(NPCs.FARMER_7128, NPCs.FARMER_7129, NPCs.FARMER_7130)
val FARMER_BLINKIN = 7131
val MRS_WINKIN = 7132
val MAX_SEEDS = 300 val MAX_SEEDS = 300
val FARMER_CLEAR_RADIUS = 3 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) { fun dig(player: Player, loc: Location) {
if(isSeed(loc)) { if(isSeed(loc)) {
val oldPoints = player.getAttribute("vinesweeper:points", 0) val oldPoints = player.getAttribute("vinesweeper:points", 0)
@ -377,7 +437,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
scheduleNPCs(player, loc, false, false) scheduleNPCs(player, loc, false, false)
val scenery = getScenery(loc) val scenery = getScenery(loc)
if(scenery != null) { if(scenery != null) {
SceneryBuilder.replace(scenery, scenery.transform(DEAD_PLANT_OBJ)) SceneryBuilder.replace(scenery, scenery.transform(Sceneries.DEAD_PLANT_29456))
} }
} else { } else {
player.incrementAttribute("/save:vinesweeper:points", 1) 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 { fun isHole(loc: Location): Boolean {
val scenery = getScenery(loc) val scenery = getScenery(loc)
return scenery != null && HOLES.contains(scenery.id) 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) { fun scheduleNPCs(player: Player, loc: Location, alive: Boolean, rabbit: Boolean) {
val dest = SeedDestination(player, loc, alive) 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)) { for(npc in findLocalNPCs(player, ids, 30)) {
if(npc is VinesweeperNPC) { if(npc is VinesweeperNPC) {
npc.seedDestinations.add(dest) npc.seedDestinations.add(dest)
@ -432,7 +506,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
player.audioManager.send(125) player.audioManager.send(125)
Projectile.create(npc, player, 109).send() Projectile.create(npc, player, 109).send()
npc.sendChat("Avach nimporto!") npc.sendChat("Avach nimporto!")
GameWorld.Pulser.submit(object : Pulse(1) { GameWorld.Pulser.submit(object : Pulse(1, player) {
var counter = 0 var counter = 0
override fun pulse(): Boolean { override fun pulse(): Boolean {
when (counter++) { when (counter++) {
@ -459,7 +533,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
@Initializable @Initializable
class VinesweeperNPC : AbstractNPC { class VinesweeperNPC : AbstractNPC {
var seedDestinations: ArrayList<Vinesweeper.SeedDestination> = ArrayList(); var seedDestinations: ArrayList<Vinesweeper.SeedDestination> = ArrayList();
constructor() : super(RABBIT, null, true) {} constructor() : super(RABBITS[0], null, true) {}
private constructor(id: Int, location: Location) : super(id, location) {} private constructor(id: Int, location: Location) : super(id, location) {}
override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC { override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC {
return VinesweeperNPC(id, location) return VinesweeperNPC(id, location)
@ -470,9 +544,8 @@ class VinesweeperNPC : AbstractNPC {
} }
override fun getIds(): IntArray { override fun getIds(): IntArray {
return intArrayOf(RABBIT, *FARMERS) return RABBITS + FARMERS
} }
override fun handleTickActions() { override fun handleTickActions() {
val dest = seedDestinations.find { sd -> sd.loc == location } val dest = seedDestinations.find { sd -> sd.loc == location }
if(dest != null) { if(dest != null) {
@ -484,24 +557,13 @@ class VinesweeperNPC : AbstractNPC {
} }
val scenery = getScenery(dest.loc) val scenery = getScenery(dest.loc)
if(scenery != null) { if(scenery != null) {
if(id == RABBIT) { if(id in RABBITS) {
val replacement = if(SEED_LOCS.contains(dest.loc)) { DEAD_PLANT_OBJ } else { HOLES[0] } handleRabbitSeed(scenery, dest)
SceneryBuilder.replace(scenery, scenery.transform(replacement))
scheduleNPCs(dest.player, dest.loc, alive = false, rabbit = false)
} else { } else {
if(dest.alive) { if(dest.alive) {
handleFarmerFlag(scenery, dest) handleFarmerFlag(scenery, dest)
} else { } else {
sendChat("Hmm. Looks like there's a plant here.") handleFarmerSeed(scenery, dest)
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
}
})
} }
} }
} }
@ -519,48 +581,91 @@ class VinesweeperNPC : AbstractNPC {
} }
} }
fun handleFarmerFlag(scenery: Scenery, dest: Vinesweeper.SeedDestination) { fun handleRabbitSeed(scenery: Scenery, dest: Vinesweeper.SeedDestination) {
sendChat("Ah, another flag to clear. Let's see what's there.")
lock(3)
animate(Animation(451))
if(SEED_LOCS.contains(dest.loc)) { if(SEED_LOCS.contains(dest.loc)) {
val npc = this val replacement = Sceneries.DEAD_PLANT_29456
GameWorld.Pulser.submit(object : Pulse(3) { lock(4)
override fun pulse(): Boolean { animate(Animation(Animations.RABBIT_EAT_SEED_8718))
sendChat("Ah! A seed. Points for everyone near me!") SceneryBuilder.replace(scenery, scenery.transform(replacement))
val level = dest.player.skills.getStaticLevel(Skills.FARMING) scheduleNPCs(dest.player, dest.loc, alive = false, rabbit = false)
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
}
})
} else { } else {
SceneryBuilder.replace(scenery, scenery.transform(HOLES[0])) scheduleNPCs(dest.player, dest.loc, alive = true, rabbit = false)
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
}
})
} }
} }
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) { fun farmerClear(dest: Vinesweeper.SeedDestination) {
for(dx in -FARMER_CLEAR_RADIUS..FARMER_CLEAR_RADIUS) { for(dx in -FARMER_CLEAR_RADIUS..FARMER_CLEAR_RADIUS) {
for(dy 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)) 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])) SceneryBuilder.replace(toClear, toClear.transform(HOLES[0]))
} }
} }

View file

@ -7,31 +7,40 @@ import org.rs09.consts.Items
import rs09.game.content.dialogue.DialogueFile import rs09.game.content.dialogue.DialogueFile
import rs09.tools.END_DIALOGUE 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() { 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<String>) { fun handleFlags(componentID: Int, buttonID: Int, lines: Array<String>) {
when(stage) { when(stage) {
20 -> npcl(lines[0]).also { stage++ } 20 -> npcl(lines[0]).also { stage++ }