package com.asteria.game.character.npc;
import static com.asteria.game.GameConstants.TARGET_DISTANCE;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.asteria.game.GameConstants;
import com.asteria.game.character.player.Player;
import com.asteria.game.location.Location;
import com.asteria.game.location.Position;
/**
* Manages the behavior of aggressive {@link Npc}s including the way the
* interact towards various {@link Player}s.
*
* @author lare96 <http://github.com/lare96>
*/
public final class NpcAggression {
/**
* The hash collection the holds the npc identifiers of aggressive
* {@link Npc}s.
*/
public static final Set<Integer> AGGRESSIVE = new HashSet<>();
/**
* Prompts all aggressive {@link Npc}s to attack the unsuspecting
* {@code player}, if they do not attack the player they will go back to
* their default movement coordinate state.
*
* @param player
* the player that will be targeted.
*/
public static void sequence(Player player) {
for (Npc npc : player.getLocalNpcs()) {
if (validate(npc, player)) {
npc.getMovementQueue().reset();
npc.getCombatBuilder().attack(player);
} else {
npc.getMovementCoordinator().setCoordinate(npc.isOriginalRandomWalk());
}
}
}
/**
* Determines if {@code npc} is able to target {@code player}.
*
* @param npc
* the npc trying to target the player.
* @param player
* the player that is being targeted by the NPC.
* @return {@code true} if the player can be targeted, {@code false}
* otherwise.
*/
private static boolean validate(Npc npc, Player player) {
Position position = npc.getOriginalPosition();
boolean wilderness = Location.inWilderness(npc) && Location.inWilderness(player);
boolean tolerance = wilderness || npc.getDefinition().getCombatLevel() > 126 ? false : player.getTolerance().elapsed(
GameConstants.TOLERANCE_SECONDS, TimeUnit.SECONDS);
if (!AGGRESSIVE.contains(npc.getId()) && !wilderness || !npc.getDefinition().isAttackable())
return false;
if (!position.withinDistance(npc.getPosition(), TARGET_DISTANCE) || !position.withinDistance(player.getPosition(), TARGET_DISTANCE) && npc
.getDefinition().isRetreats()) {
npc.getMovementQueue().walk(position);
npc.getCombatBuilder().reset();
return false;
}
if (!Location.inMultiCombat(player) && player.getCombatBuilder().isAttacking() || player.getCombatBuilder().isBeingAttacked())
return false;
if (player.determineCombatLevel() > (npc.getDefinition().getCombatLevel() * 2) && !wilderness)
return false;
return !npc.getCombatBuilder().isAttacking() && !npc.getCombatBuilder().isBeingAttacked() && !tolerance;
}
}