From e84192d985a23ec02a3bccbf054e3be9a95b678d Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Fri, 25 Aug 2023 09:28:30 +0000 Subject: [PATCH] Implemented special attacks for Morrigan's throwing axes and javelins --- .../special/HamstringSpecialHandler.java | 70 ++++++++++++++++ .../special/PhantomStrikeSpecialHandler.java | 82 +++++++++++++++++++ .../game/node/entity/impl/WalkingQueue.java | 3 + 3 files changed, 155 insertions(+) create mode 100644 Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java create mode 100644 Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java diff --git a/Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java new file mode 100644 index 000000000..fefffaabd --- /dev/null +++ b/Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java @@ -0,0 +1,70 @@ +package content.global.handlers.item.equipment.special; + +import core.api.ContentAPIKt; +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.ImpactHandler; +import core.game.node.entity.combat.RangeSwingHandler; +import core.game.node.entity.player.Player; +import core.game.system.timer.RSTimer; +import core.game.system.timer.TimerFlag; +import core.plugin.Initializable; +import core.plugin.Plugin; +import core.tools.RandomFunction; +import org.rs09.consts.Items; + +@Initializable +public final class HamstringSpecialHandler extends RangeSwingHandler implements Plugin { + private static final int SPECIAL_ENERGY = 50; + + @Override + public Object fireEvent(String identifier, Object... args) { + return null; + } + + @Override + public Plugin newInstance(Object arg) throws Throwable { + CombatStyle.RANGE.getSwingHandler().register(Items.MORRIGANS_THROWING_AXE_13883, this); + return this; + } + + @Override + public int swing(Entity entity, Entity victim, BattleState state) { + Player p = (Player) entity; + configureRangeData(p, state); + if (state.getWeapon() == null || !Companion.hasAmmo(entity, state)) { + entity.getProperties().getCombatPulse().stop(); + p.getSettings().toggleSpecialBar(); + return -1; + } + if (!((Player) entity).getSettings().drainSpecial(SPECIAL_ENERGY)) { + return -1; + } + state.setStyle(CombatStyle.RANGE); + int max = calculateHit(entity, victim, 1.2); + state.setMaximumHit(max); + int hit = 0; + if (isAccurateImpact(entity, victim)) { + hit = RandomFunction.random(max); + } + state.setEstimatedHit(hit); + Companion.useAmmo(entity, state, victim.getLocation()); + ContentAPIKt.registerTimer(victim, new RSTimer(100, "hamstrung", true, false, new TimerFlag[] { TimerFlag.ClearOnDeath } ) { + @Override + public void onRegister(Entity entity) { + if(entity instanceof Player) { + ((Player)entity).sendMessage("You've been hamstrung! For the next minute, your run energy will drain 4x faster."); + } + } + + @Override + public boolean run(Entity entity) { + return false; + } + + }); + return 1 + (int) Math.ceil(entity.getLocation().getDistance(victim.getLocation()) * 0.3); + } +} + diff --git a/Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java new file mode 100644 index 000000000..18af20d24 --- /dev/null +++ b/Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java @@ -0,0 +1,82 @@ +package content.global.handlers.item.equipment.special; + +import core.api.ContentAPIKt; +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.ImpactHandler; +import core.game.node.entity.combat.RangeSwingHandler; +import core.game.node.entity.player.Player; +import core.game.system.timer.RSTimer; +import core.game.system.timer.TimerFlag; +import core.plugin.Initializable; +import core.plugin.Plugin; +import core.tools.RandomFunction; +import org.rs09.consts.Items; + +@Initializable +public final class PhantomStrikeSpecialHandler extends RangeSwingHandler implements Plugin { + private static final int SPECIAL_ENERGY = 50; + + @Override + public Object fireEvent(String identifier, Object... args) { + return null; + } + + @Override + public Plugin newInstance(Object arg) throws Throwable { + CombatStyle.RANGE.getSwingHandler().register(Items.MORRIGANS_JAVELIN_13879, this); + CombatStyle.RANGE.getSwingHandler().register(Items.MORRIGANS_JAVELINP_13880, this); + CombatStyle.RANGE.getSwingHandler().register(Items.MORRIGANS_JAVELINP_PLUS_13881, this); + CombatStyle.RANGE.getSwingHandler().register(Items.MORRIGANS_JAVELINP_PLUS_PLUS_13882, this); + return this; + } + + @Override + public int swing(Entity entity, Entity victim, BattleState state) { + Player p = (Player) entity; + configureRangeData(p, state); + if (state.getWeapon() == null || !Companion.hasAmmo(entity, state)) { + entity.getProperties().getCombatPulse().stop(); + p.getSettings().toggleSpecialBar(); + return -1; + } + if (!((Player) entity).getSettings().drainSpecial(SPECIAL_ENERGY)) { + return -1; + } + state.setStyle(CombatStyle.RANGE); + int max = calculateHit(entity, victim, 1.0); + state.setMaximumHit(max); + int hit = 0; + if (isAccurateImpact(entity, victim)) { + hit = RandomFunction.random(max); + } + state.setEstimatedHit(hit); + Companion.useAmmo(entity, state, victim.getLocation()); + final Entity attacker = entity; + final int initialDamage = hit; + ContentAPIKt.registerTimer(victim, new RSTimer(3, "phantom-strike", true, false, new TimerFlag[] { TimerFlag.ClearOnDeath } ) { + int remainingDamage = initialDamage; + + @Override + public void onRegister(Entity entity) { + if(entity instanceof Player) { + ((Player)entity).sendMessage("You start to bleed as the result of the javelin strike."); + } + } + + @Override + public boolean run(Entity entity) { + if(entity instanceof Player) { + ((Player)entity).sendMessage("You continue to bleed as the result of the javelin strike."); + } + int tickDamage = Math.min(remainingDamage, 5); + remainingDamage -= tickDamage; + entity.getImpactHandler().manualHit(attacker, tickDamage, ImpactHandler.HitsplatType.NORMAL); + return remainingDamage > 0; + } + + }); + return 1 + (int) Math.ceil(entity.getLocation().getDistance(victim.getLocation()) * 0.3); + } +} diff --git a/Server/src/main/core/game/node/entity/impl/WalkingQueue.java b/Server/src/main/core/game/node/entity/impl/WalkingQueue.java index eaf9604dc..fbd9d2e36 100644 --- a/Server/src/main/core/game/node/entity/impl/WalkingQueue.java +++ b/Server/src/main/core/game/node/entity/impl/WalkingQueue.java @@ -190,6 +190,9 @@ public final class WalkingQueue { if (player.getSettings().getWeight() > 0.0) { rate *= 1 + (player.getSettings().getWeight() / 100); } + if (hasTimerActive(player, "hamstrung")) { + rate *= 4; + } return rate; }