diff --git a/Server/src/main/content/minigame/allfiredup/AFUBeacon.kt b/Server/src/main/content/minigame/allfiredup/AFUBeacon.kt index c97013a0f..901bec497 100644 --- a/Server/src/main/content/minigame/allfiredup/AFUBeacon.kt +++ b/Server/src/main/content/minigame/allfiredup/AFUBeacon.kt @@ -2,36 +2,35 @@ package content.minigame.allfiredup import core.api.* import core.game.node.entity.player.Player -import core.tools.SystemLogger import core.game.world.map.Location import core.tools.Log /** * Various data for beacons, such as varp and offset, required FM level, etc - * @author Ceikry + * @author Ceikry, Player Name */ enum class AFUBeacon(val title: String, val fmLevel: Int, val varbit: Int, val location: Location, val experience: Double, val keeper: Int = 0) { - RIVER_SALVE("",43,5146,Location.create(3396, 3464, 0),216.2,8065), - RAG_AND_BONE("",43,5147,Location.create(3343, 3510, 0),235.8,8066), - JOLLY_BOAR("",48,5148,Location.create(3278, 3525, 0), 193.8,8067), - NORTH_VARROCK_CASTLE("",53,5149,Location.create(3236, 3527, 0),178.5,8068), - GRAND_EXCHANGE("",59,5150,Location.create(3170, 3536, 0),194.3,8069), - EDGEVILLE("",62,5151,Location.create(3087, 3516, 0),86.7,8070), - MONASTERY("",68,5152,Location.create(3034, 3518, 0),224.4,8071), - GOBLIN_VILLAGE("",72,5153,Location.create(2968, 3516, 0),194.8,8072), - BURTHORPE("",76,5154,Location.create(2940, 3565, 0),195.3,8073), - DEATH_PLATEAU("",79,5155,Location.create(2944, 3622, 0),249.9,8074), - TROLLHEIM("",83,5156,Location.create(2939, 3680, 0),201.0,8075), - GWD("",87,5157,Location.create(2937, 3773, 0),255.0,8076), - TEMPLE("",89,5158,Location.create(2946, 3836, 0),198.9), - PLATEAU("",92,5159,Location.create(2964, 3931, 0),147.9); + RIVER_SALVE("near the River Salve", 43, 5146, Location.create(3396, 3464, 0), 216.2, 8065), + RAG_AND_BONE("near the Rag and Bone Man", 43, 5147, Location.create(3343, 3510, 0), 235.8, 8066), + JOLLY_BOAR("north of the Jolly Boar", 48, 5148, Location.create(3278, 3525, 0), 193.8, 8067), + NORTH_VARROCK_CASTLE("north of Varrock Palace", 53, 5149, Location.create(3236, 3527, 0), 178.5, 8068), + GRAND_EXCHANGE("north of the Grand Exchange", 59, 5150, Location.create(3170, 3536, 0), 194.3, 8069), + EDGEVILLE("near Edgeville", 62, 5151, Location.create(3087, 3516, 0), 86.7, 8070), + MONASTERY("near the Black Knights' Fortress", 68, 5152, Location.create(3034, 3518, 0), 224.4, 8071), + GOBLIN_VILLAGE("near Goblin Village", 72, 5153, Location.create(2968, 3516, 0), 194.8, 8072), + BURTHORPE("near Burthorpe", 76, 5154, Location.create(2940, 3565, 0), 195.3, 8073), + DEATH_PLATEAU("east of Death Plateau", 79, 5155, Location.create(2944, 3622, 0), 249.9, 8074), + TROLLHEIM("east of Trollheim", 83, 5156, Location.create(2939, 3680, 0), 201.0, 8075), + GWD("east of the God Wars dungeon temple", 87, 5157, Location.create(2937, 3773, 0), 255.0, 8076), + TEMPLE("north of the small temple in the Wilderness", 89, 5158, Location.create(2946, 3836, 0), 198.9), + PLATEAU("on the Frozen Waste Plateau", 92, 5159, Location.create(2964, 3931, 0), 147.9); companion object { fun forLocation(location: Location): AFUBeacon { for (beacon in values()) { if (beacon.location.equals(location)) return beacon } - return AFUBeacon.RIVER_SALVE.also { log(this::class.java, Log.WARN, "Unhandled Beacon Location ${location.toString()}") } + return AFUBeacon.RIVER_SALVE.also { log(this::class.java, Log.WARN, "Unhandled Beacon Location ${location.toString()}") } } fun resetAllBeacons(player: Player){ @@ -42,19 +41,19 @@ enum class AFUBeacon(val title: String, val fmLevel: Int, val varbit: Int, val l } fun light(player: Player){ - setVarbit(player, varbit, 2) + setVarbit(player, varbit, 2, true) } fun diminish(player: Player){ - setVarbit(player, varbit, 3) + setVarbit(player, varbit, 3, true) } fun extinguish(player: Player){ - setVarbit(player, varbit, 0) + setVarbit(player, varbit, 0, true) } fun lightGnomish(player: Player){ - setVarbit(player, varbit, 4) + setVarbit(player, varbit, 4, true) } fun fillWithLogs(player: Player){ diff --git a/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt b/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt index cd50cb9bf..1522add6c 100644 --- a/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt +++ b/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt @@ -4,13 +4,23 @@ 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.item.Item -import core.game.system.task.Pulse import core.game.world.update.flag.context.Animation import org.rs09.consts.Items import core.game.interaction.InteractionListener import core.game.interaction.IntType -import core.game.world.GameWorld import content.data.Quests +import core.api.delayScript +import core.api.getAttribute +import core.api.getOrStartTimer +import core.api.getQuestStage +import core.api.lock +import core.api.queueScript +import core.api.removeAttribute +import core.api.sendMessage +import core.api.setAttribute +import core.api.setQuestStage +import core.api.stopExecuting +import core.game.interaction.QueueStrength private val VALID_LOGS = intArrayOf(Items.LOGS_1511, Items.OAK_LOGS_1521,Items.WILLOW_LOGS_1519,Items.MAPLE_LOGS_1517,Items.YEW_LOGS_1515,Items.MAGIC_LOGS_1513) private val FILL_ANIM = Animation(9136) @@ -18,7 +28,7 @@ private val LIGHT_ANIM = Animation(7307) /** * Handles interactions for beacons - * @author Ceikry + * @author Ceikry, Player Name */ class AFUBeaconListeners : InteractionListener { @@ -86,112 +96,80 @@ class AFUBeaconListeners : InteractionListener { val logs = getLogs(player,20) if (logs.id != 0 && player.inventory.remove(logs)) { - player.lock() - - var session: AFUSession? = null - if(questComplete){ - session = player.getAttribute("afu-session", null) - if(session == null) { - session = AFUSession(player) - session.init() + lock(player, FILL_ANIM.duration) + queueScript(player, 0, QueueStrength.SOFT) { stage -> + if (stage == 1) { + player.animator.animate(FILL_ANIM) + return@queueScript delayScript(player, FILL_ANIM.duration) } + setAttribute(player, "/save:beacon:${beacon.ordinal}:logsId", logs.id) + beacon.fillWithLogs(player) + return@queueScript stopExecuting(player) } - - GameWorld.Pulser.submit(object : Pulse() { - var counter = 0 - override fun pulse(): Boolean { - when (counter++) { - 0 -> player.animator.animate(FILL_ANIM) - 1 -> { - beacon.fillWithLogs(player) - if(questComplete){ - session?.setLogs(beacon.ordinal,logs) - } - } - 2 -> player.unlock().also {player.animator.animate(Animation.RESET); return true } - } - return false - } - }) } else { player.dialogueInterpreter.sendDialogue("You need some logs to do this.") } } - fun lightBeacon(player: Player, beacon: AFUBeacon, questComplete: Boolean){ - var session: AFUSession? = null - if(questComplete){ - session = player.getAttribute("afu-session",null) - if(session == null) return - } - + fun lightBeacon(player: Player, beacon: AFUBeacon, questComplete: Boolean) { if(player.inventory.contains(Items.TINDERBOX_590,1)){ - player.lock() - GameWorld.Pulser.submit(object: Pulse(){ - var counter = 0 - override fun pulse(): Boolean { - when(counter++){ - 0 -> player.animator.animate(LIGHT_ANIM) - 1 -> { - beacon.light(player) - if(questComplete){ - session?.startTimer(beacon.ordinal) - if(session?.getLitBeacons() == 6 && !player.hasFireRing()){ - player.sendMessage("Congratulations on lighting 6 beacons at once! King Roald has something for you.") - player.setAttribute("/save:afu-mini:ring",true) - } - if(session?.getLitBeacons() == 10 && !player.hasFlameGloves()){ - player.sendMessage("Congratulations on lighting 10 beacons at once! King Roald has something for you.") - player.setAttribute("/save:afu-mini:gloves",true) - } - if(session?.getLitBeacons() == 14 && !player.hasInfernoAdze()){ - player.sendMessage("Congratulations on lighting all 14 beacons! King Roald has something special for you.") - player.setAttribute("/save:afu-mini:adze",true) - } - var experience = beacon.experience - experience += session?.getBonusExperience() ?: 0.0 - player.skills.addExperience(Skills.FIREMAKING,experience) - } else { - player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player, player.questRepository.getStage(Quests.ALL_FIRED_UP) + 10) - } - } - 2 -> player.unlock().also { return true } - } - return false + lock(player, LIGHT_ANIM.duration) + queueScript(player, 0, QueueStrength.SOFT) { stage -> + if (stage == 1) { + player.animator.animate(LIGHT_ANIM) + return@queueScript delayScript(player, LIGHT_ANIM.duration) } - }) + val logsId = getAttribute(player, "/save:beacon:${beacon.ordinal}:logsId", Items.LOGS_1511) + removeAttribute(player, "/save:beacon:${beacon.ordinal}:logsId") + beacon.light(player) + if (!questComplete) { + setQuestStage(player, Quests.ALL_FIRED_UP, getQuestStage(player, Quests.ALL_FIRED_UP) + 10) + return@queueScript stopExecuting(player) + } + val timer = getOrStartTimer(player) + timer.addTime(beacon.ordinal, logsId, 20) + val lit = timer.getLitBeacons() + if (lit == 6 && !player.hasFireRing()) { + sendMessage(player, "Congratulations on lighting 6 beacons at once! King Roald has something for you.") + setAttribute(player, "/save:afu-mini:ring", true) + } + if (lit == 10 && !player.hasFlameGloves()) { + sendMessage(player, "Congratulations on lighting 10 beacons at once! King Roald has something for you.") + setAttribute(player, "/save:afu-mini:gloves", true) + } + if (lit == 14 && !player.hasInfernoAdze()) { + sendMessage(player, "Congratulations on lighting all 14 beacons! King Roald has something special for you.") + setAttribute(player, "/save:afu-mini:adze", true) + } + val xp = beacon.experience + timer.getBonusExperience() + player.skills.addExperience(Skills.FIREMAKING, xp) + return@queueScript stopExecuting(player) + } } else { player.dialogueInterpreter.sendDialogue("You need a tinderbox to light this.") } } fun restoreBeacon(player: Player, beacon: AFUBeacon, questComplete: Boolean){ - var session: AFUSession? = null - if(questComplete){ - session = player.getAttribute("afu-session",null) - if(session == null) return - } - val logs = getLogs(player, 5) if (logs.id != 0 && player.inventory.remove(logs)) { - player.lock() - GameWorld.Pulser.submit(object: Pulse(){ - var counter = 0 - override fun pulse(): Boolean { - when(counter++){ - 0 -> player.animator.animate(FILL_ANIM) - 1 -> beacon.light(player).also { - if(questComplete){ - session?.refreshTimer(beacon,logs.id) - } else { - player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player, 80) - } - } - 2 -> player.unlock().also { return true } - } - return false + lock(player, FILL_ANIM.duration) + queueScript(player, 0, QueueStrength.SOFT) { stage -> + if (stage == 1) { + player.animator.animate(LIGHT_ANIM) + return@queueScript delayScript(player, LIGHT_ANIM.duration) } - }) + val backupLogsId = getAttribute(player, "/save:beacon:${beacon.ordinal}:backupLogsId", Items.LOGS_1511) + removeAttribute(player, "/save:beacon:${beacon.ordinal}:backupLogsId") + beacon.light(player) + if (!questComplete) { + setQuestStage(player, Quests.ALL_FIRED_UP, 80) + return@queueScript stopExecuting(player) + } + val timer = getOrStartTimer(player) + timer.addTime(beacon.ordinal, backupLogsId, 5) + return@queueScript stopExecuting(player) + } } else { player.dialogueInterpreter.sendDialogue("You need some logs to do this.") } diff --git a/Server/src/main/content/minigame/allfiredup/AFUSession.kt b/Server/src/main/content/minigame/allfiredup/AFUSession.kt deleted file mode 100644 index 1168a0f0f..000000000 --- a/Server/src/main/content/minigame/allfiredup/AFUSession.kt +++ /dev/null @@ -1,121 +0,0 @@ -package content.minigame.allfiredup - -import core.api.LogoutListener -import core.game.node.entity.player.Player -import core.game.node.item.Item -import core.game.system.task.Pulse -import core.game.world.GameWorld -import org.rs09.consts.Items -import core.tools.colorize - -/** - * Handles keeping track of lit beacons and their burn time remaining - * @author Ceikry - */ -class AFUSession(val player: Player? = null) : LogoutListener { - private val beaconTimers = Array(14){i -> BeaconTimer(0, AFUBeacon.values()[i]) } - private val logInventories = Array(14){Item(0,0)} - private val beaconWatched = Array(14){false} - private var isActive = false - - fun init() { - isActive = true - GameWorld.Pulser.submit(object: Pulse(){ - override fun pulse(): Boolean { - player!!.setAttribute("afu-pulse",this) - beaconTimers.forEach {timer -> - timer.ticks-- - if(timer.ticks == 300) timer.beacon.diminish(player).also { - if(beaconWatched[timer.beacon.ordinal]){ - beaconWatched[timer.beacon.ordinal] = false - timer.ticks += (getTicks(logInventories[timer.beacon.ordinal].id) * 5) - timer.beacon.light(player) - player.sendMessage(colorize("%RThe ${timer.beacon.name.toLowerCase().replace("_"," ")} watcher has used your backup logs.")) - } else { - player.sendMessage(colorize("%RThe ${timer.beacon.name.toLowerCase().replace("_", " ")} beacon is dying!")) - } - } - if(timer.ticks == 0) timer.beacon.extinguish(player).also { player.sendMessage(colorize("%RThe ${timer.beacon.name.toLowerCase().replace("_"," ")} beacon has gone out!")) } - } - return !isActive - } - }) - player!!.setAttribute("afu-session",this) - } - - fun getLitBeacons(): Int{ - return beaconTimers.count { it.ticks > 0 } - } - - fun end(){ - isActive = false - } - - fun setLogs(beaconIndex: Int, logs: Item){ - logInventories[beaconIndex] = logs - } - - fun startTimer(beaconIndex: Int){ - val ticks = getTicks(logInventories[beaconIndex].id) * 20 - logInventories[beaconIndex] = Item(0,0) - beaconTimers[beaconIndex].ticks = ticks - } - - fun refreshTimer(beacon: AFUBeacon, logID: Int){ - val ticks = getTicks(logID) * 5 - beaconTimers.forEach { - if(it.beacon.ordinal == beacon.ordinal) it.ticks += ticks - } - } - - fun setWatcher(index: Int, logs: Item){ - beaconWatched[index] = true - logInventories[index] = logs - } - - fun isWatched(index: Int): Boolean{ - return beaconWatched[index] - } - - fun getTicks(logID: Int): Int{ - val ticks = when(logID){ - Items.LOGS_1511 -> 65 - Items.OAK_LOGS_1521 -> 68 - Items.WILLOW_LOGS_1519 -> 73 - Items.MAPLE_LOGS_1517 -> 79 - Items.YEW_LOGS_1515 -> 83 - Items.MAGIC_LOGS_1513 -> 90 - else -> 0 - } - return ticks - } - - fun getBonusExperience(): Double{ - return when(getLitBeacons()){ - 1 -> 608.4 - 2 -> 1622.4 - 3 -> 1987.4 - 4 -> 2149.6 - 5 -> 2149.6 - 6 -> 2514.6 - 7 -> 2555.2 - 8 -> 2758.0 - 9 -> 2839.1 - 10 -> 3041.9 - 11 -> 3123.0 - 12 -> 3244.7 - 13 -> 3366.4 - 14 -> 4867.4 - else -> 0.0 - } - } - - override fun logout(player: Player) { - AFUBeacon.resetAllBeacons(player) - val session: AFUSession? = player.getAttribute("afu-session",null) - session?.end() - player.removeAttribute("afu-session") - } - - internal class BeaconTimer(var ticks: Int, val beacon: AFUBeacon) -} \ No newline at end of file diff --git a/Server/src/main/content/minigame/allfiredup/AFUTimer.kt b/Server/src/main/content/minigame/allfiredup/AFUTimer.kt new file mode 100644 index 000000000..b7ee735b4 --- /dev/null +++ b/Server/src/main/content/minigame/allfiredup/AFUTimer.kt @@ -0,0 +1,104 @@ +package content.minigame.allfiredup + +import core.api.getAttribute +import core.api.log +import core.api.removeAttribute +import core.api.sendMessage +import core.game.node.entity.Entity +import core.game.node.entity.player.Player +import core.game.system.timer.PersistTimer +import core.tools.Log +import core.tools.colorize +import org.json.simple.JSONArray +import org.json.simple.JSONObject +import org.rs09.consts.Items + +class AFUTimer : PersistTimer(1, "AFU timer", isSoft = true) { + private val burnTicks = Array(14) { 0 } + + fun addTime(index: Int, logsId: Int, numLogs: Int) { + val ticksPerLog = when (logsId) { + Items.LOGS_1511 -> 65 + Items.OAK_LOGS_1521 -> 68 + Items.WILLOW_LOGS_1519 -> 73 + Items.MAPLE_LOGS_1517 -> 79 + Items.YEW_LOGS_1515 -> 83 + Items.MAGIC_LOGS_1513 -> 90 + else -> 0 + } + burnTicks[index] += numLogs * ticksPerLog + } + + fun getBonusExperience(): Double { + return when (getLitBeacons()) { + 1 -> 608.4 + 2 -> 1622.4 + 3 -> 1987.4 + 4 -> 2149.6 + 5 -> 2149.6 + 6 -> 2514.6 + 7 -> 2555.2 + 8 -> 2758.0 + 9 -> 2839.1 + 10 -> 3041.9 + 11 -> 3123.0 + 12 -> 3244.7 + 13 -> 3366.4 + 14 -> 4867.4 + else -> 0.0 + } + } + + fun getLitBeacons(): Int { + return burnTicks.count { it > 0 } + } + + override fun save(root: JSONObject, entity: Entity) { + val beaconArray = JSONArray() + for (i in 0..13) { + beaconArray.add(burnTicks[i]) + } + root["beacons"] = beaconArray + } + + override fun parse(root: JSONObject, entity: Entity) { + val beacons = root["beacons"] as JSONArray + for (i in 0..13) { + burnTicks[i] = beacons[i].toString().toInt() + } + } + + override fun run(entity: Entity) : Boolean { + if (entity !is Player) { + log(this::class.java, Log.ERR, "How did a non-Player light an AFU beacon?") + return false + } + val player = entity + var keepRunning = false + for (i in 0..13) { + val beacon = AFUBeacon.values()[i] + if (burnTicks[i] > 0) { + burnTicks[i]-- + if (burnTicks[i] > 0) { + keepRunning = true + } + if (burnTicks[i] == 300) { + val backupLogsId = getAttribute(player, "/save:beacon:$i:backupLogsId", 0) + if (backupLogsId != 0) { + addTime(i, backupLogsId, 5) + removeAttribute(player, "/save:beacon:$i:backupLogsId") + sendMessage(player, colorize("%RThe beacon watcher ${beacon.title} has used your backup logs.")) + } else { + beacon.diminish(player) + sendMessage(player, colorize("%RThe beacon ${beacon.title} is dying!")) + } + } else if (burnTicks[i] == 0) { + beacon.extinguish(player) + removeAttribute(player, "/save:beacon:$i:logsId") + sendMessage(player, colorize("%RThe beacon ${beacon.title} has gone out!")) + } + } + } + return keepRunning + } +} \ No newline at end of file diff --git a/Server/src/main/content/minigame/allfiredup/BeaconTenderDialogue.kt b/Server/src/main/content/minigame/allfiredup/BeaconTenderDialogue.kt index f2b25db41..d2cf48053 100644 --- a/Server/src/main/content/minigame/allfiredup/BeaconTenderDialogue.kt +++ b/Server/src/main/content/minigame/allfiredup/BeaconTenderDialogue.kt @@ -1,13 +1,13 @@ package content.minigame.allfiredup -import core.ServerConstants import core.game.dialogue.* 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.item.Item import core.plugin.Initializable -import content.region.wilderness.dialogue.* +import core.api.getAttribute +import core.api.setAttribute import org.rs09.consts.Items private val VALID_LOGS = arrayOf(Items.LOGS_1511, Items.OAK_LOGS_1521, Items.WILLOW_LOGS_1519, Items.MAPLE_LOGS_1517, Items.YEW_LOGS_1515, Items.MAGIC_LOGS_1513) @@ -41,10 +41,9 @@ class BeaconTenderDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { val beacon = AFUBeacon.values()[index] val logs = getLogs(player,5) - val session: AFUSession? = player.getAttribute("afu-session",null) when(stage){ 0 -> player("Hello!").also { stage++ } - 1 -> if(beacon.getState(player) == BeaconState.LIT && session?.isWatched(index) == false){ + 1 -> if (beacon.getState(player) == BeaconState.LIT && getAttribute(player, "/save:beacon:${beacon.ordinal}:backupLogsId", 0) == 0) { options("Can you watch this beacon for me?","Nevermind.").also { stage = 10 } } else { npc("Carry on, adventurer.").also { stage = 1000 } @@ -62,7 +61,7 @@ class BeaconTenderDialogue(player: Player? = null) : DialoguePlugin(player) { 13 -> npc("Great, hand them over.").also { stage++ } 14 -> player("Here you go!").also { player.inventory.remove(logs) - session?.setWatcher(index,logs) + setAttribute(player, "/save:beacon:${beacon.ordinal}:backupLogsId", logs.id) stage = 1000 } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt index 29f85806b..b98445e9b 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt @@ -150,7 +150,6 @@ class AllFiredUp : Quest(Quests.ALL_FIRED_UP, 157, 156, 1){ player.skills.addExperience(Skills.FIREMAKING, 5500.0) player.inventory.add(Item(995,20000)) AFUBeacon.resetAllBeacons(player) - setVarbit(player, 1283, 0) player.questRepository.syncronizeTab(player) }