Implemented timer subsystem to eventually replace pulses
Authentic subsystem supports saving/loading arbitrary data and resuming timer countdowns Lots of documented CAPI functions for working with these new timers Converted poison to new timers Converted disease to new timers Converted farming to new timers (CropGrowth and Compost) Farming now syncs with 5 minute intervals on realtime clocks (authentic) Converted seedling growth to new timers Converted shooting star mining bonus to new timers Converted entity freezing to new timers Converted incubation to new timers Incubation now supports using both incubators (so 2 eggs at once) Converted miasmic states to the new timers Converted god spell charged state to new timers Converted teleblock to new timers Converted skulled state to new timers Converted Enhanced Excalibur special attack effect to new timers Converted passive stat restoration to timers Converted multicannon firing and decay to a timer
This commit is contained in:
@@ -4,7 +4,6 @@ import content.data.consumables.effects.*;
|
||||
import core.game.consumable.*;
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.data.consumables.effects.KegOfBeerEffect;
|
||||
@@ -164,7 +163,7 @@ public enum Consumables {
|
||||
LIME_SLICES(new Food(new int[] {2124}, new HealingEffect(2))),
|
||||
PEACH(new Food(new int[] {6883}, new HealingEffect(8))),
|
||||
WHITE_TREE_FRUIT(new Food(new int[] {6469}, new MultiEffect(new RandomEnergyEffect(5, 10), new HealingEffect(3)))),
|
||||
STRANGE_FRUIT(new Food(new int[] {464}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new EnergyEffect(30)))),
|
||||
STRANGE_FRUIT(new Food(new int[] {464}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(30)))),
|
||||
|
||||
/** Gnome Cooking */
|
||||
TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(12))),
|
||||
@@ -321,11 +320,11 @@ public enum Consumables {
|
||||
SUPER_STRENGTH(new Potion(new int[] {2440, 157, 159, 161}, new SkillEffect(Skills.STRENGTH, 3, 0.2))),
|
||||
SUPER_ATTACK(new Potion(new int[] {2436, 145, 147, 149}, new SkillEffect(Skills.ATTACK, 3, 0.2))),
|
||||
SUPER_DEFENCE(new Potion(new int[] {2442, 163, 165, 167}, new SkillEffect(Skills.DEFENCE, 3, 0.2))),
|
||||
ANTIPOISON(new Potion(new int[] {2446, 175, 177, 179}, new MultiEffect(new SetAttributeEffect("poison:immunity", 143), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new MultiEffect(new SetAttributeEffect("poison:immunity", 863), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new MultiEffect(new SetAttributeEffect("poison:immunity", 2000), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
SUPER_ANTIP(new Potion(new int[] {2448, 181, 183, 185}, new MultiEffect(new SetAttributeEffect("poison:immunity", 1000), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new MultiEffect(new SetAttributeEffect("disease:immunity", 300), new RemoveStateEffect("disease")))),
|
||||
ANTIPOISON(new Potion(new int[] {2446, 175, 177, 179}, new AddTimerEffect("poison:immunity", 143))),
|
||||
ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new AddTimerEffect("poison:immunity", 863))),
|
||||
ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new AddTimerEffect("poison:immunity", 2000))),
|
||||
SUPER_ANTIP(new Potion(new int[] {2448, 181, 183, 185}, new AddTimerEffect("poison:immunity", 1000))),
|
||||
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new MultiEffect(new SetAttributeEffect("disease:immunity", 300), new RemoveTimerEffect("disease")))),
|
||||
AGILITY(new Potion(new int[] {3032, 3034, 3036, 3038}, new SkillEffect(Skills.AGILITY, 3, 0))),
|
||||
HUNTER(new Potion(new int[] {9998, 10000, 10002, 10004}, new SkillEffect(Skills.HUNTER, 3, 0))),
|
||||
RESTORE(new Potion(new int[] {2430, 127, 129, 131}, new RestoreEffect(10, 0.3))),
|
||||
@@ -338,9 +337,9 @@ public enum Consumables {
|
||||
SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new MultiEffect(new RestoreEffect(8, 0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25)))),
|
||||
ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
|
||||
ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new SetAttributeEffect("fire:immune", 600, true))),
|
||||
GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new EnergyEffect(5), new HealingEffect(5)))),
|
||||
GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(5), new HealingEffect(5)))),
|
||||
MAGIC_ESS(new Potion(new int[] {11491, 11489}, new SkillEffect(Skills.MAGIC,3,0))),
|
||||
SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8,0.25), new RemoveStateEffect(EntityState.POISONED.ordinal()), new RemoveStateEffect("disease")))),
|
||||
SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8,0.25), new RemoveTimerEffect("poison"), new RemoveTimerEffect("disease")))),
|
||||
SUPER_ENERGY(new Potion(new int[] {3016, 3018, 3020, 3022}, new EnergyEffect(20))),
|
||||
BLAMISH_OIL(new FakeConsumable(1582, new String[] {"You know... I'd really rather not."})),
|
||||
|
||||
@@ -348,8 +347,8 @@ public enum Consumables {
|
||||
PRAYERMIX(new BarbarianMix(new int[] {11465, 11467}, new MultiEffect(new PrayerEffect(7, 0.25), new HealingEffect(6)))),
|
||||
ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
|
||||
ATT_MIX(new BarbarianMix(new int[] {11429, 11431}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new HealingEffect(3)))),
|
||||
ANTIP_MIX(new BarbarianMix(new int[] {11433, 11435}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new SetAttributeEffect("poison:immunity", 143), new HealingEffect(3)))),
|
||||
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new RemoveStateEffect("disease"), new SetAttributeEffect("disease:immunity", 300), new HealingEffect(3)))),
|
||||
ANTIP_MIX(new BarbarianMix(new int[] {11433, 11435}, new MultiEffect(new AddTimerEffect("poison:immunity", 143), new HealingEffect(3)))),
|
||||
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new RemoveTimerEffect("disease"), new SetAttributeEffect("disease:immunity", 300), new HealingEffect(3)))),
|
||||
STR_MIX(new BarbarianMix(new int[] {11443, 11441}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(3)))),
|
||||
RESTO_MIX(new BarbarianMix(new int[] {11449, 11451}, new MultiEffect(new RestoreEffect(10, 0.3), new HealingEffect(3)))),
|
||||
SUPER_RESTO_MIX(new BarbarianMix(new int [] {11493, 11495}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25), new HealingEffect(6)))),
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package content.data.consumables.effects
|
||||
|
||||
import core.api.*
|
||||
import core.game.system.timer.impl.PoisonImmunity
|
||||
import core.game.consumable.ConsumableEffect
|
||||
import core.game.node.entity.player.Player
|
||||
|
||||
class AddTimerEffect (val identifier: String, vararg val args: Any) : ConsumableEffect() {
|
||||
override fun activate (p: Player) {
|
||||
val timer = spawnTimer (identifier, args) ?: return
|
||||
registerTimer (p, timer)
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
|
||||
public class RemoveStateEffect extends ConsumableEffect {
|
||||
int state = -1;
|
||||
String statekey;
|
||||
@Deprecated
|
||||
public RemoveStateEffect(int state){
|
||||
this.state = state;
|
||||
}
|
||||
public RemoveStateEffect(String key){
|
||||
statekey = key;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if(state == -1){
|
||||
p.clearState(statekey);
|
||||
return;
|
||||
}
|
||||
p.getStateManager().remove(EntityState.values()[state]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package content.data.consumables.effects
|
||||
|
||||
import core.api.*
|
||||
import core.game.consumable.ConsumableEffect
|
||||
import core.game.node.entity.player.Player
|
||||
|
||||
class RemoveTimerEffect (val identifier: String) : ConsumableEffect() {
|
||||
override fun activate (p: Player) {
|
||||
removeTimer (p, identifier)
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import core.game.global.action.DoorActionHandler
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
@@ -174,7 +173,6 @@ class ChampionChallengeListener : InteractionListener, MapArea {
|
||||
override fun pulse(): Boolean {
|
||||
when (counter++) {
|
||||
1 -> {
|
||||
player.stateManager.get(EntityState.TELEBLOCK)
|
||||
player.familiarManager.dismiss()
|
||||
}
|
||||
2 -> DoorActionHandler.handleDoor(player, node.asScenery())
|
||||
@@ -231,4 +229,4 @@ class ChampionChallengeListener : InteractionListener, MapArea {
|
||||
ZoneRestriction.RANDOM_EVENTS
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package content.global.activity.shootingstar
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
import core.game.system.task.Pulse
|
||||
import core.tools.ticksToSeconds
|
||||
import org.json.simple.JSONObject
|
||||
|
||||
@PlayerState("shooting-star")
|
||||
class ShootingStarState(player: Player? = null) : State(player) {
|
||||
var ticksLeft = 1500
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
root["ticksLeft"] = ticksLeft
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("ticksLeft")){
|
||||
ticksLeft = _data["ticksLeft"].toString().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
return ShootingStarState(player)
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
player ?: return
|
||||
if(ticksLeft <= 0) return
|
||||
pulse = object : Pulse(){
|
||||
override fun pulse(): Boolean {
|
||||
val minutes = ticksToSeconds(ticksLeft) / 60.0
|
||||
if(minutes % 5.0 == 0.0){
|
||||
player.sendMessage("<col=f0f095>You have $minutes minutes of your mining bonus left</col>")
|
||||
}
|
||||
if(ticksLeft-- <= 0){
|
||||
player.sendMessage("<col=FF0000>Your mining bonus has run out!</col>")
|
||||
pulse = null
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package content.global.activity.shootingstar
|
||||
|
||||
import core.api.*
|
||||
import core.game.system.timer.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import org.json.simple.*
|
||||
|
||||
class StarBonus : PersistTimer (1, "shootingstar:bonus") {
|
||||
var ticksLeft = 1500
|
||||
|
||||
override fun save (root: JSONObject, entity: Entity) {
|
||||
root["ticksLeft"] = ticksLeft.toString()
|
||||
}
|
||||
|
||||
override fun parse (root: JSONObject, entity: Entity) {
|
||||
ticksLeft = root["ticksLeft"].toString().toInt()
|
||||
}
|
||||
|
||||
override fun run (entity: Entity) : Boolean {
|
||||
if (entity is Player && ticksLeft == 500) {
|
||||
entity.sendMessage("<col=f0f095>You have 5 minutes of your mining bonus left</col>")
|
||||
} else if (entity is Player && ticksLeft == 0) {
|
||||
entity.sendMessage("<col=FF0000>Your mining bonus has run out!</col>")
|
||||
}
|
||||
return ticksLeft-- > 0
|
||||
}
|
||||
}
|
||||
@@ -198,7 +198,8 @@ class StarSpriteDialogue(player: Player? = null) : core.game.dialogue.DialoguePl
|
||||
|
||||
getStoreFile()[player.username.toLowerCase()] = true //flag daily as completed
|
||||
|
||||
player.registerState("shooting-star")?.init()
|
||||
val timer = getOrStartTimer <StarBonus> (player)
|
||||
timer.ticksLeft = 1500
|
||||
|
||||
if(wearingRing){
|
||||
val item = intArrayOf(Items.COSMIC_RUNE_564, Items.ASTRAL_RUNE_9075, Items.GOLD_ORE_445, Items.COINS_995).random()
|
||||
@@ -263,8 +264,8 @@ class StarSpriteDialogue(player: Player? = null) : core.game.dialogue.DialoguePl
|
||||
|
||||
fun rollForRingBonus(player: Player, bonusId: Int, bonusBaseAmt: Int){
|
||||
if(RandomFunction.roll(3)){
|
||||
val state = player.states["shooting-star"] as? ShootingStarState ?: return
|
||||
state.ticksLeft += secondsToTicks(TimeUnit.MINUTES.toSeconds(5).toInt())
|
||||
var bonus = getOrStartTimer <StarBonus> (player)
|
||||
bonus.ticksLeft += 500
|
||||
sendMessage(player, colorize("%RYour ring shines dimly as if imbued with energy."))
|
||||
} else if(RandomFunction.roll(5)){
|
||||
addItem(player, bonusId, bonusBaseAmt)
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
//package core.game.interaction.item;
|
||||
//
|
||||
//import java.text.DecimalFormat;
|
||||
//import java.util.concurrent.TimeUnit;
|
||||
//
|
||||
//import core.cache.def.impl.ItemDefinition;
|
||||
//import core.game.dialogue.DialogueInterpreter;
|
||||
//import core.game.dialogue.DialoguePlugin;
|
||||
//import core.game.content.ttrail.ClueLevel;
|
||||
//import core.game.content.ttrail.ClueScrollPlugin;
|
||||
//import core.game.interaction.OptionHandler;
|
||||
//import core.game.node.Node;
|
||||
//import core.game.node.entity.player.Player;
|
||||
//import core.game.node.entity.state.EntityState;
|
||||
//import core.game.node.item.Item;
|
||||
//import core.game.world.repository.Repository;
|
||||
//import core.plugin.Plugin;
|
||||
//import core.plugin.PluginManager;
|
||||
//import core.plugin.InitializablePlugin;
|
||||
//import core.tools.RandomFunction;
|
||||
//
|
||||
///**
|
||||
// * Handles the keldagrim voting bond item.
|
||||
// * @author Vexia
|
||||
// *
|
||||
// */
|
||||
//@InitializablePlugin
|
||||
//public class KeldagrimVotingBond extends OptionHandler {
|
||||
//
|
||||
// /**
|
||||
// * The keldagrim bond item.
|
||||
// */
|
||||
// private static final Item BOND = new Item(14807);
|
||||
//
|
||||
// /**
|
||||
// * The ultra lamp item.
|
||||
// */
|
||||
// private static final Item ULTRA_LAMP = new Item(14820);
|
||||
//
|
||||
// @Override
|
||||
// public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
// ItemDefinition.forId(14807).getConfigurations().put("option:redeem", this);
|
||||
// ItemDefinition.forId(14807).getConfigurations().put("option:deposit", this);
|
||||
// PluginManager.definePlugin(new keldagrimVotingBondDialogue());
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean handle(Player player, Node node, String option) {
|
||||
// Item item = node.asItem();
|
||||
// switch (option) {
|
||||
// case "redeem":
|
||||
// player.getDialogueInterpreter().open(DialogueInterpreter.getDialogueKey("keldagrim-bond"));
|
||||
// break;
|
||||
// case "deposit":
|
||||
// if (!player.getBank().hasSpaceFor(item)) {
|
||||
// player.sendMessage("You don't have enough space in your bank for that item.");
|
||||
// return true;
|
||||
// }
|
||||
// if (player.getInventory().remove(item)) {
|
||||
// player.getBank().add(item);
|
||||
// player.sendMessage("You deposit your Reward bond into your bank.");
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isWalk() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Handles the keldagrim voting bond dialogue.
|
||||
// * @author Vexia
|
||||
// *
|
||||
// */
|
||||
// public class keldagrimVotingBondDialogue extends DialoguePlugin {
|
||||
//
|
||||
// /**
|
||||
// * Constructs the {@code keldagrimVotingBondDialogue}
|
||||
// */
|
||||
// public keldagrimVotingBondDialogue() {
|
||||
// /**
|
||||
// * empty.
|
||||
// */
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Constructs the {@code keldagrimVotingBondDialogue}
|
||||
// * @param player The player.
|
||||
// */
|
||||
// public keldagrimVotingBondDialogue(Player player) {
|
||||
// super(player);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public DialoguePlugin newInstance(Player player) {
|
||||
// return new keldagrimVotingBondDialogue(player);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean open(Object... args) {
|
||||
// options("Double Experience (1 Hour)", "30K Experience Lamp", "10k-75k Coins", "Clue Scroll");
|
||||
// stage = 0;
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean handle(int interfaceId, int buttonId) {
|
||||
// switch (stage) {
|
||||
// case 0:
|
||||
// stage = 1;
|
||||
// switch (buttonId) {
|
||||
// case 1:
|
||||
// if (player.getSavedData().getGlobalData().hasDoubleExp()) {
|
||||
// interpreter.sendItemMessage(14807, "You already have <col=FF0000>double EXP</col> active!");
|
||||
// return true;
|
||||
// }
|
||||
// if (player.getInventory().remove(BOND)) {
|
||||
// player.getSavedData().getGlobalData().setDoubleExp(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1));
|
||||
// player.getStateManager().set(EntityState.DOUBLE_EXPERIENCE, 6000, 0);
|
||||
// interpreter.sendItemMessage(14807, "You redeemed an <col=FF0000>hour</col> of double EXP!");
|
||||
// Repository.sendNews("" + player.getUsername() + " redeemed an hour of double EXP from a Reward bond!", 15, "<col=FF0000>");
|
||||
// }
|
||||
// break;
|
||||
// case 2:
|
||||
// if (!player.getInventory().hasSpaceFor(ULTRA_LAMP)) {
|
||||
// interpreter.sendItemMessage(14807, "Sorry, you don't have enough inventory space.");
|
||||
// return true;
|
||||
// }
|
||||
// if (player.getInventory().remove(BOND)) {
|
||||
// player.getInventory().add(ULTRA_LAMP);
|
||||
// interpreter.sendItemMessage(14807, "You redeem an <col=FF0000>ultra lamp</col>.");
|
||||
// Repository.sendNews("" + player.getUsername() + " redeemed an ultra lamp from a Reward bond!", 15, "<col=FF0000>");
|
||||
// return true;
|
||||
// }
|
||||
// break;
|
||||
// case 3:
|
||||
// Item coins = new Item(995, RandomFunction.random(10000, 75000));
|
||||
// if (!player.getInventory().hasSpaceFor(coins)) {
|
||||
// interpreter.sendItemMessage(14807, "Sorry, you don't have enough inventory space.");
|
||||
// return true;
|
||||
// }
|
||||
// if (player.getInventory().remove(BOND)) {
|
||||
// DecimalFormat formatter = new DecimalFormat("#,###");
|
||||
// player.getInventory().add(coins);
|
||||
// interpreter.sendItemMessage(14807, "You redeem <col=FF0000>" + formatter.format(coins.getAmount()) + "</col> gold coins.");
|
||||
// Repository.sendNews("" + player.getUsername() + " redeemed " + formatter.format(coins.getAmount()) + " gold coins from a Reward bond!", 15, "<col=FF0000>");
|
||||
// }
|
||||
// break;
|
||||
// case 4:
|
||||
// if (player.getInventory().freeSlots() < 1) {
|
||||
// interpreter.sendItemMessage(14807, "Sorry, you don't have enough inventory space.");
|
||||
// return true;
|
||||
// }
|
||||
// if (TreasureTrailManager.getInstance(player).hasClue()) {
|
||||
// interpreter.sendItemMessage(14807, "Sorry, you already have a clue scroll.");
|
||||
// break;
|
||||
// }
|
||||
// if (TreasureTrailManager.getInstance(player).hasTrail()) {
|
||||
// TreasureTrailManager.getInstance(player).clearTrail();
|
||||
// }
|
||||
// Item clue = ClueScrollPlugin.getClue(RandomFunction.getRandomElement(ClueLevel.values()));
|
||||
// if (player.getInventory().remove(BOND)) {
|
||||
// player.getInventory().add(clue);
|
||||
// interpreter.sendItemMessage(14807, "You redeem a <col=FF0000>clue scroll</col>.");
|
||||
// Repository.sendNews("" + player.getUsername() + " redeemed a clue scroll from a Reward bond!", 15, "<col=FF0000>");
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// case 1:
|
||||
// end();
|
||||
// break;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int[] getIds() {
|
||||
// return new int[] {DialogueInterpreter.getDialogueKey("keldagrim-bond")};
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
//}
|
||||
+3
-4
@@ -10,14 +10,13 @@ import core.game.node.entity.combat.equipment.SwitchAttack;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.calculateDragonfireMaxHit;
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles dragonfire combat.
|
||||
@@ -147,8 +146,8 @@ public class DragonfireSwingHandler extends CombatSwingHandler {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!fire && victim.getAttribute("freeze_immunity", -1) < GameWorld.getTicks() && RandomFunction.random(4) == 2) {
|
||||
victim.getStateManager().set(EntityState.FROZEN, 16);
|
||||
if (!fire && !hasTimerActive(victim, "frozen:immunity") && RandomFunction.random(4) == 2) {
|
||||
registerTimer(victim, spawnTimer("frozen", 16, true));
|
||||
victim.graphics(Graphics.create(502));
|
||||
}
|
||||
Graphics graphic = attack != null ? attack.getEndGraphic() : null;
|
||||
|
||||
+3
-2
@@ -5,7 +5,6 @@ import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.entity.combat.MeleeSwingHandler;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
@@ -14,6 +13,8 @@ import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the excalibur special attack.
|
||||
*
|
||||
@@ -67,7 +68,7 @@ public final class ExcaliburSpecialHandler extends MeleeSwingHandler implements
|
||||
p.getSkills().updateLevel(Skills.DEFENCE, 8, p.getSkills().getStaticLevel(Skills.DEFENCE) + 8);
|
||||
break;
|
||||
case 14632: // enhanced excalibur
|
||||
p.getStateManager().set(EntityState.HEALOVERTIME,p,(int)15,(int)20,(int)5);
|
||||
registerTimer(p, spawnTimer("healovertime", 3, 20, 4));
|
||||
p.getSkills().updateLevel(Skills.DEFENCE,
|
||||
(int)(p.getSkills().getStaticLevel(Skills.DEFENCE)*0.15),
|
||||
(int)(p.getSkills().getStaticLevel(Skills.DEFENCE)*1.15));
|
||||
|
||||
+3
-2
@@ -6,13 +6,14 @@ import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.MeleeSwingHandler;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the Ice cleave special attack.
|
||||
* @author Emperor
|
||||
@@ -67,7 +68,7 @@ public final class IceCleaveSpecialHandler extends MeleeSwingHandler implements
|
||||
public void adjustBattleState(Entity entity, Entity victim, BattleState state) {
|
||||
super.adjustBattleState(entity, victim, state);
|
||||
if (state.getEstimatedHit() > 0) {
|
||||
victim.getStateManager().set(EntityState.FROZEN, 33);
|
||||
registerTimer(victim, spawnTimer("frozen", 33, true));
|
||||
victim.graphics(Graphics.create(369));
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -6,7 +6,6 @@ import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.MeleeSwingHandler;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.map.Direction;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.Point;
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
package content.global.handlers.item.withobject;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.summoning.pet.IncubatorEgg;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.StringUtils;
|
||||
import content.global.skill.summoning.pet.IncubatorState;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the incubator.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class IncubatorPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ClassScanner.definePlugin(new IncubatorEggHandler());
|
||||
SceneryDefinition.forId(28359).getHandlers().put("option:take-egg", this);
|
||||
SceneryDefinition.forId(28359).getHandlers().put("option:inspect", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
int inc = player.getAttribute(IncubatorState.ATTR_INCUBATOR_PRODUCT, -1);
|
||||
if (inc == -1)
|
||||
inc = player.getAttribute("inc", -1); //deprecated, only here to avoid data loss
|
||||
switch (option) {
|
||||
case "take-egg":
|
||||
if (inc == -1) {
|
||||
player.sendMessage("The egg is still incubating.");
|
||||
return true;
|
||||
}
|
||||
IncubatorEgg egg = IncubatorEgg.values()[inc];
|
||||
if (!player.getInventory().hasSpaceFor(egg.getProduct())) {
|
||||
player.sendMessage("You don't have enough inventory space.");
|
||||
return true;
|
||||
}
|
||||
{
|
||||
String name = egg.getProduct().getName().toLowerCase();
|
||||
setVarbit(player, 4277, 0);
|
||||
player.sendMessage("You take your " + name + " out of the incubator.");
|
||||
if(!player.getInventory().add(egg.getProduct())){
|
||||
GroundItemManager.create(egg.getProduct(),player);
|
||||
}
|
||||
player.removeAttribute("inc");
|
||||
player.removeAttribute(IncubatorState.ATTR_INCUBATOR_PRODUCT);
|
||||
player.clearState("incubator");
|
||||
}
|
||||
return true;
|
||||
case "inspect":
|
||||
if (player.states.get("incubator") != null || inc != -1) {
|
||||
IncubatorState p = (IncubatorState) player.states.get("incubator");
|
||||
if(p != null && p.getPulse() == null){
|
||||
setVarbit(player, 4277, 0);
|
||||
return true;
|
||||
}
|
||||
String name = p == null ? IncubatorEgg.values()[inc].getProduct().getName().toLowerCase() : p.getEgg().getProduct().getName().toLowerCase();
|
||||
player.sendMessage("There is " + (StringUtils.isPlusN(name) ? "an" : "a") + " " + name + " incubating in there.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the reward of using an egg on the incubator.
|
||||
* @author Vexia
|
||||
*/
|
||||
public class IncubatorEggHandler extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code IncubatorEggHandler} {@Code
|
||||
* Object}
|
||||
*/
|
||||
public IncubatorEggHandler() {
|
||||
super(12483, 11964, 5077, 5076, 5078, 12494, 12477, 12480, 12478, 12479);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(28336, OBJECT_TYPE, this);
|
||||
addHandler(28352, OBJECT_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final IncubatorEgg egg = IncubatorEgg.forItem(event.getUsedItem());
|
||||
if (egg == null) {
|
||||
return false;
|
||||
}
|
||||
if (player.hasActiveState("incubator")) {
|
||||
player.sendMessage("You already have an egg in there.");
|
||||
return true;
|
||||
}
|
||||
if (player.getSkills().getStaticLevel(Skills.SUMMONING) < egg.getLevel()) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Summoning level of at least " + egg.getLevel() + " in order to do this.");
|
||||
return true;
|
||||
}
|
||||
if(player.getInventory().remove(egg.getEgg())) {
|
||||
IncubatorState state = (IncubatorState) player.registerState("incubator");
|
||||
state.setEgg(egg);
|
||||
state.setTicksLeft(egg.getInucbationTime() * 100);
|
||||
state.init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,10 @@ class CompostBin(val player: Player, val bin: CompostBins) {
|
||||
return Item(item)
|
||||
}
|
||||
|
||||
fun isDefaultState() : Boolean {
|
||||
return (isFinished == false && finishedTime == 0L && items.size == 0)
|
||||
}
|
||||
|
||||
fun isReady(): Boolean {
|
||||
return System.currentTimeMillis() > finishedTime && finishedTime != 0L
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package content.global.skill.farming
|
||||
|
||||
import core.api.*
|
||||
import core.cache.def.impl.SceneryDefinition
|
||||
import core.cache.def.impl.VarbitDefinition
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.skill.farming.timers.*
|
||||
|
||||
enum class CompostBins(val varbit: Int) {
|
||||
FALADOR_COMPOST(740),
|
||||
@@ -28,11 +30,7 @@ enum class CompostBins(val varbit: Int) {
|
||||
}
|
||||
|
||||
fun getBinForPlayer(player: Player) : CompostBin {
|
||||
var state: FarmingState? = player.states.get("farming") as FarmingState?
|
||||
return if(state == null){
|
||||
state = player.registerState("farming") as FarmingState
|
||||
state.getBin(this).also { state.init() }
|
||||
} else
|
||||
state.getBin(this)
|
||||
val bins = getOrStartTimer <Compost> (player)
|
||||
return bins.getBin (this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package content.global.skill.farming
|
||||
|
||||
import core.api.*
|
||||
import core.cache.def.impl.SceneryDefinition
|
||||
import core.cache.def.impl.VarbitDefinition
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.skill.farming.timers.CropGrowth
|
||||
|
||||
enum class FarmingPatch(val varbit: Int, val type: PatchType) {
|
||||
//Allotments
|
||||
@@ -86,11 +88,7 @@ enum class FarmingPatch(val varbit: Int, val type: PatchType) {
|
||||
}
|
||||
|
||||
fun getPatchFor(player: Player): Patch{
|
||||
var state: FarmingState? = player.states.get("farming") as FarmingState?
|
||||
return if(state == null){
|
||||
state = player.registerState("farming") as FarmingState
|
||||
state.getPatch(this).also { state.init() }
|
||||
} else
|
||||
state.getPatch(this)
|
||||
var crops = getOrStartTimer <CropGrowth> (player)!!
|
||||
return crops.getPatch(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package content.global.skill.farming
|
||||
|
||||
import core.api.*
|
||||
import core.Util.clamp
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
@@ -11,125 +12,26 @@ import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
import core.tools.SystemLogger
|
||||
import java.util.concurrent.TimeUnit
|
||||
import content.global.skill.farming.timers.*
|
||||
|
||||
@PlayerState("farming")
|
||||
/**
|
||||
* Kept around solely for the purpose of porting save data from this old system to the new one.
|
||||
* //TODO REMOVE BY END OF 2023
|
||||
**/
|
||||
class FarmingState(player: Player? = null) : State(player) {
|
||||
private val patchMap = HashMap<FarmingPatch, Patch>()
|
||||
private val binMap = HashMap<CompostBins, CompostBin>()
|
||||
|
||||
|
||||
fun getPatch(patch: FarmingPatch): Patch {
|
||||
return patchMap[patch] ?: (Patch(player!!,patch).also { patchMap[patch] = it })
|
||||
}
|
||||
|
||||
fun getBin(bin: CompostBins) : CompostBin{
|
||||
return binMap[bin] ?: (CompostBin(player!!,bin).also { binMap[bin] = it })
|
||||
}
|
||||
|
||||
fun getPatches(): MutableCollection<Patch>{
|
||||
return patchMap.values
|
||||
}
|
||||
|
||||
fun getBins(): MutableCollection<CompostBin>{
|
||||
return binMap.values
|
||||
}
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
val patches = JSONArray()
|
||||
for((key,patch) in patchMap){
|
||||
val p = JSONObject()
|
||||
p.put("patch-ordinal",key.ordinal)
|
||||
p.put("patch-plantable-ordinal",patch.plantable?.ordinal ?: -1)
|
||||
p.put("patch-watered",patch.isWatered)
|
||||
p.put("patch-diseased",patch.isDiseased)
|
||||
p.put("patch-dead",patch.isDead)
|
||||
p.put("patch-stage",patch.currentGrowthStage)
|
||||
p.put("patch-state",patch.getCurrentState())
|
||||
p.put("patch-nextGrowth",patch.nextGrowth)
|
||||
p.put("patch-harvestAmt",patch.harvestAmt)
|
||||
p.put("patch-checkHealth",patch.isCheckHealth)
|
||||
p.put("patch-compost",patch.compost.ordinal)
|
||||
p.put("patch-paidprot",patch.protectionPaid)
|
||||
p.put("patch-croplives", patch.cropLives)
|
||||
patches.add(p)
|
||||
}
|
||||
val bins = JSONArray()
|
||||
for((key,bin) in binMap){
|
||||
val b = JSONObject()
|
||||
b.put("bin-ordinal",key.ordinal)
|
||||
bin.save(b)
|
||||
bins.add(b)
|
||||
}
|
||||
root.put("farming-patches",patches)
|
||||
root.put("farming-bins",bins)
|
||||
}
|
||||
|
||||
override fun save(root: JSONObject) {}
|
||||
override fun parse(_data: JSONObject) {
|
||||
player ?: return
|
||||
if(_data.containsKey("farming-bins")){
|
||||
(_data["farming-bins"] as JSONArray).forEach {
|
||||
val bin = it as JSONObject
|
||||
val binOrdinal = bin["bin-ordinal"].toString().toInt()
|
||||
val cBin = CompostBins.values()[binOrdinal]
|
||||
val b = cBin.getBinForPlayer(player)
|
||||
b.parse(bin["binData"] as JSONObject)
|
||||
}
|
||||
_data["bins"] = _data["farming-bins"]
|
||||
val timer = getOrStartTimer <Compost> (player)
|
||||
timer.parse (_data, player)
|
||||
}
|
||||
if(_data.containsKey("farming-patches")){
|
||||
val data = _data["farming-patches"] as JSONArray
|
||||
for(d in data){
|
||||
val p = d as JSONObject
|
||||
val patchOrdinal = p["patch-ordinal"].toString().toInt()
|
||||
val patchPlantableOrdinal = p["patch-plantable-ordinal"].toString().toInt()
|
||||
val patchWatered = p["patch-watered"] as Boolean
|
||||
val patchDiseased = p["patch-diseased"] as Boolean
|
||||
val patchDead = p["patch-dead"] as Boolean
|
||||
val patchStage = p["patch-stage"].toString().toInt()
|
||||
val nextGrowth = p["patch-nextGrowth"].toString().toLong()
|
||||
val harvestAmt = (p["patch-harvestAmt"] ?: 0).toString().toInt()
|
||||
val checkHealth = p["patch-checkHealth"] as Boolean
|
||||
val savedState = p["patch-state"].toString().toInt()
|
||||
val compostOrdinal = p["patch-compost"].toString().toInt()
|
||||
val protectionPaid = p["patch-paidprot"] as Boolean
|
||||
val cropLives = if(p["patch-croplives"] != null) p["patch-croplives"].toString().toInt() else 3
|
||||
val fPatch = FarmingPatch.values()[patchOrdinal]
|
||||
val plantable = if(patchPlantableOrdinal != -1) Plantable.values()[patchPlantableOrdinal] else null
|
||||
val patch = Patch(player,fPatch,plantable,patchStage,patchDiseased,patchDead,patchWatered,nextGrowth,harvestAmt,checkHealth)
|
||||
|
||||
patch.cropLives = cropLives
|
||||
patch.compost = CompostType.values()[compostOrdinal]
|
||||
patch.protectionPaid = protectionPaid
|
||||
patch.setCurrentState(savedState)
|
||||
|
||||
if((savedState - (patch?.plantable?.value ?: 0)) > patch.currentGrowthStage){
|
||||
patch.setCurrentState(savedState)
|
||||
} else {
|
||||
patch.setCurrentState((patch.plantable?.value ?: 0) + patch.currentGrowthStage)
|
||||
}
|
||||
|
||||
val type = patch.patch.type
|
||||
val shouldPlayCatchup = !patch.isGrown() || (type == PatchType.BUSH && patch.getFruitOrBerryCount() < 4) || (type == PatchType.FRUIT_TREE && patch.getFruitOrBerryCount() < 6)
|
||||
if(shouldPlayCatchup && patch.plantable != null && !patchDead){
|
||||
var stagesToSimulate = if (!patch.isGrown()) patch.plantable!!.stages - patch.currentGrowthStage else 0
|
||||
if (type == PatchType.BUSH)
|
||||
stagesToSimulate += Math.min(4, 4 - patch.getFruitOrBerryCount())
|
||||
if (type == PatchType.FRUIT_TREE)
|
||||
stagesToSimulate += Math.min(6, 6 - patch.getFruitOrBerryCount())
|
||||
|
||||
val nowTime = System.currentTimeMillis()
|
||||
var simulatedTime = patch.nextGrowth
|
||||
|
||||
while (simulatedTime < nowTime && stagesToSimulate-- > 0 && !patch.isDead) {
|
||||
val timeToIncrement = TimeUnit.MINUTES.toMillis(patch.getStageGrowthMinutes().toLong())
|
||||
patch.update()
|
||||
simulatedTime += timeToIncrement
|
||||
}
|
||||
}
|
||||
|
||||
if(patchMap[fPatch] == null) {
|
||||
patchMap[fPatch] = patch
|
||||
}
|
||||
}
|
||||
_data["patches"] = _data["farming-patches"]
|
||||
val timer = getOrStartTimer <CropGrowth> (player)
|
||||
timer.parse(_data, player)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,35 +39,5 @@ class FarmingState(player: Player? = null) : State(player) {
|
||||
return FarmingState(player)
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
pulse = object : Pulse(3){
|
||||
override fun pulse(): Boolean {
|
||||
|
||||
GlobalScope.launch {
|
||||
var removeList = ArrayList<FarmingPatch>()
|
||||
for((_,patch) in patchMap){
|
||||
|
||||
if(patch.getCurrentState() in 1..3 && patch.nextGrowth == 0L){
|
||||
patch.nextGrowth = System.currentTimeMillis() + 60000
|
||||
continue
|
||||
}
|
||||
|
||||
if(patch.nextGrowth < System.currentTimeMillis() && !patch.isDead){
|
||||
patch.update()
|
||||
patch.nextGrowth = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(patch.getStageGrowthMinutes().toLong())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for((_,bin) in binMap){
|
||||
if(bin.isReady() && !bin.isFinished){
|
||||
bin.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun createPulse() {}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ enum class PatchType(val stageGrowthTime: Int) {
|
||||
BUSH(20),
|
||||
FLOWER(5),
|
||||
HERB(20),
|
||||
SPIRIT_TREE(293),
|
||||
SPIRIT_TREE(295),
|
||||
MUSHROOM(30),
|
||||
BELLADONNA(80),
|
||||
CACTUS(60),
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package content.global.skill.farming
|
||||
|
||||
import core.api.addItem
|
||||
import core.api.inInventory
|
||||
import core.api.removeItem
|
||||
import core.api.sendDialogue
|
||||
import core.api.*
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.player.Player
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.IntType
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.skill.farming.timers.*
|
||||
import core.game.interaction.InteractionListener
|
||||
|
||||
class SeedlingListener : InteractionListener {
|
||||
@@ -43,17 +41,8 @@ class SeedlingListener : InteractionListener {
|
||||
addItem(player, wateredSeedling)
|
||||
addItem(player, nextCan)
|
||||
|
||||
var state = player.states["seedling"] as SeedlingState?
|
||||
|
||||
if (state != null) {
|
||||
state.addSeedling(wateredSeedling)
|
||||
return true
|
||||
}
|
||||
|
||||
state = player.registerState("seedling") as SeedlingState?
|
||||
state?.addSeedling(wateredSeedling)
|
||||
state?.init()
|
||||
|
||||
var seedlings = getOrStartTimer <SeedlingGrowth> (player)
|
||||
seedlings.addSeedling(wateredSeedling)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -114,4 +103,4 @@ class SeedlingListener : InteractionListener {
|
||||
)
|
||||
|
||||
private val WATERING_CANS = intArrayOf(Items.WATERING_CAN8_5340,Items.WATERING_CAN7_5339,Items.WATERING_CAN6_5338,Items.WATERING_CAN5_5337,Items.WATERING_CAN4_5336,Items.WATERING_CAN3_5335,Items.WATERING_CAN2_5334,Items.WATERING_CAN1_5333)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
package content.global.skill.farming
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@PlayerState("seedling")
|
||||
class SeedlingState(player: Player? = null) : State(player) {
|
||||
val seedlings = ArrayList<Seedling>()
|
||||
|
||||
fun addSeedling(seedling: Int){
|
||||
seedlings.add(Seedling(seedling, System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5),seedling + if(seedling > 5400) 8 else 6))
|
||||
}
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
val seedArray = JSONArray()
|
||||
for(s in seedlings){
|
||||
val seed = JSONObject()
|
||||
seed.put("id",s.id)
|
||||
seed.put("ttl",s.TTL)
|
||||
seed.put("sapling",s.sapling)
|
||||
seedArray.add(seed)
|
||||
}
|
||||
root.put("seedlings",seedArray)
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("seedlings")){
|
||||
(_data["seedlings"] as JSONArray).forEach {
|
||||
val s = it as JSONObject
|
||||
val id = s["id"].toString().toInt()
|
||||
val ttl = s["ttl"].toString().toLong()
|
||||
val sapling = s["sapling"].toString().toInt()
|
||||
seedlings.add(Seedling(id,ttl,sapling))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
return SeedlingState(player)
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
if(seedlings.isEmpty()) return
|
||||
player ?: return
|
||||
|
||||
pulse = object : Pulse(5){
|
||||
override fun pulse(): Boolean {
|
||||
val removeList = ArrayList<Seedling>()
|
||||
GlobalScope.launch {
|
||||
for (seed in seedlings) {
|
||||
if (System.currentTimeMillis() > seed.TTL) {
|
||||
val inInventory = player.inventory.get(Item(seed.id))
|
||||
if (inInventory != null) {
|
||||
player.inventory.replace(Item(seed.sapling), inInventory.slot)
|
||||
removeList.add(seed)
|
||||
} else {
|
||||
val inBank = player.bank.get(Item(seed.id))
|
||||
if(inBank == null) removeList.add(seed)
|
||||
else {
|
||||
player.bank.remove(Item(inBank.id,1))
|
||||
player.bank.add(Item(seed.sapling))
|
||||
removeList.add(seed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
seedlings.removeAll(removeList)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package content.global.skill.farming.timers
|
||||
|
||||
import core.api.*
|
||||
import core.game.system.timer.*
|
||||
import org.json.simple.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.skill.farming.*
|
||||
|
||||
class Compost : PersistTimer (500, "farming:compost", isSoft = true) {
|
||||
private val binMap = HashMap<CompostBins, CompostBin>()
|
||||
lateinit var player: Player
|
||||
|
||||
override fun onRegister (entity: Entity) {
|
||||
player = (entity as? Player)!!
|
||||
}
|
||||
|
||||
override fun getInitialRunDelay() : Int {
|
||||
return 1 //run once immediately after log in to complete any pending-but-enough-time-has-passed bins.
|
||||
}
|
||||
|
||||
override fun run (entity: Entity) : Boolean {
|
||||
val removeList = ArrayList <CompostBins> ()
|
||||
for((cBin,bin) in binMap){
|
||||
if(bin.isReady() && !bin.isFinished){
|
||||
bin.finish()
|
||||
}
|
||||
else if (bin.isDefaultState())
|
||||
removeList.add(cBin)
|
||||
}
|
||||
removeList.forEach { binMap.remove(it) }
|
||||
removeList.clear()
|
||||
|
||||
return binMap.isNotEmpty()
|
||||
}
|
||||
|
||||
fun getBin (bin: CompostBins) : CompostBin{
|
||||
return binMap[bin] ?: (CompostBin (player, bin).also { binMap[bin] = it })
|
||||
}
|
||||
|
||||
fun getBins(): MutableCollection<CompostBin>{
|
||||
return binMap.values
|
||||
}
|
||||
|
||||
override fun save (root: JSONObject, entity: Entity) {
|
||||
val bins = JSONArray()
|
||||
for((key,bin) in binMap){
|
||||
val b = JSONObject()
|
||||
b.put("bin-ordinal",key.ordinal)
|
||||
bin.save(b)
|
||||
bins.add(b)
|
||||
}
|
||||
root.put("bins", bins)
|
||||
}
|
||||
|
||||
override fun parse (root: JSONObject, entity: Entity) {
|
||||
(root["bins"] as JSONArray).forEach {
|
||||
val bin = it as JSONObject
|
||||
val binOrdinal = bin["bin-ordinal"].toString().toInt()
|
||||
val cBin = CompostBins.values()[binOrdinal]
|
||||
val b = CompostBin ((entity as? Player)!!, cBin).also { binMap[cBin] = it }
|
||||
b.parse(bin["binData"] as JSONObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package content.global.skill.farming.timers
|
||||
|
||||
import core.api.*
|
||||
import core.tools.*
|
||||
import core.game.system.timer.*
|
||||
import org.json.simple.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.skill.farming.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.time.*
|
||||
|
||||
class CropGrowth : PersistTimer (500, "farming:crops", isSoft = true) {
|
||||
private val patchMap = HashMap<FarmingPatch, Patch>()
|
||||
lateinit var player: Player
|
||||
|
||||
override fun onRegister (entity: Entity) {
|
||||
player = (entity as? Player)!!
|
||||
runOfflineCatchupLogic()
|
||||
}
|
||||
|
||||
//Sync the 5 minute run cycles with :05 on realtime clocks - authentic
|
||||
override fun getInitialRunDelay() : Int {
|
||||
val now = LocalTime.now();
|
||||
val minsUntil5MinSync = 5 - (now.getMinute() % 5)
|
||||
val ticks = secondsToTicks (minsUntil5MinSync * 60)
|
||||
player.debug("[CropGrowth] Scheduled first growth cycle for $ticks ticks from now.")
|
||||
return ticks
|
||||
}
|
||||
|
||||
override fun run (entity: Entity) : Boolean {
|
||||
var removeList = ArrayList<FarmingPatch>()
|
||||
for((fp,patch) in patchMap){
|
||||
if(patch.getCurrentState() in 1..3 && patch.nextGrowth == 0L){
|
||||
patch.nextGrowth = System.currentTimeMillis() + 60000
|
||||
continue
|
||||
}
|
||||
|
||||
//Go ahead and grow anything within 4 minutes of the 5-minute-synced growth cycles, bringing out-of-sync patches into sync.
|
||||
//This seems to be authentic as well, with the RS wiki sometimes stating 20-minute patches can grow in as little as 7 minutes depending on timing of planting
|
||||
//It also makes sense, as otherwise if you e.g. planted something at 10:34 that takes 5 minutes to grow, it would take 6 minutes in reality instead of 5.
|
||||
//Another more extreme example is if you planted something at 10:31 that takes 5 minutes to grow. 10:35 comes around, it hasn't been 5 minutes, so it doesn't grow, meaning
|
||||
//it actually grows at 10:40, an extra 4 minutes.
|
||||
//this code makes it so crops planted both at 10:31 and 10:34 grow at 10:35 if they are supposed to take 5 minutes for each stage.
|
||||
if(patch.nextGrowth < (System.currentTimeMillis() + 240_000L) && !patch.isDead){
|
||||
patch.nextGrowth = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(patch.getStageGrowthMinutes().toLong())
|
||||
patch.update()
|
||||
}
|
||||
|
||||
if (patch.getCurrentState() == 0)
|
||||
removeList.add(fp)
|
||||
}
|
||||
removeList.forEach { patchMap.remove(it) }
|
||||
removeList.clear()
|
||||
return patchMap.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun runOfflineCatchupLogic() {
|
||||
for ((_, patch) in patchMap) {
|
||||
val type = patch.patch.type
|
||||
val shouldPlayCatchup = !patch.isGrown() || (type == PatchType.BUSH && patch.getFruitOrBerryCount() < 4) || (type == PatchType.FRUIT_TREE && patch.getFruitOrBerryCount() < 6)
|
||||
if(shouldPlayCatchup && patch.plantable != null && !patch.isDead){
|
||||
var stagesToSimulate = if (!patch.isGrown()) patch.plantable!!.stages - patch.currentGrowthStage else 0
|
||||
if (type == PatchType.BUSH)
|
||||
stagesToSimulate += Math.min(4, 4 - patch.getFruitOrBerryCount())
|
||||
if (type == PatchType.FRUIT_TREE)
|
||||
stagesToSimulate += Math.min(6, 6 - patch.getFruitOrBerryCount())
|
||||
|
||||
val nowTime = System.currentTimeMillis()
|
||||
var simulatedTime = patch.nextGrowth
|
||||
|
||||
while (simulatedTime < nowTime && stagesToSimulate-- > 0 && !patch.isDead) {
|
||||
val timeToIncrement = TimeUnit.MINUTES.toMillis(patch.getStageGrowthMinutes().toLong())
|
||||
patch.update()
|
||||
simulatedTime += timeToIncrement
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getPatch(patch: FarmingPatch): Patch {
|
||||
return patchMap[patch] ?: (Patch(player,patch).also { patchMap[patch] = it })
|
||||
}
|
||||
|
||||
fun getPatches(): MutableCollection<Patch>{
|
||||
return patchMap.values
|
||||
}
|
||||
|
||||
override fun save (root: JSONObject, entity: Entity) {
|
||||
val patches = JSONArray()
|
||||
for((key,patch) in patchMap){
|
||||
val p = JSONObject()
|
||||
p.put("patch-ordinal",key.ordinal)
|
||||
p.put("patch-plantable-ordinal",patch.plantable?.ordinal ?: -1)
|
||||
p.put("patch-watered",patch.isWatered)
|
||||
p.put("patch-diseased",patch.isDiseased)
|
||||
p.put("patch-dead",patch.isDead)
|
||||
p.put("patch-stage",patch.currentGrowthStage)
|
||||
p.put("patch-state",patch.getCurrentState())
|
||||
p.put("patch-nextGrowth",patch.nextGrowth)
|
||||
p.put("patch-harvestAmt",patch.harvestAmt)
|
||||
p.put("patch-checkHealth",patch.isCheckHealth)
|
||||
p.put("patch-compost",patch.compost.ordinal)
|
||||
p.put("patch-paidprot",patch.protectionPaid)
|
||||
p.put("patch-croplives", patch.cropLives)
|
||||
patches.add(p)
|
||||
}
|
||||
root["patches"] = patches
|
||||
}
|
||||
|
||||
override fun parse (root: JSONObject, entity: Entity) {
|
||||
val data = root["patches"] as JSONArray
|
||||
for(d in data){
|
||||
val p = d as JSONObject
|
||||
val patchOrdinal = p["patch-ordinal"].toString().toInt()
|
||||
val patchPlantableOrdinal = p["patch-plantable-ordinal"].toString().toInt()
|
||||
val patchWatered = p["patch-watered"] as Boolean
|
||||
val patchDiseased = p["patch-diseased"] as Boolean
|
||||
val patchDead = p["patch-dead"] as Boolean
|
||||
val patchStage = p["patch-stage"].toString().toInt()
|
||||
val nextGrowth = p["patch-nextGrowth"].toString().toLong()
|
||||
val harvestAmt = (p["patch-harvestAmt"] ?: 0).toString().toInt()
|
||||
val checkHealth = p["patch-checkHealth"] as Boolean
|
||||
val savedState = p["patch-state"].toString().toInt()
|
||||
val compostOrdinal = p["patch-compost"].toString().toInt()
|
||||
val protectionPaid = p["patch-paidprot"] as Boolean
|
||||
val cropLives = if(p["patch-croplives"] != null) p["patch-croplives"].toString().toInt() else 3
|
||||
val fPatch = FarmingPatch.values()[patchOrdinal]
|
||||
val plantable = if(patchPlantableOrdinal != -1) Plantable.values()[patchPlantableOrdinal] else null
|
||||
val patch = Patch((entity as? Player)!!,fPatch,plantable,patchStage,patchDiseased,patchDead,patchWatered,nextGrowth,harvestAmt,checkHealth)
|
||||
|
||||
patch.cropLives = cropLives
|
||||
patch.compost = CompostType.values()[compostOrdinal]
|
||||
patch.protectionPaid = protectionPaid
|
||||
patch.setCurrentState(savedState)
|
||||
|
||||
if((savedState - (patch?.plantable?.value ?: 0)) > patch.currentGrowthStage){
|
||||
patch.setCurrentState(savedState)
|
||||
} else {
|
||||
patch.setCurrentState((patch.plantable?.value ?: 0) + patch.currentGrowthStage)
|
||||
}
|
||||
|
||||
if(patchMap[fPatch] == null) {
|
||||
patchMap[fPatch] = patch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package content.global.skill.farming.timers
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.timer.*
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.skill.farming.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.json.simple.*
|
||||
import java.time.*
|
||||
|
||||
class SeedlingGrowth : PersistTimer (1, "farming:seedling", isSoft = true) {
|
||||
val seedlings = ArrayList<Seedling>()
|
||||
lateinit var player: Player
|
||||
|
||||
fun addSeedling(seedling: Int){
|
||||
seedlings.add(
|
||||
Seedling(
|
||||
seedling,
|
||||
System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5),
|
||||
seedling + if(seedling > 5400) 8 else 6
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onRegister (entity: Entity) {
|
||||
player = (entity as? Player)!!
|
||||
}
|
||||
|
||||
override fun run (entity: Entity) : Boolean {
|
||||
val removeList = ArrayList<Seedling>()
|
||||
for (seed in seedlings) {
|
||||
if (System.currentTimeMillis() > seed.TTL) {
|
||||
val inInventory = player.inventory.get(Item(seed.id))
|
||||
if (inInventory != null) {
|
||||
player.inventory.replace(Item(seed.sapling), inInventory.slot)
|
||||
removeList.add(seed)
|
||||
} else {
|
||||
val inBank = player.bank.get(Item(seed.id))
|
||||
if(inBank == null) removeList.add(seed)
|
||||
else {
|
||||
player.bank.remove(Item(inBank.id,1))
|
||||
player.bank.add(Item(seed.sapling))
|
||||
removeList.add(seed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
seedlings.removeAll(removeList)
|
||||
return seedlings.isNotEmpty()
|
||||
}
|
||||
|
||||
override fun save(root: JSONObject, entity: Entity) {
|
||||
val seedArray = JSONArray()
|
||||
for(s in seedlings){
|
||||
val seed = JSONObject()
|
||||
seed.put("id",s.id)
|
||||
seed.put("ttl",s.TTL)
|
||||
seed.put("sapling",s.sapling)
|
||||
seedArray.add(seed)
|
||||
}
|
||||
root.put("seedlings",seedArray)
|
||||
}
|
||||
|
||||
override fun parse(root: JSONObject, entity: Entity) {
|
||||
(root["seedlings"] as JSONArray).forEach {
|
||||
val s = it as JSONObject
|
||||
val id = s["id"].toString().toInt()
|
||||
val ttl = s["ttl"].toString().toLong()
|
||||
val sapling = s["sapling"].toString().toInt()
|
||||
seedlings.add(Seedling(id,ttl,sapling))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package content.global.skill.gather.mining
|
||||
import content.data.skill.SkillingPets
|
||||
import content.data.skill.SkillingTool
|
||||
import content.global.skill.skillcapeperks.SkillcapePerks
|
||||
import content.global.activity.shootingstar.StarBonus
|
||||
import core.api.*
|
||||
import core.cache.def.impl.ItemDefinition
|
||||
import core.game.event.ResourceProducedEvent
|
||||
@@ -159,7 +160,7 @@ class MiningListener : InteractionListener {
|
||||
}
|
||||
|
||||
// If player has mining boost from Shooting Star, roll chance at extra ore
|
||||
if (player.hasActiveState("shooting-star")) {
|
||||
if (hasTimerActive<StarBonus>(player)) {
|
||||
if (RandomFunction.getRandom(5) == 3) {
|
||||
sendMessage(player, "...you manage to mine a second ore thanks to the Star Sprite.")
|
||||
amount += 1
|
||||
@@ -222,4 +223,4 @@ class MiningListener : InteractionListener {
|
||||
}
|
||||
return node.isActive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.node.entity.player.link.audio.Audio;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
@@ -20,6 +19,8 @@ import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the Ice spells from the Ancient spellbook.
|
||||
* @author Emperor
|
||||
@@ -133,8 +134,8 @@ public final class IceSpells extends CombatSpell {
|
||||
}
|
||||
int ticks = (1 + (type.ordinal() - SpellType.RUSH.ordinal())) * 8;
|
||||
if (state.getEstimatedHit() > -1) {
|
||||
if (victim.getAttribute("freeze_immunity", -1) < GameWorld.getTicks()) {
|
||||
victim.getStateManager().set(EntityState.FROZEN, ticks);
|
||||
if (!hasTimerActive(victim, "frozen:immunity")) {
|
||||
registerTimer(victim, spawnTimer("frozen", ticks, true));
|
||||
} else if (type == SpellType.BARRAGE) {
|
||||
state.setFrozen(true);
|
||||
}
|
||||
|
||||
@@ -14,13 +14,14 @@ import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the Miasmic spells that are a part of the Ancient spellbook.
|
||||
* @author Splinter
|
||||
@@ -119,8 +120,8 @@ public final class MiasmicSpells extends CombatSpell {
|
||||
|
||||
@Override
|
||||
public void fireEffect(Entity entity, Entity victim, BattleState state) {
|
||||
if (victim.getAttribute("miasmic_immunity", -1) < GameWorld.getTicks()) {
|
||||
victim.getStateManager().register(EntityState.MIASMIC, true, (getSpellId() - 15) * 20);
|
||||
if (!hasTimerActive(victim, "miasmic:immunity")) {
|
||||
registerTimer(victim, spawnTimer("miasmic", (getSpellId() - 15) * 20));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,13 +11,14 @@ import core.game.node.entity.combat.spell.SpellType;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the Smoke spells from the Ancient spellbook.
|
||||
* @author Emperor
|
||||
@@ -111,7 +112,7 @@ public final class SmokeSpells extends CombatSpell {
|
||||
@Override
|
||||
public void fireEffect(Entity entity, Entity victim, BattleState state) {
|
||||
if (state.getEstimatedHit() > -1) {
|
||||
victim.getStateManager().register(EntityState.POISONED, false, type.ordinal() >= SpellType.BLITZ.ordinal() ? 48 : 28, entity);
|
||||
applyPoison(victim, entity, type.ordinal() >= SpellType.BLITZ.ordinal() ? 4 : 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.node.item.Item
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.system.command.Privilege
|
||||
@@ -206,7 +205,7 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
||||
return@define
|
||||
}
|
||||
if(dmg != null) {
|
||||
p?.let { addState(it, EntityState.POISONED, false, (dmg * 10 + 8), player) }
|
||||
p?.let { applyPoison(it, it, dmg) }
|
||||
} else {
|
||||
sendMessage(player, "Damage must be an integer. Format:")
|
||||
sendMessage(player, "::poison username damage")
|
||||
@@ -480,14 +479,14 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
||||
}
|
||||
|
||||
private fun cureMe(player: Player) {
|
||||
if(!hasState(player, EntityState.POISONED)) {
|
||||
if(!isPoisoned(player)) {
|
||||
sendMessage(player, "You are not poisoned.")
|
||||
return
|
||||
}
|
||||
requires(player, 71, arrayOf(Item(Items.ASTRAL_RUNE_9075, 2), Item(Items.LAW_RUNE_563, 1), Item(Items.COSMIC_RUNE_564, 2)))
|
||||
removeRunes(player, true)
|
||||
visualizeSpell(player, CURE_ME_ANIM, CURE_ME_GFX, 2880)
|
||||
removeState(player, EntityState.POISONED)
|
||||
curePoison(player)
|
||||
addXP(player, 69.0)
|
||||
playAudio(player, Audio(2900))
|
||||
sendMessage(player, "You have been cured of poison.")
|
||||
@@ -497,7 +496,7 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
||||
requires(player, 74, arrayOf(Item(Items.ASTRAL_RUNE_9075, 2), Item(Items.LAW_RUNE_563, 2), Item(Items.COSMIC_RUNE_564, 2)))
|
||||
removeRunes(player, true)
|
||||
visualizeSpell(player, CURE_GROUP_ANIM, CURE_GROUP_GFX, 2882)
|
||||
removeState(player, EntityState.POISONED)
|
||||
curePoison(player)
|
||||
for(acct in RegionManager.getLocalPlayers(player, 1)) {
|
||||
if(!acct.isActive || acct.locks.isInteractionLocked) {
|
||||
continue
|
||||
@@ -505,7 +504,7 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
||||
if(!acct.settings.isAcceptAid) {
|
||||
continue
|
||||
}
|
||||
removeState(acct, EntityState.POISONED)
|
||||
curePoison(acct)
|
||||
sendMessage(acct, "You have been cured of poison.")
|
||||
playAudio(acct, Audio(2889), true)
|
||||
visualize(acct, -1, CURE_GROUP_GFX)
|
||||
@@ -527,7 +526,7 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
||||
sendMessage(player, "This player is not accepting any aid.")
|
||||
return
|
||||
}
|
||||
if(!hasState(p, EntityState.POISONED)) {
|
||||
if(!isPoisoned(p)) {
|
||||
sendMessage(player, "This player is not poisoned.")
|
||||
return
|
||||
}
|
||||
@@ -537,7 +536,7 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
||||
visualize(p, -1, CURE_OTHER_GFX)
|
||||
playAudio(p, Audio(2889), true)
|
||||
removeRunes(player, true)
|
||||
removeState(p, EntityState.POISONED)
|
||||
curePoison(p)
|
||||
sendMessage(p, "You have been cured of poison.")
|
||||
addXP(player, 65.0)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import org.rs09.consts.Sounds;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Represents the charge spell magic spell.
|
||||
* @author Emperor
|
||||
@@ -49,8 +51,8 @@ public final class ChargeSpell extends MagicSpell {
|
||||
p.getLocks().lock("charge_cast", 100);
|
||||
visualize(entity, target);
|
||||
// Remove the previous copy of the state in order to refresh the duration if recast before 7 minutes
|
||||
p.clearState("godcharge");
|
||||
p.registerState("godcharge").init();
|
||||
removeTimer (p, "magic:spellcharge");
|
||||
registerTimer (p, spawnTimer("magic:spellcharge"));
|
||||
p.getPacketDispatch().sendMessage("You feel charged with magic power.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package content.global.skill.magic.modern
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.system.task.Pulse
|
||||
import org.json.simple.JSONObject
|
||||
import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
import core.game.world.GameWorld;
|
||||
|
||||
@PlayerState("godcharge")
|
||||
class GodspellChargedState(player: Player? = null) : State(player) {
|
||||
val DURATION = 700
|
||||
var startTick: Int = 0
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
root.put("ticks_elapsed", GameWorld.ticks - startTick)
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("ticks_elapsed")){
|
||||
startTick = GameWorld.ticks - _data["ticks_elapsed"].toString().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
var ret = GodspellChargedState(player)
|
||||
ret.startTick = GameWorld.ticks
|
||||
return ret
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
player ?: return
|
||||
if(GameWorld.ticks - startTick >= DURATION) return
|
||||
pulse = object : Pulse(DURATION) {
|
||||
override fun pulse(): Boolean {
|
||||
player.sendMessage("Your magical charge fades away.")
|
||||
player.clearState("godcharge")
|
||||
player.audioManager.send(Audio(1650))
|
||||
pulse = null
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package content.global.skill.magic.modern
|
||||
|
||||
import core.api.*
|
||||
import org.json.simple.*
|
||||
import core.game.system.timer.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
|
||||
class SpellCharge : PersistTimer (700, "magic:spellcharge") {
|
||||
override fun run (entity: Entity) : Boolean {
|
||||
if (entity !is Player) return false
|
||||
sendMessage(entity, "Your magical charge fades away.")
|
||||
playAudio(entity, getAudio(1650))
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,14 @@ import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.node.entity.player.link.prayer.PrayerType;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the teleportation block spell in the modern spellbook.
|
||||
* @author Splinter
|
||||
@@ -117,7 +118,7 @@ public final class TeleblockSpell extends CombatSpell {
|
||||
if(((Player) victim).getPrayer().get(PrayerType.PROTECT_FROM_MAGIC)){
|
||||
ticks /= 2;
|
||||
}
|
||||
victim.getStateManager().set(EntityState.TELEBLOCK, ticks);
|
||||
registerTimer(victim, spawnTimer("teleblock", ticks));
|
||||
} else if(victim.isTeleBlocked()){
|
||||
entity.asPlayer().sendMessage("Your target is already blocked from teleporting.");
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.component.Component;
|
||||
import core.game.node.entity.player.link.prayer.PrayerType;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillRestoration;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
|
||||
@@ -5,9 +5,10 @@ import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Represents the Bloated Leech familiar.
|
||||
* @author Aero
|
||||
@@ -38,7 +39,7 @@ public class BloatedLeechNPC extends Familiar {
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
owner.getStateManager().remove(EntityState.POISONED);
|
||||
curePoison(owner);
|
||||
for (int i = 0; i < Skills.SKILL_NAME.length; i++) {
|
||||
if (owner.getSkills().getLevel(i) < owner.getSkills().getStaticLevel(i)) {
|
||||
owner.getSkills().setLevel(i, owner.getSkills().getStaticLevel(i));
|
||||
|
||||
@@ -5,7 +5,6 @@ import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
|
||||
@@ -8,11 +8,12 @@ import core.game.node.entity.combat.equipment.Weapon;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Scorpion familiar.
|
||||
* @author Vexia
|
||||
@@ -49,7 +50,7 @@ public class SpiritScorpionNPC extends Familiar {
|
||||
if (isCharged() && new Item(weapon.getId() + 6).getName().startsWith(weapon.getName())) {
|
||||
final Entity victim = state.getVictim();
|
||||
setCharged(false);
|
||||
victim.getStateManager().register(EntityState.POISONED, false, 10, owner);
|
||||
applyPoison(victim, owner, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@ import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Represents the Stranger Plant familiar.
|
||||
* @author Aero
|
||||
@@ -45,7 +46,7 @@ public class StrangerPlantNPC extends Forager {
|
||||
}
|
||||
Entity target = special.getTarget();
|
||||
if (RandomFunction.random(2) == 1) {
|
||||
target.getStateManager().register(EntityState.POISONED, false, 40, target);
|
||||
applyPoison(target, owner, 20);
|
||||
}
|
||||
animate(Animation.create(8211));
|
||||
Projectile.ranged(this, target, 1508, 50, 40, 1, 45).send();
|
||||
|
||||
@@ -7,12 +7,13 @@ import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Represents the Unicorn Stallion familiar.
|
||||
* @author Aero
|
||||
@@ -72,13 +73,13 @@ public class UnicornStallionNPC extends Familiar {
|
||||
player.sendMessage("You don't have enough summoning points left");
|
||||
return true;
|
||||
}
|
||||
if (!owner.getStateManager().hasState(EntityState.POISONED)) {
|
||||
if (!isPoisoned(owner)) {
|
||||
player.sendMessage("You are not poisoned.");
|
||||
return true;
|
||||
}
|
||||
player.getAudioManager().send(4372);
|
||||
familiar.visualize(Animation.create(8267), Graphics.create(1356));
|
||||
player.getStateManager().remove(EntityState.POISONED);
|
||||
curePoison(player);
|
||||
player.getSkills().updateLevel(Skills.SUMMONING, -2, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package content.global.skill.summoning.pet
|
||||
|
||||
import core.api.*
|
||||
import core.cache.def.impl.SceneryDefinition
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.interaction.*
|
||||
import core.tools.StringUtils
|
||||
|
||||
class IncubatorHandler : InteractionListener {
|
||||
val eggIds = IncubatorEgg.values().map { it.egg.id }.toIntArray()
|
||||
val incubators = intArrayOf(28550, 28352, 28359)
|
||||
|
||||
override fun defineListeners() {
|
||||
on (incubators, IntType.SCENERY, "inspect", handler = ::handleInspectOption)
|
||||
on (incubators, IntType.SCENERY, "take-egg", handler = ::handleTakeOption)
|
||||
onUseWith (IntType.SCENERY, eggIds, *incubators, handler = ::handleEggOnIncubator)
|
||||
}
|
||||
|
||||
fun handleEggOnIncubator (player: Player, used: Node, with: Node) : Boolean {
|
||||
val egg = IncubatorEgg.forItem (used.asItem()) ?: return false
|
||||
val activeEgg = IncubatorTimer.getEggFor (player, player.location.regionId)
|
||||
|
||||
if (activeEgg != null) {
|
||||
sendMessage (player, "You already have an egg in this incubator.")
|
||||
return true
|
||||
}
|
||||
|
||||
if (removeItem(player, used.asItem()))
|
||||
IncubatorTimer.registerEgg (player, player.location.regionId, egg)
|
||||
return true
|
||||
}
|
||||
|
||||
fun handleInspectOption (player: Player, node: Node) : Boolean {
|
||||
val activeEgg = IncubatorTimer.getEggFor (player, player.location.regionId)
|
||||
|
||||
if (activeEgg == null) {
|
||||
sendMessage (player, "The incubator is currently empty.")
|
||||
return true
|
||||
}
|
||||
|
||||
if (activeEgg.finished) {
|
||||
sendMessage (player, "The egg inside has finished incubating.")
|
||||
return true
|
||||
}
|
||||
|
||||
val creatureName = activeEgg.egg.product.name.lowercase()
|
||||
sendMessage (player, "There is currently ${if (StringUtils.isPlusN(creatureName)) "an" else "a"} $creatureName egg incubating.")
|
||||
return true
|
||||
}
|
||||
|
||||
fun handleTakeOption (player: Player, node: Node) : Boolean {
|
||||
val region = player.location.regionId
|
||||
val activeEgg = IncubatorTimer.getEggFor (player, region) ?: return false
|
||||
|
||||
if (!activeEgg.finished) {
|
||||
sendMessage (player, "That egg hasn't finished incubating!")
|
||||
return true
|
||||
}
|
||||
|
||||
if (freeSlots(player) < 1) {
|
||||
sendMessage (player, "You do not have enough inventory space to do that.")
|
||||
return true
|
||||
}
|
||||
|
||||
val egg = IncubatorTimer.removeEgg (player, region) ?: return false
|
||||
val product = egg.product
|
||||
val name = product.name.lowercase()
|
||||
|
||||
sendMessage(player, "You take your $name out of the incubator.")
|
||||
addItem(player, product.id)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package content.global.skill.summoning.pet
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
import core.game.system.task.Pulse
|
||||
import org.json.simple.JSONObject
|
||||
import core.api.*
|
||||
import core.tools.*
|
||||
|
||||
@PlayerState("incubator")
|
||||
class IncubatorState(player: Player? = null) : State(player) {
|
||||
var egg: IncubatorEgg? = null
|
||||
var completionTimeMs = 0L
|
||||
|
||||
fun setTicksLeft (ticks: Int) {
|
||||
completionTimeMs = System.currentTimeMillis() + (ticksToSeconds(ticks) * 1000)
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
return IncubatorState(player)
|
||||
}
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
if(pulse == null) return
|
||||
|
||||
val data = JSONObject()
|
||||
data.put("eggOrdinal",(egg?.ordinal ?: 0).toString())
|
||||
data.put("endTime", completionTimeMs.toString())
|
||||
root.put("eggdata",data)
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("eggdata")){
|
||||
val data = _data["eggdata"] as JSONObject
|
||||
egg = IncubatorEgg.values()[data["eggOrdinal"].toString().toInt()]
|
||||
|
||||
if (data.containsKey("ticksLeft"))
|
||||
completionTimeMs = System.currentTimeMillis() + ticksToSeconds(data["ticksLeft"].toString().toInt() * 1000)
|
||||
else
|
||||
completionTimeMs = data["endTime"].toString().toLong()
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
player ?: return
|
||||
egg ?: return
|
||||
setVarbit(player, 4277, 1)
|
||||
pulse = object : Pulse(){
|
||||
override fun pulse(): Boolean {
|
||||
if(System.currentTimeMillis() >= completionTimeMs){
|
||||
player.setAttribute(ATTR_INCUBATOR_PRODUCT, egg!!.ordinal)
|
||||
player.sendMessage("Your " + egg!!.product.name.toLowerCase() + " has finished hatching.")
|
||||
pulse = null
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ATTR_INCUBATOR_PRODUCT = "/save:incubator:egg-product"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package content.global.skill.summoning.pet
|
||||
|
||||
import core.api.*
|
||||
import core.tools.*
|
||||
import core.game.system.timer.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import java.util.*
|
||||
import org.json.simple.*
|
||||
|
||||
class IncubatorTimer : PersistTimer (500, "incubation") {
|
||||
val incubatingEggs = HashMap<Int, IncubatingEgg>()
|
||||
|
||||
override fun getInitialRunDelay() : Int {
|
||||
return 50
|
||||
}
|
||||
|
||||
override fun parse (root: JSONObject, entity: Entity) {
|
||||
val eggs = root["eggs"] as? JSONArray ?: return
|
||||
for (eggData in eggs) {
|
||||
val eggInfo = eggData as JSONArray
|
||||
val egg = IncubatingEgg (
|
||||
eggInfo[0].toString().toInt(),
|
||||
IncubatorEgg.values()[eggInfo[1].toString().toInt()],
|
||||
eggInfo[2].toString().toLong(),
|
||||
eggInfo[3].toString().toBoolean()
|
||||
)
|
||||
incubatingEggs[egg.region] = egg
|
||||
}
|
||||
}
|
||||
|
||||
override fun save (root: JSONObject, entity: Entity) {
|
||||
val arr = JSONArray()
|
||||
for ((_, eggInfo) in incubatingEggs) {
|
||||
val eggArr = JSONArray()
|
||||
eggArr.add(eggInfo.region.toString())
|
||||
eggArr.add(eggInfo.egg.ordinal.toString())
|
||||
eggArr.add(eggInfo.endTime.toString())
|
||||
eggArr.add(eggInfo.finished)
|
||||
arr.add(eggArr)
|
||||
}
|
||||
root["eggs"] = arr
|
||||
}
|
||||
|
||||
override fun run (entity: Entity) : Boolean {
|
||||
if (entity !is Player) return false
|
||||
for ((_, egg) in incubatingEggs) {
|
||||
if (egg.finished) continue
|
||||
if (egg.isDone()) {
|
||||
sendMessage(entity, colorize("%RYour ${egg.egg.product.name.lowercase()} egg has finished hatching."))
|
||||
egg.finished = true
|
||||
}
|
||||
}
|
||||
return !incubatingEggs.isEmpty()
|
||||
}
|
||||
|
||||
data class IncubatingEgg (val region: Int, val egg: IncubatorEgg, var endTime: Long, var finished: Boolean = false)
|
||||
fun IncubatingEgg.isDone() : Boolean {
|
||||
return endTime < System.currentTimeMillis()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAVERLY_REGION = 11573
|
||||
val TAVERLY_VARBIT = 4277
|
||||
val YANILLE_REGION = 10288
|
||||
val YANILLE_VARBIT = 4221
|
||||
|
||||
fun varbitForRegion (region: Int) : Int {
|
||||
return when (region) {
|
||||
TAVERLY_REGION -> TAVERLY_VARBIT
|
||||
YANILLE_REGION -> YANILLE_VARBIT
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
fun getEggFor (player: Player, region: Int) : IncubatingEgg? {
|
||||
val playerTimer = getTimer<IncubatorTimer>(player) ?: return null
|
||||
return playerTimer.incubatingEggs[region]
|
||||
}
|
||||
|
||||
fun registerEgg (player: Player, region: Int, egg: IncubatorEgg) {
|
||||
val timer = getTimer<IncubatorTimer>(player) ?: IncubatorTimer()
|
||||
timer.incubatingEggs [region] = IncubatingEgg (region, egg, System.currentTimeMillis() + (ticksToSeconds(egg.inucbationTime * 100) * 1000))
|
||||
|
||||
if (!hasTimerActive<IncubatorTimer>(player))
|
||||
registerTimer(player, timer)
|
||||
setVarbit(player, varbitForRegion(region), 1, true)
|
||||
}
|
||||
|
||||
fun removeEgg (player: Player, region: Int) : IncubatorEgg? {
|
||||
val egg = getEggFor (player, region) ?: return null
|
||||
val timer = getTimer<IncubatorTimer>(player) ?: return null
|
||||
timer.incubatingEggs.remove(region)
|
||||
setVarbit(player, varbitForRegion(region), 0, true)
|
||||
return egg.egg
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import core.game.node.entity.impl.Animator
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
@@ -75,4 +74,4 @@ class ThievingListeners : InteractionListener {
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package content.global.state
|
||||
|
||||
import core.game.node.entity.combat.ImpactHandler
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import core.tools.RandomFunction
|
||||
import org.json.simple.JSONObject
|
||||
import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
import core.game.world.GameWorld
|
||||
|
||||
@PlayerState("disease")
|
||||
class DiseasedState(player: Player? = null) : State(player){
|
||||
var hitsLeft = 25
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
if(hitsLeft > 0){
|
||||
root.put("hitsLeft",hitsLeft)
|
||||
}
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("hitsLeft")){
|
||||
hitsLeft = _data["hitsLeft"].toString().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
return DiseasedState(player)
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
player ?: return
|
||||
if(player.getAttribute("immunity:disease",0) > GameWorld.ticks){
|
||||
return
|
||||
}
|
||||
if(hitsLeft <= 0) return
|
||||
player.sendMessage("You have been diseased!")
|
||||
pulse = object : Pulse(30){
|
||||
override fun pulse(): Boolean {
|
||||
val damage = RandomFunction.random(1,5)
|
||||
player.impactHandler.manualHit(player,damage,ImpactHandler.HitsplatType.DISEASE)
|
||||
var skillId = RandomFunction.random(24)
|
||||
if(skillId == 3) skillId--
|
||||
player.skills.updateLevel(skillId,-damage,0)
|
||||
hitsLeft--
|
||||
if(hitsLeft <= 0) player.sendMessage("The disease has wore off.")
|
||||
return hitsLeft <= 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,14 +10,13 @@ import core.game.node.entity.combat.spell.SpellType;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.node.entity.player.link.TeleportManager.TeleportType;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
import static core.api.ContentAPIKt.isStunned;
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the bounty target locate spell.
|
||||
@@ -45,7 +44,7 @@ public final class BountyLocateSpell extends MagicSpell {
|
||||
player.getPacketDispatch().sendMessage("You don't have a target to teleport to.");
|
||||
return true;
|
||||
}
|
||||
if (player.getStateManager().hasState(EntityState.FROZEN) || isStunned(player)) {
|
||||
if (hasTimerActive(player, "frozen") || isStunned(player)) {
|
||||
player.getPacketDispatch().sendMessage("You can't use this when " + (isStunned(player) ? "stunned." : "frozen."));
|
||||
return true;
|
||||
}
|
||||
@@ -98,4 +97,4 @@ public final class BountyLocateSpell extends MagicSpell {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
package rs09.game.content.activity.castlewars.areas
|
||||
|
||||
import content.global.skill.summoning.familiar.BurdenBeast
|
||||
import core.api.LogoutListener
|
||||
import core.api.MapArea
|
||||
import core.api.log
|
||||
import core.api.sendMessage
|
||||
import core.api.*
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.tools.Log
|
||||
import rs09.game.content.activity.castlewars.CastleWars
|
||||
|
||||
abstract class CastleWarsArea : MapArea, LogoutListener, InteractionListener {
|
||||
@@ -51,7 +46,7 @@ abstract class CastleWarsArea : MapArea, LogoutListener, InteractionListener {
|
||||
player.interfaceManager.closeOverlay()
|
||||
|
||||
// Remove teleblock
|
||||
player.stateManager.remove(EntityState.TELEBLOCK)
|
||||
removeTimer(player, "teleblock")
|
||||
|
||||
// Remove any Castle Wars items
|
||||
// Todo Remove any tinderboxes or other castle wars items - See Jan 2018 update: https://oldschool.runescape.wiki/w/Castle_Wars
|
||||
@@ -78,4 +73,4 @@ abstract class CastleWarsArea : MapArea, LogoutListener, InteractionListener {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package rs09.game.content.activity.castlewars.areas
|
||||
|
||||
import core.api.TickListener
|
||||
import core.api.log
|
||||
import core.api.*
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
@@ -72,8 +70,7 @@ class CastleWarsGameArea : CastleWarsArea(), TickListener {
|
||||
override fun areaEnter(entity: Entity) {
|
||||
val player = entity as? Player ?: return
|
||||
super.areaEnter(player)
|
||||
// Block player teleport (for the remaining duration of the game)
|
||||
player.stateManager.set(EntityState.TELEBLOCK, (CastleWars.gameTimeMinutes)*60*2)
|
||||
registerTimer (player, spawnTimer("teleblock", (CastleWars.gameTimeMinutes)*60*2))
|
||||
|
||||
if (saradominPlayers.contains(player)) {
|
||||
player.interfaceManager.openOverlay(Component(Components.CASTLEWARS_STATUS_OVERLAY_SARADOMIN_58))
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
package rs09.game.content.activity.castlewars.areas
|
||||
|
||||
import CastleWarsOverlay
|
||||
import core.api.God
|
||||
import core.api.TickListener
|
||||
import core.api.hasGodItem
|
||||
import core.api.sendDialogue
|
||||
import core.api.*
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.tools.ticksPerMinute
|
||||
@@ -37,8 +33,7 @@ class CastleWarsWaitingArea : CastleWarsArea(), TickListener {
|
||||
override fun areaEnter(entity: Entity) {
|
||||
val player = entity as? Player ?: return
|
||||
super.areaEnter(player)
|
||||
// Block player teleport (for at least the max wait time)
|
||||
player.stateManager.set(EntityState.TELEBLOCK, (CastleWars.gameCooldownMinutes + CastleWars.gameTimeMinutes)*60*2)
|
||||
registerTimer(player, spawnTimer("teleblock", (CastleWars.gameCooldownMinutes + CastleWars.gameTimeMinutes)*60*2))
|
||||
|
||||
// Set team attribute and equip the hooded cloak on the entity based on which waiting room they're in
|
||||
if (zamorakWaitingRoom.insideBorder(player.location)) {
|
||||
|
||||
@@ -12,7 +12,6 @@ import core.game.container.impl.EquipmentContainer;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.LogType;
|
||||
import core.game.node.entity.player.info.login.PlayerParser;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
@@ -205,8 +204,8 @@ public final class DuelSession extends ComponentPlugin {
|
||||
*/
|
||||
public void heal(Player p) {
|
||||
p.fullRestore();
|
||||
if (p.getStateManager().hasState(EntityState.POISONED)) {
|
||||
p.getStateManager().remove(EntityState.POISONED);
|
||||
if (isPoisoned(p)) {
|
||||
curePoison(p);
|
||||
}
|
||||
p.getSkills().restore();
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@ package content.minigame.fishingtrawler
|
||||
import core.api.LogoutListener
|
||||
import core.api.MapArea
|
||||
import core.api.getRegionBorders
|
||||
import core.api.log
|
||||
import core.api.*
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.scenery.SceneryBuilder
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.GameWorld
|
||||
@@ -81,7 +80,7 @@ class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : Logo
|
||||
updateOverlay(player)
|
||||
player.properties.teleportLocation = base.transform(36,24,0)
|
||||
player.setAttribute("ft-session",this)
|
||||
player.stateManager.set(EntityState.TELEBLOCK,timeLeft)
|
||||
registerTimer (player, spawnTimer("teleblock", timeLeft))
|
||||
}
|
||||
zone.register(getRegionBorders(region.id))
|
||||
}
|
||||
@@ -105,7 +104,7 @@ class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : Logo
|
||||
player.appearance.setAnimations(Animation(188))
|
||||
player.properties.teleportLocation = session.base.transform(36,24,0)
|
||||
player.incrementAttribute("/save:$STATS_BASE:$FISHING_TRAWLER_SHIPS_SANK")
|
||||
player.stateManager.remove(EntityState.TELEBLOCK)
|
||||
removeTimer(player, "teleblock")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.impl.PulseManager;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.Rights;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
@@ -30,6 +29,8 @@ import core.plugin.ClassScanner;
|
||||
import core.tools.RandomFunction;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
|
||||
/**
|
||||
* Handles the Pest Control activity.
|
||||
@@ -147,8 +148,8 @@ public final class PestControlActivityPlugin extends ActivityPlugin {
|
||||
p.removeAttribute("pc_zeal");
|
||||
p.removeExtension(PestControlSession.class);
|
||||
p.fullRestore();
|
||||
if (p.getStateManager().hasState(EntityState.POISONED)) {
|
||||
p.getStateManager().remove(EntityState.POISONED);
|
||||
if (isPoisoned(p)) {
|
||||
curePoison(p);
|
||||
}
|
||||
PulseManager.cancelDeathTask(p);
|
||||
GameWorld.getPulser().submit(new Pulse(1, p) {
|
||||
|
||||
@@ -11,7 +11,6 @@ import core.game.node.entity.impl.PulseType;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
@@ -20,6 +19,8 @@ import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles a pest control spinner NPC.
|
||||
* @author Emperor
|
||||
@@ -101,8 +102,7 @@ public final class PCSpinnerNPC extends AbstractNPC {
|
||||
animate(getProperties().getDeathAnimation());
|
||||
for (Player p : RegionManager.getLocalPlayers(this, 1)) {
|
||||
p.getImpactHandler().manualHit(this, 5, HitsplatType.POISON);
|
||||
p.setAttribute("/save:poison_damage", 18);
|
||||
p.getStateManager().register(EntityState.POISONED, false, 18, this);
|
||||
applyPoison(p, this, 1);
|
||||
}
|
||||
GameWorld.getPulser().submit(new Pulse(1, this) {
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,6 @@ package content.minigame.pyramidplunder
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Direction
|
||||
import core.game.world.map.Location
|
||||
@@ -117,7 +116,7 @@ class PyramidPlunderMinigame : InteractionListener, TickListener, LogoutListener
|
||||
animate(player, URN_BIT)
|
||||
sendMessage(player, "You've been bitten by something moving around in the urn.")
|
||||
impact(player, RandomFunction.random(1,5))
|
||||
player.stateManager.register(EntityState.POISONED, true, 20, player)
|
||||
applyPoison(player, player, 2)
|
||||
}
|
||||
else {
|
||||
animate(player, URN_SUCCESS)
|
||||
@@ -169,7 +168,7 @@ class PyramidPlunderMinigame : InteractionListener, TickListener, LogoutListener
|
||||
animate(player, URN_BIT)
|
||||
sendMessage(player, "You've been bitten by something moving around in the urn.")
|
||||
impact(player, RandomFunction.random(1,5))
|
||||
player.stateManager.register(EntityState.POISONED, true, 20, player)
|
||||
applyPoison(player, player, 2)
|
||||
}
|
||||
else {
|
||||
animate(player, URN_SUCCESS)
|
||||
|
||||
@@ -13,7 +13,6 @@ import core.game.node.entity.npc.AbstractNPC
|
||||
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.entity.state.EntityState
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.node.scenery.Scenery
|
||||
@@ -498,7 +497,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea {
|
||||
object VinesweeperTeleport {
|
||||
@JvmStatic
|
||||
fun teleport(npc: NPC, player: Player) {
|
||||
if (player.stateManager.hasState(EntityState.TELEBLOCK)) {
|
||||
if (hasTimerActive(player, "teleblock")) {
|
||||
sendNPCDialogue(player, npc.id, "I can't do that, you're teleblocked!", core.game.dialogue.FacialExpression.OLD_ANGRY1)
|
||||
return
|
||||
}
|
||||
|
||||
+4
-3
@@ -9,11 +9,12 @@ import core.game.node.entity.combat.equipment.ArmourSet;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles K'ril Tsutsaroth's combat.
|
||||
* @author Emperor
|
||||
@@ -72,7 +73,7 @@ public final class GWDTsutsarothSwingHandler extends CombatSwingHandler {
|
||||
hit = RandomFunction.random(max);
|
||||
state.setMaximumHit(max);
|
||||
if (style == CombatStyle.MELEE) {
|
||||
victim.getStateManager().register(EntityState.POISONED, false, 168, entity);
|
||||
applyPoison(victim, entity, 16);
|
||||
}
|
||||
if (special) {
|
||||
((Player) victim).getSkills().decrementPrayerPoints((double) hit / 2);
|
||||
@@ -152,4 +153,4 @@ public final class GWDTsutsarothSwingHandler extends CombatSwingHandler {
|
||||
return getType().getSwingHandler().calculateHit(entity, victim, modifier);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,13 @@ import core.game.node.entity.combat.InteractionType;
|
||||
import core.game.node.entity.combat.equipment.SwitchAttack;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.map.Location;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.combat.CombatSwingHandler;
|
||||
import core.game.node.entity.combat.MultiSwingHandler;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Represents a spinolyp npc.
|
||||
* @author Vexia
|
||||
@@ -147,7 +148,7 @@ public final class SpinolypNPC extends AbstractNPC {
|
||||
victim.getSkills().decrementPrayerPoints(1);
|
||||
} else {
|
||||
if (RandomFunction.random(20) == 5) {
|
||||
victim.getStateManager().register(EntityState.POISONED, false, 68, entity);
|
||||
applyPoison(victim, entity, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package content.region.kandarin.quest.dwarfcannon.dmc
|
||||
|
||||
import core.api.*
|
||||
import core.tools.*
|
||||
import core.game.system.timer.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
|
||||
class CannonTimer : RSTimer (1, "dmc:timer") {
|
||||
lateinit var dmcHandler: DMCHandler
|
||||
var ticksUntilDecay = 2500
|
||||
var isFiring = false
|
||||
|
||||
override fun run (entity: Entity) : Boolean {
|
||||
if (entity !is Player)
|
||||
return false
|
||||
if (!dmcHandler.cannon.isActive())
|
||||
return false
|
||||
if (isFiring)
|
||||
isFiring = dmcHandler.rotate()
|
||||
if (--ticksUntilDecay == 500) {
|
||||
sendMessage (entity, colorize("%RYour cannon is about to decay."))
|
||||
} else if (ticksUntilDecay == 0) {
|
||||
dmcHandler.explode(true)
|
||||
}
|
||||
return ticksUntilDecay > 0 && dmcHandler.cannon.isActive()
|
||||
}
|
||||
|
||||
override fun getTimer (vararg args: Any) : RSTimer {
|
||||
val t = retrieveInstance() as CannonTimer
|
||||
t.dmcHandler = args[0] as DMCHandler
|
||||
return t
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import core.game.node.entity.combat.CombatSwingHandler;
|
||||
import core.game.world.GameWorld;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles a player's Dwarf Multi-cannon.
|
||||
* @author Emperor
|
||||
@@ -43,23 +45,15 @@ public final class DMCHandler implements LogoutListener {
|
||||
*/
|
||||
private int cannonballs;
|
||||
|
||||
/**
|
||||
* The firing pulse.
|
||||
*/
|
||||
private Pulse firingPulse;
|
||||
|
||||
/**
|
||||
* The current direction.
|
||||
*/
|
||||
private DMCRevolution direction = DMCRevolution.NORTH;
|
||||
|
||||
/**
|
||||
* The decaying pulse.
|
||||
*/
|
||||
private Pulse decayPulse;
|
||||
private CannonTimer timer;
|
||||
|
||||
public DMCHandler() {
|
||||
this.player = null;
|
||||
this.player = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,44 +62,16 @@ public final class DMCHandler implements LogoutListener {
|
||||
*/
|
||||
public DMCHandler(final Player player) {
|
||||
this.player = player;
|
||||
this.firingPulse = new Pulse(1, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (!cannon.isActive()) {
|
||||
return true;
|
||||
}
|
||||
return rotate();
|
||||
}
|
||||
|
||||
};
|
||||
firingPulse.stop();
|
||||
this.decayPulse = new Pulse(2000, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (!cannon.isActive()) {
|
||||
return true;
|
||||
}
|
||||
if (getDelay() == 2000) {
|
||||
setDelay(500);
|
||||
player.sendMessage("Your cannon is about to decay!");
|
||||
return false;
|
||||
}
|
||||
explode(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
decayPulse.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the cannon.
|
||||
* @return {@code True} if the cannon should stop rotating.
|
||||
*/
|
||||
private boolean rotate() {
|
||||
public boolean rotate() {
|
||||
if (cannonballs < 1) {
|
||||
player.getPacketDispatch().sendMessage("Your cannon has run out of ammo!");
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
player.getPacketDispatch().sendSceneryAnimation(cannon, Animation.create(direction.getAnimationId()));
|
||||
Location l = cannon.getLocation().transform(1, 1, 0);
|
||||
@@ -127,7 +93,7 @@ public final class DMCHandler implements LogoutListener {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,9 +104,9 @@ public final class DMCHandler implements LogoutListener {
|
||||
player.getPacketDispatch().sendMessage("You don't have a cannon active.");
|
||||
return;
|
||||
}
|
||||
if (firingPulse.isRunning()) {
|
||||
firingPulse.stop();
|
||||
return;
|
||||
if (timer.isFiring()) {
|
||||
timer.setFiring(false);
|
||||
return;
|
||||
}
|
||||
if (cannonballs < 1) {
|
||||
int amount = player.getInventory().getAmount(new Item(2));
|
||||
@@ -160,9 +126,7 @@ public final class DMCHandler implements LogoutListener {
|
||||
player.sendMessage("Your cannon is already fully loaded.");
|
||||
}
|
||||
}
|
||||
firingPulse.restart();
|
||||
firingPulse.start();
|
||||
GameWorld.getPulser().submit(firingPulse);
|
||||
timer.setFiring(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,10 +157,6 @@ public final class DMCHandler implements LogoutListener {
|
||||
return;
|
||||
}
|
||||
final DMCHandler handler = new DMCHandler(player);
|
||||
if (handler.decayPulse.isRunning()) {
|
||||
handler.decayPulse.stop();
|
||||
return;
|
||||
}
|
||||
player.setAttribute("dmc", handler);
|
||||
player.getPulseManager().clear();
|
||||
player.getWalkingQueue().reset();
|
||||
@@ -233,6 +193,8 @@ public final class DMCHandler implements LogoutListener {
|
||||
player.getPacketDispatch().sendMessage("You add the furnace.");
|
||||
SceneryBuilder.remove(object);
|
||||
handler.configure(SceneryBuilder.add(object = object.transform(6)));
|
||||
handler.timer = (CannonTimer) spawnTimer ("dmc:timer", handler);
|
||||
registerTimer (player, handler.timer);
|
||||
return true;
|
||||
}
|
||||
player.getAudioManager().send(new Audio(2876), true);
|
||||
@@ -267,9 +229,6 @@ public final class DMCHandler implements LogoutListener {
|
||||
* @param pickup If the cannon is getting picked up.
|
||||
*/
|
||||
public void clear(boolean pickup) {
|
||||
if (decayPulse.isRunning()) {
|
||||
decayPulse.stop();
|
||||
}
|
||||
SceneryBuilder.remove(cannon);
|
||||
player.removeAttribute("dmc");
|
||||
if (!pickup) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import core.game.node.entity.combat.BattleState
|
||||
import core.game.node.entity.combat.CombatStyle
|
||||
import core.game.node.entity.npc.AbstractNPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.node.item.Item
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.scenery.SceneryBuilder
|
||||
@@ -72,7 +71,7 @@ public class YanilleAgilityDungeonListeners : InteractionListener {
|
||||
player.lock(1)
|
||||
if(player.inventory.remove(Item(Items.SINISTER_KEY_993, 1))) {
|
||||
player.sendMessages("You unlock the chest with your key...", "A foul gas seeps from the chest");
|
||||
player.getStateManager().register(EntityState.POISONED, true, 28, player);
|
||||
applyPoison (player, player, 2)
|
||||
for(item in SINISTER_CHEST_HERBS) {
|
||||
addItemOrDrop(player, item.id, item.amount)
|
||||
}
|
||||
|
||||
@@ -6,14 +6,13 @@ import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.isStunned;
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the Dark Energy Core NPC.
|
||||
@@ -71,7 +70,7 @@ public final class DarkEnergyCoreNPC extends AbstractNPC {
|
||||
@Override
|
||||
public void handleTickActions() {
|
||||
ticks++;
|
||||
boolean poisoned = getStateManager().hasState(EntityState.POISONED);
|
||||
boolean poisoned = isPoisoned(this);
|
||||
if (isStunned(this) || isInvisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package content.region.wilderness.handlers
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import org.json.simple.JSONObject
|
||||
import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
|
||||
@PlayerState("skull")
|
||||
class SkulledState(player: Player? = null) : State(player) {
|
||||
var ticksLeft = 2000
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
root.put("ticksLeft",ticksLeft)
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("ticksLeft")){
|
||||
ticksLeft = _data["ticksLeft"].toString().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
return SkulledState(player)
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
player ?: return
|
||||
if(ticksLeft <= 0) return
|
||||
player.skullManager.setSkullIcon(0)
|
||||
player.skullManager.isSkulled = true
|
||||
pulse = object : Pulse(){
|
||||
override fun pulse(): Boolean {
|
||||
ticksLeft--
|
||||
if(ticksLeft <= 0) {
|
||||
player.skullManager.reset()
|
||||
pulse = null
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+9
-7
@@ -7,13 +7,14 @@ import core.game.node.entity.combat.equipment.SwitchAttack;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.prayer.PrayerType;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.map.zone.impl.WildernessZone;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.game.node.entity.combat.MultiSwingHandler;
|
||||
import core.game.world.GameWorld;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
|
||||
/**
|
||||
* Handles the multi swing combat handler for revenants.
|
||||
* @author Vexia
|
||||
@@ -55,24 +56,25 @@ public class RevenantCombatHandler extends MultiSwingHandler {
|
||||
if (victim instanceof Player) {
|
||||
SwitchAttack attack = getCurrent();
|
||||
if (attack != null) {
|
||||
if (attack.getStyle() == CombatStyle.RANGE && victim.getAttribute("freeze_immunity", -1) < GameWorld.getTicks()) {
|
||||
victim.getStateManager().set(EntityState.FROZEN, 16, "The icy darts freeze your muscles!");
|
||||
if (attack.getStyle() == CombatStyle.RANGE && !hasTimerActive(victim, "frozen") && !hasTimerActive(victim, "frozen:immunity")) {
|
||||
registerTimer(victim, spawnTimer("frozen", 16, true));
|
||||
sendMessage((Player) victim, "The icy darts freeze your muscles!");
|
||||
victim.asPlayer().getAudioManager().send(4059, true);
|
||||
} else if (attack.getStyle() == CombatStyle.MAGIC) {
|
||||
int ticks = 500;
|
||||
if (victim.asPlayer().getPrayer().get(PrayerType.PROTECT_FROM_MAGIC)) {
|
||||
ticks /= 2;
|
||||
}
|
||||
if (victim.getStateManager().hasState(EntityState.TELEBLOCK)) {
|
||||
if (hasTimerActive(victim, "teleblock")) {
|
||||
victim.asPlayer().getAudioManager().send(4064, true);
|
||||
} else {
|
||||
victim.getStateManager().set(EntityState.TELEBLOCK, ticks);
|
||||
registerTimer (victim, spawnTimer("teleblock", ticks));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!victim.getStateManager().hasState(EntityState.POISONED) && (WildernessZone.getWilderness(entity) >= 50 || entity.getId() == 6998)) {
|
||||
victim.getStateManager().register(EntityState.POISONED, false, 68, entity);
|
||||
if (!isPoisoned(victim) && (WildernessZone.getWilderness(entity) >= 50 || entity.getId() == 6998)) {
|
||||
applyPoison(victim, entity, 6);
|
||||
}
|
||||
super.impact(entity, victim, state);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user