Unified dragonfire protection logic

Fixed KBD's attack range resulting in only certain spots allowing him to melee
This commit is contained in:
Ceikry
2023-04-18 08:44:03 +00:00
committed by Ryan
parent 4ded3b90de
commit cb92ad0577
5 changed files with 673 additions and 660 deletions
@@ -17,205 +17,193 @@ import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.tools.RandomFunction;
import static core.api.ContentAPIKt.calculateDragonfireMaxHit;
/**
* Handles dragonfire combat.
* @author Emperor
*/
public class DragonfireSwingHandler extends CombatSwingHandler {
/**
* If the NPC has to be in melee range.
*/
private boolean meleeRange;
/**
* If the NPC has to be in melee range.
*/
private boolean meleeRange;
/**
* The maximum hit.
*/
private int maximumHit;
/**
* The maximum hit.
*/
private int maximumHit;
/**
* The attack data.
*/
private SwitchAttack attack;
/**
* The attack data.
*/
private SwitchAttack attack;
/**
* IF the dragon attack is firey or icey.
*/
private boolean fire;
/**
* IF the dragon attack is firey or icey.
*/
private boolean fire;
/**
* Constructs a new {@code DragonfireSwingHandler} {@code Object}.
* @param meleeRange If the NPC has to be in melee range.
* @param maximumHit The maximum hit.
* @param fire if firey.
*/
public DragonfireSwingHandler(boolean meleeRange, int maximumHit, SwitchAttack attack, boolean fire) {
super(CombatStyle.MAGIC);
this.meleeRange = meleeRange;
this.maximumHit = maximumHit;
this.attack = attack;
this.fire = fire;
}
/**
* Constructs a new {@code DragonfireSwingHandler} {@code Object}.
* @param meleeRange If the NPC has to be in melee range.
* @param maximumHit The maximum hit.
* @param fire if firey.
*/
public DragonfireSwingHandler(boolean meleeRange, int maximumHit, SwitchAttack attack, boolean fire) {
super(CombatStyle.MAGIC);
this.meleeRange = meleeRange;
this.maximumHit = maximumHit;
this.attack = attack;
this.fire = fire;
}
/**
* Gets the switch attack instance for a dragonfire attack.
* @param meleeRange If the attack is melee range.
* @param maximumHit The maximum hit.
* @param animation The animation.
* @param startGraphic The start graphic.
* @param endGraphic The end graphic.
* @param projectile The projectile.
* @return The switch attack instance.
*/
public static SwitchAttack get(boolean meleeRange, int maximumHit, Animation animation, Graphics startGraphic, Graphics endGraphic, Projectile projectile) {
SwitchAttack attack = new SwitchAttack(null, animation, startGraphic, endGraphic, projectile).setUseHandler(true);
attack.setHandler(new DragonfireSwingHandler(meleeRange, maximumHit, attack, true));
return attack;
}
/**
* Gets the switch attack instance for a dragonfire attack.
* @param meleeRange If the attack is melee range.
* @param maximumHit The maximum hit.
* @param animation The animation.
* @param startGraphic The start graphic.
* @param endGraphic The end graphic.
* @param projectile The projectile.
* @return The switch attack instance.
*/
public static SwitchAttack get(boolean meleeRange, int maximumHit, Animation animation, Graphics startGraphic, Graphics endGraphic, Projectile projectile) {
SwitchAttack attack = new SwitchAttack(null, animation, startGraphic, endGraphic, projectile).setUseHandler(true);
attack.setHandler(new DragonfireSwingHandler(meleeRange, maximumHit, attack, true));
return attack;
}
/**
* Gets the switch attack instance for a dragonfire attack.
* @param meleeRange If the attack is melee range.
* @param maximumHit The maximum hit.
* @param animation The animation.
* @param startGraphic The start graphic.
* @param endGraphic The end graphic.
* @param projectile The projectile.
* @return The switch attack instance.
*/
public static SwitchAttack get(boolean meleeRange, int maximumHit, Animation animation, Graphics startGraphic, Graphics endGraphic, Projectile projectile, boolean fire) {
SwitchAttack attack = new SwitchAttack(null, animation, startGraphic, endGraphic, projectile).setUseHandler(true);
attack.setHandler(new DragonfireSwingHandler(meleeRange, maximumHit, attack, fire));
return attack;
}
/**
* Gets the switch attack instance for a dragonfire attack.
* @param meleeRange If the attack is melee range.
* @param maximumHit The maximum hit.
* @param animation The animation.
* @param startGraphic The start graphic.
* @param endGraphic The end graphic.
* @param projectile The projectile.
* @return The switch attack instance.
*/
public static SwitchAttack get(boolean meleeRange, int maximumHit, Animation animation, Graphics startGraphic, Graphics endGraphic, Projectile projectile, boolean fire) {
SwitchAttack attack = new SwitchAttack(null, animation, startGraphic, endGraphic, projectile).setUseHandler(true);
attack.setHandler(new DragonfireSwingHandler(meleeRange, maximumHit, attack, fire));
return attack;
}
@Override
public InteractionType canSwing(Entity entity, Entity victim) {
if (meleeRange) {
return CombatStyle.MELEE.getSwingHandler().canSwing(entity, victim);
}
return CombatStyle.MAGIC.getSwingHandler().canSwing(entity, victim);
}
@Override
public InteractionType canSwing(Entity entity, Entity victim) {
if (meleeRange) {
return CombatStyle.MELEE.getSwingHandler().canSwing(entity, victim);
}
return CombatStyle.MAGIC.getSwingHandler().canSwing(entity, victim);
}
@Override
public int swing(Entity entity, Entity victim, BattleState state) {
int max = calculateHit(entity, victim, 1.0);
int hit = RandomFunction.random(max);
assert state != null;
state.setMaximumHit(max);
state.setStyle(CombatStyle.MAGIC);
state.setEstimatedHit(hit);
if (meleeRange) {
return 1;
}
int ticks = 2 + (int) Math.floor(entity.getLocation().getDistance(victim.getLocation()) * 0.5);
entity.setAttribute("fireBreath", GameWorld.getTicks() + (ticks + 2));
return ticks;
}
@Override
public int swing(Entity entity, Entity victim, BattleState state) {
int max = calculateHit(entity, victim, 1.0);
int hit = RandomFunction.random(max + 1);
assert state != null;
state.setMaximumHit(max);
state.setStyle(CombatStyle.MAGIC);
state.setEstimatedHit(hit);
if (meleeRange) {
return 1;
}
int ticks = 2 + (int) Math.floor(entity.getLocation().getDistance(victim.getLocation()) * 0.5);
entity.setAttribute("fireBreath", GameWorld.getTicks() + (ticks + 2));
return ticks;
}
@Override
public void visualize(Entity entity, Entity victim, BattleState state) {
entity.visualize(attack.getAnimation(), attack.getStartGraphic());
if (attack.getProjectile() != null) {
attack.getProjectile().copy(entity, victim, 5).send();
}
}
@Override
public void visualize(Entity entity, Entity victim, BattleState state) {
entity.visualize(attack.getAnimation(), attack.getStartGraphic());
if (attack.getProjectile() != null) {
attack.getProjectile().copy(entity, victim, 5).send();
}
}
@Override
public void visualizeImpact(Entity entity, Entity victim, BattleState state) {
if (entity instanceof NPC && victim instanceof Player) {
Player p = (Player) victim;
p.getPacketDispatch().sendMessage(getDragonfireMessage(victim.getAttribute("fire_resistance", 0), !fire ? "icy breath" : "fiery breath"));
Item shield = p.getEquipment().get(EquipmentContainer.SLOT_SHIELD);
if (shield != null && (shield.getId() == 11283 || shield.getId() == 11284)) {
if (shield.getId() == 11284) {
p.getEquipment().replace(new Item(11283), EquipmentContainer.SLOT_SHIELD);
shield = p.getEquipment().get(EquipmentContainer.SLOT_SHIELD);
shield.setCharge(0);
}
if (shield.getCharge() < 1000) {
shield.setCharge(shield.getCharge() + 20);
EquipmentContainer.updateBonuses(p);
p.getPacketDispatch().sendMessage("Your dragonfire shield glows more brightly.");
@Override
public void visualizeImpact(Entity entity, Entity victim, BattleState state) {
if (entity instanceof NPC && victim instanceof Player) {
Player p = (Player) victim;
Item shield = p.getEquipment().get(EquipmentContainer.SLOT_SHIELD);
if (shield != null && (shield.getId() == 11283 || shield.getId() == 11284)) {
if (shield.getId() == 11284) {
p.getEquipment().replace(new Item(11283), EquipmentContainer.SLOT_SHIELD);
shield = p.getEquipment().get(EquipmentContainer.SLOT_SHIELD);
shield.setCharge(0);
}
if (shield.getCharge() < 1000) {
shield.setCharge(shield.getCharge() + 20);
EquipmentContainer.updateBonuses(p);
p.getPacketDispatch().sendMessage("Your dragonfire shield glows more brightly.");
p.faceLocation(entity.getCenterLocation());
victim.visualize(Animation.create(6695), Graphics.create(1163));
} else {
p.getPacketDispatch().sendMessage("Your dragonfire shield is already fully charged.");
}
return;
}
}
if (!fire && victim.getAttribute("freeze_immunity", -1) < GameWorld.getTicks() && RandomFunction.random(4) == 2) {
victim.getStateManager().set(EntityState.FROZEN, 16);
victim.graphics(Graphics.create(502));
}
Graphics graphic = attack != null ? attack.getEndGraphic() : null;
victim.visualize(victim.getProperties().getDefenceAnimation(), graphic);
}
p.faceLocation(entity.getCenterLocation());
victim.visualize(Animation.create(6695), Graphics.create(1163));
} else {
p.getPacketDispatch().sendMessage("Your dragonfire shield is already fully charged.");
}
return;
}
}
if (!fire && victim.getAttribute("freeze_immunity", -1) < GameWorld.getTicks() && RandomFunction.random(4) == 2) {
victim.getStateManager().set(EntityState.FROZEN, 16);
victim.graphics(Graphics.create(502));
}
Graphics graphic = attack != null ? attack.getEndGraphic() : null;
victim.visualize(victim.getProperties().getDefenceAnimation(), graphic);
}
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
assert state != null;
int hit = state.getEstimatedHit();
if (hit > -1) {
victim.getImpactHandler().handleImpact(entity, hit, CombatStyle.MAGIC, state);
}
hit = state.getSecondaryHit();
if (hit > -1) {
victim.getImpactHandler().handleImpact(entity, hit, CombatStyle.MAGIC, state);
}
}
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
assert state != null;
int hit = state.getEstimatedHit();
if (hit > -1) {
victim.getImpactHandler().handleImpact(entity, hit, CombatStyle.MAGIC, state);
}
hit = state.getSecondaryHit();
if (hit > -1) {
victim.getImpactHandler().handleImpact(entity, hit, CombatStyle.MAGIC, state);
}
}
@Override
public void adjustBattleState(Entity entity, Entity victim, BattleState state) {
if (victim.isPlayer() && !fire) {
Item item = victim.asPlayer().getEquipment().get(EquipmentContainer.SLOT_SHIELD);
if (item != null && (item.getId() == 2890 || item.getId() == 9731) && state.getEstimatedHit() > 10) {
state.setEstimatedHit(RandomFunction.random(10));
}
}
CombatStyle style = state.getStyle();
super.adjustBattleState(entity, victim, state);
state.setStyle(style);
}
@Override
public void adjustBattleState(Entity entity, Entity victim, BattleState state) {
if (victim.isPlayer() && !fire) {
Item item = victim.asPlayer().getEquipment().get(EquipmentContainer.SLOT_SHIELD);
if (item != null && (item.getId() == 2890 || item.getId() == 9731) && state.getEstimatedHit() > 10) {
state.setEstimatedHit(RandomFunction.random(10));
}
}
CombatStyle style = state.getStyle();
super.adjustBattleState(entity, victim, state);
state.setStyle(style);
}
@Override
protected int getFormattedHit(Entity entity, Entity victim, BattleState state, int hit) {
return formatHit(victim, hit);
}
@Override
protected int getFormattedHit(Entity entity, Entity victim, BattleState state, int hit) {
return formatHit(victim, hit);
}
@Override
public int calculateAccuracy(Entity entity) {
return 4000;
}
@Override
public int calculateAccuracy(Entity entity) {
return 4000;
}
@Override
public int calculateHit(Entity entity, Entity victim, double modifier) {
int damage = maximumHit;
if (victim instanceof Player) {
int val = victim.getDragonfireProtection(fire);
if ((val & 0x2) != 0) {
damage *= 0.1;
}
if ((val & 0x4) != 0) {
damage *= 0.1;
}
if ((val & 0x8) != 0) {
damage *= 0.6;
}
}
return damage;
}
@Override
public int calculateHit(Entity entity, Entity victim, double modifier) {
return calculateDragonfireMaxHit(victim, maximumHit, !fire, 0, true);
}
@Override
public int calculateDefence(Entity victim, Entity attacker) {
return CombatStyle.MAGIC.getSwingHandler().calculateDefence(victim, attacker);
}
@Override
public int calculateDefence(Entity victim, Entity attacker) {
return CombatStyle.MAGIC.getSwingHandler().calculateDefence(victim, attacker);
}
@Override
public double getSetMultiplier(Entity e, int skillId) {
return 1.0;
}
@Override
public double getSetMultiplier(Entity e, int skillId) {
return 1.0;
}
}
}
@@ -31,19 +31,6 @@ class SkeletalWyvernBehavior : NPCBehavior(*Tasks.SKELETAL_WYVERN.ids) {
private val SHIELDS = intArrayOf(Items.DRAGONFIRE_SHIELD_11283, Items.DRAGONFIRE_SHIELD_11285, Items.ELEMENTAL_SHIELD_2890, Items.MIND_SHIELD_9731)
override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) {
if (victim !is Player) return
if (state.style != CombatStyle.MAGIC) return
val shield = getItemFromEquipment(victim, EquipmentSlot.SHIELD)
val hasShieldProtection = shield != null && shield.id in SHIELDS
if (!hasShieldProtection) return
state.estimatedHit = RandomFunction.random(11)
if (victim.location.getDistance(self.location) >= 5 && victim.prayer.get(PrayerType.PROTECT_FROM_MAGIC))
state.estimatedHit = 0
}
override fun getSwingHandlerOverride(self: NPC, original: CombatSwingHandler): CombatSwingHandler {
val victim = self.properties.combatPulse.getVictim() ?: return original
if (victim !is Player) return original
@@ -53,4 +40,4 @@ class SkeletalWyvernBehavior : NPCBehavior(*Tasks.SKELETAL_WYVERN.ids) {
else
COMBAT_HANDLER
}
}
}