package ai; import java.util.concurrent.Future; import com.aionemu.gameserver.ai.AIActions; import com.aionemu.gameserver.ai.AIName; import com.aionemu.gameserver.ai.poll.AIQuestion; import com.aionemu.gameserver.model.TaskId; import com.aionemu.gameserver.model.gameobjects.Creature; import com.aionemu.gameserver.model.gameobjects.Npc; import com.aionemu.gameserver.model.gameobjects.NpcObjectType; import com.aionemu.gameserver.model.skill.NpcSkillEntry; import com.aionemu.gameserver.skillengine.SkillEngine; import com.aionemu.gameserver.skillengine.effect.AbnormalState; import com.aionemu.gameserver.skillengine.model.SkillTemplate; import com.aionemu.gameserver.skillengine.model.SkillType; import com.aionemu.gameserver.utils.ThreadPoolManager; /** * @author ATracer */ @AIName("servant") public class ServantNpcAI extends GeneralNpcAI { private Future skillTask; public ServantNpcAI(Npc owner) { super(owner); } @Override public void think() { // servants are not thinking } @Override public boolean canThink() { return false; } @Override protected void handleSpawned() { super.handleSpawned(); if (getCreator() != null) { ThreadPoolManager.getInstance().schedule(() -> { if (getOwner().getNpcObjectType() != NpcObjectType.TOTEM) AIActions.targetCreature(ServantNpcAI.this, (Creature) getCreator().getTarget()); else AIActions.targetSelf(ServantNpcAI.this); healOrAttack(); }, 200); } } private void healOrAttack() { NpcSkillEntry skill = getSkillList().getRandomSkill(); if (skill == null) return; getOwner().getGameStats().setLastSkill(skill); int duration = getOwner().getNpcObjectType() == NpcObjectType.TOTEM ? 3000 : 5000; int startDelay = 1000; switch (getOwner().getNpcId()) { // Taunting Spirit case 833403, 833404, 833478, 833479, 833480, 833481 -> duration = 5000; // Battle Banner case 833077, 833078, 833452, 833453, 833454, 833455 -> { duration = 3000; startDelay = 100; } } final Creature target = (Creature) getOwner().getTarget(); skillTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(() -> { if (target == null || target.isDead()) { AIActions.deleteOwner(ServantNpcAI.this); cancelTask(); } else { SkillTemplate template = skill.getTemplate().getSkillTemplate(); if ((template.getType() != SkillType.MAGICAL || !getOwner().getEffectController().isAbnormalSet(AbnormalState.SILENCE)) && (template.getType() != SkillType.PHYSICAL || !getOwner().getEffectController().isAbnormalSet(AbnormalState.BIND)) && (!getOwner().getEffectController().isInAnyAbnormalState(AbnormalState.CANT_ATTACK_STATE)) && (!getOwner().isTransformed() || getOwner().getTransformModel().getBanUseSkills() != 1)) { SkillEngine.getInstance().getSkill(getOwner(), skill.getSkillId(), skill.getSkillLevel(), getOwner().getTarget()).useSkill(); } } }, startDelay, duration); getOwner().getController().addTask(TaskId.SKILL_USE, skillTask); } @Override public boolean isMoveSupported() { return false; } private void cancelTask() { if (skillTask != null && !skillTask.isDone()) skillTask.cancel(true); } @Override public boolean ask(AIQuestion question) { return switch (question) { case ALLOW_DECAY, ALLOW_RESPAWN, REWARD_AP_XP_DP_LOOT -> false; default -> super.ask(question); }; } }