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:
-1
@@ -113,7 +113,6 @@ public final class AnimalMagnetism extends Quest {
|
||||
ClassScanner.definePlugin(new WitchDialogue());
|
||||
ClassScanner.definePlugin(new ContainerHandler());
|
||||
ClassScanner.definePlugin(new UndeadTreePlugin());
|
||||
ClassScanner.definePlugin(new AvasDevicePlugin());
|
||||
ClassScanner.definePlugin(new HammerMagnetPlugin());
|
||||
ClassScanner.definePlugin(new ResearchNoteHandler());
|
||||
ClassScanner.definePlugin(new AliceHusbandDialogue());
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
package core.game.content.quest.members.animalmagnetism;
|
||||
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Plugin;
|
||||
import rs09.game.node.entity.state.newsys.states.AvaDeviceState;
|
||||
import rs09.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Handles the equippage event of an ava device.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class AvasDevicePlugin implements Plugin<Object> {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
AnimalMagnetism.AVAS_ACCUMULATOR.getDefinition().getHandlers().put("equipment", this);
|
||||
AnimalMagnetism.AVAS_ATTRACTOR.getDefinition().getHandlers().put("equipment", this);
|
||||
ClassScanner.definePlugin(new DisableDevicePlugin());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fireEvent(String identifier, Object... args) {
|
||||
final Player player = (Player) args[0];
|
||||
final Item item = (Item) args[1];
|
||||
switch (identifier) {
|
||||
case "equip":
|
||||
AvaDeviceState state = (AvaDeviceState) player.registerState("avadevice");
|
||||
state.setDevice(item.getId());
|
||||
state.init();
|
||||
break;
|
||||
case "unequip":
|
||||
player.clearState("avadevice");
|
||||
if (args.length == 3) {
|
||||
Item second = (Item) args[2];
|
||||
if (second.getId() == 10498 || second.getId() == 10499) {
|
||||
AvaDeviceState newState = (AvaDeviceState) player.registerState("avadevice");
|
||||
newState.setDevice(second.getId());
|
||||
newState.init();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the disabling of Ava's devices -- they'll no longer randomly collect loot.
|
||||
* @author Splinter
|
||||
*/
|
||||
public final class DisableDevicePlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ItemDefinition.forId(10499).getHandlers().put("option:operate", this);
|
||||
ItemDefinition.forId(10498).getHandlers().put("option:operate", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
player.getGlobalData().setAvasDisabled(!player.getGlobalData().isAvasDisabled());
|
||||
player.sendMessage("<col=990000>Ava's device will "+(player.getGlobalData().isAvasDisabled() ? "no longer" : "now")+" randomly collect loot for you.</col>");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import core.game.component.CloseEvent;
|
||||
import core.game.component.Component;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.emote.Emotes;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.player.AppearanceFlag;
|
||||
import core.net.amsc.MSPacketRepository;
|
||||
@@ -13,6 +14,7 @@ import core.net.packet.context.InterfaceContext;
|
||||
import core.net.packet.out.Interface;
|
||||
import core.plugin.Plugin;
|
||||
import rs09.ServerConstants;
|
||||
import rs09.game.interaction.InteractionListeners;
|
||||
import rs09.game.interaction.inter.RulesAndInfo;
|
||||
import rs09.game.system.SystemLogger;
|
||||
import rs09.game.world.GameWorld;
|
||||
@@ -140,6 +142,13 @@ public final class LoginConfiguration {
|
||||
player.getEmoteManager().unlock(Emotes.SAFETY_FIRST);
|
||||
}
|
||||
player.varpManager.sendAllVarps();
|
||||
for (Item item : player.getEquipment().toArray()) {
|
||||
//Run equip hooks for all items equipped on login.
|
||||
//We should have already been doing this.
|
||||
//Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused.
|
||||
if (item == null) continue;
|
||||
InteractionListeners.run(item.getId(), player, item, true);
|
||||
}
|
||||
if(ServerConstants.RULES_AND_INFO_ENABLED)
|
||||
RulesAndInfo.openFor(player);
|
||||
/*if (GameWorld.getSettings().isPvp()) {
|
||||
|
||||
@@ -231,12 +231,7 @@ public final class GlobalData {
|
||||
* The double exp time.
|
||||
*/
|
||||
private long doubleExp;
|
||||
|
||||
/**
|
||||
* If Ava's device should randomly collect loot.
|
||||
*/
|
||||
private boolean avasDevice;
|
||||
|
||||
|
||||
/**
|
||||
* The delay of the global teleporter system.
|
||||
*/
|
||||
@@ -373,7 +368,6 @@ public final class GlobalData {
|
||||
lootShareDelay = Long.parseLong(data.get("lootShareDelay").toString());
|
||||
lootSharePoints = Integer.parseInt( data.get("lootSharePoints").toString());
|
||||
doubleExp = Long.parseLong(data.get("doubleExp").toString());
|
||||
avasDevice = (boolean) data.get("avasDevice");
|
||||
globalTeleporterDelay = Long.parseLong(data.get("globalTeleporterDelay").toString());
|
||||
starSpriteDelay = Long.parseLong(data.get("starSpriteDelay").toString());
|
||||
runReplenishDelay = Long.parseLong(data.get("runReplenishDelay").toString());
|
||||
@@ -1143,22 +1137,6 @@ public final class GlobalData {
|
||||
public boolean hasDoubleExp() {
|
||||
return doubleExp > System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the avasDevice
|
||||
* @return the avasDevice
|
||||
*/
|
||||
public boolean isAvasDisabled() {
|
||||
return avasDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the avasDevice
|
||||
* @param avasDevice
|
||||
*/
|
||||
public void setAvasDisabled(boolean avasDevice) {
|
||||
this.avasDevice = avasDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the globalTeleporterDelay.
|
||||
|
||||
@@ -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