Repository reorganisation

Unified kotlin and java into just src/main
Unified the rs09 and core packages
Took all content out of the core package, and placed it into the new content package
Reorganised all source code relating to content to be easier to find and explore
This commit is contained in:
Ceikry
2023-01-26 13:59:28 +00:00
committed by Ryan
parent e4b799c44a
commit a100affda2
3156 changed files with 24205 additions and 30585 deletions
@@ -0,0 +1,86 @@
package content.global.skill.slayer;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.skill.Skills;
import core.game.world.map.Location;
import core.plugin.Initializable;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.MagicSwingHandler;
/**
* Handles the aberrant spectre npc.
* @author Vexia
*/
@Initializable
public final class AberrantSpectreNPC extends AbstractNPC {
/**
* The skills to drain.
*/
private static final int[] SKILLS = new int[] { Skills.ATTACK, Skills.STRENGTH, Skills.DEFENCE, Skills.RANGE, Skills.MAGIC, Skills.PRAYER, Skills.AGILITY };
/**
* The combat handler to use.
*/
private static final MagicSwingHandler COMBAT_HANDLER = new MagicSwingHandler() {
@Override
public void impact(final Entity entity, final Entity victim, BattleState state) {
if (victim instanceof Player) {
Player player = (Player) victim;
if (!SlayerEquipmentFlags.hasNosePeg(player)) {
for (int skill : SKILLS) {
int drain = (int) (player.getSkills().getStaticLevel(skill) * 0.5);
player.getSkills().updateLevel(skill, -drain, 0);
}
}
}
super.impact(entity, victim, state);
}
};
/**
* Constructs a new {@code AberrantSpectreNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public AberrantSpectreNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code AberrantSpectreNPC} {@code Object}.
*/
public AberrantSpectreNPC() {
super(0, null);
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
if (state.getAttacker() instanceof Player) {
final Player player = (Player) state.getAttacker();
if (!SlayerEquipmentFlags.hasNosePeg(player)) {
state.neutralizeHits();
}
}
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return COMBAT_HANDLER;
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new AberrantSpectreNPC(id, location);
}
@Override
public int[] getIds() {
return Tasks.ABERRANT_SPECTRES.getNpcs();
}
}
@@ -0,0 +1,73 @@
package content.global.skill.slayer;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.MeleeSwingHandler;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Graphics;
import core.plugin.Initializable;
import core.tools.RandomFunction;
import static core.api.ContentAPIKt.getPathableRandomLocalCoordinate;
/**
* Handles the abyssal npc.
* @author Vexia
*/
@Initializable
public class AbyssalDemonNPC extends AbstractNPC {
/**
* The melee swing handler.
*/
private static final MeleeSwingHandler SWING_HANDLER = new MeleeSwingHandler() {
@Override
public int swing(Entity entity, Entity victim, BattleState state) {
if (victim instanceof Player && RandomFunction.random(8) <= 2) {
boolean npc = RandomFunction.random(100) <= 50;
Entity source = npc ? victim : entity;
Entity teleported = npc ? entity : victim;
Location loc = getPathableRandomLocalCoordinate(teleported, 1, source.getLocation(), 3);
teleported.graphics(Graphics.create(409));
teleported.teleport(loc, 1);
}
return super.swing(entity, victim, state);
}
};
/**
* Constructs a new {@Code AbyssalNPC} {@Code Object}
*/
public AbyssalDemonNPC() {
super(-1, null);
}
/**
* Constructs a new {@Code AbyssalNPC} {@Code Object}
* @param id the id.
* @param location the location.
*/
public AbyssalDemonNPC(int id, Location location) {
super(id, location);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return SWING_HANDLER;
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new AbyssalDemonNPC(id, location);
}
@Override
public int[] getIds() {
return Tasks.ABYSSAL_DEMONS.getNpcs();
}
}
@@ -0,0 +1,116 @@
package content.global.skill.slayer;
import core.plugin.Initializable;
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.combat.CombatSwingHandler;
import core.game.node.entity.combat.InteractionType;
import core.game.node.entity.combat.MeleeSwingHandler;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.tools.RandomFunction;
/**
* Handles the banshee npc.
* @author Vexia
*/
@Initializable
public final class BansheeNPC extends AbstractNPC {
/**
* The skills to drain.
*/
private static final int[] SKILLS = new int[] { Skills.ATTACK, Skills.STRENGTH, Skills.DEFENCE, Skills.RANGE, Skills.MAGIC, Skills.PRAYER, Skills.AGILITY };
/**
* The combat handler.
*/
private static final MeleeSwingHandler COMBAT_HANDLER = new MeleeSwingHandler() {
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
if (victim instanceof Player) {
final Player player = (Player) victim;
if (!hasEarMuffs(player)) {
if (RandomFunction.random(10) < 4 && player.getProperties().getCombatPulse().getNextAttack() <= GameWorld.getTicks()) {
player.getWalkingQueue().reset();
player.getLocks().lockMovement(3);
player.getProperties().getCombatPulse().setNextAttack(3);
player.animate(new Animation(1572, Priority.HIGH));
}
for (int skill : SKILLS) {
int drain = (int) (player.getSkills().getStaticLevel(skill) * 0.5);
player.getSkills().updateLevel(skill, -drain, 0);
}
state.setEstimatedHit(8);
}
}
super.impact(entity, victim, state);
}
@Override
public InteractionType isAttackable(Entity entity, Entity victim) {
return CombatStyle.MAGIC.getSwingHandler().isAttackable(entity, victim);
}
};
/**
* Constructs a new {@code BansheeNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public BansheeNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code BansheeNPC} {@code Object}.
*/
public BansheeNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new BansheeNPC(id, location);
}
@Override
public void onImpact(Entity entity, BattleState state) {
super.onImpact(entity, state);
if (state.getAttacker() instanceof Player) {
final Player player = (Player) state.getAttacker();
if (!hasEarMuffs(player)) {
state.neutralizeHits();
}
}
if (state.getEstimatedHit() > 0 || state.getSecondaryHit() > 0) {
getSkills().heal(1);
}
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return COMBAT_HANDLER;
}
/**
* Checks if the player has ear muffs.
* @param player the player.
* @return {@code True} if they have it.
*/
public static boolean hasEarMuffs(Player player) {
return SlayerEquipmentFlags.hasEarmuffs(player);
}
@Override
public int[] getIds() {
return new int[] { 1612 };
}
}
@@ -0,0 +1,53 @@
package content.global.skill.slayer;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.npc.AbstractNPC;
import core.game.world.map.Location;
import core.plugin.Initializable;
/**
* Handles the basilisk npc.
* @author Vexia
*/
@Initializable
public final class BasiliskNPC extends AbstractNPC {
/**
* Constructs a new {@code BasiliskNPC} {@code Object}.
*/
public BasiliskNPC() {
super(0, null);
}
/**
* Constructs a new {@code BasiliskNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public BasiliskNPC(int id, Location location) {
super(id, location);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new BasiliskNPC(id, location);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return MirrorShieldHandler.SINGLETON;
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
MirrorShieldHandler.SINGLETON.checkImpact(state);
}
@Override
public int[] getIds() {
return new int[] { 1616, 1617 };
}
}
@@ -0,0 +1,69 @@
package content.global.skill.slayer;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.equipment.SwitchAttack;
import content.global.handlers.item.equipment.special.DragonfireSwingHandler;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.impl.Projectile;
import core.game.node.entity.npc.AbstractNPC;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.plugin.Initializable;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.MultiSwingHandler;
/**
* Handles a brutal dragon npc.
* @author Vexia
*/
@Initializable
public final class BrutalDragonNPC extends AbstractNPC {
/**
* The dragonfire attack.
*/
private static final SwitchAttack DRAGONFIRE = DragonfireSwingHandler.get(false, 52, new Animation(81, Priority.HIGH), Graphics.create(1), null, null);
/**
* Handles the combat.
*/
private final CombatSwingHandler combatAction = new MultiSwingHandler(true, new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), new Animation(80, Priority.HIGH)), new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), new Animation(80, Priority.HIGH)), new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), new Animation(81, Priority.HIGH), null, null, Projectile.create((Entity) null, null, 500, 20, 20, 41, 40, 18, 255)), DRAGONFIRE);
/**
* Constructs a new {@code BrutalDragonNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public BrutalDragonNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code MithrilDragonNPC} {@code Object}.
*/
public BrutalDragonNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new BrutalDragonNPC(id, location);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return combatAction;
}
@Override
public int getDragonfireProtection(boolean fire) {
return 0x2 | 0x4 | 0x8;
}
@Override
public int[] getIds() {
return new int[] { 5362 };
}
}
@@ -0,0 +1,65 @@
package content.global.skill.slayer;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.world.map.Location;
import core.plugin.Initializable;
/**
* Represents the plugin used to handle the harpie bug swarm.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class BugSwarmNPC extends AbstractNPC {
/**
* Represents the lit latern item.
*/
private static final Item LIT_LANTERN = new Item(7053);
/**
* Constructs a new {@code BugSwarmNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public BugSwarmNPC(int id, Location location) {
super(id, location, true);
}
/**
* Constructs a new {@code BugSwarmNPC} {@code Object}.
*/
public BugSwarmNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new BugSwarmNPC(id, location);
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
if (state.getAttacker() instanceof Player) {
final Player player = (Player) state.getAttacker();
if (!player.getEquipment().containsItem(LIT_LANTERN)) {
if (state.getEstimatedHit() > -1) {
state.setEstimatedHit(0);
}
if (state.getSecondaryHit() > -1) {
state.setSecondaryHit(0);
}
}
}
}
@Override
public int[] getIds() {
return new int[] { 3153 };
}
}
@@ -0,0 +1,95 @@
package content.global.skill.slayer;
import core.cache.def.impl.ItemDefinition;
import core.plugin.Initializable;
import core.game.node.entity.skill.Skills;
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.item.Item;
import core.plugin.Plugin;
/**
* Represents the plugin used to handle a bug lantern.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class BuglanternPlugin implements Plugin<Object> {
/**
* Represents the unlit lantern item.
*/
private static final Item UNLIT_LANTERN = new Item(7051);
/**
* Represents the lit latern item.
*/
private static final Item LIT_LANTERN = new Item(7053);
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
new LightLanternPlugin().newInstance(arg);
ItemDefinition.forId(LIT_LANTERN.getId()).getHandlers().put("option:extinguish", new OptionHandler() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
if (player.getInventory().remove(LIT_LANTERN)) {
player.getInventory().add(UNLIT_LANTERN);
}
return true;
}
@Override
public boolean isWalk() {
return false;
}
});
return this;
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
/**
* Represents the plugin used to light the lantern.
* @author 'Vexia
* @version 1.0
*/
public final class LightLanternPlugin extends UseWithHandler {
/**
* Constructs a new {@code LightLanternPlugin} {@code Object}.
*/
public LightLanternPlugin() {
super(590);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
addHandler(UNLIT_LANTERN.getId(), ITEM_TYPE, this);
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
if (player.getSkills().getLevel(Skills.FIREMAKING) < 33) {
player.sendMessage("You need a Firemaking level of at least 33 in order to do this.");
return true;
}
player.getInventory().replace(LIT_LANTERN, event.getUsedItem().getSlot());
return true;
}
}
}
@@ -0,0 +1,60 @@
package content.global.skill.slayer;
import core.game.node.entity.Entity;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.Initializable;
/**
* Handles the cave bug npc.
* @author Vexia
*
*/
@Initializable
public class CaveBugNPC extends AbstractNPC {
/**
* The cave border.
*/
// private static final ZoneBorders CAVE_BORDER = new ZoneBorders(3139, 9534, 3260, 9587);
/**
* Constructs the {@code CaveBugNPC}
*/
public CaveBugNPC() {
super(-1, null);
}
/**
* Constructs the {@code CaveBugNPC}
* @param id The id.
* @param location The location.
*/
public CaveBugNPC(int id, Location location) {
super(id, location);
}
@Override
public void finalizeDeath(Entity killer) {
super.finalizeDeath(killer);
if (killer instanceof Player) {
Player p = killer.asPlayer();
/* AchievementDiary diary = p.getAchievementDiaryManager().getDiary(DiaryType.LUMBRIDGE);
if (!diary.isComplete(0, 0) && CAVE_BORDER.insideBorder(p)) {
diary.updateTask(p, 0, 0, true);
}*/
}
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new CaveBugNPC(id, location);
}
@Override
public int[] getIds() {
return new int[] {1832, 1833, 5750};
}
}
@@ -0,0 +1,85 @@
package content.global.skill.slayer;
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.combat.CombatSwingHandler;
import core.game.node.entity.combat.InteractionType;
import core.game.node.entity.combat.MeleeSwingHandler;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.Initializable;
import core.tools.RandomFunction;
/**
* Handles the Cave Horrors on Mos'le Harmless. You technically do not need a witchwood icon to fight them.
* "Without the icon, cave horrors can damage the player for 10% of their total hitpoints, although it does not lower stats."
* @author Splinter
*/
@Initializable
public final class CaveHorrorNPC extends AbstractNPC {
/**
* The Cave Horror combat handler.
*/
private static final MeleeSwingHandler COMBAT_HANDLER = new MeleeSwingHandler() {
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
if (victim instanceof Player) {
final Player player = (Player) victim;
if (!hasWitchwood(player)) {
if (RandomFunction.random(10) < 5) {
state.setEstimatedHit(player.getSkills().getLifepoints() / 10);
}
}
}
super.impact(entity, victim, state);
}
@Override
public InteractionType isAttackable(Entity entity, Entity victim) {
return CombatStyle.MELEE.getSwingHandler().isAttackable(entity, victim);
}
};
/**
* Constructs a new {@code CaveHorrorNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public CaveHorrorNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code CaveHorrorNPC} {@code Object}.
*/
public CaveHorrorNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new CaveHorrorNPC(id, location);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return COMBAT_HANDLER;
}
/**
* Checks if the player has the icon equipped.
* @param player the player.
* @return {@code true} if it is equipped.
*/
public static boolean hasWitchwood(Player player) {
return SlayerEquipmentFlags.hasWitchwoodIcon(player);
}
@Override
public int[] getIds() {
return new int[] { 4354, 4355, 4353, 4356, 4357 };
}
}
@@ -0,0 +1,53 @@
package content.global.skill.slayer;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.npc.AbstractNPC;
import core.game.world.map.Location;
import core.plugin.Initializable;
/**
* Handles a cockatrice npc.
* @author Vexia
*/
@Initializable
public final class CockatriceNPC extends AbstractNPC {
/**
* Constructs a new {@code CockatriceNPC} {@code Object}.
*/
public CockatriceNPC() {
super(0, null);
}
/**
* Constructs a new {@code CockatriceNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public CockatriceNPC(int id, Location location) {
super(id, location);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new CockatriceNPC(id, location);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return MirrorShieldHandler.SINGLETON;
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
MirrorShieldHandler.SINGLETON.checkImpact(state);
}
@Override
public int[] getIds() {
return new int[] { 1620, 1621 };
}
}
@@ -0,0 +1,148 @@
package content.global.skill.slayer;
import core.plugin.Initializable;
import core.game.node.entity.skill.Skills;
import core.game.interaction.NodeUsageEvent;
import core.game.interaction.UseWithHandler;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
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.item.Item;
import core.game.world.map.Location;
import core.plugin.Plugin;
/**
* Represents the dezert lizard plugin.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class DesertLizardPlugin implements Plugin<Object> {
/**
* Represents the ids to use.
*/
private static final int[] IDS = new int[] { 2803, 2804, 2805, 2806, 2807, 2808 };
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
new IcecoolerPlugin().newInstance(arg);
new DezertLizardNPC().newInstance(arg);
return this;
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
/**
* Represents the ice cooler plugin.
* @author 'Vexia
* @version 1.0
*/
public static final class IcecoolerPlugin extends UseWithHandler {
/**
* Represents the ice cooler item.
*/
private static final Item ICE_COOLER = new Item(6696);
/**
* Constructs a new {@code IcecoolerPlugin} {@code Object}.
*/
public IcecoolerPlugin() {
super(ICE_COOLER.getId());
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (int id : IDS) {
addHandler(id, NPC_TYPE, this);
}
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
if (player.getSkills().getLevel(Skills.SLAYER) < 22) {
player.getPacketDispatch().sendMessage("You need a Slayer level of at least 22 to do this.");
return true;
}
final NPC npc = (NPC) event.getUsedWith();
if (npc.getSkills().getLifepoints() > 2) {
player.getPacketDispatch().sendMessage("The lizard isn't weak enough to be affected by the icy water.");
return true;
}
if (player.getInventory().remove(ICE_COOLER)) {
npc.getImpactHandler().manualHit(player, npc.getSkills().getLifepoints(), HitsplatType.NORMAL);
player.getPacketDispatch().sendMessage("The lizard shudders and collapses from the freezing water.");
}
return true;
}
}
/**
* Represents the desert lizard npc.
* @author 'Vexia
* @version 1.0
*/
public final class DezertLizardNPC extends AbstractNPC {
/**
* Constructs a new {@code DezertLizardNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public DezertLizardNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code DezertLizardNPC} {@code Object}.
*/
public DezertLizardNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new DezertLizardNPC(id, location);
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
int lifepoints = getSkills().getLifepoints();
if (state.getEstimatedHit() > -1) {
lifepoints -= state.getEstimatedHit();
if (lifepoints < 1) {
state.setEstimatedHit(lifepoints - 1);
}
if (state.getEstimatedHit() < 0) {
state.setEstimatedHit(0);
getSkills().setLifepoints(2);
}
}
if (state.getSecondaryHit() > -1) {
lifepoints -= state.getSecondaryHit();
if (lifepoints < 1) {
state.setSecondaryHit(lifepoints - 1);
}
if (state.getSecondaryHit() < 0) {
state.setSecondaryHit(0);
}
}
}
@Override
public int[] getIds() {
return IDS;
}
}
}
@@ -0,0 +1,95 @@
package content.global.skill.slayer;
import core.plugin.Initializable;
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.combat.CombatSwingHandler;
import core.game.node.entity.combat.InteractionType;
import core.game.node.entity.combat.MeleeSwingHandler;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
/**
* Handles the dust devil npc.
* @author Vexia
*/
@Initializable
public final class DustDevilNPC extends AbstractNPC {
/**
* The skills.
*/
private static final int[] SKILLS = new int[] { Skills.ATTACK, Skills.STRENGTH, Skills.RANGE, Skills.MAGIC };
/**
* The combat handler.
*/
private static final MeleeSwingHandler COMBAT_HANDLER = new MeleeSwingHandler() {
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
if (victim instanceof Player) {
final Player player = (Player) victim;
if (!SlayerEquipmentFlags.hasFaceMask(player)) {
for (int i : SKILLS) {
player.getSkills().updateLevel(i, -player.getSkills().getStaticLevel(i), 0);
}
player.getSkills().decrementPrayerPoints((double) player.getSkills().getStaticLevel(Skills.PRAYER) / 2);
state.setEstimatedHit(14);
}
}
super.impact(entity, victim, state);
}
@Override
public InteractionType isAttackable(Entity entity, Entity victim) {
return CombatStyle.MAGIC.getSwingHandler().isAttackable(entity, victim);
}
};
/**
* Constructs a new {@code DustDevilNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public DustDevilNPC(int id, Location location) {
super(id, location);
super.getProperties().getCombatPulse().setHandler(COMBAT_HANDLER);
}
/**
* Constructs a new {@code DustDevilNPC} {@code Object}.
*/
public DustDevilNPC() {
super(0, null);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return COMBAT_HANDLER;
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
if (state.getAttacker() instanceof Player) {
Player player = (Player) state.getAttacker();
if (!SlayerEquipmentFlags.hasFaceMask(player)) {
state.neutralizeHits();
}
}
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new DustDevilNPC(id, location);
}
@Override
public int[] getIds() {
return Tasks.DUST_DEVILS.getNpcs();
}
}
@@ -0,0 +1,228 @@
package content.global.skill.slayer;
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.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
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.player.link.HintIconManager;
import core.game.node.entity.player.link.diary.DiaryType;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Direction;
import core.game.world.map.Location;
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 core.tools.RandomFunction;
/**
* Represents the plugin used to handle the fishing expolosive on a omnious
* fishing spot.
* @author 'Vexia
*/
@Initializable
public final class FishingExplosivePlugin extends OptionHandler {
/**
* Represents the ominous fishing spot ids.
*/
private final static int[] IDS = new int[] { 10087, 10088, 10089 };
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (int id : IDS) {
SceneryDefinition.forId(id).getHandlers().put("option:lure", this);
SceneryDefinition.forId(id).getHandlers().put("option:bait", this);
}
new FishingExplosiveHandler().newInstance(arg);
new MogreNPC().newInstance(arg);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
player.getPacketDispatch().sendMessage("Something seems to have scared all the fishes away...");
return true;
}
@Override
public Location getDestination(Node node, Node n) {
return node.getLocation();
}
/**
* Represents the handler for the fishing expolsive on a fishing spot.
* @author 'Vexia
* @version 1.0
*/
public static final class FishingExplosiveHandler extends UseWithHandler {
/**
* Represents the throwing animation.
*/
private static final Animation ANIMATION = new Animation(385);
/**
* Represents the splashing graphics.
*/
private static final Graphics SPLASH_GRAPHIC = new Graphics(68);
/**
* Represents the npc mogre id.
*/
private static final int MOGRE_ID = 114;
/**
* Represents the messages used to send for the mogres.
*/
private static final String[] MESSAGES = new String[] { "Da boom-boom kill all da fishies!", "I smack you good!", "Smash stupid human!", "Tasty human!", "Human hit me on the head!", "I get you!", "Human scare all da fishies!" };
/**
* Constructs a new {@code FishingExplosiveHandler} {@code Object}.
*/
public FishingExplosiveHandler() {
super(6664, 12633);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (int i : IDS) {
addHandler(i, OBJECT_TYPE, this);
}
return this;
}
@Override
public boolean handle(final NodeUsageEvent event) {
final Player player = event.getPlayer();
if (player.getAttributes().containsKey("hasMogre")) {
player.getDialogueInterpreter().sendDialogues(player, null, "Sinister as that fishing spot is, why would I want to", "explode it?");
return true;
}
if (!player.getInventory().remove(new Item(event.getUsedItem().getId(), 1))) {
return true;
}
final int delay = (int) (2 + (player.getLocation().getDistance(event.getUsedWith().getLocation())) * 0.5);
player.animate(ANIMATION);
player.getPacketDispatch().sendMessage("You hurl the shuddering vial into the water...");
sendProjectile(player, (Scenery) event.getUsedWith());
GameWorld.getPulser().submit(new Pulse(delay, player) {
@Override
public boolean pulse() {
Direction dir = event.getUsedWith().getDirection();
NPC mogre = NPC.create(MOGRE_ID, event.getUsedWith().getLocation().transform(dir.getStepX() << 1, dir.getStepY() << 1, 0));
mogre.init();
mogre.moveStep();
mogre.setRespawn(false);
mogre.getProperties().getCombatPulse().attack(player);
mogre.setAttribute("player", player);
mogre.sendChat(MESSAGES[RandomFunction.random(MESSAGES.length)]);
HintIconManager.registerHintIcon(player, mogre);
if (event.getUsedItem().getId() == 12633) {
mogre.getImpactHandler().manualHit(player, 15, HitsplatType.NORMAL);
}
player.setAttribute("hasMogre", true);
mogre.graphics(SPLASH_GRAPHIC);
player.getPacketDispatch().sendMessage("...and a Mogre appears!");
return true;
}
});
return true;
}
/**
* Method used to send the fishign explosive projectile.
* @param player the player.
* @param object the object.
*/
private void sendProjectile(final Player player, final Scenery object) {
Projectile p = Projectile.create(player, null, 49, 30, 20, 30, Projectile.getSpeed(player, object.getLocation()));
p.setEndLocation(object.getLocation());
p.send();
}
@Override
public Location getDestination(Player player, Node with) {
return player.getLocation();
}
}
/**
* Represents a mogre npc.
* @author 'Vexia
* @version 1.0
*/
public final class MogreNPC extends AbstractNPC {
/**
* Constructs a new {@code MogreNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public MogreNPC(int id, Location location) {
super(id, location, true);
}
/**
* Constructs a new {@code MogreNPC} {@code Object}.
*/
public MogreNPC() {
super(0, null);
}
@Override
public void tick() {
super.tick();
final Player pl = getAttribute("player", null);
if (pl == null || pl.getLocation().getDistance(getLocation()) > 15) {
clear();
}
}
@Override
public void clear() {
super.clear();
final Player pl = getAttribute("player", null);
if (pl != null) {
pl.removeAttribute("hasMogre");
}
}
@Override
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
final Player pl = getAttribute("player", null);
return pl != null && pl == entity && super.isAttackable(entity, style, message);
}
@Override
public void finalizeDeath(final Entity killer) {
super.finalizeDeath(killer);
if (killer instanceof Player) {
final Player player = killer.asPlayer();
player.getAchievementDiaryManager().finishTask(player,DiaryType.FALADOR, 2, 7);
}
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new MogreNPC(id, location);
}
@Override
public int[] getIds() {
return new int[] { 114 };
}
}
}
@@ -0,0 +1,118 @@
package content.global.skill.slayer;
import core.game.interaction.NodeUsageEvent;
import core.game.interaction.UseWithHandler;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.Initializable;
import core.plugin.Plugin;
import org.rs09.consts.Items;
import core.plugin.ClassScanner;
/**
* Handles the gargoyle npc.
* @author Vexia
*/
@Initializable
public final class GargoyleNPC extends AbstractNPC {
/**
* Constructs a new {@code GargoyleNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public GargoyleNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code GargoyleNPC} {@code Object}.
*/
public GargoyleNPC() {
super(0, null);
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
int lp = getSkills().getLifepoints();
if (state.getEstimatedHit() > -1) {
if (lp - state.getEstimatedHit() < 1) {
state.setEstimatedHit(0);
if (lp > 1) {
state.setEstimatedHit(lp - 1);
}
}
}
if (state.getSecondaryHit() > -1) {
if (lp - state.getSecondaryHit() < 1) {
state.setSecondaryHit(0);
if (lp > 1) {
state.setSecondaryHit(lp - 1);
}
}
}
int totalHit = state.getEstimatedHit() + state.getSecondaryHit();
if (lp - totalHit < 1) {
state.setEstimatedHit(0);
state.setSecondaryHit(0);
}
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ClassScanner.definePlugin(new RockHammerHandler());
return super.newInstance(arg);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new GargoyleNPC(id, location);
}
@Override
public int[] getIds() {
return Tasks.GARGOYLES.getNpcs();
}
/**
* The rock hammer handler plugin.
* @author Vexia
*/
public final class RockHammerHandler extends UseWithHandler {
/**
* Constructs a new {@code RockHammerHandler} {@code Object}.
*/
public RockHammerHandler() {
super(Items.ROCK_HAMMER_4162);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (int id : getIds()) {
addHandler(id, NPC_TYPE, this);
}
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
final NPC npc = (NPC) event.getUsedWith();
if (npc.getSkills().getLifepoints() > 10) {
player.getPacketDispatch().sendMessage("The gargoyle isn't weak enough to be harmed by the hammer.");
} else {
player.getPacketDispatch().sendMessage("The gargoyle cracks apart.");
npc.getImpactHandler().manualHit(player, npc.getSkills().getLifepoints(), HitsplatType.NORMAL);
}
return true;
}
}
}
@@ -0,0 +1,48 @@
package content.global.skill.slayer;
import core.game.node.entity.combat.spell.CombatSpell;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
import core.game.world.map.Location;
import core.plugin.Initializable;
/**
* Handles the infernal mage npc.
* @author Vexia
*/
@Initializable
public final class InfernalMageNPC extends AbstractNPC {
/**
* Constructs a new {@code InfernalMageNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public InfernalMageNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code InfernalMageNPC} {@code Object}.
*/
public InfernalMageNPC() {
super(0, null);
}
@Override
public void init() {
super.init();
getProperties().setAutocastSpell((CombatSpell) SpellBook.MODERN.getSpell(8));
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new InfernalMageNPC(id, location);
}
@Override
public int[] getIds() {
return Tasks.INFERNAL_MAGES.getNpcs();
}
}
@@ -0,0 +1,58 @@
package content.global.skill.slayer;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.Initializable;
/**
* Handles the kurask npc.
* @author Vexia
*/
@Initializable
public final class KuraskNPC extends AbstractNPC {
/**
* Constructs a new {@code KuraskNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public KuraskNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code KuraskNPC} {@code Object}.
*/
public KuraskNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new KuraskNPC(id, location);
}
@Override
public void checkImpact(final BattleState state) {
super.checkImpact(state);
boolean effective = false;
if (state.getAttacker() instanceof Player) {
final Player player = (Player) state.getAttacker();
effective = SlayerUtils.hasBroadWeaponEquipped(player, state);
}
if (!effective) {
state.setEstimatedHit(0);
if (state.getSecondaryHit() > 0) {
state.setSecondaryHit(0);
}
}
}
@Override
public int[] getIds() {
return new int[] { 1608, 1609, 4229 };
}
}
@@ -0,0 +1,309 @@
package content.global.skill.slayer;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.player.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/**
* A non-garbage way of representing slayer masters
* @author ceik
*/
public enum Master {
TURAEL(8273, 0, 0, new int[]{15, 50}, new int[]{0, 0, 0},
new Task(Tasks.BANSHEE, 8),
new Task(Tasks.BATS, 7),
new Task(Tasks.BIRDS, 6),
new Task(Tasks.BEARS, 7),
new Task(Tasks.CAVE_BUG, 8),
new Task(Tasks.CAVE_CRAWLERS, 8),
new Task(Tasks.CAVE_SLIMES, 8),
new Task(Tasks.COWS, 8),
new Task(Tasks.CRAWLING_HAND, 8),
new Task(Tasks.DOG, 7),
new Task(Tasks.DWARF, 7),
new Task(Tasks.GHOSTS, 7),
new Task(Tasks.GOBLINS, 7),
new Task(Tasks.ICE_FIENDS, 8),
new Task(Tasks.KALPHITES, 6),
new Task(Tasks.DESERT_LIZARDS, 8),
new Task(Tasks.MINOTAURS, 7),
new Task(Tasks.MONKEYS, 6),
new Task(Tasks.RATS, 7),
new Task(Tasks.SCORPIONS, 7),
new Task(Tasks.SKELETONS, 7),
new Task(Tasks.SPIDERS, 6),
new Task(Tasks.WOLVES, 7),
new Task(Tasks.ZOMBIES, 7)),
MAZCHNA(8274, 20, 0, new int[]{30, 70}, new int[]{2, 5, 15},
new Task(Tasks.BANSHEE, 8),
new Task(Tasks.BATS,7),
new Task(Tasks.BEARS,6),
new Task(Tasks.CATABLEPONS,8),
new Task(Tasks.CAVE_BUG,8),
new Task(Tasks.CAVE_CRAWLERS, 8),
new Task(Tasks.CAVE_SLIMES, 8),
new Task(Tasks.COCKATRICES, 8),
new Task(Tasks.CRAWLING_HAND, 8),
new Task(Tasks.DESERT_LIZARDS, 8),
new Task(Tasks.DOG,7),
new Task(Tasks.EARTH_WARRIORS,6),
new Task(Tasks.FLESH_CRAWLERS,7),
new Task(Tasks.GHOSTS,7),
new Task(Tasks.GHOULS, 7),
new Task(Tasks.HILL_GIANTS,7),
new Task(Tasks.HOBGOBLINS, 7),
new Task(Tasks.ICE_WARRIOR, 7),
new Task(Tasks.KALPHITES,6),
//new Task(Tasks.KILLERWATTS, 6),
//new Task(Tasks.MOGRES, 8),
new Task(Tasks.PYREFIENDS, 8),
new Task(Tasks.ROCK_SLUGS,8),
new Task(Tasks.SCORPIONS,7),
new Task(Tasks.SHADE,8),
new Task(Tasks.SKELETONS, 7),
new Task(Tasks.VAMPIRES, 6),
//new Task(Tasks.WALL_BEASTS,7),
new Task(Tasks.WOLVES, 7),
new Task(Tasks.ZOMBIES,7)),
VANNAKA(1597, 40, 0, new int[]{30, 80}, new int[]{4, 20, 60},
new Task(Tasks.ABERRANT_SPECTRES, 8),
new Task(Tasks.ABYSSAL_DEMONS, 5),
new Task(Tasks.ANKOU,7),
new Task(Tasks.BANSHEE,6),
new Task(Tasks.BASILISKS,8),
new Task(Tasks.BLOODVELDS,8),
new Task(Tasks.BLUE_DRAGONS,7),
new Task(Tasks.BRINE_RATS,7),
new Task(Tasks.BRONZE_DRAGONS,7),
new Task(Tasks.CAVE_BUG,7),
new Task(Tasks.CAVE_CRAWLERS,7),
new Task(Tasks.CAVE_SLIMES,7),
new Task(Tasks.COCKATRICES,8),
new Task(Tasks.CRAWLING_HAND,6),
new Task(Tasks.CROCODILES,6),
new Task(Tasks.DAGANNOTHS, 7),
new Task(Tasks.DUST_DEVILS,8),
new Task(Tasks.EARTH_WARRIORS,6),
new Task(Tasks.ELVES, 7),
//new Task(Tasks.FEVER_SPIDERS,7),
new Task(Tasks.FIRE_GIANTS,7),
new Task(Tasks.GARGOYLES, 5),
new Task(Tasks.GHOULS,7),
new Task(Tasks.GREEN_DRAGON,6),
new Task(Tasks.HARPIE_BUG_SWARMS,8),
new Task(Tasks.HELLHOUNDS,7),
new Task(Tasks.HILL_GIANTS,7),
new Task(Tasks.HOBGOBLINS,7),
new Task(Tasks.ICE_GIANTS,7),
new Task(Tasks.ICE_WARRIOR,7),
new Task(Tasks.INFERNAL_MAGES,8),
new Task(Tasks.JELLIES,8),
new Task(Tasks.JUNGLE_HORRORS, 8),
new Task(Tasks.KALPHITES,7),
//new Task(Tasks.KILLERWATTS,6),
new Task(Tasks.KURASKS,7),
new Task(Tasks.DESERT_LIZARDS,7),
new Task(Tasks.LESSER_DEMONS,7),
//new Task(Tasks.MOGRES,7),
//new Task(Tasks.MOLANISKS,7),
new Task(Tasks.MOSS_GIANTS,7),
new Task(Tasks.NECHRYAELS, 5),
new Task(Tasks.OGRES,7),
new Task(Tasks.OTHERWORDLY_BEING,8),
new Task(Tasks.PYREFIENDS,8),
new Task(Tasks.ROCK_SLUGS,7),
new Task(Tasks.SHADE,8),
//new Task(Tasks.SEA_SNAKES,6),
//new Task(Tasks.SHADOW_WARRIORS, 8),
new Task(Tasks.SPIRTUAL_MAGES,3),
new Task(Tasks.SPIRTUAL_RANGERS, 3),
new Task(Tasks.SPIRTUAL_WARRIORS,3),
//new Task(Tasks.TERROR_DOGS,6),
new Task(Tasks.TROLLS,7),
new Task(Tasks.TUROTHS, 8),
new Task(Tasks.VAMPIRES,7),
//new Task(Tasks.WALL_BEAST,6),
new Task(Tasks.WEREWOLFS,7)),
CHAELDAR(1598, 70, 0, new int[]{110, 170}, new int[]{10, 50, 150},
new Task(Tasks.ABERRANT_SPECTRES,8),
new Task(Tasks.ABYSSAL_DEMONS,12),
new Task(Tasks.AVIANSIES,9),
new Task(Tasks.BANSHEE, 5),
new Task(Tasks.BASILISKS,7),
new Task(Tasks.BLACK_DEMONS,10),
new Task(Tasks.BLOODVELDS,8),
new Task(Tasks.BLUE_DRAGONS,8),
new Task(Tasks.BRINE_RATS,7),
new Task(Tasks.BRONZE_DRAGONS,11),
new Task(Tasks.CAVE_CRAWLERS, 5),
new Task(Tasks.CAVE_HORRORS,10),
new Task(Tasks.CAVE_SLIMES,6),
new Task(Tasks.COCKATRICES,6),
new Task(Tasks.DAGANNOTHS,11),
new Task(Tasks.DUST_DEVILS,9),
new Task(Tasks.ELVES,8),
//new Task(Tasks.FEVER_SPIDERS,7),
new Task(Tasks.FIRE_GIANTS, 12),
new Task(Tasks.GARGOYLES,11),
new Task(Tasks.GREATER_DEMONS,9),
new Task(Tasks.HARPIE_BUG_SWARMS,6),
new Task(Tasks.HELLHOUNDS,9),
new Task(Tasks.INFERNAL_MAGES,7),
new Task(Tasks.IRON_DRAGONS,12),
new Task(Tasks.JELLIES, 10),
new Task(Tasks.JUNGLE_HORRORS,10),
new Task(Tasks.KALPHITES,11),
new Task(Tasks.KURASKS, 12),
new Task(Tasks.LESSER_DEMONS,9),
new Task(Tasks.DESERT_LIZARDS, 5),
//new Task(Tasks.MOGRES,6),
//new Task(Tasks.MOLANISKS,6),
//new Task(Tasks.MUTATED_ZYGOMITES,7),
new Task(Tasks.NECHRYAELS, 12),
new Task(Tasks.PYREFIENDS,6),
new Task(Tasks.ROCK_SLUGS, 5),
//new Task(Tasks.SHADOW_WARRIORS,8),
new Task(Tasks.SKELETAL_WYVERN,7),
new Task(Tasks.SPIRTUAL_WARRIORS,4),
new Task(Tasks.SPIRTUAL_RANGERS,4),
new Task(Tasks.SPIRTUAL_MAGES,4),
new Task(Tasks.STEEL_DRAGONS,9),
new Task(Tasks.TROLLS,11),
new Task(Tasks.TUROTHS, 10)),
//new Task(Tasks.WALL_BEASTS,6),
SUMONA(7780, 90, 35, new int[]{50, 185}, new int[]{12, 60, 180},
new Task(Tasks.ABERRANT_SPECTRES, 15),
new Task(Tasks.ABYSSAL_DEMONS, 10),
new Task(Tasks.AVIANSIES, 7),
new Task(Tasks.BANSHEE, 15),
new Task(Tasks.BASILISKS, 15),
new Task(Tasks.BLACK_DEMONS, 10),
new Task(Tasks.BLOODVELDS, 10),
new Task(Tasks.BLUE_DRAGONS, 5),
new Task(Tasks.CAVE_CRAWLERS, 15),
new Task(Tasks.CAVE_HORRORS, 15),
new Task(Tasks.CROCODILES, 4),
new Task(Tasks.DAGANNOTHS, 10),
new Task(Tasks.DESERT_LIZARDS, 4),
new Task(Tasks.DUST_DEVILS, 15),
new Task(Tasks.ELVES, 10),
new Task(Tasks.FIRE_GIANTS, 10),
new Task(Tasks.GARGOYLES, 10),
new Task(Tasks.GREATER_DEMONS, 10),
new Task(Tasks.HELLHOUNDS, 10),
new Task(Tasks.IRON_DRAGONS, 7),
new Task(Tasks.KALPHITES, 10),
new Task(Tasks.KURASKS, 15),
new Task(Tasks.NECHRYAELS, 10),
// newTask(Tasks.RED_DRAGON, 5),
new Task(Tasks.SCORPIONS, 4),
new Task(Tasks.SPIRTUAL_MAGES, 10),
new Task(Tasks.SPIRTUAL_WARRIORS, 10),
// new Task(Tasks.TERROR_DOGS, 10),
new Task(Tasks.TROLLS, 10),
new Task(Tasks.TUROTHS, 15),
new Task(Tasks.VAMPIRES, 10)),
//new Task(Tasks.WARPED_TORTOISE, 15)),
DURADEL(8275, 100, 50, new int[]{50, 199}, new int[]{15, 75, 225},
new Task(Tasks.ABERRANT_SPECTRES,7),
new Task(Tasks.ABYSSAL_DEMONS,12),
new Task(Tasks.ANKOU,5),
new Task(Tasks.AVIANSIES,8),
new Task(Tasks.BLACK_DEMONS,8),
new Task(Tasks.BLACK_DRAGONS,9),
new Task(Tasks.BLOODVELDS,8),
new Task(Tasks.BLUE_DRAGONS,4),
new Task(Tasks.CAVE_HORRORS,4),
new Task(Tasks.DAGANNOTHS,9),
new Task(Tasks.DARK_BEASTS,11),
new Task(Tasks.DUST_DEVILS,5),
new Task(Tasks.ELVES,4),
new Task(Tasks.FIRE_GIANTS,7),
new Task(Tasks.GARGOYLES,8),
new Task(Tasks.GREATER_DEMONS,9),
new Task(Tasks.HELLHOUNDS, 10),
new Task(Tasks.IRON_DRAGONS,5),
new Task(Tasks.KALPHITES,9),
new Task(Tasks.KURASKS,4),
new Task(Tasks.MITHRIL_DRAGON,9),
new Task(Tasks.NECHRYAELS,9),
//new Task(Tasks.RED_DRAGONS,8),
new Task(Tasks.SKELETAL_WYVERN,7),
new Task(Tasks.SPIRTUAL_MAGES,2),
new Task(Tasks.SPIRTUAL_RANGERS,2),
new Task(Tasks.SPIRTUAL_WARRIORS,2),
new Task(Tasks.STEEL_DRAGONS,7),
//new Task(Tasks.SUQAHS,8),
new Task(Tasks.TROLLS,6),
new Task(Tasks.TZHAAR, 10),
new Task(Tasks.VAMPIRES,8),
// new Task(Tasks.WARPED_TERRORBIRD,8),
new Task(Tasks.WATERFIENDS,2));
//new Task(Tasks.MUTATED_ZYGOMITES,2),
//Boss Tasks below this point - Crash
//new Task(Tasks.JAD, 1),
//new Task(Tasks.COMMANDER_ZILYANA,1),
//new Task(Tasks.CHAOS_ELEMENTAL, 1),
//new Task(Tasks.GENERAL_GRARDOOR,1),
//new Task(Tasks.GIANT_MOLE,1),
//new Task(Tasks.KING_BLACK_DRAGON,1),
//new Task(Tasks.KRIL_TSUTSAROTH,1),
//new Task(Tasks.KREE_ARRA,1));
private static HashMap<Integer,Master> idMap = new HashMap<>();
static{
Arrays.stream(Master.values()).forEach(m -> idMap.putIfAbsent(m.npc_id, m));
}
int npc_id,required_combat,required_slayer;
public int[] assignment_range;
int[] streakPoints;
public List<Task> tasks;
Master(int npc_id, int required_combat, int required_slayer, int[] assignment_range, int[] streakPoints, Task... tasks) {
this.npc_id = npc_id;
this.required_combat = required_combat;
this.required_slayer = required_slayer;
this.assignment_range = assignment_range;
this.streakPoints = streakPoints;
this.tasks = new ArrayList<>(Arrays.asList(tasks));
}
public static Master forId(int id){
return idMap.get(id);
}
public int getNpc(){
return this.npc_id;
}
public int[] getTaskPoints(){
return streakPoints;
}
public boolean hasRequirements(Player player){
return player.getProperties().getCurrentCombatLevel() >= this.required_combat && player.getSkills().getLevel(Skills.SLAYER) >= this.required_slayer;
}
public static boolean hasSameTask(Master master, Player player){
return master.tasks.stream().filter(task -> task.task == SlayerManager.getInstance(player).getTask()).count() != 0;
}
public static class Task{
public Tasks task;
public Integer weight;
Task(Tasks task, Integer weight){
this.task = task;
this.weight = weight;
}
}
}
@@ -0,0 +1,66 @@
package content.global.skill.slayer;
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.MeleeSwingHandler;
import core.game.node.entity.player.Player;
/**
* The swing handler for an npc that requires a mirror shield with its victim.
* @author Vexia
* @version 1.0
*/
public final class MirrorShieldHandler extends MeleeSwingHandler {
/**
* The singleton of this handler.
*/
public static final MirrorShieldHandler SINGLETON = new MirrorShieldHandler();
/**
* The skills to drain.
*/
private static final int[] SKILLS = new int[] { Skills.ATTACK, Skills.STRENGTH, Skills.DEFENCE, Skills.RANGE };
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
if (victim instanceof Player) {
final Player player = (Player) victim;
if (!hasShield(player)) {
state.setEstimatedHit(11);
for (int skill : SKILLS) {
int drain = (int) (player.getSkills().getStaticLevel(skill) * 0.25);
player.getSkills().updateLevel(skill, -drain, player.getSkills().getStaticLevel(skill) - drain);
}
}
}
super.impact(entity, victim, state);
}
/**
* Checks the impact of a victim with or without a shield.
* @param state the state.
*/
public void checkImpact(final BattleState state) {
if (state.getAttacker() instanceof Player) {
final Player player = (Player) state.getAttacker();
if (!hasShield(player)) {
state.setEstimatedHit(0);
if (state.getSecondaryHit() > 0) {
state.setSecondaryHit(0);
}
}
}
}
/**
* Checks if the player has the mirror shield.
* @param player the player.
* @return {@code True} if so.
*/
private static boolean hasShield(final Player player) {
return SlayerEquipmentFlags.hasMirrorShield(player);
}
}
@@ -0,0 +1,97 @@
package content.global.skill.slayer;
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.combat.equipment.SwitchAttack;
import content.global.handlers.item.equipment.special.DragonfireSwingHandler;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.impl.Projectile;
import core.game.node.entity.npc.AbstractNPC;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.plugin.Initializable;
import core.tools.RandomFunction;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.MultiSwingHandler;
/**
* Handles a mithril dragon npc.
* @author Vexia
*/
@Initializable
public final class MithrilDragonNPC extends AbstractNPC {
/**
* The dragonfire attack.
*/
private static final SwitchAttack DRAGONFIRE = DragonfireSwingHandler.get(false, 52, new Animation(81, Priority.HIGH), Graphics.create(1), null, null);
/**
* Handles the combat.
*/
private final CombatSwingHandler combatAction = new MultiSwingHandler(true, new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), new Animation(80, Priority.HIGH)), new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), new Animation(80, Priority.HIGH)), new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), new Animation(81, Priority.HIGH), null, null, Projectile.create((Entity) null, null, 500, 20, 20, 41, 40, 18, 255)), DRAGONFIRE, new SwitchAttack(CombatStyle.RANGE.getSwingHandler(), new Animation(81, Priority.HIGH), null, null, Projectile.create((Entity) null, null, 16, 20, 20, 41, 40, 18, 255)));
/**
* Constructs a new {@code MithrilDragonNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public MithrilDragonNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code MithrilDragonNPC} {@code Object}.
*/
public MithrilDragonNPC() {
super(0, null);
}
@Override
public void sendImpact(BattleState state) {
CombatStyle style = state.getStyle();
if (style == null) {
return;
}
int maxHit = state.getEstimatedHit();
if (maxHit < 1) {
return;
}
switch (style) {
case MELEE:
maxHit = 28;
break;
case MAGIC:
maxHit = 18;
break;
case RANGE:
maxHit = 18;
break;
}
if (state.getEstimatedHit() > maxHit) {
state.setEstimatedHit(RandomFunction.random(maxHit - 5, maxHit));
}
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new MithrilDragonNPC(id, location);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return combatAction;
}
@Override
public int getDragonfireProtection(boolean fire) {
return 0x2 | 0x4 | 0x8;
}
@Override
public int[] getIds() {
return Tasks.MITHRIL_DRAGON.getNpcs();
}
}
@@ -0,0 +1,193 @@
package content.global.skill.slayer;
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.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.tools.RandomFunction;
import java.util.ArrayList;
import java.util.List;
/**
* Handles the nechryael npc.
* @author Vexia
*/
@Initializable
public final class NechryaelNPC extends AbstractNPC {
/**
* The death spawn id.
*/
private static final int DEATH_SPAWN = 1614;
/**
* The death spawn npcs.
*/
private List<DeathSpawnNPC> spawns = new ArrayList<>(10);
/**
* The next spawn time.
*/
private int nextSpawn;
/**
* Constructs a new {@code NechryaelNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public NechryaelNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code NechryaelNPC} {@code Object}.
*/
public NechryaelNPC() {
super(0, null);
}
@Override
public void onImpact(Entity entity, final BattleState state) {
super.onImpact(entity, state);
if (entity instanceof Player && RandomFunction.random(5) == 1) {
spawn((Player) entity);
}
}
/**
* Spawns a death spawn.
* @param player the player.
*/
public void spawn(Player player) {
if (!canSpawn()) {
return;
}
final DeathSpawnNPC spawn = new DeathSpawnNPC(DEATH_SPAWN, getLocation().transform(getDirection(), 1), player, this);
spawn.init();
setSpawnTime();
spawns.add(spawn);
animate(Animation.create(9491));
spawn.getProperties().getCombatPulse().attack(player);
}
/**
* Sets the next spawn time.
*/
private void setSpawnTime() {
nextSpawn = GameWorld.getTicks() + 50;
}
/**
* Checks if a death spawn can spawn.
* @return {@code True} if so.
*/
private boolean canSpawn() {
if (spawns.size() >= 2) {
setSpawnTime();
return false;
}
return nextSpawn < GameWorld.getTicks();
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new NechryaelNPC(id, location);
}
@Override
public int[] getIds() {
return Tasks.NECHRYAELS.getNpcs();
}
/**
* Handles the death spawn npc.
* @author Vexia
*/
public static final class DeathSpawnNPC extends AbstractNPC {
/**
* The player binded with the death spawn.
*/
private final Player player;
/**
* The parent npc.
*/
private final NechryaelNPC parent;
/**
* The time until its cleared.
*/
private int time;
/**
* Constructs a new {@code DeathSpawnNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public DeathSpawnNPC(int id, Location location, final Player player, NechryaelNPC parent) {
super(id, location);
this.player = player;
this.parent = parent;
this.setRespawn(false);
this.time = GameWorld.getTicks() + 120;
}
@Override
public void handleTickActions() {
super.handleTickActions();
if (!inCombat() || !player.inCombat()) {
getProperties().getCombatPulse().attack(player);
}
if (time < GameWorld.getTicks() || !player.isActive() || player.getLocation().getDistance(getLocation()) > 15) {
clear();
}
}
@Override
public void clear() {
super.clear();
parent.spawns.remove(this);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new DeathSpawnNPC(id, location, null, null);
}
@Override
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
if (entity instanceof Player) {
final Player t = (Player) entity;
if (t != player) {
if(message) {
t.getPacketDispatch().sendMessage("This isn't spawned for you.");
}
return false;
}
}
return super.isAttackable(entity, style, message);
}
@Override
public boolean isIgnoreMultiBoundaries(Entity victim) {
return victim == player;
}
@Override
public boolean isPoisonImmune() {
return true;
}
@Override
public int[] getIds() {
return new int[] { DEATH_SPAWN };
}
}
}
@@ -0,0 +1,148 @@
package content.global.skill.slayer;
import core.game.interaction.NodeUsageEvent;
import core.game.interaction.UseWithHandler;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
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.item.Item;
import core.game.world.map.Location;
import core.game.world.map.path.Pathfinder;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
/**
* Handles the interactions of a rock slug.
* @author Vexia
*/
@Initializable
public final class RockSlugPlugin implements Plugin<Object> {
/**
* The bag of salt item.
*/
private static final Item SALT = new Item(4161, 1);
/**
* The rockslug npc ids.
*/
private static final int[] IDS = new int[] { 1631, 1632 };
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ClassScanner.definePlugin(new RockSlugNPC());
ClassScanner.definePlugin(new SaltBagHandler());
return this;
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
/**
* The use with handler for the bag of salt on a rock slug.
* @author Vexia
*/
public final class SaltBagHandler extends UseWithHandler {
/**
* Constructs a new {@code SaltBagHandler} {@code Object}.
*/
public SaltBagHandler() {
super(SALT.getId());
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (int id : IDS) {
addHandler(id, NPC_TYPE, this);
}
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
final NPC npc = (NPC) event.getUsedWith();
player.getInventory().remove(SALT);
if (npc.getSkills().getLifepoints() < 10) {
npc.getImpactHandler().manualHit(player, npc.getSkills().getLifepoints(), HitsplatType.NORMAL);
player.getPacketDispatch().sendMessage("The rockslug shrivels up and dies.");
} else {
player.sendMessage("Your bag of salt is ineffective. The Rockslug is not weak enough.");
}
return true;
}
}
/**
* The rock slug npc.
* @author Vexia
*/
public final class RockSlugNPC extends AbstractNPC {
/**
* Constructs a new {@code RockSlugNPC} {@code Object}.
*/
public RockSlugNPC() {
super(-1, null);
}
/**
* Constructs a new {@code RockSlugNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public RockSlugNPC(int id, Location location) {
super(id, location, true);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new RockSlugNPC(id, location);
}
@Override
public void checkImpact(BattleState state) {
super.checkImpact(state);
int lifepoints = getSkills().getLifepoints();
boolean run = false;
if (state.getEstimatedHit() > -1) {
lifepoints -= state.getEstimatedHit();
if (lifepoints < 1) {
run = true;
state.setEstimatedHit(lifepoints - 1);
}
if (state.getEstimatedHit() < 0) {
state.setEstimatedHit(0);
}
}
if (state.getSecondaryHit() > -1) {
lifepoints -= state.getSecondaryHit();
if (lifepoints < 1) {
run = true;
state.setSecondaryHit(lifepoints - 1);
}
if (state.getSecondaryHit() < 0) {
state.setSecondaryHit(0);
}
}
if (run) {
getProperties().getCombatPulse().stop();
Pathfinder.find(getLocation(), getProperties().getSpawnLocation());
}
}
@Override
public int[] getIds() {
return IDS;
}
}
}
@@ -0,0 +1,90 @@
package content.global.skill.slayer;
import core.game.container.impl.EquipmentContainer;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.equipment.SwitchAttack;
import content.global.handlers.item.equipment.special.DragonfireSwingHandler;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.prayer.PrayerType;
import core.game.node.item.Item;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.plugin.Initializable;
import core.tools.RandomFunction;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.MultiSwingHandler;
/**
* Handles the skeletal wyvern npc.
* @author Vexia
* @author Splinter
* @version 1.0
*/
@Initializable
public final class SkeletalWyvernNPC extends AbstractNPC {
/**
* The combat swing handler.
*/
private static final MultiSwingHandler COMBAT_HANDLER = new MultiSwingHandler(new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), new Animation(2985)), new SwitchAttack(CombatStyle.RANGE.getSwingHandler(), new Animation(2989), new Graphics(499)), DragonfireSwingHandler.get(false, 54, new Animation(2988), new Graphics(501), null, null, false));
/**
* The combat swing handler for far combat (5+ tile distance)
*/
private static final MultiSwingHandler COMBAT_HANDLER_FAR = new MultiSwingHandler(new SwitchAttack(CombatStyle.RANGE.getSwingHandler(), new Animation(2989), new Graphics(499)));
/**
* Constructs a new {@code SkeletalWyvernNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public SkeletalWyvernNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code SkeletalWyvernNPC} {@code Object}.
*/
public SkeletalWyvernNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new SkeletalWyvernNPC(id, location);
}
@Override
public void sendImpact(BattleState state) {
if (state.getStyle() == CombatStyle.MAGIC && state.getVictim() != null && state.getVictim().isPlayer()) {
Player p = state.getVictim().asPlayer();
Item item = p.getEquipment().get(EquipmentContainer.SLOT_SHIELD);
if (item != null && (item.getId() == 2890 || item.getId() == 9731 || item.getId() == 11283) && state.getEstimatedHit() > 10) {
state.setEstimatedHit(RandomFunction.random(10));
}
}
Player p = state.getVictim().asPlayer();
Item item = p.getEquipment().get(EquipmentContainer.SLOT_SHIELD);
if(state.getVictim().getLocation().getDistance(state.getAttacker().getLocation()) >= 5
&& state.getVictim().asPlayer().getPrayer().get(PrayerType.PROTECT_FROM_MAGIC) && (item.getId() == 2890 || item.getId() == 9731 || item.getId() == 11283)){
state.setEstimatedHit(0);
}
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
if (this.getProperties().getCombatPulse().getVictim() != null && this.getProperties().getCombatPulse().getVictim().getLocation().getDistance(this.getLocation()) >= 5){
return COMBAT_HANDLER_FAR;
}
return COMBAT_HANDLER;
}
@Override
public int[] getIds() {
return Tasks.SKELETAL_WYVERN.getNpcs();
}
}
@@ -0,0 +1,88 @@
package content.global.skill.slayer
import content.global.skill.skillcapeperks.SkillcapePerks
import core.api.EquipmentSlot
import core.api.getAttribute
import core.api.getItemFromEquipment
import core.game.node.entity.player.Player
import org.rs09.consts.Items
/**
* Represents a slayer equipment.
* @author Ceikry
*/
object SlayerEquipmentFlags {
val blackMasks = (Items.BLACK_MASK_10_8901..Items.BLACK_MASK_8921).map { it }.toIntArray()
val slayerItems = intArrayOf(Items.NOSE_PEG_4168, Items.EARMUFFS_4166, Items.FACE_MASK_4164, *blackMasks, Items.SPINY_HELMET_4551, Items.SLAYER_CAPET_9787, Items.SLAYER_CAPE_9786, Items.SLAYER_HELMET_13263, Items.WITCHWOOD_ICON_8923, Items.MIRROR_SHIELD_4156)
@JvmStatic
fun updateFlags(player: Player){
var flags = 0
if(SkillcapePerks.isActive(SkillcapePerks.TRICKS_OF_THE_TRADE, player) && getAttribute(player, "cape_perks:tott:helmet-stored", false)) flags = 0x3F
else if(hasItem(player, Items.SLAYER_HELMET_13263)) flags = 0x1F
else if(hasItem(player, Items.NOSE_PEG_4168)) flags = 1
else if(hasItem(player, Items.EARMUFFS_4166)) flags = flags or (1 shl 1)
else if(hasItem(player, Items.FACE_MASK_4164)) flags = flags or (1 shl 2)
else if((getItemFromEquipment(player, EquipmentSlot.HAT)?.id ?: 0) in blackMasks) flags = flags or (1 shl 3)
else if(hasItem(player, Items.SPINY_HELMET_4551)) flags = flags or (1 shl 4)
if((getItemFromEquipment(player, EquipmentSlot.AMULET)?.id ?: 0) == Items.WITCHWOOD_ICON_8923) flags = flags or (1 shl 7)
if((getItemFromEquipment(player, EquipmentSlot.SHIELD)?.id ?: 0) == Items.MIRROR_SHIELD_4156) flags = flags or (1 shl 8)
SlayerManager.getInstance(player).flags.equipmentFlags = flags
}
@JvmStatic
fun hasNosePeg(player: Player): Boolean{
return SlayerManager.getInstance(player).flags.equipmentFlags and 1 == 1
}
@JvmStatic
fun hasEarmuffs(player: Player): Boolean {
return (SlayerManager.getInstance(player).flags.equipmentFlags shr 1) and 1 == 1
}
@JvmStatic
fun hasFaceMask(player: Player): Boolean {
return (SlayerManager.getInstance(player).flags.equipmentFlags shr 2) and 1 == 1
}
@JvmStatic
fun hasBlackMask(player: Player): Boolean {
return (SlayerManager.getInstance(player).flags.equipmentFlags shr 3) and 1 == 1
}
@JvmStatic
fun hasSpinyHelmet(player: Player): Boolean {
return (SlayerManager.getInstance(player).flags.equipmentFlags shr 4) and 1 == 1
}
@JvmStatic
fun hasWitchwoodIcon(player: Player): Boolean {
return (SlayerManager.getInstance(player).flags.equipmentFlags shr 7) and 1 == 1
}
@JvmStatic
fun hasMirrorShield(player: Player): Boolean {
return (SlayerManager.getInstance(player).flags.equipmentFlags shr 8) and 1 == 1
}
@JvmStatic
fun getDamAccBonus(player: Player): Double {
val isCape = SlayerManager.getInstance(player).flags.equipmentFlags == 0x3F
val hasMask = hasBlackMask(player)
return if(isCape) 1.075
else if(hasMask) 1.15
else 1.0
}
private fun hasItem(player: Player, id: Int): Boolean{
return (getItemFromEquipment(player, EquipmentSlot.HAT)?.id ?: 0) == id
}
fun isSlayerEq(item: Int): Boolean{
return item in slayerItems
}
}
@@ -0,0 +1,159 @@
package content.global.skill.slayer
import content.global.skill.slayer.Master
import content.global.skill.slayer.Tasks
/**
* Bitflag-based system for storing slayer-related data for a player and various helper functions.
* @author Ceikry
*/
class SlayerFlags {
var taskFlags = 0
var rewardFlags = 0
var equipmentFlags = 0
var completedTasks = 0
var taskStreak = 0
/**
* The removed tasks.
*/
val removed: ArrayList<Tasks> = ArrayList(4)
/**
* Get/set master flags
*/
fun getMaster(): Master {
val ordinal = taskFlags and 0xF
return Master.values()[ordinal]
}
fun setMaster(master: Master){
taskFlags = (taskFlags - (taskFlags and 0xF)) or master.ordinal
}
/**
*==============================================
*/
/**
* Get/set task flags
*/
fun getTask(): Tasks {
val ordinal = (taskFlags shr 4) and 0x7F
return Tasks.values()[ordinal]
}
fun setTask(tasks: Tasks){
taskFlags = (taskFlags - (getTask().ordinal shl 4)) or (tasks.ordinal shl 4)
}
/**
*==============================================
*/
/**
* Get/set/decrement task amount flag
*/
fun getTaskAmount(): Int {
return (taskFlags shr 11) and 0xFF
}
fun setTaskAmount(amount: Int) {
taskFlags = (taskFlags - (getTaskAmount() shl 11)) or (amount shl 11)
}
fun decrementTaskAmount(amount: Int){
setTaskAmount(getTaskAmount() - amount)
}
/**
*==============================================
*/
/**
* Get/Set canEarnPoints flag
*/
fun canEarnPoints(): Boolean {
return (taskFlags shr 20) and 1 == 1
}
fun flagCanEarnPoints() {
taskFlags = taskFlags or (1 shl 20)
}
/**
*==============================================
*/
/**
* Get/set reward unlock flags
*/
fun isBroadsUnlocked(): Boolean{
return rewardFlags and 1 == 1
}
fun unlockBroads() {
rewardFlags = rewardFlags or 1
}
fun isRingUnlocked(): Boolean {
return (rewardFlags shr 1) and 1 == 1
}
fun unlockRing() {
rewardFlags = rewardFlags or (1 shl 1)
}
fun isHelmUnlocked(): Boolean {
return (rewardFlags shr 2) and 1 ==1
}
fun unlockHelm() {
rewardFlags = rewardFlags or (1 shl 2)
}
/**
*==============================================
*/
/**
* Get/set/increment points flag
*/
fun setPoints(amount: Int) {
rewardFlags = (rewardFlags - (getPoints() shl 15)) or (amount shl 15)
}
fun getPoints(): Int {
return (rewardFlags shr 15) and 0xFFFF
}
fun incrementPoints(amount: Int){
setPoints(getPoints() + amount)
}
/**
*==============================================
*/
/**
* Reset task and task amount to 0
*/
fun clearTask() {
setTask(Tasks.values()[0])
setTaskAmount(0)
}
/**
* Checks if we have a task
*/
fun hasTask(): Boolean{
return getTaskAmount() != 0
}
fun fullClear() {
taskFlags = 0
rewardFlags = 0
equipmentFlags = 0
completedTasks = 0
taskStreak = 0
}
}
@@ -0,0 +1,241 @@
package content.global.skill.slayer
import core.api.LoginListener
import core.api.PersistPlayer
import core.game.event.EventHook
import core.game.event.NPCKillEvent
import core.api.getAttribute
import core.api.rewardXP
import core.cache.def.impl.NPCDefinition
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import org.json.simple.JSONArray
import org.json.simple.JSONObject
import core.api.Event
import java.util.*
/**
* Manages the players slayer data.
* @author Ceikry
*/
class SlayerManager(val player: Player? = null) : LoginListener, PersistPlayer, EventHook<NPCKillEvent> {
override fun login(player: Player) {
val instance = SlayerManager(player)
player.hook(Event.NPCKilled, instance)
player.setAttribute("slayer-manager", instance)
}
/**
* The player's slayer flags
*/
@JvmField
val flags: SlayerFlags = SlayerFlags()
override fun savePlayer(player: Player, save: JSONObject) {
val slayer = JSONObject()
val slayerManager = getInstance(player)
if(slayerManager.removed.isNotEmpty()) {
val removedTasks = JSONArray()
slayerManager.removed.map {
removedTasks.add(it.ordinal.toString())
}
slayer["removedTasks"] = removedTasks
}
slayer["taskStreak"] = slayerManager.flags.taskStreak.toString()
slayer["totalTasks"] = slayerManager.flags.completedTasks.toString()
slayer["equipmentFlags"] = slayerManager.flags.equipmentFlags
slayer["taskFlags"] = slayerManager.flags.taskFlags
slayer["rewardFlags"] = slayerManager.flags.rewardFlags
save["slayer"] = slayer
}
override fun parsePlayer(player: Player, data: JSONObject) {
val slayerData = data["slayer"] as JSONObject
val m = slayerData["master"]
val flags = getInstance(player).flags
if (m != null) {
flags.setMaster(Master.forId(m.toString().toInt()))
}
val t = slayerData["taskId"]
if (t != null) flags.setTask(Tasks.values()[t.toString().toInt()])
val a = slayerData["taskAmount"]
if (a != null) flags.setTaskAmount(a.toString().toInt())
val points = slayerData["points"]
if (points != null) {
flags.setPoints(points.toString().toInt())
}
val taskStreak = slayerData["taskStreak"]
if (taskStreak != null) {
flags.taskStreak = taskStreak.toString().toInt()
}
val la = slayerData["learned_rewards"]
if (la != null) {
val learnedArray = slayerData["learned_rewards"] as JSONArray?
for (i in learnedArray!!.indices) {
val unlocked = learnedArray[i] as Boolean
when (i) {
0 -> if (unlocked) flags.unlockBroads()
1 -> if (unlocked) flags.unlockRing()
2 -> if (unlocked) flags.unlockHelm()
else -> {}
}
}
}
val removedTasks = slayerData["removedTasks"] as JSONArray?
if (removedTasks != null) {
for (i in removedTasks.indices) {
flags.removed.add(Tasks.values()[removedTasks[i].toString().toInt()])
}
}
val completedTasks: Any = slayerData["totalTasks"].toString()
flags.completedTasks = completedTasks.toString().toInt()
if (flags.completedTasks >= 4) flags.flagCanEarnPoints()
//New system parsing
if (slayerData.containsKey("equipmentFlags")) flags.equipmentFlags = slayerData["equipmentFlags"].toString().toInt()
if (slayerData.containsKey("taskFlags")) flags.taskFlags = slayerData["taskFlags"].toString().toInt()
if (slayerData.containsKey("rewardFlags")) flags.rewardFlags = slayerData["rewardFlags"].toString().toInt()
}
override fun process(entity: Entity, event: NPCKillEvent) {
val npc = event.npc
val player = entity as? Player ?: return
val slayer = getInstance(player)
val flags = slayer.flags
if (slayer.hasTask() && npc.id in slayer.task!!.npcs) {
rewardXP(player, Skills.SLAYER, npc.skills.maximumLifepoints.toDouble())
slayer.decrementAmount(1)
if(slayer.hasTask()) return
flags.taskStreak = flags.taskStreak + 1
flags.completedTasks = flags.completedTasks + 1
if ((flags.completedTasks > 4 || flags.canEarnPoints()) && flags.getMaster() != Master.TURAEL && flags.getPoints() < 64000) {
var points = flags.getMaster().taskPoints[0]
if (flags.taskStreak % 50 == 0) {
points = flags.getMaster().taskPoints[2]
} else if (flags.taskStreak % 10 == 0) {
points = flags.getMaster().taskPoints[1]
}
flags.incrementPoints(points)
if (flags.getPoints() > 64000) {
flags.setPoints(64000)
}
player.sendMessages("You've completed " + flags.taskStreak + " tasks in a row and received " + points + " points, with a total of " + flags.getPoints(), "You have completed " + flags.completedTasks + " tasks in total. Return to a Slayer master.")
} else if (flags.completedTasks == 4) {
player.sendMessage("You've completed your task; you will start gaining points on your next task!")
flags.flagCanEarnPoints()
} else if (flags.getMaster() == Master.TURAEL) {
player.sendMessages("You've completed your task; Tasks from Turael do not award points.", "Return to a Slayer master.")
} else {
player.sendMessages("You've completed your task; Complete " + (4 - flags.completedTasks) + " more task(s) to start gaining points.", "Return to a Slayer master.")
}
}
}
/**
* Method used to assign a new task for a player.
* @param master the master to give the task.
*/
fun generate(master: Master) {
val task = SlayerUtils.generate(player!!, master) ?: return
SlayerUtils.assign(player!!, task, master)
}
/**
* Clears the task.
*/
fun clear() {
amount = 0
}
/**
* Gets the task name.
* @return the name.
*/
val taskName: String
get() {
val task = flags.getTask()
if (task.npcs == null) {
return "no npcs report me"
}
return if (task.npcs.isEmpty()) {
"npc length too small report me"
} else NPCDefinition.forId(task.npcs[0]).name.toLowerCase()
}
var task: Tasks?
get() = flags.getTask()
set(task) {
flags.setTask(task!!)
}
var master: Master?
get() = flags.getMaster()
set(master) {
flags.setMaster(master!!)
}
/**
* Checks if a **Player** contains a task.
* @return `True` if so.
*/
fun hasTask(): Boolean {
return amount > 0
}
/**
* Method used to check if the task is completed.
* @return `True` if so.
*/
val isCompleted: Boolean
get() = flags.getTaskAmount() <= 0
var amount: Int
get() = flags.getTaskAmount()
set(amount) {
flags.setTaskAmount(amount)
}
fun decrementAmount(amount: Int) {
flags.decrementTaskAmount(amount)
player!!.varpManager.get(2502).setVarbit(0, flags.taskFlags shr 4).send(player)
}
/**
* Method used to check if the player has started slayer.
* @return `True` if so.
*/
fun hasStarted(): Boolean {
return flags.completedTasks > 0 || flags.getTaskAmount() > 0
}
/**
* Gets the slayerPoints.
* @return the slayerPoints.
*/
/**
* Sets the slayerPoints.
* @param slayerPoints the slayerPoints to set
*/
var slayerPoints: Int
get() = flags.getPoints()
set(slayerPoints) {
flags.setPoints(slayerPoints)
}
/**
* Gets the removed.
* @return the removed.
*/
val removed: List<Tasks>
get() = flags.removed
val isCanEarnPoints: Boolean
get() = flags.canEarnPoints()
companion object {
@JvmStatic fun getInstance(player: Player) : SlayerManager
{
return getAttribute(player, "slayer-manager", SlayerManager())
}
}
}
@@ -0,0 +1,704 @@
package content.global.skill.slayer;
import org.json.simple.JSONObject;
import core.ServerStore;
import core.game.world.GameWorld;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.global.Skillcape;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.diary.AchievementDiary;
import core.game.node.entity.player.link.diary.DiaryType;
import core.game.node.entity.player.link.quest.Quest;
import core.game.node.item.Item;
import core.plugin.Initializable;
import static core.tools.DialogueConstKt.END_DIALOGUE;
/**
* Represents the dialogue plugin used for a slayer master.
*
* @author Vexia
*/
@Initializable
public final class SlayerMasterDialogue extends DialoguePlugin {
/**
* The enchanted gem item.
*/
private static final Item GEM = new Item(4155, 1);
/**
* The mithril axe item.
*/
private static final Item MITHRIL_AXE = new Item(1355);
/**
* The holy symbol item.
*/
private static final Item HOLY_SYMBOL = new Item(1718);
/**
* Represents the items to use.
*/
private static final Item[] ITEMS = new Item[]{new Item(9813), new Item(9814)};
/**
* Represents the coins item.
*/
private static final Item COINS = new Item(995, 99000);
/**
* Represents the master talking.
*/
private Master master;
/**
* The quest instance.
*/
private Quest quest;
/**
* If we're chatting about our diary.
*/
private boolean isDiary;
private final int level = 2;
private int rerolls = 0;
/**
* Constructs a new {@code SlayerMasterDialogue} {@code Object}.
*/
public SlayerMasterDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code SlayerMasterDialogue} {@code Object}.
*
* @param player the player.
*/
public SlayerMasterDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new SlayerMasterDialogue(player);
}
@Override
public boolean open(Object... args) {
if (args[0] instanceof NPC) {
npc = (NPC) args[0];
}
master = Master.forId(args[0] instanceof NPC ? ((NPC) args[0]).getId() : (int) args[0]);
quest = player.getQuestRepository().getQuest("Animal Magnetism");
if (master == Master.DURADEL) {
if (Skillcape.isMaster(player, Skills.SLAYER)) {
options("Ask about Skillcape", "Something else");
stage = 900;
return true;
}
}
interpreter.sendDialogues(master.getNpc(), getExpression(master), "'Ello, and what are you after, then?");
if (master == Master.VANNAKA) {
stage = -1;
} else {
stage = 0;
}
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
rerolls = ServerStore.getInt(getStoreFile(), player.getUsername().toLowerCase());
if (isDiary) {
switch (stage) {
case 999:
end();
break;
case -1:
options("What is the Achievement Diary?", "What are the rewards?", "How do I claim the rewards?", "See you later.");
stage++;
break;
case 0:
switch (buttonId) {
case 1:
player("What is the Achievement Diary?");
stage = 410;
break;
case 2:
player("What are the rewards?");
stage = 420;
break;
case 3:
player("How do I claim the rewards?");
stage = 430;
break;
case 4:
player("See you later.");
stage = 999;
break;
}
break;
case 440:
npc("I can imagine! I expect you'll be wanting a reward for", "your hard efforts, eh?");
stage++;
break;
case 441:
player("Yes, please.");
stage++;
break;
case 442:
AchievementDiary.grantReplacement(player, DiaryType.VARROCK, level);
npc("I'm happy to say that you've done well, so I will reward", "you suitably for your work.");
stage++;
break;
case 443:
player("Great! Thanks.");
stage++;
break;
case 444:
sendDialogue("Vannaka takes the Varrock armour and carves some symbols into it.", "He waves his hands over the symbols and the armour appears to glow", "brilliantly.");
stage++;
break;
case 450:
AchievementDiary.grantReplacement(player, DiaryType.VARROCK, level);
npc("You better be more careful this time.");
stage = 41;
break;
case 410:
npc("It's a diary that helps you keep track of particular", "achievements. Here in Varrock it can help you", "discover some quite useful things. Eventually, with", "enough exploration, the people of Varrock will reward");
stage++;
break;
case 411:
npc("you.");
stage++;
break;
case 412:
npc("You can see what tasks you have listed by clicking on", "the green button in the Quest List.");
stage = 41;
break;
case 420:
npc("Well, there's three different levels of Varrock Armour,", "which match up with the three levels of difficulty. Each", "has the same rewards as the previous level, and an", "additional one too... but I won't spoil your surprise.");
stage++;
break;
case 421:
npc("Rest assured, the people of Varrock are happy to see", "you visiting the land.");
stage = 41;
break;
case 430:
npc("Just complete the tasks so they're all ticked off, then", "you can claim your reward. Most of them are", "straightforward; you might find some require quests to", "be started, if not finished.");
stage++;
break;
case 431:
npc("To claim the different Varrock Armour, speak to Vannaka", "Rat Burgis, and myself.");
stage = 41;
break;
case 50:
end();
break;
}
return true;
}
switch (stage) {
case 999:
end();
break;
case -1: // vannaka - has options for achievement diary
if (!SlayerManager.getInstance(player).hasStarted()) {
options("Who are you?", "Do you have anything for trade?", "Er...nothing...", "I have a question about my Achievement Diary.");
stage = 1;
} else {
options("I need another assignment.", "Do you have anything for trade?", "Er...nothing...", "I have a question about my Achievement Diary.");
stage = 690;
}
break;
case 0: // not vannaka
if (master == Master.TURAEL) { // only give option to talk about holy axe with Turael
if (quest.getStage(player) == 30) {
options("I need another assignment.", "Do you have anything for trade?", "Er...nothing...", "I'm here about a quest.");
stage = 700;
break;
} else if (quest.getStage(player) == 31) {
options("I need another assignment.", "Do you have anything for trade?", "Er...nothing...", "Hello, I'm here about those trees again.");
stage = 700;
break;
}
}
if (!SlayerManager.getInstance(player).hasStarted()) {
options("Who are you?", "Do you have anything for trade?", "Er...nothing...");
stage = 1;
} else {
options("I need another assignment.", "Do you have anything for trade?", "Er...nothing...");
stage = 700;
}
break;
case 1:
switch (buttonId) {
case 1:
player("Who are you?");
stage = 10;
break;
case 2:
player("Do you have anything for trade?");
stage = 20;
break;
case 3:
player("Er...nothing...");
stage = 999;
break;
case 4:
player("I have a question about my Achievement Diary.");
stage = 691;
break;
}
break;
case 10:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "I'm " + (master.getNpc() == 8273 ? "the lowest level Slayer Master available." : "one of the elite Slayer Masters."),
master.getNpc() == 8273 ? "The other Slayer Masters are spread around the world." : "I can teach you about the ways of the Slayer.");
stage = 11;
break;
case 11:
options("What's a Slayer?", "Never heard of you...");
stage = 12;
break;
case 12:
switch (buttonId) {
case 1:
player("What's a Slayer?");
stage = 100;
break;
case 2:
player("Never heard of you...");
stage = 2000;
break;
}
break;
case 20:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "I have a wide selection of Slayer equipment; take a look!");
stage = 21;
break;
case 21:
end();
if (npc != null) {
npc.openShop(player);
}
break;
case 100:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Oh dear, what do they teach you in school?");
stage = 101;
break;
case 101:
player("Well....er...");
stage = 102;
break;
case 102:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "I suppose I'll have to educate you, then. A Slayer is", "someone who is trained to fight specific creatures. They", "know those creatures' every weakenss and strength. As", "you can guess, it makes killing those creatures a lot");
stage = 103;
break;
case 103:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "easier.");
stage = 104;
break;
case 104:
options("Wow, can you teach me?", "Sounds useless to me.");
stage = 105;
break;
case 105:
switch (buttonId) {
case 1:
player("Wow, can you teach me?");
stage = 500;
break;
case 2:
player("Sounds useless to me.");
stage = 1000;
break;
}
break;
case 500:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Hmmm, well, I'm not so sure...");
stage = 501;
break;
case 501:
player("Pleeeaasssse! I'll be your best friend!");
stage = 502;
break;
case 502:
if (!master.hasRequirements(player)) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Sorry, but you're not strong enough to be taught by", "me.");
stage = 99;
break;
}
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Oh, okay then; you twisted my arm. You'll have to", "train against specific groups of creatures.");
stage = 503;
break;
case 503:
player("Okay then, what's first?");
stage = 504;
break;
case 504:
if (player.getInventory().freeSlots() != 0) {
player.getInventory().add(GEM);
SlayerManager.getInstance(player).generate(master);
interpreter.sendDialogues(master.getNpc(), getExpression(master), "We'll start you off hunting " + SlayerManager.getInstance(player).getTaskName() + "'s, you'll need to", "kill " + SlayerManager.getInstance(player).getAmount() + " of them.");
stage = 510;
} else if (player.getInventory().freeSlots() == 0) {
player("Sorry, I don't have enough inventory space.");
stage = 999;
}
break;
case 510:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "You'll also need this enchanted gem. It allows Slayer", "Masters like myself to contact you and update you on", "your progress. Don't worry if you lose it; you can buy", "another from any Slayer Master.");
stage = 511;
break;
case 511:
player("Okay, great!");
stage = 999;
break;
case 1000:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "That's what you think..");
stage = 999;
break;
case 2000:
interpreter.sendDialogues(master.getNpc(), getExpression(master), "I am one of the greatest Slayer masters!");
stage = 999;
break;
case 690:
switch (buttonId) {
case 1:
player("I need another assignment.");
stage = 701;
break;
case 2:
player("Do you have anything for trade?");
stage = 20;
break;
case 3:
player("Er...nothing...");
stage = 30;
break;
case 4:
player("I have a question about my Achievement Diary.");
stage = 691;
break;
}
break;
case 691:
sendDiaryDialogue();
break;
case 700:
switch (buttonId) {
case 1:
player("I need another assignment.");
stage = 701;
break;
case 2:
player("Do you have anything for trade?");
stage = 20;
break;
case 3:
player("Er...nothing...");
stage = 30;
break;
case 4:
if (quest.getStage(player) == 30) {
player("I'm here about a quest. Ava said she saw you hanging", "around the moving trees near Draynor Manor.");
stage = 8000;
} else if (quest.getStage(player) == 31) {
player("Hello, I'm here about those trees again.");
stage = 8006;
}
break;
}
break;
case 8000:// avas.
npc("Ahh, you came to the right man, odd things, those trees.", "What is it you are needing exactly?");
stage++;
break;
case 8001:
player("I think I need some of the wood from them, but my", "axe just bounced off the trunk.");
stage++;
break;
case 8002:
npc("Sounds like you need a blessed axe. No one really", "makes them, though these days.");
stage++;
break;
case 8003:
npc("If you can give me a mithril axe and a holy symbol of", "Saradomin I can let you have my axe. I'll make myself", "a new one when no one is pestering me for Slayer", "tasks.");
stage++;
break;
case 8004:
player("Okay, so I'll see whether I can spare an axe and a", "symbol. Thanks.");
stage++;
break;
case 8005:
quest.setStage(player, 31);
end();
break;
case 8006:
if (player.hasItem(new Item(10491))) {
npc("You already have an axe.");
stage = 999;
break;
}
npc("I can make an axe for you now, if you wish.", "Remember, it will be no use for normal wooducutting", "after I have added the silver edge.");
stage++;
break;
case 8007:
player("I'd love one, thanks.");
stage++;
break;
case 8008:
if (!player.getInventory().containsItem(MITHRIL_AXE)) {
npc("You'll need to hand over both a mithril axe and a holy", "symbol of Saradomin. You don't have an axe in your", "pack, so I'm not able to help.");
stage = 999;
break;
}
if (!player.getInventory().containsItem(HOLY_SYMBOL)) {
npc("You'll need to hand over both a mithril axe and a holy", "symbol of Saradomin. You don't have a holy symbol in", "your pack, so I'm not able to help.");
stage = 999;
break;
}
if (player.getInventory().remove(MITHRIL_AXE, HOLY_SYMBOL)) {
player.getInventory().add(new Item(10491));
npc("Here's a new axe; may it serve you well.");
stage = 999;
}
break;
case 701:
if (!master.hasRequirements(player)) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Sorry, but you're not strong enough to be taught by", "me.");
stage = 99;
break;
}
if (!SlayerManager.getInstance(player).hasTask()) {
SlayerManager.getInstance(player).generate(master);
if (SlayerManager.getInstance(player).getTask() == Tasks.JAD) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to", "defeat the almighty TzTok-Jad.");
} else {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerManager.getInstance(player).getTaskName() + "s.");
}
stage = 844;
break;
}
if (Master.hasSameTask(master, player)) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "You're still hunting something. But let me check something...");
stage = 847;
} else {
SlayerManager.getInstance(player).flags.setTaskStreak(0);
SlayerManager.getInstance(player).generate(master);
if (SlayerManager.getInstance(player).getTask() == Tasks.JAD) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to", "defeat the almighty TzTok-Jad.");
} else {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerManager.getInstance(player).getTaskName() + "'s.");
}
stage = 844;
}
break;
case 844:
if (GameWorld.getSettings().getAllow_slayer_reroll()) {
options("Got any tips for me?", "Okay, great!", "I'd like to re-roll that task.");
} else {
options("Got any tips for me?", "Okay, great!");
}
stage++;
break;
case 845:
switch (buttonId) {
case 1:
interpreter.sendDialogues(master.getNpc(), getExpression(master), SlayerManager.getInstance(player).getTask().getTip());
stage = 860;
break;
case 2:
player("Okay, great!");
stage = 999;
break;
case 3:
player("I'd like to re-roll this task.");
if(rerolls == 10){
stage++;
} else {
SlayerManager.getInstance(player).clear();
getStoreFile().put(player.getUsername().toLowerCase(), rerolls + 1);
stage = 701;
}
}
break;
case 846:
npcl(FacialExpression.NEUTRAL, "Actually, you're out of free rerolls. You can buy a reroll from my reward store, though.");
stage = END_DIALOGUE;
break;
case 847:
if(rerolls < 10){
npcl(FacialExpression.NEUTRAL, "You do have " + (10 - rerolls) + " rerolls left today, would you like to use one?");
stage++;
}
else {
npcl(FacialExpression.NEUTRAL, "And it also seems you're out of rerolls for today. That's unfortunate.");
stage = END_DIALOGUE;
}
break;
case 848:
options("Yes, please.", "No, thanks.");
stage++;
break;
case 849:
switch(buttonId){
case 1:
playerl(FacialExpression.FRIENDLY, "Yes, please.");
SlayerManager.getInstance(player).clear();
getStoreFile().put(player.getUsername().toLowerCase(), rerolls + 1);
stage = 701;
break;
case 2:
playerl(FacialExpression.NEUTRAL, "No, thanks.");
stage = END_DIALOGUE;
break;
}
break;
case 860:
player("Great, thanks!");
stage = 999;
break;
case 900:
switch (buttonId) {
case 1:
player("Can I buy a Skillcape of Slayer?");
stage = 901;
break;
case 2:
interpreter.sendDialogues(master.getNpc(), FacialExpression.HALF_GUILTY, "'Ello, and what are you after, then?");
stage = 0;
break;
}
break;
case 901:
interpreter.sendDialogues(Master.DURADEL.getNpc(), FacialExpression.HALF_GUILTY, "Certainly! Right when you give me 99000 coins.");
stage = 902;
break;
case 902:
options("Okay, here you go.", "No, thanks.");
stage = 903;
break;
case 903:
switch (buttonId) {
case 1:
player("Okay, here you go.");
stage = 904;
break;
case 2:
end();
break;
}
break;
case 904:
if (Skillcape.purchase(player, Skills.SLAYER)) {
interpreter.sendDialogues(Master.DURADEL.getNpc(), FacialExpression.HALF_GUILTY, "There you go! Enjoy.");
}
stage = 999;
break;
case 906:
switch (buttonId) {
case 1:
player("May I buy a Quest Point cape?");
stage = 907;
break;
case 2:
interpreter.sendDialogues(master.getNpc(), FacialExpression.HALF_GUILTY, "'Ello, and what are you after, then?");
stage = 0;
break;
}
break;
case 907:
npc("You bet, " + player.getUsername() + "! Right when you give me 99000 coins.");
stage = 908;
break;
case 908:
options("Okay, here you go.", "No, thanks.");
stage = 909;
break;
case 909:
switch (buttonId) {
case 1:
player("Okay, here you go.");
stage = 910;
break;
case 2:
end();
break;
}
break;
case 910:
if (player.getInventory().freeSlots() < 2) {
player("I don't seem to have enough inventory space.");
stage = 999;
return true;
}
if (!player.getInventory().containsItem(COINS)) {
player("I don't seem to have enough coins with", "me at this time.");
stage = 999;
return true;
}
if (player.getInventory().remove(COINS) && player.getInventory().add(ITEMS)) {
npc("Have fun with it.");
stage = 999;
} else {
player("I don't seem to have enough coins with", "me at this time.");
stage = 999;
}
break;
}
return true;
}
/**
* Checks which expression to use.
*
* @param master the master.
* @return the expression.
*/
private FacialExpression getExpression(Master master) {
if (master == Master.CHAELDAR) {
return FacialExpression.OLD_NORMAL;
}
return FacialExpression.HALF_GUILTY;
}
/**
* Sends the diary dialogue.
*/
private void sendDiaryDialogue() {
isDiary = true;
if (AchievementDiary.canClaimLevelRewards(player, DiaryType.VARROCK, level)) {
player("I've completed all the hard tasks in my Varrock", "Achievement Diary and, let me tell you, it wasn't an", "easy job.");
stage = 440;
return;
}
if (AchievementDiary.canReplaceReward(player, DiaryType.VARROCK, level)) {
player("I've seemed to have lost my armour...");
stage = 460;
return;
}
options("What is the Achievement Diary?", "What are the rewards?", "How do I claim the rewards?", "See you later.");
stage = 0;
}
@Override
public int[] getIds() {
return new int[]{70, 1598, 1596, 1597, 1599, 7780, 8275, 8273, 8274, 8649};
}
private JSONObject getStoreFile() {
return ServerStore.getArchive("daily-slayer-rerolls");
}
}
@@ -0,0 +1,91 @@
package content.global.skill.slayer;
import core.cache.def.impl.SceneryDefinition;
import core.game.global.action.ClimbActionHandler;
import core.game.global.action.DigAction;
import core.game.global.action.DigSpadeHandler;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Handles related slayer nodes.
* @author Vexia
*/
@Initializable
public class SlayerPlugin extends OptionHandler {
/**
* The bryne dig locations.
*/
private static final Location[] BRYNE_DIGS = new Location[] { new Location(2749, 3733, 0), new Location(2748, 3733, 0), new Location(2747, 3733, 0), new Location(2747, 3734, 0), new Location(2747, 3735, 0), new Location(2747, 3736, 0), new Location(2748, 3736, 0), new Location(2749, 3736, 0) };
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.forId(8783).getHandlers().put("option:open", this);
SceneryDefinition.forId(8785).getHandlers().put("option:climb-up", this);
SceneryDefinition.forId(23158).getHandlers().put("option:exit", this);
SceneryDefinition.forId(23157).getHandlers().put("option:exit", this);
SceneryDefinition.forId(15767).getHandlers().put("option:enter", this);
SceneryDefinition.forId(15811).getHandlers().put("option:exit", this);
SceneryDefinition.forId(15812).getHandlers().put("option:exit", this);
SceneryDefinition.forId(96).getHandlers().put("option:climb-up", this);
SceneryDefinition.forId(35121).getHandlers().put("option:climb-down", this);
for (Location loc : BRYNE_DIGS) {
DigSpadeHandler.register(loc, new DigAction() {
@Override
public void run(Player player) {
player.teleport(new Location(2697, 10119, 0));
player.sendMessages("You dig a hole...", "...And fall into a dark and slimy pit!");
}
});
}
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
switch (node.getId()) {
case 8783:
player.teleport(new Location(2044, 4649, 0));
break;
case 8785:
player.teleport(new Location(2543, 3327, 0));
break;
case 23158:
case 23157:
player.teleport(new Location(2729, 3733, 0));
break;
case 15767:
player.teleport(new Location(3748, 9373, 0));
break;
case 15811:
case 15812:
player.teleport(new Location(3749, 2973, 0));
break;
case 96:
ClimbActionHandler.climb(player, null, new Location(2649, 9804, 0));
break;
case 35121:
ClimbActionHandler.climb(player, null, new Location(2641, 9763, 0));
break;
}
return true;
}
@Override
public Location getDestination(Node node, Node n) {
if (n.getId() == 23158 || n.getId() == 23157) {
return new Location(2690, 10124, 0);
}
if (n.getId() == 96) {
return new Location(2641, 9763, 0);
}
return null;
}
}
@@ -0,0 +1,406 @@
package content.global.skill.slayer;
import core.cache.def.impl.ItemDefinition;
import core.cache.def.impl.NPCDefinition;
import core.game.component.Component;
import core.game.component.ComponentDefinition;
import core.game.component.ComponentPlugin;
import core.game.node.entity.skill.Skills;
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.item.Item;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
/**
* Handles the slayer reward interface plugin.
* @author Vexia
*
*/
@Initializable
public class SlayerRewardPlugin extends ComponentPlugin {
/**
* The assignment component tab.
*/
private static final Component ASSIGNMENT = new Component(161);
/**
* The learn component tab.
*/
private static final Component LEARN = new Component(163);
/**
* The buy component tab.
*/
private static final Component BUY = new Component(164);
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ComponentDefinition.forId(161).setPlugin(this);//assignment
ComponentDefinition.forId(163).setPlugin(this);//learn
ComponentDefinition.forId(164).setPlugin(this);//buy
ClassScanner.definePlugins(new SlayerMasterPlugin(), new SlayerHelmCraftPlugin());
return this;
}
@Override
public void open(Player player, Component open) {
updateInterface(player, open);
}
@Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
switch (component.getId()) {
case 161://asignment
switch (button) {
case 23://reassign
case 26:
if (!SlayerManager.getInstance(player).hasTask()) {
player.sendMessage("You don't have an active task right now.");
break;
}
if (purchase(player, 30)) {
SlayerManager.getInstance(player).clear();
player.sendMessage("You have canceled your current task.");
}
break;
case 24:
case 27:
if (SlayerManager.getInstance(player).getTask() == null) {
player.sendMessage("You don't have a slayer task.");
break;
}
if (SlayerManager.getInstance(player).getRemoved().size() >= 4) {
player.sendMessage("You can't remove anymore tasks.");
break;
}
if (SlayerManager.getInstance(player).getSlayerPoints() >= 30 && !player.isAdmin()) {
int size = SlayerManager.getInstance(player).getRemoved().size();
int qp = player.getQuestRepository().getAvailablePoints();
if (size == 0 && qp < 50) {
player.sendMessage("You need 50 quest points as a requirement in order to block one task.");
break;
} else if (size == 1 && qp < 100) {
player.sendMessage("You need 100 quest points as a requirement in order to block two tasks.");
break;
} else if (size == 2 && qp < 150) {
player.sendMessage("You need 150 quest points as a requirement in order to block three tasks.");
break;
} else if (size == 3 && qp < 200) {
player.sendMessage("You need 200 quest points as a requirement in order to block four tasks.");
break;
}
}
if (purchase(player, 100)) {
SlayerManager.getInstance(player).getRemoved().add(SlayerManager.getInstance(player).getTask());
SlayerManager.getInstance(player).clear();
updateInterface(player, player.getInterfaceManager().getOpened());
}
break;
case 36:
case 37:
case 38:
case 39:
int index = 3 - (39 - button);
if (SlayerManager.getInstance(player).getRemoved().isEmpty() || index > SlayerManager.getInstance(player).getRemoved().size() - 1 || SlayerManager.getInstance(player).getRemoved().get(index) == null) {
break;
}
SlayerManager.getInstance(player).getRemoved().remove(index);
updateInterface(player, player.getInterfaceManager().getOpened());
break;
case 15:
openTab(player, BUY);
break;
case 14:
openTab(player, LEARN);
break;
}
break;
case 163://learn
switch (button) {
case 14:
openTab(player, ASSIGNMENT);
break;
case 15:
openTab(player, BUY);
break;
case 22://Broad arrows
case 29:
if (SlayerManager.getInstance(player).flags.isBroadsUnlocked()) {
player.sendMessage("You don't need to learn this ability again.");
break;
}
if (purchase(player, 300)) {
SlayerManager.getInstance(player).flags.unlockBroads();
updateInterface(player, component);
}
break;
case 23://Slayer ring
case 30:
if (SlayerManager.getInstance(player).flags.isRingUnlocked()) {
player.sendMessage("You don't need to learn this ability again.");
break;
}
if (purchase(player, 300)) {
SlayerManager.getInstance(player).flags.unlockRing();
updateInterface(player, component);
}
break;
case 24://Slayer helm
case 31:
if (SlayerManager.getInstance(player).flags.isHelmUnlocked()) {
player.sendMessage("You don't need to learn this ability again.");
break;
}
if (purchase(player, 400)) {
SlayerManager.getInstance(player).flags.unlockHelm();
updateInterface(player, component);
}
break;
}
break;
case 164://buy
switch (button) {
case 16:
openTab(player, LEARN);
break;
case 17:
openTab(player, ASSIGNMENT);
break;
case 24://slayer exp
case 32:
if (purchase(player, 400)) {
player.getSkills().addExperience(Skills.SLAYER, 10000, false);
}
break;
case 26://ring of slaying
case 33:
if (player.getInventory().freeSlots() < 1 && SlayerManager.getInstance(player).getSlayerPoints() >= 75) {
player.sendMessage("You don't have enough inventory space.");
break;
}
if (purchase(player, 75)) {
player.getInventory().add(new Item(13281), player);
}
break;
case 28:
case 36:
if (purchase(player, 35)) {
player.getInventory().add(new Item(558, 1000), player);
player.getInventory().add(new Item(560, 250), player);
}
break;
case 34:
case 37:
if (purchase(player, 35)) {
player.getInventory().add(new Item(13280, 250), player);
}
break;
case 35:
case 39:
if (purchase(player, 35)) {
player.getInventory().add(new Item(4172, 250), player);
}
break;
}
break;
}
return true;
}
/**
* Purchases a slayer point reward.
* @param player The player.
* @param amount The amount of points.
* @return {@code True} if purchased.
*/
private boolean purchase(Player player, int amount) {
if (SlayerManager.getInstance(player).getSlayerPoints() < amount) {
player.sendMessage("You need " + amount + " slayer points in order to purchase this reward.");
return false;
}
SlayerManager.getInstance(player).setSlayerPoints(SlayerManager.getInstance(player).getSlayerPoints() - amount);
updateInterface(player, player.getInterfaceManager().getOpened());
return true;
}
/**
* Switches the tab on the reward interface.
* @param player The player instance
* @param open The component to open.
*/
private void openTab(Player player, Component open) {
player.getInterfaceManager().open(open);
updateInterface(player, open);
}
/**
* Update the current points text.
* @param player the player.
* @param open the component.
*/
private void updateInterface(Player player, Component open) {
if (open == null) {
return;
}
String space = "";
String num = String.valueOf(SlayerManager.getInstance(player).getSlayerPoints());
if (num != "0") {
for (int i = 0; i < num.length(); i++) {
space += " ";
}
}
switch (open.getId()) {
case 161://assignment
int childs[] = new int[] {35, 30, 31, 32};
String[] letters = new String[] {"A", "B", "C", "D"};
Tasks task = null;
for (int i = 0; i < 4; i++) {
task = i > SlayerManager.getInstance(player).getRemoved().size() - 1 ? null : SlayerManager.getInstance(player).getRemoved().get(i);
player.getPacketDispatch().sendString(task == null ? letters[i] : task.getName(), open.getId(), childs[i]);
}
player.getPacketDispatch().sendString(space + SlayerManager.getInstance(player).getSlayerPoints(), open.getId(), 19);
break;
case 163://learn
for (int i = 0; i < 3; i++) {
switch(i){
case 0:
player.getPacketDispatch().sendInterfaceConfig(open.getId(), 25 + i, !SlayerManager.getInstance(player).flags.isBroadsUnlocked());
break;
case 1:
player.getPacketDispatch().sendInterfaceConfig(open.getId(), 25 + i, !SlayerManager.getInstance(player).flags.isRingUnlocked());
break;
case 2:
player.getPacketDispatch().sendInterfaceConfig(open.getId(), 25 + i, !SlayerManager.getInstance(player).flags.isHelmUnlocked());
break;
default:
break;
}
}
player.getPacketDispatch().sendString(space + SlayerManager.getInstance(player).getSlayerPoints(), open.getId(), 18);
break;
case 164://buy
player.getPacketDispatch().sendString(space + SlayerManager.getInstance(player).getSlayerPoints(), open.getId(), 20);
break;
}
}
/**
* Handles the slayer master option plugin.
* @author Vexia
*
*/
public class SlayerMasterPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (Master m : Master.values()) {
NPCDefinition.forId(m.getNpc()).getHandlers().put("option:rewards", this);
}
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
openTab(player, BUY);
return true;
}
}
/**
* Handles the crafting of a slayer helmet.
* @author Vexia
*
*/
public static class SlayerHelmCraftPlugin extends UseWithHandler {
/**
* The slayer helm item.
*/
private static final Item SLAYER_HELM = new Item(13263);
/**
* The spiny helmet.
*/
private static final Item SPINY_HELMET = new Item(4551);
/**
* The ingredients needed.
*/
private static final int[] INGREDIENTS = new int[] {4168, 4166, 4164, 8921};
/**
* Constructs a new {@Code SlayerHelmCraftPlugin} {@Code Object}
*/
public SlayerHelmCraftPlugin() {
super(INGREDIENTS);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
addHandler(SPINY_HELMET.getId(), ITEM_TYPE, this);
ClassScanner.definePlugin(new OptionHandler() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ItemDefinition.forId(SLAYER_HELM.getId()).getHandlers().put("option:disassemble", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
if (player.getInventory().freeSlots() < 4) {
player.sendMessage("You don't have enough inventory space.");
return true;
}
player.lock(1);
if (player.getInventory().remove(node.asItem())) {
for (int id : INGREDIENTS) {
player.getInventory().add(new Item(id));
}
player.getInventory().add(SPINY_HELMET);
}
player.sendMessage("You dissasemble your Slayer helm.");
return true;
}
});
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
if (player.getSkills().getStaticLevel(Skills.CRAFTING) < 55) {
player.sendMessage("You need a Crafting level of at least 55 in order to do this.");
return true;
}
if (!SlayerManager.getInstance(player).flags.isHelmUnlocked()) {
player.sendMessage("You need to unlock the ability to do that first.");
return true;
}
if (!player.getInventory().containItems(INGREDIENTS)) {
player.sendMessages("You need a nosepeg, facemask, earmuffs, spiny helmet, and a black mask in", "your inventory in order to construct a Slayer helm.");
return true;
}
player.lock(1);
if (player.getInventory().remove(SPINY_HELMET)) {
for (int id : INGREDIENTS) {
if (!player.getInventory().remove(new Item(id))) {
return true;
}
}
player.getInventory().add(SLAYER_HELM);
player.sendMessage("You combine the items into a Slayer helm.");
}
return true;
}
}
}
@@ -0,0 +1,69 @@
package content.global.skill.slayer;
import core.cache.def.impl.SceneryDefinition;
import core.game.global.action.DoorActionHandler;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.node.scenery.Scenery;
import core.game.node.scenery.SceneryBuilder;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Handles the interactions for the slayer tower.
* @author Vexia
*/
@Initializable
public final class SlayerTowerPlugin extends OptionHandler {
/**
* The locations of the states.
*/
private static final Location[] LOCATIONS = new Location[] { new Location(3430, 3534, 0), new Location(3426, 3534, 0) };
/**
* The open id.
*/
private static final int OPEN_ID = 5117;
/**
* The closed id.
*/
private static final int CLOSED_ID = 5116;
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.forId(4490).getHandlers().put("option:open", this);
SceneryDefinition.forId(4487).getHandlers().put("option:open", this);
SceneryDefinition.forId(4492).getHandlers().put("option:close", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
switch (node.getId()) {
case 4490:
case 4487:
DoorActionHandler.handleAutowalkDoor(player, (Scenery) node);
switchStatue();
return true;
}
return true;
}
/**
* Switches the object id of the statue.
*/
private void switchStatue() {
for (Location l : LOCATIONS) {
Scenery object = RegionManager.getObject(l);
if (object != null) {
int id = object.getId() == OPEN_ID ? CLOSED_ID : OPEN_ID;
SceneryBuilder.replace(object, object.transform(id));
}
}
}
}
@@ -0,0 +1,64 @@
package content.global.skill.slayer;
import core.game.global.action.DoorActionHandler;
import core.game.node.entity.skill.Skills;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.player.Player;
import core.game.node.scenery.Scenery;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.game.world.map.zone.ZoneRestriction;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Handles the slayer tower map zone.
* @author Vexia
*/
@Initializable
public final class SlayerTowerZone extends MapZone implements Plugin<Object> {
/**
* Constructs a new {@code SlayerTowerZone} {@code Object}.
*/
public SlayerTowerZone() {
super("slayer tower", true, ZoneRestriction.CANNON);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
return this;
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (e instanceof Player) {
Player player = (Player) e;
int level = player.getLocation().getZ() == 0 ? 61 : 71;
if (target.getId() == 9319 && e.getSkills().getLevel(Skills.AGILITY) < level) {
player.getPacketDispatch().sendMessage("You need an Agility level of at least " + level + " in order to do this.");
return true;
}
if (target.getId() == 10527 || target.getId() == 10528) {
DoorActionHandler.handleAutowalkDoor(player, (Scenery) target);
return true;
}
}
return super.interact(e, target, option);
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
@Override
public void configure() {
register(new ZoneBorders(3401, 3527, 3459, 3585));
}
}
@@ -0,0 +1,59 @@
package content.global.skill.slayer
import core.game.node.entity.combat.BattleState
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.SpellBookManager.SpellBook
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.skill.Skills
import content.global.skill.slayer.Master
import content.global.skill.slayer.Tasks
import core.tools.RandomFunction
import org.rs09.consts.Items
import java.util.ArrayList
object SlayerUtils {
fun generate(player: Player, master: Master): Tasks?
{
val tasks: MutableList<Master.Task?> = ArrayList(10)
val taskWeightSum = intArrayOf(0)
master.tasks.stream().filter { task: Master.Task -> canBeAssigned(player, task.task) && task.task.combatCheck <= player.properties.currentCombatLevel }.forEach { task: Master.Task ->
taskWeightSum[0] += task.weight
tasks.add(task)
}
tasks.shuffle(RandomFunction.RANDOM)
var rnd = RandomFunction.random(taskWeightSum[0])
for (task in tasks) {
if (rnd < task!!.weight) return task.task
rnd -= task.weight
}
return null
}
fun canBeAssigned(player: Player, task: Tasks): Boolean
{
return player.getSkills().getLevel(Skills.SLAYER) >= task.levelReq && !SlayerManager.getInstance(player).flags.removed.contains(task)
}
fun assign(player: Player, task: Tasks, master: Master)
{
SlayerManager.getInstance(player).master = master
SlayerManager.getInstance(player).task = task
SlayerManager.getInstance(player).amount = RandomFunction.random(master.assignment_range[0], master.assignment_range[1])
if (master == Master.DURADEL) {
player.achievementDiaryManager.finishTask(player, DiaryType.KARAMJA, 2, 8)
} else if (master == Master.VANNAKA) {
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 1, 14)
}
player.varpManager.get(2502).setVarbit(0, SlayerManager.getInstance(player).flags.taskFlags shr 4).send(player)
}
@JvmStatic
fun hasBroadWeaponEquipped(player: Player, state: BattleState): Boolean {
return (state.weapon != null && state.weapon.id == Items.LEAF_BLADED_SPEAR_4158 ||
state.weapon != null && state.weapon.id == Items.LEAF_BLADED_SWORD_13290 ||
state.ammunition != null && (state.ammunition.itemId == Items.BROAD_ARROW_4160 || state.ammunition.itemId == Items.BROAD_TIPPED_BOLTS_13280) ||
state.spell != null && state.spell.spellId == 31 && player.spellBookManager
.spellBook == SpellBook.MODERN.interfaceId
)
}
}
@@ -0,0 +1,149 @@
package content.global.skill.slayer;
import core.cache.def.impl.NPCDefinition;
import java.util.Arrays;
import java.util.HashMap;
/**
* A non-garbage way of representing tasks
* @author ceik
*/
public enum Tasks {
ABERRANT_SPECTRES(65, new int[] { 1604, 1605, 1606, 1607 }, new String[] { "Aberrant spectres have an extremely potent stench that drains", "stats and life points. A nose peg, protects against the stench." }, 60, true),
ABYSSAL_DEMONS(85, new int[] { 1615, 4230 }, new String[] { "Abyssal Demons are nasty creatures to deal with, they aren't really part, ", "of this realm, and are able to move very quickly to trap their prey"}, 85, false),
ANKOU(40, new int[] { 4381, 4382, 4383 }, new String[] { "Neither skeleton nor ghost, but a combination of both." }, 1, true),
AVIANSIES(60, new int[] { 6245, 6243, 6235, 6232, 6244, 6246, 6233, 6241, 6238, 6237, 6240, 6242, 6239, 6234 }, new String[] { "Graceful, bird-like creature." }, 1, false),
BANSHEE(20, new int[] { 1612 }, new String[] { "Banshees use a piercing scream to shock their enemies, you'll", "need some Earmuffs to protect yourself from them." }, 15, true),
BASILISKS(40, new int[] { 1616, 1617, 4228 }, new String[] { "A mirror shield is much neccesary when hunting these", "mad creatures." }, 40, false),
BATS(5, new int[] { 412, 78, 1005, 2482, 3711, }, new String[] { "These little creatures are incredibly quick.", "make sure you keep your eye on them at all times." }, 1, false),
BEARS(13, new int[] { 106, 105, 1195, 3645, 3664, 1326, 1327 }, new String[] { "A large animal with a crunching punch." }, 1, false),
BIRDS(1, new int[] { 1475, 5120, 5121, 5122, 5123, 5133, 1475, 1476, 41, 951, 1017, 1401, 1402, 2313, 2314, 2315, 1016, 1550, 147, 1180, 1754, 1755, 1756, 2252, 4570, 4571, 1911, 6114, 46, 2693, 6113, 6112, 146, 149, 150, 450, 451, 1179, 1322, 1323, 1324, 1325, 1400, 2726, 2727, 3197, 138, 48, 4373, 4374, 4535, 139, 1751, 148, 1181, 6382, 2459, 2460, 2461, 2462, 2707, 2708, 6115, 6116, 3296, 6378, 1996, 3675, 3676, 6792, 6946, 7320, 7322, 7324, 7326, 7328, 1692, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6322, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, }, new String[] { "irds aren't the most intelligent of creatures, but watch out for their", "sharp, stabbing beaks." }, 1, false),
BLACK_DEMONS(80, new int[] { 84, 677, 4702, 4703, 4704, 4705, 6208, }, new String[] { "Black Demons are magic creatures that are weak to magic attacks.", "They're the strongest demon and very dangerous." }, 1, false),
BLACK_DRAGONS(80, new int[] {54, 4673, 4674, 4675, 4676, 3376, 50 }, new String[] { "Black dragons are the strongest dragons", "watch out for their firey breath" }, 1, false, 40 | 80 << 16),
BLOODVELDS(50, new int[] { 1618, 1619, 6215, 7643, 7642 }, new String[] { "Bloodvelds are strange demonic creatures, they use their long rasping tongue", "to feed on just about anything they can find." }, 50, false),
BLUE_DRAGONS(65, new int[] { 55, 4681, 4682, 4683, 4684, 5178, 52, 4665, 4666, }, new String[] { "Blue dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their firey breath." }, 1, false),
BRINE_RATS(45, new int[] { 3707 }, new String[] { "Small little creatures they are, yet so very", "powerfull." }, 47, false),
BRONZE_DRAGONS(75, new int[] { 1590 }, new String[] { "Bronze dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their firey breath." }, 1, false, 30 | 60 << 16),
CATABLEPONS(35, new int[] { 4397, 4398, 4399, }, new String[] { "They use the magic spell Weaken to drain up to 15% of their", "opponent's maximum Strength level." }, 1, false),
CAVE_BUG(1, new int[] { 1832, 5750, }, new String[] { "It regenerates life points quickly and seems to be a good", "herblore monster." }, 7, false),
CAVE_CRAWLERS(10, new int[] { 1600, 1601, 1602, 1603, }, new String[] { "The poisonous parts of them are presumably removed." }, 10, false),
CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "A Cave horror wears a creepy mask, it is", "prefered to wear a witchwood icon." }, 58, false),
CAVE_SLIMES(15, new int[] { 1831 }, new String[] { "These are lesser versions of jellies, watch out they can poison you." }, 17, false),
COCKATRICES(25, new int[] { 1620, 1621, 4227, }, new String[] { "A Mirror shield is necessary when fighting these monsters." }, 25, false),
COWS(5, new int[] { 1766, 1768, 2310, 81, 397, 955, 1767, 3309 }, new String[] { "Cow's may seem stupid, however they know more then", "you think. Don't under estimate them." }, 1, false),
CRAWLING_HAND(1,new int[] { 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 4226, 7640, 7641 }, new String[] { "Crawling Hands are undead severed hands, fast and", "dexterous they claw their victims." }, 5, true),
CROCODILES(50, new int[] { 1993, 6779 }, new String[] { "Crocodiles can be found near water and marshes in and near the Kharidian Desert." }, 1, false),
CYCLOPES(25,new int[] { 116, 4291, 4292, 6078, 6079, 6080, 6081, 6269, 6270 }, new String[] { "Large one eyed creatures who normally wield a", "large mallet." }, 1, false),
DAGANNOTHS(75, new int[] { 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 2454, 2455, 2456, 2881, 2882, 2883, 2887, 2888, 3591, }, new String[] { "There are many types of Dagannoth, the most powerful being the three Dagannoth Kings." }, 1, false),
DARK_BEASTS(90, new int[] { 2783 }, new String[] { "A dark beast can attack using magic or melee." }, 90, false),
DESERT_LIZARDS(15, new int[] { 2803, 2804, 2805, 2806, 2807 }, new String[] { "Desert lizards are big Slayer monsters found in the Kharidian Desert." }, 22, false),
DOG(15, new int[] { 98, 99, 3582, 6374, 1994, 1593, 1594, 3582, 6374 }, new String[] { "Dogs are much like Wolves, they are pack creatures which will hunt in groups." }, 1, false),
DUST_DEVILS(70, new int[] { 1624 }, new String[] { "Dust Devils use clouds of dust, sand, ash and whatever", "else they can inhale to blind and disorientate", "their victims." }, 65, false),
DWARF(6, new int[] { 118, 120, 121, 382, 3219, 3220, 3221, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3294, 3295, 4316, 5880, 5881, 5882, 5883, 5884, 5885, 2130, 2131, 2132, 2133, 3276, 3277, 3278, 3279, 119, 2423 }, new String[] { "They are slightly resistant to Magic attacks, and", "are not recommended for low levels." }, 1, false),
EARTH_WARRIORS(35, new int[] { 124 }, new String[] { "An Earth warrior is a monster made of earth which fights using melee." }, 1, false),
ELVES(70, new int[] { 1183, 1184, 2359, 2360, 2361, 2362, 7438, 7439, 7440, 7441 }, new String[]{"Elves are agile creatures."}, 1, false),
FIRE_GIANTS(65, new int[] { 110, 1582, 1583, 1584, 1585, 1586, 7003, 7004 }, new String[] { "Like other giants, Fire Giants often wield large weapons", "learn to recognise what kind of weapon it is, and act accordingly." }, 1, false),
FLESH_CRAWLERS(15, new int[] { 4389, 4390, 4391 }, new String[] { "Flesh crawlers are medium level monsters found on", "level 2 of the Stronghold of Security." }, 1, false),
GARGOYLES(80, new int[] { 1610, 1611, 6389 }, new String[] { "Gargoyles are winged creatures of stone. You'll need to fight them to", "near death before breaking them apart with a rock hammer." }, 75, false),
GHOSTS(13, new int[] { 103, 104, 491, 1541, 1549, 2716, 2931, 4387, 388, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 1698, 5349, 5350, 5351, 5352, 5369, 5370, 5371, 5372, 5373, 5374, 5572, 6094, 6095, 6096, 6097, 6098, 6504, 13645, 13466, 13467, 13468, 13469, 13470, 13471, 13472, 13473, 13474, 13475, 13476, 13477, 13478, 13479, 13480, 13481 }, new String[] { "A Ghost is an undead monster that is found", "in various places and dungeons. " }, 1, false),
GHOULS(25, new int[] { 1218, 3059 }, new String[] { "Ghouls are a humanoid race and the descendants of a long-dead society", "that degraded to the point that its people ate their dead." }, 1, false),
GOBLINS(1, new int[] { 100, 101, 102, 444, 445, 489, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2678, 2679, 2680, 2681, 3060, 3264, 3265, 3266, 3267, 3413, 3414, 3415, 3726, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4407, 4408, 4409, 4410, 4411, 4412, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4499, 4633, 4634, 4635, 4636, 4637, 5786, 5824, 5855, 5856, 6125, 6126, 6132, 6133, 6279, 6280, 6281, 6282, 6283, 6402, 6403, 6404, 6405, 6406, 6407, 6408, 6409, 6410, 6411, 6412, 6413, 6414, 6415, 6416, 6417, 6418, 6419, 6420, 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6428, 6429, 6430, 6431, 6432, 6433, 6434, 6435, 6436, 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6444, 6445, 6446, 6447, 6448, 6449, 6450, 6451, 6452, 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, 6463, 6464, 6465, 6466, 6467, 6490, 6491, 6492, 6493, 6494, 6495, 6496, 6497 }, new String[] { "Goblins are mostly just annoying, but they can be vicious.", "Watch out for the spears they sometimes carry." }, 1, false),
GORAKS(70, new int[] { 4418, 6218 }, new String[] { "Goraks can be tough monsters to fight. Be prepared." }, 1, false),
GREATER_DEMONS(75, new int[] { 83, 4698, 4699, 4700, 4701, 6204 }, new String[] { "Greater Demons are magic creatures so they are weak to magical attacks.", "They're the strongest demon and very dangerous." }, 1, false),
GREEN_DRAGON(52, new int[] { 941, 4677, 4678, 4679, 4680, 5362 }, new String[] { "Green dragons are very powerfull, they have fierce", "fiery breath." }, 1, false),
HARPIE_BUG_SWARMS(45, new int[] { 3153 }, new String[] { "Harpie Bug Swarms are insectoid Slayer monsters." }, 33, false),
HELLHOUNDS(75, new int[] { 49, 3586, 6210, }, new String[] { "Hellhounds are mid to high level demons." }, 1, false),
HILL_GIANTS(25, new int[] { 117, 4689, 4690, 3058, 4691, 4692, 4693 }, new String[] { "Hill giants can hit up to 19 damage, and they only attack with Melee." }, 1, false),
HOBGOBLINS(20, new int[] { 122, 123, 2685, 2686, 3061, 6608, 6642, 6661, 6684, 6710, 6722, 6727, 2687, 2688, 3583, 4898, 6275 }, new String[] { "Mysterious goblin like creatures." }, 1, false),
ICE_FIENDS(20, new int[] { 3406, 6217, 7714, 7715, 7716 }, new String[] { "An Icefiend is a monster found on top of Ice Mountain." }, 1, false),
ICE_GIANTS(50, new int[] { 111, 3072, 4685, 4686, 4687 }, new String[] { "Ice Giants often wield large weapons, learn to recognise", "what kind of weapon it is, and act accordingly" }, 1, false),
ICE_WARRIOR(45, new int[] { 125, 145, 3073 }, new String[] { "Ice warriors, are cold magestic creatures." }, 1, false),
INFERNAL_MAGES(40, new int[] { 1643, 1644, 1645, 1646, 1647 }, new String[] { "Infernal Mages are dangerous spell users, beware of their magic", "spells an go properly prepared" }, 45, false),
IRON_DRAGONS(80, new int[] { 1591 }, new String[] { "Iron dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their firey breath." }, 1, false, 40 | 59 << 16),
JELLIES(57, new int[] { 1637, 1638, 1639, 1640, 1641, 1642 }, new String[] { "Jellies are nasty cube-like gelatinous creatures which", "absorb everything they come across into themselves." }, 52, false),
JUNGLE_HORRORS(65, new int[] { 4348, 4349, 4350, 4351, 4352 }, new String[] { "Jungle Horrors can be found all over Mos Le'Harmless.", "They are strong and aggressive, so watch out!" }, 1, false),
KALPHITES(15, new int[] { 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161 }, new String[] { "Kalaphite are large insects which live in great hives under the desert sands." }, 1, false),
KURASKS(65, new int[] { 1608, 1609, 4229, 7805, 7797 }, new String[] { "A kurask is a very quick creature." }, 70, false),
LESSER_DEMONS(60, new int[] { 82, 6203, 3064, 4694, 4695, 6206, 3064, 4696, 4697, 6101 }, new String[] { "Lesser Demons are magic creatures so they are weak to magical attacks." }, 1, false),
MITHRIL_DRAGON(60, new int[] { 5363 }, new String[] { "Mithril dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their firey breath." }, 1, false, 5 | 9 << 16),
MINOTAURS(7, new int[] { 4404, 4405, 4406 }, new String[] { "Minotaurs are large manlike creatures but you'll", "want to be careful of their horns." }, 1, false),
MONKEYS(1, new int[] { 132, 1463, 1464, 2301, 4344, 4363, 6943, 7211, 7213, 7215, 7217, 7219, 7221, 7223, 7225, 7227, 1455, 1459, 1460, 1456, 1457, 1458 }, new String[] { "Small agile creatures, watch out they pinch!" }, 1, false),
MOSS_GIANTS(40, new int[] { 112, 1587, 1588, 1681, 4534, 4688, 4706 }, new String[] { "They are known to carry large sticks." }, 1, false),
NECHRYAELS(85, new int[] { 1613 }, new String[] { "Nechryael are demons of decay which summon small winged beings which", "help them fight their victems." }, 80, false),
OGRES(40, new int[] { 115, 374, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 3587, 6267, 7078, 7079, 7080, 7081, 7082 }, new String[] { "Ogres are brutal creatures, favouring large blunt maces and clubs", "they often attack without warning." }, 1, false),
OTHERWORDLY_BEING(40, new int[] { 126 }, new String[] { "A creature filled with everlasting power." }, 1, false),
PYREFIENDS(25, new int[] { 1633, 1634, 1635, 1636, 6216, 6631, 6641, 6660, 6668, 6683, 6709, 6721, }, new String[] { "A scorching hot creature, watch out!" }, 30, false),
RATS(1, new int[] { 2682, 2980, 2981, 3007, 88, 224, 4928, 4929, 4936, 4937, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 4396, 4415, 7202, 7204, 7417, 7461, 87, 446, 950, 4395, 4922, 4923, 4924, 4925, 4926, 4927, 4942, 4943, 4944, 4945, 86, 87, 446, 950, 4395, 4922, 4923, 4924, 4925, 4926, 4927, 4942, 4943, 4944, 4945 }, new String[] { "Quick little rodents!" }, 1, false),
ROCK_SLUGS(20, new int[] { 1631, 1632 }, new String[] { "A rock slug can leave behind a trail of his presence.." }, 20, false),
SCORPIONS(7, new int[] { 107, 1477, 4402, 4403, 144 }, new String[] { "A scorpion makes a piercing sound, watch out for it's", " long sharp tail." }, 1, false),
SHADE(30, new int[] { 3617, 1250, 1241, 1246, 1248, 1250, 428, 1240 }, new String[] { "Shades are dark and mysterious, they hide in the shadows so be wary of ambushes." }, 1, true),
SKELETONS(15, new int[] { 90, 91, 92, 93, 94, 459, 1471, 1575, 1973, 2036, 2037, 2715, 2717, 3065, 3151, 3291, 3581, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3844, 3850, 3851, 4384, 4385, 4386, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5359, 5365, 5366, 5367, 5368, 5381, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5411, 5412, 5422, 6091, 6092, 6093, 6103, 6104, 6105, 6106, 6107, 6764, 6765, 6766, 6767, 6768 }, new String[] { "Skeletons are undead monsters found in various locations." }, 1, true),
SPIDERS(1, new int[] { 61, 1004, 1221, 1473, 1474, 63, 4401, 2034, 977, 7207, 134, 1009, 59, 60, 4400, 58, 62, 1478, 2491, 2492, 6376, 6377, }, new String[] { "Level 24 spiders are aggressive and can hit up to 60 life points." }, 1, false),
SPIRTUAL_MAGES(60, new int[] { 6221, 6231, 6257, 6278 }, new String[] { "They are dangerous, they hit with mage." }, 83, false),
SPIRTUAL_RANGERS(60, new int[] { 6220, 6230, 6256, 6276 }, new String[] { "They are dangerous, they hit with range." }, 63, false),
SPIRTUAL_WARRIORS(60, new int[] { 6219, 6229, 6255, 6277, }, new String[] { "They are dangerous, they hit with melee." }, 68, false),
STEEL_DRAGONS( 85,new int[] { 1592, 3590 }, new String[] { "Steel dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their firey breath." }, 1, false, 10 | 20 << 16),
TROLLS(60, new int[] { 72, 3584, 1098, 1096, 1097, 1095, 1101, 1105, 1102, 1103, 1104, 1130, 1131, 1132, 1133, 1134, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1138, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 3840, 3841, 3842, 3843, 3845, 1933, 1934, }, new String[] { "Trolls have a crushing attack, it's bets to wear a high crushing defence." }, 1, false),
TUROTHS(60, new int[] { 1626, 1627, 1628, 1629, 1630 }, new String[] { "Turoths are Slayer monsters that require a Slayer level of 55 to kill" }, 55, false),
TZHAAR(45, new int[] { 2591, 2592, 2593, 2745, 2594, 2595, 2596, 2597, 2604, 2605, 2606, 2607, 2608, 2609, 7755, 7753, 2598, 2599, 2600, 2601, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2624, 2617, 2618, 2625, 2602, 2603, 7754, 7767, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2624, 2625, 2627, 2628, 2629, 2630, 2631, 2632, 7746, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7754, 7755, 7756, 7757, 7758, 7759, 7760, 7761, 7762, 7763, 7764, 7765, 7766, 7767, 7768, 7769, 7770, 7771, 7747, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7757, 7765, 7769, 7768 }, new String[] { "Young Tzhaar's of the century are furious with your kind." }, 1, false),
VAMPIRES(35, new int[] { 1023, 1220, 1223, 1225, 6214 }, new String[] { "Vampies arr equiped with large fangs", "they can do serious damage." }, 1, false),
WATERFIENDS(75, new int[] { 5361 }, new String[] { "A waterfiend takes no damage from fire!" }, 1, false),
WEREWOLFS(60, new int[] { 1665, 6006, 6007, 6008, 6009, 6010, 6011, 6012, 6013, 6014, 6015, 6016, 6017, 6018, 6019, 6020, 6021, 6022, 6023, 6024, 6025, 6212, 6213, 6607, 6609, 6614, 6617, 6625, 6632, 6644, 6663, 6675, 6686, 6701, 6712, 6724, 6728, }, new String[] { "There temper is alot more nasty then a regular wolf!" }, 1, false),
WOLVES(20, new int[] { 95, 96, 97, 141, 142, 143, 839, 1198, 1330, 1558, 1559, 1951, 1952, 1953, 1954, 1955, 1956, 4413, 4414, 6046, 6047, 6048, 6049, 6050, 6051, 6052, 6829, 6830, 7005 }, new String[] { "Wolves are more agressive then dog's." }, 1, false),
ZOMBIES(10, new int[] { 73, 74, 75, 76, 2058, 2714, 2863, 2866, 2869, 2878, 3622, 4392, 4393, 4394, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5375, 5376, 5377, 5378, 5379, 5380, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 6099, 6100, 6131, }, new String[] { "Zombies are creatures with no brain, they do hit farley", "high though." }, 1, true),
JAD(90, new int[] { }, new String[] { "TzTok-Jad is the king of the Fight Caves." }, 1, false, 1 | 1 << 16),
CHAOS_ELEMENTAL(90, new int[] { 3200 }, new String[] { "The Chaos Elemental is located in the deep Wilderness." }, 1, false, 5 | 25 << 16),
GIANT_MOLE(75, new int[] { 3340 }, new String[] { "Fighting the Giant Mole will require a light source." }, 1, false, 5 | 25 << 16),
KING_BLACK_DRAGON(75, new int[] { 50 }, new String[] { "The King Black Dragon is located in the deep wilderness." }, 1, false, 5 | 25 << 16),
COMMANDER_ZILYANA(90, new int[] { 6247 }, new String[] { "Commander Zilyana is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16),
GENERAL_GRARDOOR(90, new int[] { 6260 }, new String[] { "General Grardoor is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16),
KRIL_TSUTSAROTH(90, new int[] { 6203 }, new String[] { "Kril Tsutsaroth is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16),
KREE_ARRA(90, new int[] { 6222 }, new String[] { "Kree'arra is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16),
SKELETAL_WYVERN(70, new int[] { 3068, 3069, 3070, 3071 }, new String[] { "A skeletal wyvern requires an elemental, mirror", "or dragonfire shield." }, 72, false, 24 | 39 << 16);
static final HashMap<Integer, Tasks> taskMap = new HashMap<>();
static{
Arrays.stream(Tasks.values()).forEach(entry -> Arrays.stream(entry.ids).forEach(id -> taskMap.putIfAbsent(id,entry)));
}
public final int levelReq;
public final int combatCheck;
public final String[] info;
public final int[] ids;
public final boolean undead;
public int amtHash;
Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead){
this.levelReq = levelReq;
this.ids = ids;
this.info = info;
this.undead = undead;
this.combatCheck = combatCheck;
}
Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, int amtHash){
this.levelReq = levelReq;
this.ids = ids;
this.info = info;
this.undead = undead;
this.amtHash = amtHash;
this.combatCheck = combatCheck;
}
public int[] getNpcs(){
return ids;
}
public String[] getTip(){
return info;
}
public static Tasks forId(int id){
return taskMap.get(id);
}
public String getName(){
return NPCDefinition.forId(ids[0]).getName();
}
}
@@ -0,0 +1,58 @@
package content.global.skill.slayer;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.Initializable;
/**
* Handles the turoth npc.
* @author Vexia
*/
@Initializable
public final class TurothNPC extends AbstractNPC {
/**
* Constructs a new {@code TurothNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public TurothNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code TurothNPC} {@code Object}.
*/
public TurothNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new TurothNPC(id, location);
}
@Override
public void checkImpact(final BattleState state) {
super.checkImpact(state);
boolean effective = false;
if (state.getAttacker() instanceof Player) {
final Player player = (Player) state.getAttacker();
effective = SlayerUtils.hasBroadWeaponEquipped(player, state);
}
if (!effective) {
state.setEstimatedHit(0);
if (state.getSecondaryHit() > 0) {
state.setSecondaryHit(0);
}
}
}
@Override
public int[] getIds() {
return new int[] { 1626, 1627, 1628, 1629, 1630 };
}
}
@@ -0,0 +1,58 @@
package content.global.skill.slayer;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.equipment.SwitchAttack;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.impl.Projectile;
import core.game.node.entity.npc.AbstractNPC;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.MultiSwingHandler;
/**
* Handles the water fiend npc.
* @author Vexia
*/
@Initializable
public final class WaterFiendNPC extends AbstractNPC {
/**
* Handles the combat.
*/
private final CombatSwingHandler combatAction = new MultiSwingHandler(true, new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), new Animation(1581, Priority.HIGH), null, null, Projectile.create((Entity) null, null, 500, 15, 30, 50, 50, 14, 255)), new SwitchAttack(CombatStyle.RANGE.getSwingHandler(), new Animation(1581, Priority.HIGH), null, null, Projectile.create((Entity) null, null, 16, 15, 30, 50, 50, 14, 255)));
/**
* Constructs a new {@code WaterFiendNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public WaterFiendNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code WaterFiendNPC} {@code Object}.
*/
public WaterFiendNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new WaterFiendNPC(id, location);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return combatAction;
}
@Override
public int[] getIds() {
return Tasks.WATERFIENDS.getNpcs();
}
}
@@ -0,0 +1,239 @@
package content.global.skill.slayer.dungeon;
import static core.api.ContentAPIKt.*;
import core.cache.def.impl.SceneryDefinition;
import core.game.component.CloseEvent;
import core.game.component.Component;
import core.plugin.Initializable;
import content.global.skill.agility.AgilityHandler;
import core.game.interaction.Option;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.node.scenery.SceneryBuilder;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.game.world.map.zone.ZoneRestriction;
import core.game.world.update.flag.context.Animation;
import core.net.packet.PacketRepository;
import core.net.packet.context.MinimapStateContext;
import core.net.packet.out.MinimapState;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
import core.tools.RandomFunction;
/**
* Handles the ancient cavern.
* @author Vexia
*/
@Initializable
public final class AncientCavern extends MapZone implements Plugin<Object> {
/**
* The loots recieved when rummaging a skeleton.
*/
private static final Item[] LOOTS = new Item[] { new Item(526), new Item(11337), new Item(11341) };
/**
* The skeleton barbarian id.
*/
private static final int[] SKELETONS = new int[] { 6103, 6106 };
/**
* Constructs a new {@code AnicentCavern} {@code Object}.
*/
public AncientCavern() {
super("ancient cavern", true, ZoneRestriction.CANNON);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
ClassScanner.definePlugin(new OptionHandler() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.forId(25274).getHandlers().put("option:dive in", this);
return this;
}
@Override
public boolean handle(final Player player, Node node, String option) {
lock(player, 30);
AgilityHandler.forceWalk(player, -1, player.getLocation(), player.getLocation().transform(0, -6, 0), Animation.create(6723), 10, 0.0, null);
GameWorld.getPulser().submit(new Pulse(1, player) {
int count;
@Override
public boolean pulse() {
switch (++count) {
case 4:
player.getInterfaceManager().openOverlay(new Component(115));
break;
case 7:
player.getAnimator().reset();
player.getInterfaceManager().close();
player.getInterfaceManager().closeOverlay();
player.getProperties().setTeleportLocation(Location.create(1763, 5365, 1));
player.getPacketDispatch().sendMessages("You dive into the swirling maelstorm of the whirlpool.", "You are swirled beneath the water, the darkness and pressure are overwhelming.", "Mystical forces guide you into a cavern below the whirlpool.");
break;
case 8:
unlock(player);
return true;
}
return false;
}
});
return true;
}
@Override
public Location getDestination(Node node, Node n) {
if (node.getLocation().getX() <= 2511) {
return Location.create(2511, 3516, 0);
} else {
return Location.create(2512, 3516, 0);
}
}
});
return this;
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (e instanceof Player) {
Player player = (Player) e;
switch (target.getId()) {
case 25216:
handleLog(player);
return true;
case 25362:
rummageSkeleton(player, (Scenery) target);
return true;
}
}
return super.interact(e, target, option);
}
/**
* Handles the log ride.
* @param player the player.
*/
private void handleLog(final Player player) {
player.removeAttribute("canClose");
player.lock(14);
player.getImpactHandler().setDisabledTicks(14);
GameWorld.getPulser().submit(new Pulse(1) {
int count = 0;
@Override
public boolean pulse() {
switch (count++) {
case 1:
Component c = new Component(115);
c.setCloseEvent(new CloseEvent() {
@Override
public boolean close(Player player, Component c) {
if (player.getAttribute("canClose", false)) {
return true;
}
return false;
}
});
player.getInterfaceManager().open(c);
break;
case 3:
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2));
player.getInterfaceManager().removeTabs(0, 1, 2, 3, 4, 5, 6, 11, 12);
break;
case 13:
player.getProperties().setTeleportLocation(Location.create(2532, 3412, 0));
break;
case 14:
player.setAttribute("canClose", true);
player.unlock();
player.getInterfaceManager().close();
player.getInterfaceManager().closeOverlay();
player.getInterfaceManager().restoreTabs();
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
return true;
}
return false;
}
});
}
/**
* Rummages a skeleton.
* @param player the player.
* @param object the object.
*/
private void rummageSkeleton(Player player, Scenery object) {
final boolean fullInvy = player.getInventory().freeSlots() < 1;
final int random = RandomFunction.random(0, 2);
player.getPacketDispatch().sendMessages("You rummage in the sharp, slimy pile of bones in search of something useful...");
if (random == 0) {
if (!fullInvy) {
player.getInventory().add(LOOTS[RandomFunction.random(LOOTS.length)], player);
player.getPacketDispatch().sendMessage("...you find something and stow it in your pack.");
} else {
player.getPacketDispatch().sendMessage("...you find something, but it drops to the floor.");
}
} else if (random == 1) {
NPC spawn = NPC.create(SKELETONS[RandomFunction.random(SKELETONS.length)], object.getLocation());
spawn.init();
spawn.setRespawn(false);
removeSkeleton(object, spawn);
spawn.getProperties().getCombatPulse().attack(player);
player.getPacketDispatch().sendMessage("...the bones object.");
} else {
player.getPacketDispatch().sendMessage("...but there's nothing remotely valuable.");
}
if (RandomFunction.random(10) < 3) {
player.getImpactHandler().manualHit(player, RandomFunction.random(14), HitsplatType.NORMAL);
}
}
/**
* Removes a skeleton.
* @param object the object.
* @param spawn the spawn.
*/
private void removeSkeleton(final Scenery object, final NPC spawn) {
SceneryBuilder.remove(object);
GameWorld.getPulser().submit(new Pulse(200) {
@Override
public boolean pulse() {
if (spawn != null && spawn.isActive()) {
spawn.clear();
}
SceneryBuilder.add(object);
return true;
}
});
}
@Override
public Object fireEvent(String identifier, Object... args) {
return this;
}
@Override
public void configure() {
register(new ZoneBorders(1723, 5296, 1831, 5394));
}
}
@@ -0,0 +1,112 @@
package content.global.skill.slayer.dungeon;
import core.plugin.Initializable;
import core.game.node.entity.skill.Skills;
import content.global.skill.agility.AgilityHandler;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
import core.game.node.entity.player.Player;
import core.game.node.scenery.Scenery;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.game.world.map.zone.ZoneRestriction;
import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin;
import core.tools.RandomFunction;
/**
* Represents the femennik dungeon zone.
* @author Vexia
*/
@Initializable
public final class FremennikDungeon extends MapZone implements Plugin<Object> {
/**
* Constructs a new {@code FremennikDungeon} {@code Object}.
*/
public FremennikDungeon() {
super("fremennik", true, ZoneRestriction.CANNON);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
return this;
}
@Override
public Object fireEvent(String identifier, Object... args) {
return true;
}
@Override
public boolean interact(Entity entity, Node target, Option option) {
if (entity instanceof Player && target instanceof Scenery) {
final Player player = (Player) entity;
final Scenery object = (Scenery) target;
final Direction dir = Direction.getLogicalDirection(player.getLocation(), object.getLocation());
switch (target.getId()) {
case 9326:// pyrefiend area.
if (player.getSkills().getLevel(Skills.AGILITY) < 81) {
player.getPacketDispatch().sendMessage("You need an Agility level of at least 81 to do this.");
return true;
}
player.lock();
GameWorld.getPulser().submit(new Pulse(1, player) {
int count;
@Override
public boolean pulse() {
switch (++count) {
case 1:
Location start = object.getLocation().transform(dir.getOpposite(), 2);
player.getWalkingQueue().reset();
player.getWalkingQueue().addPath(start.getX(), start.getY());
break;
case 2:
player.faceLocation(object.getLocation());
break;
case 3:
Location end = object.getLocation().transform(dir, 1);
AgilityHandler.forceWalk(player, -1, player.getLocation(), end, Animation.create(1995), 20, 0.0, null);
break;
case 4:
final boolean fail = AgilityHandler.hasFailed(player, 20, 0.1);
if (fail) {
player.getImpactHandler().manualHit(player, RandomFunction.random(6), HitsplatType.NORMAL);
player.getPacketDispatch().sendMessage("You trigger the trap as you jump over it.");
}
player.animate(Animation.create(1603));
player.unlock();
return true;
}
return false;
}
});
return true;
case 9321:
if (player.getSkills().getLevel(Skills.AGILITY) < 62) {
player.getPacketDispatch().sendMessage("You need an Agility level of at least 62 to do this.");
return true;
}
Location end = object.getLocation().transform(dir, 4);
AgilityHandler.walk(player, -1, player.getLocation(), end, Animation.create(156), 10, "You climb your way through the narrow crevice.");
return true;
}
}
return super.interact(entity, target, option);
}
@Override
public void configure() {
register(new ZoneBorders(2671, 9950, 2813, 10054));
}
}
@@ -0,0 +1,181 @@
package content.global.skill.slayer.dungeon;
import content.global.skill.slayer.SlayerEquipmentFlags;
import core.cache.def.impl.NPCDefinition;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
import core.tools.RandomFunction;
import java.util.HashMap;
import java.util.Map;
/**
* Handles the lumbridge dungeon.
* @author Vexia
*/
@Initializable
public final class LumbridgeDungeon extends MapZone implements Plugin<Object> {
/**
* The beast locations to check.
*/
private static final Map<Location, WallBeastNPC> BEASTS = new HashMap<>();
/**
* Constructs a new {@code LumbridgeDungeon} {@code Object}.
*/
public LumbridgeDungeon() {
super("lumbridge swamp dungeon", true);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
ClassScanner.definePlugin(new WallBeastNPC());
return this;
}
/*
* @Override public boolean move(Entity e, Location loc, Location dest) { if
* (!e.getLocks().isMovementLocked() && e instanceof Player) { final
* WallBeastNPC npc = BEASTS.get(e.getLocation()); if (npc != null) {
* e.setDirection(Direction.getLogicalDirection(loc, dest)); return false; }
* } return super.move(e, loc, dest); }
*/
@Override
public void locationUpdate(Entity entity, Location last) {
if (entity instanceof Player) {
final Player player = (Player) entity;
final WallBeastNPC npc = BEASTS.get(last);
if (npc != null && npc.canAttack(player)) {
npc.trigger(player);
}
}
}
/**
* Checks if the player has the helmet.
* @param player the player.
* @return {@code True} if so.
*/
private boolean hasHelmet(final Player player) {
return SlayerEquipmentFlags.hasSpinyHelmet(player);
}
@Override
public boolean interact(Entity e, Node target, Option option) {
return super.interact(e, target, option);
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
@Override
public void configure() {
register(new ZoneBorders(3137, 9534, 3295, 9602));
}
/**
* Handles the wall beast npc.
* @author Vexia
*/
public final class WallBeastNPC extends AbstractNPC {
/**
* Constructs a new {@code WallBeastNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public WallBeastNPC(int id, Location location) {
super(id, location,false);
}
/**
* Constructs a new {@code WallBeastNPC} {@code Object}.
*/
public WallBeastNPC() {
super(7823, null,false);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new WallBeastNPC(id, location);
}
@Override
public void init() {
super.init();
getLocks().lockMovement(Integer.MAX_VALUE);
BEASTS.put(getLocation().transform(Direction.SOUTH, 1), this);
}
@Override
public void handleTickActions() {
super.handleTickActions();
}
/**
* Triggers the beast.
* @param player the player.
*/
public void trigger(final Player player) {
boolean isProtected = hasHelmet(player);
player.face(this);
if (!isProtected) {
animate(NPCDefinition.forId(7823).getCombatAnimation(3));
player.animate(Animation.create(1810));
GameWorld.getPulser().submit(new Pulse(8, player) {
@Override
public boolean pulse() {
getAnimator().reset();
player.getAnimator().reset();
player.getImpactHandler().handleImpact(WallBeastNPC.this, RandomFunction.random(1, 18), CombatStyle.MELEE);
return true;
}
});
return;
} else {
transform(7823);
attack(player);
}
}
@Override
public void finalizeDeath(Entity killer) {
//TODO
}
@Override
public boolean isPoisonImmune() {
return true;
}
@Override
public int[] getIds() {
//return Tasks.WALL_BEASTS.getTask().getNpcs();
int[] empty = {};
return empty;
}
}
}
@@ -0,0 +1,181 @@
package content.global.skill.slayer.dungeon;
import content.global.skill.slayer.SlayerEquipmentFlags;
import core.cache.def.impl.SceneryDefinition;
import core.game.component.Component;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
import core.game.node.entity.player.Player;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
import core.tools.RandomFunction;
import java.util.ArrayList;
import java.util.List;
/**
* Handles the smoke dungeon.
* @author Vexia
*/
@Initializable
public final class SmokeDungeon extends MapZone implements Plugin<Object> {
/**
* The chats to send.
*/
private static final String[] CHATS = new String[] { "*choke*", "*cough*" };
/**
* The players list.
*/
private static final List<Player> PLAYERS = new ArrayList<>(20);
/**
* The tick delay until the next effect.
*/
private static final int DELAY = 20;
/**
* The smoke effect pulse.
*/
private static Pulse pulse = new Pulse(3) {
@Override
public boolean pulse() {
for (Player player : PLAYERS) {
if (player.getInterfaceManager().isOpened() || player.getInterfaceManager().hasChatbox() || player.getLocks().isMovementLocked()) {
continue;
}
if (SmokeDungeon.getDelay(player) < GameWorld.getTicks() && !isProtected(player)) {
effect(player);
}
}
return PLAYERS.isEmpty();
}
};
/**
* Constructs a new {@code SmokeDungeon} {@code Object}
*/
public SmokeDungeon() {
super("zmoke dungeon", true);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ClassScanner.definePlugin(new OptionHandler() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.forId(36002).getHandlers().put("option:climb-down", this);
SceneryDefinition.forId(6439).getHandlers().put("option:climb-up", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
switch (node.getId()) {
case 36002:
player.getProperties().setTeleportLocation(Location.create(3206, 9379, 0));
player.getPacketDispatch().sendMessage("You climb down the well.");
break;
case 6439:
player.getProperties().setTeleportLocation(Location.create(3310, 2963, 0));
player.getPacketDispatch().sendMessage("You climb up the rope.");
break;
}
return true;
}
});
ZoneBuilder.configure(this);
return this;
}
@Override
public boolean enter(Entity e) {
if (e instanceof Player) {
Player p = (Player) e;
setDelay(p);
PLAYERS.add(p);
if (!pulse.isRunning()) {
pulse.restart();
pulse.start();
GameWorld.getPulser().submit(pulse);
}
p.getInterfaceManager().openOverlay(new Component(118));
}
return true;
}
@Override
public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) {
Player p = (Player) e;
p.getInterfaceManager().closeOverlay();
PLAYERS.remove(e);
e.removeAttribute("smoke-delay");
}
return super.leave(e, logout);
}
/**
* Effects the player with smoke.
* @param player the player.
*/
private static void effect(Player player) {
int hit = 2;
setDelay(player);
if (RandomFunction.random(2) == 1) {
player.sendChat(CHATS[RandomFunction.random(CHATS.length)]);
player.getPacketDispatch().sendMessage("The stagnant, smoky air chokes you.");
}
player.getImpactHandler().manualHit(player, hit, HitsplatType.NORMAL);
}
/**
* Sets the delay on the player.
* @param player the player.
*/
private static void setDelay(Player player) {
player.setAttribute("smoke-delay", GameWorld.getTicks() + DELAY);
}
/**
* Gets the smoke delay.
* @param player the player.
* @return the delay.
*/
private static int getDelay(Player player) {
return player.getAttribute("smoke-delay", 0);
}
/**
* Checks if the player is protected.
* @param player the player.
* @return {@code True} if so.
*/
private static boolean isProtected(Player player) {
return SlayerEquipmentFlags.hasFaceMask(player);
}
@Override
public Object fireEvent(String identifier, Object... args) {
return this;
}
@Override
public void configure() {
register(new ZoneBorders(3196, 9337, 3344, 9407));
pulse.stop();
}
}
@@ -0,0 +1,241 @@
/*
package core.game.node.entity.skill.slayer.dungeon;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.skill.gather.SkillingTool;
import core.game.node.entity.skill.slayer.Master;
import org.crandor.game.interaction.Option;
import org.crandor.game.node.Node;
import org.crandor.game.node.entity.Entity;
import org.crandor.game.node.entity.combat.CombatStyle;
import org.crandor.game.node.entity.impl.ForceMovement;
import org.crandor.game.node.entity.npc.NPC;
import org.crandor.game.node.entity.player.Player;
import org.crandor.game.node.object.GameObject;
import org.crandor.game.node.object.ObjectBuilder;
import org.crandor.game.system.task.Pulse;
import org.crandor.game.world.map.Location;
import org.crandor.game.world.map.zone.MapZone;
import org.crandor.game.world.map.zone.ZoneBorders;
import org.crandor.game.world.map.zone.ZoneBuilder;
import org.crandor.game.world.update.flag.context.Animation;
import org.crandor.plugin.InitializablePlugin;
import org.crandor.plugin.Plugin;
*/
/**
* Handles the stronghold slayer cave.
* @author Vexia
* @author Empathy
*
*//*
@InitializablePlugin
public class StrongholdSlayerCave extends MapZone implements Plugin<Object> {
*/
/**
* The step over animation.
*//*
private final Animation stepOver = new Animation(1603);
*/
/**
* The climb animation.
*//*
private final Animation climb = new Animation(3063);
*/
/**
* Constructs a new @{Code StrongholdSlayerCave} object.
*//*
public StrongholdSlayerCave() {
super("Slayer stronghold zone", true);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
return this;
}
@Override
public boolean interact(Entity e, final Node node, Option option) {
int id = node.getId();
final Player player = e.asPlayer();
switch (option.getName().toLowerCase()) {
case "attack":
if (player.isAdmin()) {
player.attack(node);
return true;
}
attack: {
if (SlayerManager.getInstance(player).getMaster() == Master.NIEVE) {
for (int i : SlayerManager.getInstance(player).getTask().getNpcs()) {
if (i != id) {
continue;
}
player.attack(node);
break attack;
}
}
player.face(node.asNpc());
player.getDialogueInterpreter().sendDialogues(Master.NIEVE.getNpc(), FacialExpression.OLD_NORMAL, "That's not your assigned Slayer target. In my cave,", "I expect people to focus on their Slayer training.");
}
return true;
case "enter":
switch (id){
case 44131://stronghold entrance
player.teleport(Location.create(2444, 9825, 0));
break;
case 42284://kraken entrance
player.teleport(Location.create(3696, 5798, 0));
break;
}
return true;
case "use":
switch (id) {
case 42287:
player.teleport(Location.create(2430, 3424, 0));
break;
case 42340:
player.teleport(Location.create(2486, 9797, 0));
break;
}
return true;
case "chop":
final GameObject object = node.asObject();
SkillingTool axe = SkillingTool.getHatchet(player);
if (axe == null) {
player.sendMessage("You need an axe to chop through this.");
return true;
}
player.animate(axe.getAnimation());
player.getPulseManager().run(new Pulse(3, player) {
@Override
public boolean pulse() {
if (ObjectBuilder.replace(object, object.transform(0), 2)) {
Location destination = getRootLocation(player, object);
player.lock(3);
player.getWalkingQueue().reset();
player.getWalkingQueue().addPath(destination.getX(), destination.getY(), true);
return true;
}
return true;
}
});
return true;
case "climb":
final GameObject mud = node.asObject();
final Location rightPile = Location.create(2427, 9763, 0);
final Location leftPile = Location.create(2427, 9766, 0);
if (id == 42311) {
if (player.getSkills().getLevel(Skills.AGILITY) < 72) {
player.sendMessage("You need an Agility level of at least 72 to negotiate this obstacle.");
return true;
}
final boolean northPile = mud.getLocation().equals(leftPile);
ForceMovement.run(player, player.getLocation(), northPile ? leftPile : rightPile, climb);
player.getPulseManager().run(new Pulse(1, player) {
int count;
@Override
public boolean pulse() {
count++;
if (count == 6) {
player.teleport(Location.create(2427, northPile ? 9762 : 9767, 0));
return true;
}
if (count == 3) {
player.teleport(northPile ? rightPile : leftPile);
player.faceLocation(northPile ? leftPile : rightPile);
return false;
}
return false;
}
});
}
return true;
case "step-over":
final GameObject root = node.asObject();
final Location destination = getRootLocation(player, root);
player.getPulseManager().run(new Pulse(1, player) {
@Override
public boolean pulse() {
ForceMovement.run(player, player.getLocation(), destination, stepOver);
return true;
}
});
return true;
}
return super.interact(e, node, option);
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
@Override
public void configure() {
register(new ZoneBorders(2244, 9730, 2506, 9845));
registerRegion(14682);
registerRegion(9525);
registerRegion(14939);
}
@Override
public boolean continueAttack(Entity e, Node target, CombatStyle style, boolean message) {
if (!e.isPlayer() || !(target instanceof NPC)) {
return super.continueAttack(e, target, style, message);
}
Player player = e.asPlayer();
if (player.isAdmin()) {
return super.continueAttack(player, target, style, message);
}
int id = target.getId();
if (SlayerManager.getInstance(player).getMaster() == Master.NIEVE) {
for (int i : SlayerManager.getInstance(player).getTask().getNpcs()) {
if (i != id) {
continue;
}
return super.continueAttack(player, target, style, message);
}
}
player.face(target.asNpc());
player.getDialogueInterpreter().sendDialogues(Master.NIEVE.getNpc(), FacialExpression.OLD_NORMAL, "That's not your assigned Slayer target. In my cave,", "I expect people to focus on their Slayer training.");
return false;
}
*/
/**
* Gets the location for the player to move to.
* @param player The player.
* @param object The object.
*//*
private Location getRootLocation(Player player, GameObject object) {
Location obj = object.getLocation();
Location play = player.getLocation();
if (obj.getY() == play.getY()) {
int newX = (play.getX() - obj.getX() > 0 ? obj.getX() - 1 : obj.getX() + 1);
return Location.create(newX, play.getY(), play.getZ());
}
int newY = (play.getY() - obj.getY() > 0 ? obj.getY() - 1 : obj.getY() + 1);
return Location.create(play.getX(), newY, play.getZ());
}
}
*/
@@ -0,0 +1,92 @@
/*WALL_BEASTS(new Task(new int[] { 7823 }, new String[] { "A spiny helmet or equivalent is required to start fighting one " }, 35, new Master[] { Master.MAZCHNA }, false, Equipment.SPINY_HELMET) {
@Override
public boolean isDisabled() {
return true;
}
}),
WARPED_TERRORBIRDS(new Task(new int[] { 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6322, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, }, new String[] { "They require 56 Slayer and a Crystal chime to be killed. " }, 56, new Master[] { Master.DURADEL }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),
WARPED_TORTOISES(new Task(new int[] { 6296, 6297 }, new String[] { "A warped tortoise is not as slow as they look." }, 56, new Master[] { Master.DURADEL }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*CERBERUS(new Task(new int[] {8632, 8634}, new String[] {"Cerberus is about the best guard dog there is!"}, 91, new Master[] {Master.VANNAKA, Master.CHAELDAR, Master.NIEVE, Master.DURADEL}, false, 20 | 25 << 16) {
@Override
public boolean isDisabled() {
return true;
}
})*/
/*ZYGOMITES(new Task(new int[] { 3346, 3347 }, new String[] { "Mutated zygomites are monsters that appear as Fungi until provoked." }, 57, new Master[] { Master.CHAELDAR }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*SUQAHS(new Task(new int[] { 4527, 4528, 4529, 4530, 4531, 4532, 4533 }, new String[] {}, 1, new Master[] { Master.DURADEL }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),
TERROR_DOG(new Task(new int[] { 5417, 5418 }, new String[] { "Terror Dogs are much like Wolves, they are pack creatures which will hunt in groups." }, 1, new Master[] { Master.VANNAKA, Master.DURADEL }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*SHADOW_WARRIORS(new Task(new int[] { 158 }, new String[] { "Shadow warriors are dark and mysterious, they hide in the shadows so be wary of ambushes." }, 1, new Master[] { Master.VANNAKA, Master.CHAELDAR }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
//MOGRES(new Task(new int[] { 114 }, new String[] { "Mogres are Slayer monsters and require level 32 Slayer to kill. " }, 32, new Master[] { Master.MAZCHNA, Master.VANNAKA }, false)),
/*MOLANISKS(new Task(new int[] { 5751 }, new String[] { "Molanisks are found attached to cave walls and must be lured", "off with a Slayer bell" }, 39, new Master[] { Master.VANNAKA }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*RED_DRAGONS(new Task(new int[] { 53, 4669, 4670, 4671, 4672, 1589, 3588, 4667, 4668, }, new String[] { "Red dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their firey breath." }, 1, new Master[] { Master.DURADEL }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*SCABARITES(new Task(new int[] { 2009 }, new String[] { "The Scabarites are fairly strong monsters, and can hit pretty hard." }, 1, new Master[] { Master.CHAELDAR }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*SEA_SNAKES(new Task(new int[] { 3943, 3939, }, new String[] { "They are quick, make sure you don't let your", "eye off of them for 1 second." }, 1, new Master[] { Master.VANNAKA }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*ELVES(new Task(new int[] { 1184, 1183, 1185 }, new String[] { "Elves are quick, agile and vicious fighters which", "often favour bows and polearms." }, 1, new Master[] { Master.VANNAKA, Master.CHAELDAR, Master.NIEVE }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),
FEVER_SPIDERS(new Task(new int[] { 2850 }, new String[] { "Fever Spiders are giant spiders that carry the deadly Spider Fever.", "If you don't want to catch it I suggest you wear Slayer Gloves to fight them." }, 1, new Master[] { Master.CHAELDAR, Master.DURADEL }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/
/*KILLERWATTS(new Task(new int[] { 3201, 3202 }, new String[] { "Vexia halfassed this... (this was shadow knight text)" }, 37, new Master[] { Master.VANNAKA }, false) {
@Override
public boolean isDisabled() {
return true;
}
}),*/