From ac884839787fc40e64dee9bc5fa8ee95dd3f9fb9 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Fri, 10 Sep 2021 01:52:49 +0000 Subject: [PATCH] Improve mechanics relating to Tormented Demons. --- .../java/core/game/node/entity/Entity.java | 4 +-- .../entity/npc/bosses/TormentedDemonNPC.java | 26 ++++++++++++++----- .../npc/bosses/corp/CorporealBeastNPC.java | 6 ++--- .../node/entity/combat/CombatSwingHandler.kt | 14 ++++++++-- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/Server/src/main/java/core/game/node/entity/Entity.java b/Server/src/main/java/core/game/node/entity/Entity.java index 8d2046eba..4c4045b3e 100644 --- a/Server/src/main/java/core/game/node/entity/Entity.java +++ b/Server/src/main/java/core/game/node/entity/Entity.java @@ -507,7 +507,7 @@ public abstract class Entity extends Node { * @param hit the hit. * @return {@code True} if so. */ - public double getFormatedHit(BattleState state, int hit) { + public double getFormattedHit(BattleState state, int hit) { if (state.getAttacker() == null || state.getVictim() == null || state.getStyle() == null) { return hit; } @@ -863,4 +863,4 @@ public abstract class Entity extends Node { this.invisible = invisible; } -} \ No newline at end of file +} diff --git a/Server/src/main/java/core/game/node/entity/npc/bosses/TormentedDemonNPC.java b/Server/src/main/java/core/game/node/entity/npc/bosses/TormentedDemonNPC.java index df824b3e7..0273d6559 100644 --- a/Server/src/main/java/core/game/node/entity/npc/bosses/TormentedDemonNPC.java +++ b/Server/src/main/java/core/game/node/entity/npc/bosses/TormentedDemonNPC.java @@ -115,23 +115,37 @@ public class TormentedDemonNPC extends AbstractNPC { @Override public void checkImpact(BattleState state) { - if (fireShield && state.getAttacker().isPlayer() && state.getEstimatedHit() > 0 && state.getWeapon() != null && (state.getWeapon().getId() == 6746 || state.getWeapon().getId() == 732)) { + // Use the formatted hit to ensure protection prayers are applied (i.e. can't darklight while the demon is praying melee). + int formattedHit = (int) state.getAttacker().getFormattedHit(state, state.getEstimatedHit()); + if (state.getAttacker().isPlayer() && formattedHit > 0 && state.getWeapon() != null && (state.getWeapon().getId() == 6746 || state.getWeapon().getId() == 732)) { + // The message doesn't get sent twice, but additional darklight strikes while the shield is down do delay the shield's return. + if(fireShield) { + state.getAttacker().asPlayer().sendMessage("The demon is temporarily weakened by your weapon."); + } shieldDelay = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(60); fireShield = false; setAttribute("shield-player", state.getAttacker()); - state.getAttacker().asPlayer().sendMessage("The demon is temporarily weakened by your weapon."); } if (fireShield) { - state.setEstimatedHit((int) (state.getEstimatedHit() * 0.75)); + state.setEstimatedHit((int) (state.getEstimatedHit() * 0.25)); graphics(Graphics.create(1885)); } if (state.getStyle() == null) { return; } - int hit = state.getEstimatedHit() > 0 ? state.getEstimatedHit() : 1; + // Use formattedHit for the prayer swap calculation since it's before the fire + // shield reduction was applied (a ranged hit of 8 through the shield corresponds to a + // pre-shield hit of 32, which should cause the demon to switch to praying range). + int hit = formattedHit > 0 ? formattedHit : 1; damageLog[state.getStyle().ordinal()] = damageLog[state.getStyle().ordinal()] + hit; + } + + @Override + public void onImpact(final Entity entity, BattleState state) { + // "The demon will switch prayers after it receives 31 damage from one attack style." + // This is done in onImpact so that it happens after the damage that caused the switch is dealt. CombatStyle damaged = getMostDamagedStyle(); - if (damaged != null && damageLog[damaged.ordinal()] > 30 + hit && damaged != getProperties().getProtectStyle()) { + if (damaged != null && damageLog[damaged.ordinal()] >= 31 && damaged != getProperties().getProtectStyle()) { for (int i = 0; i < 3; i++) { damageLog[i] = 0; } @@ -141,7 +155,7 @@ public class TormentedDemonNPC extends AbstractNPC { transformDemon(RandomFunction.getRandomElement(getAlternateStyle(TD_SWING_HANDLER.style)), null); lastSwitch = System.currentTimeMillis() + 15000; } - } + } @Override public void finalizeDeath(Entity killer) { diff --git a/Server/src/main/java/core/game/node/entity/npc/bosses/corp/CorporealBeastNPC.java b/Server/src/main/java/core/game/node/entity/npc/bosses/corp/CorporealBeastNPC.java index c9ab3a858..cdb03ce13 100644 --- a/Server/src/main/java/core/game/node/entity/npc/bosses/corp/CorporealBeastNPC.java +++ b/Server/src/main/java/core/game/node/entity/npc/bosses/corp/CorporealBeastNPC.java @@ -99,11 +99,11 @@ public final class CorporealBeastNPC extends AbstractNPC { } @Override - public double getFormatedHit(BattleState state, int hit) { + public double getFormattedHit(BattleState state, int hit) { if (hit > 100) { hit = 100; } - return super.getFormatedHit(state, hit); + return super.getFormattedHit(state, hit); } @Override @@ -312,7 +312,7 @@ public final class CorporealBeastNPC extends AbstractNPC { @Override protected int getFormattedHit(Entity entity, Entity victim, BattleState state, int hit) { if (getCurrent().getProjectile() == null || getCurrent().getProjectile().getProjectileId() != 1825) { - hit = (int) entity.getFormatedHit(state, hit); + hit = (int) entity.getFormattedHit(state, hit); } return formatHit(victim, hit); } diff --git a/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt b/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt index 451b37126..c23a1505c 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt @@ -370,6 +370,16 @@ abstract class CombatSwingHandler(var type: CombatStyle?) { if (victim.id == 757) { EXPERIENCE_MOD = 0.01 } + // Recursively adjustBattleState targets so that multi-target attacks have protection prayers applied. + if (state.targets != null && state.targets.isNotEmpty()) { + if (!(state.targets.size == 1 && state.targets[0] == state)) { + for (s in state.targets) { + if (s != null && s != state) { + adjustBattleState(entity, victim, s); + } + } + } + } if (state.estimatedHit > 0) { state.estimatedHit = getFormattedHit(entity, victim, state, state.estimatedHit) totalHit += state.estimatedHit @@ -412,7 +422,7 @@ abstract class CombatSwingHandler(var type: CombatStyle?) { */ protected open fun getFormattedHit(attacker: Entity, victim: Entity, state: BattleState, rawHit: Int): Int { var hit = rawHit - hit = attacker.getFormatedHit(state, hit).toInt() + hit = attacker.getFormattedHit(state, hit).toInt() if (victim is Player) { val player = victim.asPlayer() val shield = player.equipment[EquipmentContainer.SLOT_SHIELD] @@ -523,4 +533,4 @@ abstract class CombatSwingHandler(var type: CombatStyle?) { } } -} \ No newline at end of file +}