mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-09 16:45:44 -07:00
Converted vinesweeper to new systems
This commit is contained in:
parent
6553ed1e4c
commit
4557ac03de
5 changed files with 379 additions and 376 deletions
|
|
@ -13,6 +13,6 @@ interface MapArea {
|
|||
fun defineAreaBorders() : Array<ZoneBorders>
|
||||
fun getRestrictions() : Array<ZoneRestriction> {return arrayOf()}
|
||||
fun areaEnter(entity: Entity) {}
|
||||
fun areaLeave(entity: Entity) {}
|
||||
fun areaLeave(entity: Entity, logout: Boolean) {}
|
||||
fun entityStep(entity: Entity, location: Location, lastLocation: Location) {}
|
||||
}
|
||||
|
|
@ -1,3 +1,17 @@
|
|||
package rs09.game.content.activity.vinesweeper
|
||||
|
||||
import BlinkinDialogue
|
||||
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.node.entity.Entity
|
||||
|
|
@ -13,164 +27,52 @@ 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.zone.MapZone
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneBuilder
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Items
|
||||
import rs09.game.content.dialogue.DialogueFile
|
||||
import rs09.game.interaction.InteractionListener
|
||||
import rs09.game.interaction.InterfaceListener
|
||||
import rs09.game.world.GameWorld;
|
||||
|
||||
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 NUMBERS = intArrayOf(29447, 29448, 29449, 29450, 29451, 29452, 29453, 29454, 29455)
|
||||
val DEAD_PLANT_OBJ = 29456
|
||||
val FLAG_OBJ = 29457
|
||||
class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return arrayOf(getRegionBorders(6473))
|
||||
}
|
||||
|
||||
val TUTORIAL = 685
|
||||
override fun areaEnter(entity: Entity) {
|
||||
if(entity is Player)
|
||||
{
|
||||
openOverlay(entity, Components.RABBIT_OVERLAY_689)
|
||||
sendUpdatedPoints(entity)
|
||||
}
|
||||
}
|
||||
|
||||
val INSTRUCTION_SIGNS = hashMapOf(
|
||||
29463 to 684,
|
||||
29464 to 687,
|
||||
29462 to 688,
|
||||
29461 to 690
|
||||
)
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
if(entity is Player) {
|
||||
entity.interfaceManager.closeOverlay()
|
||||
if(!logout) {
|
||||
entity.sendMessage("Winkin's Farm thanks you for your visit.")
|
||||
entity.sendMessage("Leftover ogleroots and flags have been returned to the establishment.")
|
||||
entity.sendMessage("You have been reimbursed at a rate of 10gp per ogleroot and the flags have been collected.")
|
||||
val flags = entity.inventory.getAmount(Item(Items.FLAG_12625))
|
||||
if(flags > 0) {
|
||||
entity.setAttribute("/save:vinesweeper:stored-flags", flags)
|
||||
entity.inventory.remove(Item(Items.FLAG_12625, flags))
|
||||
}
|
||||
val roots = entity.inventory.getAmount(Item(Items.OGLEROOT_12624))
|
||||
if(roots > 0) {
|
||||
entity.inventory.remove(Item(Items.OGLEROOT_12624, roots))
|
||||
entity.inventory.add(Item(Items.COINS_995, roots * 10))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val RABBIT = 7125
|
||||
val FARMERS = intArrayOf(7128, 7129, 7130)
|
||||
val FARMER_BLINKIN = 7131
|
||||
val MRS_WINKIN = 7132
|
||||
|
||||
val MAX_SEEDS = 300
|
||||
val FARMER_CLEAR_RADIUS = 3
|
||||
val VINESWEEPER_BORDERS = ZoneBorders(1600,4672,1663,4735)
|
||||
|
||||
fun sendUpdatedPoints(player: Player) {
|
||||
val points = player.getAttribute("vinesweeper:points", 0);
|
||||
player.varpManager.get(1195).setVarbit(6, points).send(player)
|
||||
}
|
||||
|
||||
data class SeedDestination(val player: Player, val loc: Location, val alive: Boolean) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if(other is SeedDestination) {
|
||||
return loc.equals(other.loc)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
var SEED_LOCS: HashSet<Location> = HashSet()
|
||||
|
||||
fun isSeed(loc: Location): Boolean {
|
||||
val scenery = getScenery(loc)
|
||||
return scenery != null && SEED_LOCS.contains(scenery.location)
|
||||
}
|
||||
|
||||
fun populateSeeds() {
|
||||
while(SEED_LOCS.size < MAX_SEEDS) {
|
||||
val loc = VINESWEEPER_BORDERS.getRandomLoc()
|
||||
val scenery = getScenery(loc)
|
||||
if(scenery != null && HOLES.contains(scenery.id)) {
|
||||
SEED_LOCS.add(loc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isHole(loc: Location): Boolean {
|
||||
val scenery = getScenery(loc)
|
||||
return scenery != null && HOLES.contains(scenery.id)
|
||||
}
|
||||
|
||||
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 }
|
||||
for(npc in findLocalNPCs(player, ids, 30)) {
|
||||
if(npc is VinesweeperNPC) {
|
||||
npc.seedDestinations.add(dest)
|
||||
npc.resetWalk()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object VinesweeperTeleport {
|
||||
@JvmStatic
|
||||
fun teleport(npc: NPC, player: Player) {
|
||||
npc.animate(Animation(437))
|
||||
npc.faceTemporary(player, 1)
|
||||
npc.graphics(Graphics(108))
|
||||
player.lock()
|
||||
player.audioManager.send(125)
|
||||
Projectile.create(npc, player, 109).send()
|
||||
npc.sendChat("Avach nimporto!")
|
||||
GameWorld.Pulser.submit(object : Pulse(1) {
|
||||
var counter = 0
|
||||
override fun pulse(): Boolean {
|
||||
when (counter++) {
|
||||
2 -> {
|
||||
player.savedData.globalData.essenceTeleporter = npc.id
|
||||
player.setAttribute("/save:vinesweeper:return-tele:x", npc.location.x)
|
||||
player.setAttribute("/save:vinesweeper:return-tele:y", npc.location.y)
|
||||
player.properties.teleportLocation = AVACH_NIMPORTO_LOC
|
||||
}
|
||||
3 -> {
|
||||
player.graphics(Graphics(110))
|
||||
player.unlock()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class VinesweeperListener : InteractionListener {
|
||||
fun dig(player: Player, loc: Location) {
|
||||
if(isSeed(loc)) {
|
||||
val oldPoints = player.getAttribute("vinesweeper:points", 0)
|
||||
player.setAttribute("/save:vinesweeper:points", Math.max(oldPoints-10, 0))
|
||||
sendUpdatedPoints(player)
|
||||
player.sendMessage("Oh dear! It looks like you dug up a potato seed by mistake.");
|
||||
scheduleNPCs(player, loc, false, false)
|
||||
val scenery = getScenery(loc)
|
||||
if(scenery != null) {
|
||||
SceneryBuilder.replace(scenery, scenery.transform(DEAD_PLANT_OBJ))
|
||||
}
|
||||
} else {
|
||||
player.incrementAttribute("/save:vinesweeper:points", 1)
|
||||
sendUpdatedPoints(player)
|
||||
var count = 0
|
||||
for(dx in -1..1) {
|
||||
for(dy in -1..1) {
|
||||
if(isSeed(loc.transform(dx, dy, 0))) {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
val scenery = getScenery(loc)
|
||||
if(scenery != null) {
|
||||
SceneryBuilder.replace(scenery, scenery.transform(NUMBERS[count]))
|
||||
}
|
||||
if(count == 0) {
|
||||
for(dx in -1..1) {
|
||||
for(dy in -1..1) {
|
||||
val newLoc = loc.transform(dx, dy, 0)
|
||||
if(isHole(newLoc))
|
||||
dig(player, newLoc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun defineListeners() {
|
||||
ZoneBuilder.configure(VinesweeperZone())
|
||||
populateSeeds()
|
||||
on(PORTAL, SCENERY, "enter") { player, _ ->
|
||||
val x = player.getAttribute("vinesweeper:return-tele:x", 3052)
|
||||
|
|
@ -280,166 +182,85 @@ class VinesweeperListener : InteractionListener {
|
|||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Initializable
|
||||
class VinesweeperNPC : AbstractNPC {
|
||||
fun compareDistance(a: SeedDestination, b: SeedDestination): Int {
|
||||
val da = a.loc.getDistance(location).toInt()
|
||||
val db = b.loc.getDistance(location).toInt()
|
||||
return db - da
|
||||
override fun defineInterfaceListeners() {
|
||||
on(IFACE) { player, _, opcode, buttonID, _, _ ->
|
||||
when(opcode) {
|
||||
Opcode.VALUE.value -> {
|
||||
when(buttonID) {
|
||||
TRADE_FOR_XP_BUTTON -> {
|
||||
player.packetDispatch.sendInterfaceConfig(686, 60, false)
|
||||
}
|
||||
XP_CONFIRM -> {
|
||||
player.packetDispatch.sendInterfaceConfig(686, 60, true)
|
||||
val level = player.skills.getStaticLevel(Skills.FARMING)
|
||||
// TODO: more precise formula
|
||||
val points_per_xp = if (level < 40) { 2.0*(40.0 - level.toDouble())/10.0 } else { 1.0 }
|
||||
val points = player.getAttribute("vinesweeper:points", 0)
|
||||
val xp = points / points_per_xp;
|
||||
player.skills.addExperience(Skills.FARMING, xp)
|
||||
player.setAttribute("/save:vinesweeper:points", 0)
|
||||
sendUpdatedPoints(player)
|
||||
|
||||
}
|
||||
XP_DENY -> {
|
||||
player.packetDispatch.sendInterfaceConfig(686, 60, true)
|
||||
}
|
||||
else -> {
|
||||
val reward = REWARDS[buttonID] ?: return@on true
|
||||
player.sendMessage("${Item(reward.itemID).name}: ${reward.points} vinesweeper points")
|
||||
}
|
||||
}
|
||||
}
|
||||
Opcode.BUY1.value -> {
|
||||
buy(player, buttonID, 1)
|
||||
return@on true
|
||||
}
|
||||
Opcode.BUY5.value -> {
|
||||
buy(player, buttonID, 5)
|
||||
return@on true
|
||||
}
|
||||
Opcode.BUY10.value -> {
|
||||
buy(player, buttonID, 10)
|
||||
return@on true
|
||||
}
|
||||
Opcode.BUYX.value -> {
|
||||
player.setAttribute("runscript") { amount: Int ->
|
||||
buy(player, buttonID, amount)
|
||||
}
|
||||
player.dialogueInterpreter.sendInput(false, "Enter the amount:")
|
||||
return@on true
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
var seedDestinations: ArrayList<SeedDestination> = ArrayList();
|
||||
constructor() : super(RABBIT, 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)
|
||||
}
|
||||
|
||||
init {
|
||||
walkRadius = 22
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(RABBIT, *FARMERS)
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
val dest = seedDestinations.find { sd -> sd.loc == location }
|
||||
if(dest != null) {
|
||||
for(npc in RegionManager.getRegionPlane(location).npcs) {
|
||||
if(npc is VinesweeperNPC) {
|
||||
npc.seedDestinations.remove(dest)
|
||||
npc.resetWalk()
|
||||
}
|
||||
}
|
||||
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, false, false)
|
||||
data class SeedDestination(val player: Player, val loc: Location, val alive: Boolean) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if(other is SeedDestination) {
|
||||
loc == other.loc
|
||||
} 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
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
seedDestinations.remove(dest)
|
||||
}
|
||||
super.handleTickActions()
|
||||
}
|
||||
|
||||
override fun getMovementDestination(): Location? {
|
||||
if(seedDestinations.size > 0) {
|
||||
seedDestinations.sortBy { a -> a.loc.getDistance(location).toInt() }
|
||||
return seedDestinations.first().loc
|
||||
} else {
|
||||
return super.getMovementDestination()
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun handleFarmerFlag(scenery: Scenery, dest: SeedDestination) {
|
||||
sendChat("Ah, another flag to clear. Let's see what's there.")
|
||||
lock(3)
|
||||
animate(Animation(451))
|
||||
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
|
||||
}
|
||||
})
|
||||
} 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
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
fun farmerClear(dest: 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)) {
|
||||
SceneryBuilder.replace(toClear, toClear.transform(HOLES[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
SEED_LOCS.remove(dest.loc)
|
||||
populateSeeds()
|
||||
}
|
||||
}
|
||||
|
||||
class VinesweeperZone : MapZone("Vinesweeper", true) {
|
||||
override fun enter(e: Entity): Boolean {
|
||||
if(e is Player) {
|
||||
e.interfaceManager.openOverlay(Component(689))
|
||||
sendUpdatedPoints(e)
|
||||
}
|
||||
|
||||
return super.enter(e)
|
||||
}
|
||||
|
||||
override fun leave(e: Entity, logout: Boolean): Boolean {
|
||||
if(e is Player) {
|
||||
e.interfaceManager.closeOverlay()
|
||||
if(!logout) {
|
||||
e.sendMessage("Winkin's Farm thanks you for your visit.")
|
||||
e.sendMessage("Leftover ogleroots and flags have been returned to the establishment.")
|
||||
e.sendMessage("You have been reimbursed at a rate of 10gp per ogleroot and the flags have been collected.")
|
||||
val flags = e.inventory.getAmount(Item(Items.FLAG_12625))
|
||||
if(flags > 0) {
|
||||
e.setAttribute("/save:vinesweeper:stored-flags", flags)
|
||||
e.inventory.remove(Item(Items.FLAG_12625, flags))
|
||||
}
|
||||
val roots = e.inventory.getAmount(Item(Items.OGLEROOT_12624))
|
||||
if(roots > 0) {
|
||||
e.inventory.remove(Item(Items.OGLEROOT_12624, roots))
|
||||
e.inventory.add(Item(Items.COINS_995, roots * 10))
|
||||
}
|
||||
override fun hashCode(): Int {
|
||||
return loc.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
return super.leave(e, logout)
|
||||
}
|
||||
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 NUMBERS = intArrayOf(29447, 29448, 29449, 29450, 29451, 29452, 29453, 29454, 29455)
|
||||
val DEAD_PLANT_OBJ = 29456
|
||||
val FLAG_OBJ = 29457
|
||||
|
||||
override fun configure() {
|
||||
super.registerRegion(6473)
|
||||
}
|
||||
}
|
||||
|
||||
class VinesweeperRewards : InterfaceListener {
|
||||
val IFACE = 686
|
||||
val TRADE_FOR_XP_BUTTON = 53
|
||||
val XP_CONFIRM = 72
|
||||
|
|
@ -506,66 +327,247 @@ class VinesweeperRewards : InterfaceListener {
|
|||
}
|
||||
}
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
onOpen(IFACE) { _, _ ->
|
||||
/*for((buttonID, reward) in REWARDS) {
|
||||
sendItemOnInterface(player, IFACE, buttonID, reward.itemID, 5)
|
||||
}*/
|
||||
//player.packetDispatch.sendRunScript(2003, "")
|
||||
return@onOpen true
|
||||
}
|
||||
on(IFACE) { player, _, opcode, buttonID, _, _ ->
|
||||
when(opcode) {
|
||||
Opcode.VALUE.value -> {
|
||||
when(buttonID) {
|
||||
TRADE_FOR_XP_BUTTON -> {
|
||||
player.packetDispatch.sendInterfaceConfig(686, 60, false)
|
||||
}
|
||||
XP_CONFIRM -> {
|
||||
player.packetDispatch.sendInterfaceConfig(686, 60, true)
|
||||
val level = player.skills.getStaticLevel(Skills.FARMING)
|
||||
// TODO: more precise formula
|
||||
val points_per_xp = if (level < 40) { 2.0*(40.0 - level.toDouble())/10.0 } else { 1.0 }
|
||||
val points = player.getAttribute("vinesweeper:points", 0)
|
||||
val xp = points / points_per_xp;
|
||||
player.skills.addExperience(Skills.FARMING, xp)
|
||||
player.setAttribute("/save:vinesweeper:points", 0)
|
||||
sendUpdatedPoints(player)
|
||||
|
||||
val TUTORIAL = 685
|
||||
|
||||
val INSTRUCTION_SIGNS = hashMapOf(
|
||||
29463 to 684,
|
||||
29464 to 687,
|
||||
29462 to 688,
|
||||
29461 to 690
|
||||
)
|
||||
|
||||
val RABBIT = 7125
|
||||
val FARMERS = intArrayOf(7128, 7129, 7130)
|
||||
val FARMER_BLINKIN = 7131
|
||||
val MRS_WINKIN = 7132
|
||||
|
||||
val MAX_SEEDS = 300
|
||||
val FARMER_CLEAR_RADIUS = 3
|
||||
val VINESWEEPER_BORDERS = ZoneBorders(1600,4672,1663,4735)
|
||||
|
||||
fun sendUpdatedPoints(player: Player) {
|
||||
val points = player.getAttribute("vinesweeper:points", 0);
|
||||
player.varpManager.get(1195).setVarbit(6, points).send(player)
|
||||
}
|
||||
XP_DENY -> {
|
||||
player.packetDispatch.sendInterfaceConfig(686, 60, true)
|
||||
|
||||
var SEED_LOCS: HashSet<Location> = HashSet()
|
||||
|
||||
fun isSeed(loc: Location): Boolean {
|
||||
val scenery = getScenery(loc)
|
||||
return scenery != null && SEED_LOCS.contains(scenery.location)
|
||||
}
|
||||
else -> {
|
||||
val reward = REWARDS[buttonID] ?: return@on true
|
||||
player.sendMessage("${Item(reward.itemID).name}: ${reward.points} vinesweeper points")
|
||||
|
||||
fun populateSeeds() {
|
||||
while(SEED_LOCS.size < MAX_SEEDS) {
|
||||
val loc = VINESWEEPER_BORDERS.getRandomLoc()
|
||||
val scenery = getScenery(loc)
|
||||
if(scenery != null && HOLES.contains(scenery.id)) {
|
||||
SEED_LOCS.add(loc)
|
||||
}
|
||||
}
|
||||
}
|
||||
Opcode.BUY1.value -> {
|
||||
buy(player, buttonID, 1)
|
||||
return@on true
|
||||
|
||||
fun dig(player: Player, loc: Location) {
|
||||
if(isSeed(loc)) {
|
||||
val oldPoints = player.getAttribute("vinesweeper:points", 0)
|
||||
player.setAttribute("/save:vinesweeper:points", Math.max(oldPoints-10, 0))
|
||||
sendUpdatedPoints(player)
|
||||
player.sendMessage("Oh dear! It looks like you dug up a potato seed by mistake.");
|
||||
scheduleNPCs(player, loc, false, false)
|
||||
val scenery = getScenery(loc)
|
||||
if(scenery != null) {
|
||||
SceneryBuilder.replace(scenery, scenery.transform(DEAD_PLANT_OBJ))
|
||||
}
|
||||
Opcode.BUY5.value -> {
|
||||
buy(player, buttonID, 5)
|
||||
return@on true
|
||||
} else {
|
||||
player.incrementAttribute("/save:vinesweeper:points", 1)
|
||||
sendUpdatedPoints(player)
|
||||
var count = 0
|
||||
for(dx in -1..1) {
|
||||
for(dy in -1..1) {
|
||||
if(isSeed(loc.transform(dx, dy, 0))) {
|
||||
count += 1
|
||||
}
|
||||
Opcode.BUY10.value -> {
|
||||
buy(player, buttonID, 10)
|
||||
return@on true
|
||||
}
|
||||
Opcode.BUYX.value -> {
|
||||
player.setAttribute("runscript") { amount: Int ->
|
||||
buy(player, buttonID, amount)
|
||||
}
|
||||
player.dialogueInterpreter.sendInput(false, "Enter the amount:")
|
||||
return@on true
|
||||
val scenery = getScenery(loc)
|
||||
if(scenery != null) {
|
||||
SceneryBuilder.replace(scenery, scenery.transform(NUMBERS[count]))
|
||||
}
|
||||
else -> {}
|
||||
if(count == 0) {
|
||||
for(dx in -1..1) {
|
||||
for(dy in -1..1) {
|
||||
val newLoc = loc.transform(dx, dy, 0)
|
||||
if(isHole(newLoc))
|
||||
dig(player, newLoc)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isHole(loc: Location): Boolean {
|
||||
val scenery = getScenery(loc)
|
||||
return scenery != null && HOLES.contains(scenery.id)
|
||||
}
|
||||
|
||||
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 }
|
||||
for(npc in findLocalNPCs(player, ids, 30)) {
|
||||
if(npc is VinesweeperNPC) {
|
||||
npc.seedDestinations.add(dest)
|
||||
npc.resetWalk()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object VinesweeperTeleport {
|
||||
@JvmStatic
|
||||
fun teleport(npc: NPC, player: Player) {
|
||||
npc.animate(Animation(437))
|
||||
npc.faceTemporary(player, 1)
|
||||
npc.graphics(Graphics(108))
|
||||
player.lock()
|
||||
player.audioManager.send(125)
|
||||
Projectile.create(npc, player, 109).send()
|
||||
npc.sendChat("Avach nimporto!")
|
||||
GameWorld.Pulser.submit(object : Pulse(1) {
|
||||
var counter = 0
|
||||
override fun pulse(): Boolean {
|
||||
when (counter++) {
|
||||
2 -> {
|
||||
player.savedData.globalData.essenceTeleporter = npc.id
|
||||
player.setAttribute("/save:vinesweeper:return-tele:x", npc.location.x)
|
||||
player.setAttribute("/save:vinesweeper:return-tele:y", npc.location.y)
|
||||
player.properties.teleportLocation = AVACH_NIMPORTO_LOC
|
||||
}
|
||||
3 -> {
|
||||
player.graphics(Graphics(110))
|
||||
player.unlock()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Initializable
|
||||
class VinesweeperNPC : AbstractNPC {
|
||||
var seedDestinations: ArrayList<Vinesweeper.SeedDestination> = ArrayList();
|
||||
constructor() : super(RABBIT, 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)
|
||||
}
|
||||
|
||||
init {
|
||||
walkRadius = 22
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(RABBIT, *FARMERS)
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
val dest = seedDestinations.find { sd -> sd.loc == location }
|
||||
if(dest != null) {
|
||||
for(npc in RegionManager.getRegionPlane(location).npcs) {
|
||||
if(npc is VinesweeperNPC) {
|
||||
npc.seedDestinations.remove(dest)
|
||||
npc.resetWalk()
|
||||
}
|
||||
}
|
||||
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)
|
||||
} 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
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
seedDestinations.remove(dest)
|
||||
}
|
||||
super.handleTickActions()
|
||||
}
|
||||
|
||||
override fun getMovementDestination(): Location? {
|
||||
if(seedDestinations.size > 0) {
|
||||
seedDestinations.sortBy { a -> a.loc.getDistance(location).toInt() }
|
||||
return seedDestinations.first().loc
|
||||
} else {
|
||||
return super.getMovementDestination()
|
||||
}
|
||||
}
|
||||
|
||||
fun handleFarmerFlag(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)) {
|
||||
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
|
||||
}
|
||||
})
|
||||
} 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
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
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)) {
|
||||
SceneryBuilder.replace(toClear, toClear.transform(HOLES[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
SEED_LOCS.remove(dest.loc)
|
||||
populateSeeds()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class FarmingPatchZone : MapArea, TickListener {
|
|||
}
|
||||
}
|
||||
|
||||
override fun areaLeave(entity: Entity) {
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
if(entity is Player)
|
||||
playersInZone.remove(entity)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import core.plugin.Initializable
|
|||
import core.plugin.Plugin
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.NPCs
|
||||
import rs09.game.content.activity.vinesweeper.Vinesweeper
|
||||
|
||||
val TL_IDS = arrayOf(NPCs.TOOL_LEPRECHAUN_3021,NPCs.GOTH_LEPRECHAUN_8000,NPCs.TOOL_LEPRECHAUN_4965,NPCs.TECLYN_2861)
|
||||
@Initializable
|
||||
|
|
@ -28,7 +29,7 @@ class ToolLeprechaunHandler : OptionHandler() {
|
|||
node ?: return false
|
||||
when(option){
|
||||
"exchange" -> player?.interfaceManager?.open(Component(Components.FARMING_TOOLS_125))
|
||||
"teleport" -> VinesweeperTeleport.teleport(node!! as NPC, player!!)
|
||||
"teleport" -> Vinesweeper.Companion.VinesweeperTeleport.teleport(node!! as NPC, player!!)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ object ClassScanner {
|
|||
}
|
||||
|
||||
override fun leave(e: Entity?, logout: Boolean): Boolean {
|
||||
clazz.areaLeave(e ?: return super.leave(null, logout))
|
||||
clazz.areaLeave(e ?: return super.leave(null, logout), logout)
|
||||
return super.leave(e, logout)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue