package com.asteria.game.character.npc; import com.asteria.game.NodeType; import com.asteria.game.World; import com.asteria.game.character.CharacterNode; import com.asteria.game.character.Flag; import com.asteria.game.character.Hit; import com.asteria.game.character.PoisonType; import com.asteria.game.character.combat.Combat; import com.asteria.game.character.combat.CombatStrategy; import com.asteria.game.character.combat.CombatType; import com.asteria.game.character.combat.effect.CombatPoisonEffect; import com.asteria.game.character.combat.magic.CombatWeaken; import com.asteria.game.location.Position; /** * The character implementation that represents a node that is operated by the * server. This type of node functions solely through the server executing * functions. * * @author lare96 <http://github.com/lare96> */ public final class Npc extends CharacterNode { /** * The identification for this NPC. */ private final int id; /** * The maximum health of this NPC. */ private final int maxHealth; /** * The original position that this NPC was created on. */ private final Position originalPosition; /** * The movement coordinator for this NPC. */ private final NpcMovementCoordinator movementCoordinator = new NpcMovementCoordinator(this); /** * The current health of this NPC. */ private int currentHealth; /** * Determines if this NPC was originally random walking. */ private boolean originalRandomWalk; /** * Determines if this NPC respawns. */ private boolean respawn; /** * The spell that this NPC is weakened by. */ private CombatWeaken weakenedBy; /** * The transformation identifier. */ private int transform = -1; /** * Creates a new {@link Npc}. * * @param id * the identification for this NPC. * @param position * the position of this character in the world. */ public Npc(int id, Position position) { super(position, NodeType.NPC); this.id = id; this.originalPosition = position.copy(); this.maxHealth = getDefinition().getHitpoints(); this.currentHealth = maxHealth; } @Override public void create() { } @Override public void dispose() { setPosition(new Position(1, 1)); World.getTaskQueue().cancel(this); } @Override public void sequence() throws Exception { movementCoordinator.sequence(); } @Override public Hit decrementHealth(Hit hit) { if (hit.getDamage() > currentHealth) hit = new Hit(currentHealth, hit.getType()); currentHealth -= hit.getDamage(); return hit; } @Override public int getAttackSpeed() { return this.getDefinition().getAttackSpeed(); } @Override public int getCurrentHealth() { return currentHealth; } @Override public String toString() { return "NPC[slot= " + getSlot() + ", name=" + getDefinition().getName() + "]"; } @Override public CombatStrategy determineStrategy() { return Combat.determineStrategy(id); } @Override public int getBaseAttack(CombatType type) { int value = getDefinition().getAttackBonus(); if (weakenedBy == CombatWeaken.ATTACK_LOW || weakenedBy == CombatWeaken.ATTACK_HIGH) value -= (int) ((weakenedBy.getRate()) * (value)); return value; } @Override public int getBaseDefence(CombatType type) { int value = type == CombatType.MAGIC ? getDefinition().getMagicDefence() : type == CombatType.RANGED ? getDefinition() .getRangedDefence() : getDefinition().getMeleeDefence(); if (weakenedBy == CombatWeaken.DEFENCE_LOW || weakenedBy == CombatWeaken.DEFENCE_HIGH) value -= (int) ((weakenedBy.getRate()) * (value)); return value; } @Override public void onSuccessfulHit(CharacterNode victim, CombatType type) { if (getDefinition().isPoisonous()) victim.poison(CombatPoisonEffect.getPoisonType(id).orElse(PoisonType.DEFAULT_NPC)); } @Override public void healCharacter(int damage) { if ((currentHealth + damage) > maxHealth) { currentHealth = maxHealth; return; } currentHealth += damage; } @Override public boolean weaken(CombatWeaken effect) { if (weakenedBy == null) { weakenedBy = effect; return true; } return false; } /** * Activates the {@code TRANSFORM} update mask for this non-player * character. * * @param id * the new npc to transform this npc into. */ public void transform(int id) { transform = id; getFlags().set(Flag.TRANSFORM); } /** * Gets the movement coordinator for this NPC. * * @return the movement coordinator. */ public NpcMovementCoordinator getMovementCoordinator() { return movementCoordinator; } /** * Determines if this NPC was originally random walking. * * @return {@code true} if this NPC was originally walking, {@code false} * otherwise. */ public boolean isOriginalRandomWalk() { return originalRandomWalk; } /** * Sets the value for {@link Npc#originalRandomWalk}. * * @param originalRandomWalk * the new value to set. */ public void setOriginalRandomWalk(boolean originalRandomWalk) { this.originalRandomWalk = originalRandomWalk; } /** * Determines if this NPC respawns. * * @return {@code true} if this NPC respawns, {@code false} otherwise. */ public boolean isRespawn() { return respawn; } /** * Sets the value for {@link Npc#respawn}. * * @param respawn * the new value to set. */ public void setRespawn(boolean respawn) { this.respawn = respawn; } /** * Gets the identification for this NPC. * * @return the identification. */ public int getId() { return id; } /** * Gets the maximum health of this NPC. * * @return the maximum health. */ public int getMaxHealth() { return maxHealth; } /** * Gets the original position that this NPC was created on. * * @return the original position. */ public Position getOriginalPosition() { return originalPosition; } /** * Sets the value for {@link Npc#currentHealth}. * * @param currentHealth * the new value to set. */ public void setCurrentHealth(int currentHealth) { this.currentHealth = currentHealth; } /** * Gets the spell that this NPC is weakened by. * * @return the weakening spell. */ public CombatWeaken getWeakenedBy() { return weakenedBy; } /** * Sets the value for {@link Npc#weakenedBy}. * * @param weakenedBy * the new value to set. */ public void setWeakenedBy(CombatWeaken weakenedBy) { this.weakenedBy = weakenedBy; } /** * Gets the definition for this NPC. * * @return the definition. */ public NpcDefinition getDefinition() { return NpcDefinition.DEFINITIONS[id]; } /** * Gets the transformation identifier. * * @return the transformation id. */ public int getTransform() { return transform; } }