Rewrote Ava's device handling

Rewrote the handling for both the accumulator and the attractor in new systems
Fixed a bug that would cause the devices to attract unwanted items at inappropriate times
Fixed a bug that prevented equip listeners from firing on login
This commit is contained in:
Ceikry
2022-08-20 08:10:26 +00:00
committed by Ryan
parent e7804fdd42
commit 69aa7a7557
8 changed files with 140 additions and 194 deletions
+11
View File
@@ -2084,4 +2084,15 @@ fun clearHintIcon(player: Player) {
val slot = getAttribute(player, "hinticon", -1)
player.removeAttribute("hinticon")
HintIconManager.removeHintIcon(player, slot)
}
/**
* Gets the equipment slot the item belongs to
* @param item the Id of the item to check
* @return the EquipmentSlot, or null if the item cannot be equipped, or has no slot defined.
*/
fun equipSlot(item: Int) : EquipmentSlot? {
return EquipmentSlot
.values()
.getOrNull(itemDefinition(item).getConfiguration(ItemConfigParser.EQUIP_SLOT, -1))
}
@@ -0,0 +1,119 @@
package rs09.game.node.entity.equipment
import api.*
import api.events.EventHook
import api.events.TickEvent
import core.game.node.entity.Entity
import core.game.node.entity.combat.equipment.Ammunition
import core.game.node.entity.player.Player
import org.rs09.consts.Items
import rs09.game.Event
import rs09.game.interaction.InteractionListener
import rs09.game.system.config.ItemConfigParser
import rs09.tools.secondsToTicks
import rs09.tools.stringtools.colorize
/**
* Handles Ava's device
* @source https://runescape.wiki/w/Ava%27s_accumulator?oldid=2097350
*/
class AvasDevice : InteractionListener, EventHook<TickEvent> {
override fun defineListeners() {
onEquip(devices) { player, _ ->
if (!isQuestComplete(player, "Animal Magnetism")) {
sendMessage(player, "You need to complete Animal Magnetism to equip this.")
return@onEquip false
}
if (attractEnabled(player))
player.hook(Event.Tick, this)
setAttribute(player, LAST_TICK, getWorldTicks()) //set this on equip so can't be spam-re-equipped to spawn infinite items.
return@onEquip true
}
onUnequip(devices) { player, _ ->
if (attractEnabled(player))
player.unhook(this)
return@onUnequip true
}
on(devices, ITEM, "operate") { player, _ ->
val attract = !attractEnabled(player)
setAttribute(player, ATTRACT_ENABLED, attract)
sendMessage(
player,
colorize(
"Ava's device will ${if (attract) "now" else "no longer"} randomly collect loot for you.",
"990000"
)
)
if (attract) {
player.hook(Event.Tick, this)
} else {
player.unhook(this)
}
return@on true
}
}
override fun process(entity: Entity, event: TickEvent) {
if (entity !is Player) {
entity.unhook(this)
return
}
if (getWorldTicks() - getLastTick(entity) < attractDelay)
return
else
setAttribute(entity, LAST_TICK, getWorldTicks())
if (isInterfered(entity)) {
sendMessage(entity, "Your armour interferes with Ava's device.")
return
}
val wornId = getItemFromEquipment(entity, EquipmentSlot.CAPE)?.id ?: -1
val reward = when (wornId) {
Items.AVAS_ACCUMULATOR_10499 -> ACCUMULATOR_REWARDS
Items.AVAS_ATTRACTOR_10498 -> ATTRACTOR_REWARDS
else -> {
entity.unhook(this)
return
}
}.random()
if (equipSlot(reward) == EquipmentSlot.AMMO) {
val equippedId = getItemFromEquipment(entity, EquipmentSlot.AMMO)?.id ?: -1
if (reward == equippedId || equippedId == -1) {
entity.equipment.add(reward.asItem(), true, false)
return
}
}
addItemOrDrop(entity, reward)
}
private fun attractEnabled(entity: Entity) : Boolean {
return getAttribute(entity, ATTRACT_ENABLED, true) //defaults to enabled
}
private fun getLastTick(entity: Entity) : Int {
return getAttribute(entity, LAST_TICK, 0)
}
private fun isInterfered(player: Player) : Boolean {
val chestPiece = getItemFromEquipment(player, EquipmentSlot.CHEST)
val modelId = chestPiece?.definition?.maleWornModelId1 ?: -1
return modelId != -1 && modelId in metalBodies
}
companion object {
const val ATTRACT_ENABLED = "/save:avadevice:attract"
const val LAST_TICK = "avadevice:tick"
val devices = intArrayOf(Items.AVAS_ACCUMULATOR_10499, Items.AVAS_ATTRACTOR_10498)
val metalBodies = intArrayOf(301, 306, 3379)
val attractDelay = secondsToTicks(180)
val ATTRACTOR_REWARDS = arrayOf(Items.IRON_BAR_2351, Items.IRON_KNIFE_863,Items.IRON_DART_807,Items.IRON_DAGGER_1203,Items.IRON_BOLTS_9140,Items.IRON_ARROW_884,Items.IRON_ORE_440,Items.COPPER_ORE_436,Items.IRON_FULL_HELM_1153,Items.IRON_2H_SWORD_1309,Items.STEEL_BAR_2353)
val ACCUMULATOR_REWARDS = arrayOf(Items.STEEL_BAR_2353,Items.STEEL_2H_SWORD_1311,Items.STEEL_KNIFE_865,Items.STEEL_DAGGER_1207,Items.STEEL_MED_HELM_1141,Items.STEEL_DART_808,Items.STEEL_BOLTS_9141,Items.STEEL_ARROW_886,Items.IRON_BAR_2351)
}
}
@@ -426,7 +426,6 @@ class PlayerSaver (val player: Player){
globalData.put("lootSharePoints",player.savedData.globalData.lootSharePoints.toString())
globalData.put("lootShareDelay",player.savedData.globalData.lootShareDelay.toString())
globalData.put("doubleExp",player.savedData.globalData.doubleExp.toString())
globalData.put("avasDevice",player.savedData.globalData.isAvasDisabled)
globalData.put("globalTeleporterDelay",player.savedData.globalData.globalTeleporterDelay.toString())
globalData.put("starSpriteDelay",player.savedData.globalData.starSpriteDelay.toString())
globalData.put("runReplenishDelay",player.savedData.globalData.runReplenishDelay.toString())
@@ -1,97 +0,0 @@
package rs09.game.node.entity.state.newsys.states
import core.game.container.impl.EquipmentContainer
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.game.system.task.Pulse
import core.tools.RandomFunction
import org.json.simple.JSONObject
import org.rs09.consts.Items
import rs09.game.node.entity.state.newsys.PlayerState
import rs09.game.node.entity.state.newsys.State
import rs09.game.system.config.ItemConfigParser
import kotlin.math.ceil
@PlayerState("avadevice")
class AvaDeviceState(player: Player? = null) : State(player) {
val TICKS = ceil(180 / 0.6).toInt()
var device = 0
private val ATTRACTOR_REWARDS = arrayOf(Items.IRON_BAR_2351,
Items.IRON_KNIFE_863,Items.IRON_DART_807,Items.IRON_DAGGER_1203,Items.IRON_BOLTS_9140,Items.IRON_ARROW_884,Items.IRON_ORE_440,Items.COPPER_ORE_436,Items.IRON_FULL_HELM_1153,Items.IRON_2H_SWORD_1309,Items.STEEL_BAR_2353)
private val ACCUMULATOR_REWARDS = arrayOf(Items.STEEL_BAR_2353,Items.STEEL_2H_SWORD_1311,Items.STEEL_KNIFE_865,Items.STEEL_DAGGER_1207,Items.STEEL_MED_HELM_1141,Items.STEEL_DART_808,Items.STEEL_BOLTS_9141,Items.STEEL_ARROW_886,Items.IRON_BAR_2351)
override fun save(root: JSONObject) {
root.put("device-id",device)
}
override fun parse(_data: JSONObject) {
if(_data.containsKey("device-id")){
device = _data["device-id"].toString().toInt()
}
}
override fun newInstance(player: Player?): State {
return AvaDeviceState(player)
}
override fun createPulse() {
player ?: return
if(device == 0 && !hasDevice(player)) return
if(player.savedData.globalData.isAvasDisabled) return
pulse = object : Pulse(TICKS){
override fun pulse(): Boolean {
if(!hasDevice(player)){
player.clearState("avadevice")
pulse = null
return true
}
if(isInterfered()) return false
if(RandomFunction.random(10) > 4) return false
val rewards = if(isAccumulator()) ACCUMULATOR_REWARDS else ATTRACTOR_REWARDS
val item = Item(rewards.random())
if (item.definition.getConfiguration(ItemConfigParser.EQUIP_SLOT, -1) == EquipmentContainer.SLOT_ARROWS) {
val arrowSlot = player.equipment[EquipmentContainer.SLOT_ARROWS]
if (arrowSlot == null || arrowSlot.id == item.getId()) {
player.equipment.add(item, true, EquipmentContainer.SLOT_ARROWS)
return false
}
}
player.inventory.add(item, player)
return !hasDevice(player)
}
}
}
fun hasDevice(player: Player?) : Boolean{
player ?: return false
return player.equipment.containsAtLeastOneItem(intArrayOf(Items.AVAS_ACCUMULATOR_10499,Items.AVAS_ATTRACTOR_10498))
}
fun isAccumulator() : Boolean{
return device == Items.AVAS_ACCUMULATOR_10499
}
//just took this method from the old arios pulse as well (I'm being lazy)
private fun isInterfered(): Boolean {
player ?: return true
val cape = player.equipment[EquipmentContainer.SLOT_CAPE]
if (cape != null && (cape.id == 10498 || cape.id == 10499)) {
val torso = player.equipment[EquipmentContainer.SLOT_CHEST]
val modelId = torso?.definition?.maleWornModelId1 ?: -1
if (modelId == 301 || modelId == 306 || modelId == 3379) {
player.packetDispatch.sendMessage("Your armour interferes with Ava's device.")
return true
}
}
return false
}
}