77public final class CombatUtil {
84 private CombatUtil() {
85 throw new UnsupportedOperationException(
"This class cannot be instantiated!");
106 public static void areaAction(
Mob mob,
int max,
int distance, Consumer<Mob> action) {
107 if (!
Area.inMulti(mob)) {
113 players.sort((first, second) -> {
114 int firstD =
Utility.getDistance(first, mob);
115 int secondD =
Utility.getDistance(second, mob);
116 return firstD - secondD;
119 for (
Player other : players) {
120 if (other ==
null)
continue;
121 if (other.instance != mob.instance)
continue;
122 if (!
Utility.withinViewingDistance(other, mob, distance))
continue;
123 if (other.equals(mob))
continue;
124 if (other.getCurrentHealth() <= 0 || other.isDead())
continue;
125 if (!
Area.inMulti(other))
continue;
126 if (mob.isPlayer() && other.isPlayer() && (!
Area.inWilderness(mob) || !
Area.inWilderness(other)))
128 action.accept(other);
129 if (++added == max)
return;
133 npcs.sort((first, second) -> {
134 int firstD =
Utility.getDistance(first, mob);
135 int secondD =
Utility.getDistance(second, mob);
136 return firstD - secondD;
139 for (
Npc other : npcs) {
140 if (other ==
null)
continue;
141 if (other.instance != mob.instance)
continue;
142 if (!
Utility.withinViewingDistance(other, mob, distance))
continue;
143 if (other.equals(mob))
continue;
144 if (other.getCurrentHealth() <= 0 || other.isDead())
continue;
145 if (!
Area.inMulti(other))
continue;
146 if (!other.definition.isAttackable())
continue;
147 action.accept(other);
148 if (++added == max)
return;
163 final CombatStrategy<? super Mob> strategy = attacker.
getStrategy();
164 if (strategy !=
null) {
166 if (combatProjectile !=
null) {
167 final int serverTicks = combatProjectile.getServerTicks();
168 if (serverTicks > 0) {
173 return getOldHitDelay(attacker, defender, type);
176 private static int getOldHitDelay(
final Mob attacker,
final Mob defender,
final CombatType type) {
177 final int distance = Math.min(10,
Utility.getDistance(attacker, defender));
178 return switch (type) {
192 return type.getHitsplatDelay();
195 static boolean validateMobs(
Mob attacker,
Mob defender) {
196 if (!validate(attacker) || !validate(defender)) {
201 if (attacker.instance != defender.instance) {
206 if (!canAttack(attacker, defender)) {
213 static boolean validate(Mob attacker, Mob defender) {
214 if (!validate(attacker) || !validate(defender)) {
215 attacker.getCombat().reset();
219 if (attacker.instance != defender.instance) {
220 attacker.getCombat().reset();
224 if (!canBasicAttack(attacker, defender)) {
225 attacker.getCombat().reset();
251 public static boolean canAttack(
Mob attacker,
Mob defender) {
253 return canAttack(attacker.getPlayer(), defender);
254 return canAttack(attacker.getNpc(), defender);
257 private static boolean canAttack(
Player attacker,
Mob defender) {
260 if (defender.
isNpc() && !SlayerTask.canAttack(attacker, defender.
getName())) {
261 attacker.send(
new SendMessage(
"You do not meet the slayer requirements to attack this npc!"));
264 if (attacker.equals(defender)) {
268 if (defender.
isNpc() && defender.getNpc().owner !=
null && !attacker.equals(defender.getNpc().owner)) {
269 attacker.send(
new SendMessage(
"You can't attack this npc!"));
273 if (attacker.
getCombat().isUnderAttack() && !attacker.
getCombat().isUnderAttackBy(defender)) {
274 if (!Area.inMulti(attacker) || !Area.inMulti(defender)) {
275 attacker.send(
new SendMessage(
"You are already under attack!"));
280 if (defender.
getCombat().isUnderAttack() && !defender.
getCombat().isUnderAttackBy(attacker)) {
281 if (!Area.inMulti(attacker) || !Area.inMulti(defender)) {
283 attacker.send(
new SendMessage(defender.
getName() +
" is currently in combat and can not be attacked."));
285 attacker.send(
new SendMessage(
"This monster is already under attack!"));
291 if (attacker.locking.
locked(PacketType.COMBAT)) {
295 if (LMSGame.inGameArea(attacker) && LMSGame.canAttack(attacker, defender.getPlayer())) {
299 if (Activity.evaluate(attacker, activity -> defender.activity == activity) && attacker.inActivity(ActivityType.DUEL_ARENA)) {
311 if (attacker.pvpInstance) {
312 if (!defender.getPlayer().pvpInstance) {
313 attacker.message(defender.
getName() +
" is not in a PvP instance.");
316 if (!Area.inPvP(attacker) && !attacker.hasPvPTimer) {
317 attacker.message(
"You must be in a PvP zone to attack " + defender.
getName() +
"!");
321 if (!Area.inPvP(defender) && !defender.getPlayer().hasPvPTimer) {
322 attacker.message(defender.
getName() +
" must be in a PvP zone for you to attack!");
326 if (difference > 10) {
327 if (!Area.inDuelObsticleArena(attacker)) {
328 attacker.message(
"Your combat level difference is too great!");
335 if (difference > attacker.wilderness) {
336 if (!Area.inDuelObsticleArena(attacker)) {
337 attacker.send(
new SendMessage(
"Your combat level difference is too great!"));
342 if (!Area.inWilderness(attacker)) {
343 attacker.send(
new SendMessage(
"You need to be in the wilderness to attack " + Utility.formatName(defender.
getName()) +
"."));
347 if (!Area.inWilderness(defender)) {
348 attacker.send(
new SendMessage(Utility.formatName(defender.
getName()) +
" must be in the wilderness for you to attack."));
355 private static boolean canAttack(Npc attacker, Mob defender) {
356 if (attacker.equals(defender)) {
359 if (defender.isNpc() && defender.getNpc().owner !=
null && !defender.getNpc().owner.equals(attacker)) {
362 if (attacker.getCombat().isUnderAttack() && !attacker.getCombat().isUnderAttackBy(defender)) {
363 if (!Area.inMulti(attacker) || !Area.inMulti(defender)) {
367 if (defender.getCombat().isUnderAttack() && !defender.getCombat().isUnderAttackBy(attacker)) {
368 return Area.inMulti(attacker) && Area.inMulti(defender);
373 public static boolean canBasicAttack(Mob attacker, Mob defender) {
374 if (attacker.equals(defender)) {
377 if (defender.isNpc() && defender.getNpc().owner !=
null && !attacker.equals(defender.getNpc().owner)) {
380 if (Activity.evaluate(attacker, activity -> defender.activity == activity) && attacker.inActivity(ActivityType.DUEL_ARENA)) {
383 if (attacker.getCombat().isUnderAttack() && !attacker.getCombat().isUnderAttackBy(defender)) {
384 if (!Area.inMulti(attacker) || !Area.inMulti(defender)) {
388 if (defender.getCombat().isUnderAttack() && !defender.getCombat().isUnderAttackBy(attacker)) {
389 if (!Area.inMulti(attacker) || !Area.inMulti(defender)) {
393 if (attacker.isPlayer() && defender.isPlayer()) {
394 int difference = Math.abs(attacker.skills.getCombatLevel() - defender.skills.getCombatLevel());
396 if (attacker.getPlayer().pvpInstance || defender.getPlayer().pvpInstance) {
397 if (!defender.getPlayer().pvpInstance) {
400 if (!attacker.getPlayer().pvpInstance) {
403 if (!Area.inPvP(attacker)) {
406 if (!Area.inPvP(defender)) {
409 return difference <= 10;
413 if (difference > attacker.getPlayer().wilderness) {
416 if (!Area.inWilderness(attacker)) {
419 return Area.inWilderness(defender);
424 private static boolean validate(Mob mob) {
425 return mob !=
null && !mob.isDead() && mob.isVisible() && mob.isValid() && !mob.teleporting && !mob.inTeleport;
428 public static Animation getBlockAnimation(Mob mob) {
430 if (mob.isPlayer()) {
431 final var shieldOverride = mob.getPlayer().overrides.hasOverride(Equipment.SHIELD_SLOT);
432 if (mob.getPlayer().equipment.hasShield() || shieldOverride) {
433 Item shield = shieldOverride ? mob.getPlayer().overrides.get(Equipment.SHIELD_SLOT) : mob.getPlayer().equipment.getShield();
434 animation = shield.getBlockAnimation().orElse(424);
435 }
else if (mob.isPlayer()) {
436 final var weaponOverride = mob.getPlayer().overrides.hasOverride(Equipment.WEAPON_SLOT);
437 if (mob.getPlayer().equipment.hasWeapon() || weaponOverride) {
438 Item weapon = weaponOverride ? mob.getPlayer().overrides.get(Equipment.WEAPON_SLOT) : mob.getPlayer().equipment.getWeapon();
439 animation = weapon.getBlockAnimation().orElse(424);
445 Npc npc = mob.getNpc();
446 animation = npc.definition.getBlockAnimation();
448 int delay = (int) mob.getCombat().lastBlocked.elapsedTime();
450 return new Animation(animation, delay / 50, UpdatePriority.LOW);
451 return new Animation(animation, UpdatePriority.LOW);
454 public static CombatHit generateDragonfire(Mob attacker, Mob defender,
int max,
boolean prayer) {
455 int hitDelay =
getHitDelay(attacker, defender, CombatType.MAGIC);
456 int hitsplatDelay = 1;
457 return generateDragonfire(attacker, defender, max, hitDelay, hitsplatDelay, prayer);
460 public static CombatHit generateDragonfire(Mob attacker, Mob defender,
int max,
int hitDelay,
int hitsplatDelay,
boolean prayer) {
463 if (defender.isPlayer()) {
464 Player player = defender.getPlayer();
466 if (Equipment.isWearingDFS(player) && player.dragonfireCharges < 50) {
467 if (player.equipment.getShield().getId() == 11284) {
468 player.equipment.set(Equipment.SHIELD_SLOT,
new Item(11283),
true);
469 player.equipment.refresh();
471 player.animate(6695);
472 player.graphic(1164);
473 player.dragonfireCharges++;
474 player.getCombat().setCooldown(5);
475 player.send(
new SendMessage(
"Your dragonfire Shield Absorbs the Dragon breath."));
476 player.face(attacker);
479 prayer &= player.prayer.isActive(Prayer.PROTECT_FROM_MAGIC);
480 boolean shield = player.equipment.containsAny(1540, 11283, 21633);
481 boolean potion = player.getAntifireDetails().isPresent();
483 if (shield && potion) {
486 AntifireDetails.AntifireType type = player.getAntifireDetails().get().getType();
487 max -= type.getReduction();
498 damage = RandomUtils.inclusive(max);
504 player.send(
new SendMessage(
"You are horribly burned by the dragonfire!",
true));
505 }
else if (!shield && !potion && !prayer && damage < 9 && damage > 0) {
506 player.send(
new SendMessage(
"You manage to resist some of the dragonfire.",
true));
510 damage = max == 0 ? 0 : RandomUtils.inclusive(max);
513 Hit hit =
new Hit(damage, Hitsplat.NORMAL, HitIcon.NONE,
true);
514 return new CombatHit(hit, hitDelay, hitsplatDelay);
517 public static CombatStrategy<Npc> randomStrategy(CombatStrategy<Npc>[] strategies) {
518 return RandomUtils.random(strategies);
522 public static CombatStrategy<Npc>[] createStrategyArray(CombatStrategy<Npc>... strategies) {
527 public static CombatStrategy<Npc>[] createStrategyArray(CombatStrategy<Npc>[] strategies,
528 CombatStrategy<Npc>... moreStrategies) {
529 final CombatStrategy<Npc>[] array =
new CombatStrategy[strategies.length + moreStrategies.length];
530 System.arraycopy(strategies, 0, array, 0, strategies.length);
531 System.arraycopy(moreStrategies, 0, array, strategies.length, moreStrategies.length);