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:
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user