Advertisement
Guest User

Untitled

a guest
Jul 30th, 2015
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 79.06 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2004-2013 L2J Server
  3.  *
  4.  * This file is part of L2J Server.
  5.  *
  6.  * L2J Server is free software: you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation, either version 3 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * L2J Server is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14.  * General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18.  */
  19. package com.l2jserver.gameserver.ai;
  20.  
  21. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
  22. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
  23. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
  24.  
  25. import java.util.ArrayList;
  26. import java.util.Collection;
  27. import java.util.List;
  28. import java.util.concurrent.Future;
  29.  
  30. import com.l2jserver.Config;
  31. import com.l2jserver.gameserver.GameTimeController;
  32. import com.l2jserver.gameserver.GeoData;
  33. import com.l2jserver.gameserver.ThreadPoolManager;
  34. import com.l2jserver.gameserver.datatables.NpcTable;
  35. import com.l2jserver.gameserver.datatables.TerritoryTable;
  36. import com.l2jserver.gameserver.instancemanager.DimensionalRiftManager;
  37. import com.l2jserver.gameserver.model.L2CharPosition;
  38. import com.l2jserver.gameserver.model.L2Object;
  39. import com.l2jserver.gameserver.model.actor.L2Attackable;
  40. import com.l2jserver.gameserver.model.actor.L2Character;
  41. import com.l2jserver.gameserver.model.actor.L2Npc;
  42. import com.l2jserver.gameserver.model.actor.L2Playable;
  43. import com.l2jserver.gameserver.model.actor.L2Summon;
  44. import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
  45. import com.l2jserver.gameserver.model.actor.instance.L2FestivalMonsterInstance;
  46. import com.l2jserver.gameserver.model.actor.instance.L2FriendlyMobInstance;
  47. import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
  48. import com.l2jserver.gameserver.model.actor.instance.L2GuardInstance;
  49. import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
  50. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  51. import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
  52. import com.l2jserver.gameserver.model.actor.instance.L2RiftInvaderInstance;
  53. import com.l2jserver.gameserver.model.actor.instance.L2StaticObjectInstance;
  54. import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
  55. import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate.AIType;
  56. import com.l2jserver.gameserver.model.effects.L2EffectType;
  57. import com.l2jserver.gameserver.model.quest.Quest;
  58. import com.l2jserver.gameserver.model.quest.Quest.QuestEventType;
  59. import com.l2jserver.gameserver.model.skills.L2Skill;
  60. import com.l2jserver.gameserver.model.skills.targets.L2TargetType;
  61. import com.l2jserver.gameserver.model.zone.ZoneId;
  62. import com.l2jserver.gameserver.util.Util;
  63. import com.l2jserver.util.Rnd;
  64.  
  65. /**
  66.  * This class manages AI of L2Attackable.
  67.  */
  68. public class L2AttackableAI extends L2CharacterAI implements Runnable
  69. {
  70.     private static final int RANDOM_WALK_RATE = 30; // confirmed
  71.     // private static final int MAX_DRIFT_RANGE = 300;
  72.     private static final int MAX_ATTACK_TIMEOUT = 1200; // int ticks, i.e. 2min
  73.     /**
  74.      * The L2Attackable AI task executed every 1s (call onEvtThink method).
  75.      */
  76.     private Future<?> _aiTask;
  77.     /**
  78.      * The delay after which the attacked is stopped.
  79.      */
  80.     private int _attackTimeout;
  81.     /**
  82.      * The L2Attackable aggro counter.
  83.      */
  84.     private int _globalAggro;
  85.     /**
  86.      * The flag used to indicate that a thinking action is in progress, to prevent recursive thinking.
  87.      */
  88.     private boolean _thinking;
  89.  
  90.     private int timepass = 0;
  91.     private int chaostime = 0;
  92.     private final L2NpcTemplate _skillrender;
  93.     private List<L2Skill> shortRangeSkills = new ArrayList<>();
  94.     private List<L2Skill> longRangeSkills = new ArrayList<>();
  95.     int lastBuffTick;
  96.  
  97.     /**
  98.      * Constructor of L2AttackableAI.
  99.      * @param accessor The AI accessor of the L2Character
  100.      */
  101.     public L2AttackableAI(L2Character.AIAccessor accessor)
  102.     {
  103.         super(accessor);
  104.         _skillrender = NpcTable.getInstance().getTemplate(getActiveChar().getTemplate().getNpcId());
  105.         _attackTimeout = Integer.MAX_VALUE;
  106.         _globalAggro = -10; // 10 seconds timeout of ATTACK after respawn
  107.     }
  108.  
  109.     @Override
  110.     public void run()
  111.     {
  112.         // Launch actions corresponding to the Event Think
  113.         onEvtThink();
  114.     }
  115.  
  116.     /**
  117.      * <B><U> Actor is a L2GuardInstance</U> :</B>
  118.      * <ul>
  119.      * <li>The target isn't a Folk or a Door</li>
  120.      * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
  121.      * <li>The target is in the actor Aggro range and is at the same height</li>
  122.      * <li>The L2PcInstance target has karma (=PK)</li>
  123.      * <li>The L2MonsterInstance target is aggressive</li>
  124.      * </ul>
  125.      * <B><U> Actor is a L2SiegeGuardInstance</U> :</B>
  126.      * <ul>
  127.      * <li>The target isn't a Folk or a Door</li>
  128.      * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
  129.      * <li>The target is in the actor Aggro range and is at the same height</li>
  130.      * <li>A siege is in progress</li>
  131.      * <li>The L2PcInstance target isn't a Defender</li>
  132.      * </ul>
  133.      * <B><U> Actor is a L2FriendlyMobInstance</U> :</B>
  134.      * <ul>
  135.      * <li>The target isn't a Folk, a Door or another L2Npc</li>
  136.      * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
  137.      * <li>The target is in the actor Aggro range and is at the same height</li>
  138.      * <li>The L2PcInstance target has karma (=PK)</li>
  139.      * </ul>
  140.      * <B><U> Actor is a L2MonsterInstance</U> :</B>
  141.      * <ul>
  142.      * <li>The target isn't a Folk, a Door or another L2Npc</li>
  143.      * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
  144.      * <li>The target is in the actor Aggro range and is at the same height</li>
  145.      * <li>The actor is Aggressive</li>
  146.      * </ul>
  147.      * @param target The targeted L2Object
  148.      * @return True if the target is autoattackable (depends on the actor type).
  149.      */
  150.     private boolean autoAttackCondition(L2Character target)
  151.     {
  152.         if ((target == null) || (getActiveChar() == null))
  153.         {
  154.             return false;
  155.         }
  156.         final L2Attackable me = getActiveChar();
  157.        
  158.         // Check if the target isn't invulnerable
  159.         if (target.isInvul())
  160.         {
  161.             // However EffectInvincible requires to check GMs specially
  162.             if ((target instanceof L2PcInstance) && ((L2PcInstance) target).isGM())
  163.             {
  164.                 return false;
  165.             }
  166.             if ((target instanceof L2Summon) && ((L2Summon) target).getOwner().isGM())
  167.             {
  168.                 return false;
  169.             }
  170.         }
  171.  
  172.         // Check if the target isn't a Folk or a Door
  173.         if (target instanceof L2DoorInstance)
  174.         {
  175.             return false;
  176.         }
  177.  
  178.         // Check if the target isn't dead, is in the Aggro range and is at the same height
  179.         if (target.isAlikeDead() || ((target instanceof L2Playable) && !me.isInsideRadius(target, me.getAggroRange(), true, false)))
  180.         {
  181.             return false;
  182.         }
  183.  
  184.         // Check if the target is a L2Playable
  185.         if (target.isPlayable())
  186.         {
  187.             // Check if the AI isn't a Raid Boss, can See Silent Moving players and the target isn't in silent move mode
  188.             if (!(me.isRaid()) && !(me.canSeeThroughSilentMove()) && ((L2Playable) target).isSilentMoving())
  189.             {
  190.                 return false;
  191.             }
  192.         }
  193.  
  194.         // Gets the player if there is any.
  195.         final L2PcInstance player = target.getActingPlayer();
  196.         if (player != null)
  197.         {
  198.            
  199.             if (player.isTeam1() && me.getClan().equals("Team1"))
  200.             {
  201.                 return false;
  202.             }
  203.  
  204.             if (player.isTeam2() && me.getClan().equals("Team2"))
  205.             {
  206.                 return false;
  207.             }
  208.            
  209.             // Don't take the aggro if the GM has the access level below or equal to GM_DONT_TAKE_AGGRO
  210.             if (player.isGM() && !player.getAccessLevel().canTakeAggro())
  211.             {
  212.                 return false;
  213.             }
  214.  
  215.             // check if the target is within the grace period for JUST getting up from fake death
  216.             if (player.isRecentFakeDeath())
  217.             {
  218.                 return false;
  219.             }
  220.  
  221.             if (player.isInParty() && player.getParty().isInDimensionalRift())
  222.             {
  223.                 byte riftType = player.getParty().getDimensionalRift().getType();
  224.                 byte riftRoom = player.getParty().getDimensionalRift().getCurrentRoom();
  225.  
  226.                 if ((me instanceof L2RiftInvaderInstance) && !DimensionalRiftManager.getInstance().getRoom(riftType, riftRoom).checkIfInZone(me.getX(), me.getY(), me.getZ()))
  227.                 {
  228.                     return false;
  229.                 }
  230.             }
  231.         }
  232.  
  233.         // Check if the actor is a L2GuardInstance
  234.         if (me instanceof L2GuardInstance)
  235.         {
  236.             // verificamos que sea de otro equipo
  237.  
  238.             // Check if the L2PcInstance target has karma (=PK)
  239.             // Check if the L2MonsterInstance target is aggressive
  240.  
  241.             return false;
  242.         }
  243.         else if (me instanceof L2FriendlyMobInstance)
  244.         {
  245.             // Check if the target isn't another L2Npc
  246.             if (target instanceof L2Npc)
  247.             {
  248.                 return false;
  249.             }
  250.  
  251.             // Check if the L2PcInstance target has karma (=PK)
  252.             if ((target instanceof L2PcInstance) && (((L2PcInstance) target).getKarma() > 0))
  253.             {
  254.                 return GeoData.getInstance().canSeeTarget(me, target); // Los Check
  255.             }
  256.             return false;
  257.         }
  258.         else
  259.         {
  260.             if (target instanceof L2Attackable)
  261.             {
  262.                
  263.                 if ((me.getEnemyClan() == null) || (((L2Attackable) target).getClan() == null))
  264.                 {
  265.                     return false;
  266.                 }
  267.  
  268.                 if (!target.isAutoAttackable(me))
  269.                 {
  270.                     return false;
  271.                 }
  272.  
  273.                 if (me.getEnemyClan().equals(((L2Attackable) target).getClan()))
  274.                 {
  275.                     if (me.isInsideRadius(target, me.getEnemyRange(), false, false))
  276.                     {
  277.                         return GeoData.getInstance().canSeeTarget(me, target);
  278.                     }
  279.                     return false;
  280.                 }
  281.                 if ((me.getIsChaos() > 0) && me.isInsideRadius(target, me.getIsChaos(), false, false))
  282.                 {
  283.                     if ((me.getFactionId() != null) && me.getFactionId().equals(((L2Attackable) target).getFactionId()))
  284.                     {
  285.                         return false;
  286.                     }
  287.                     // Los Check
  288.                     return GeoData.getInstance().canSeeTarget(me, target);
  289.                 }
  290.             }
  291.  
  292.             if ((target instanceof L2Attackable) || (target instanceof L2Npc))
  293.             {
  294.                 return false;
  295.             }
  296.  
  297.             // depending on config, do not allow mobs to attack _new_ players in peacezones,
  298.             // unless they are already following those players from outside the peacezone.
  299.             if (!Config.ALT_MOB_AGRO_IN_PEACEZONE && target.isInsideZone(ZoneId.PEACE))
  300.             {
  301.                 return false;
  302.             }
  303.  
  304.             if (me.isChampion() && Config.L2JMOD_CHAMPION_PASSIVE)
  305.             {
  306.                 return false;
  307.             }
  308.  
  309.             // Check if the actor is Aggressive
  310.             return (me.isAggressive() && GeoData.getInstance().canSeeTarget(me, target));
  311.         }
  312.     }
  313.  
  314.     public void startAITask()
  315.     {
  316.         // If not idle - create an AI task (schedule onEvtThink repeatedly)
  317.         if (_aiTask == null)
  318.         {
  319.             _aiTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(this, 1000, 1000);
  320.         }
  321.     }
  322.  
  323.     @Override
  324.     public void stopAITask()
  325.     {
  326.         if (_aiTask != null)
  327.         {
  328.             _aiTask.cancel(false);
  329.             _aiTask = null;
  330.         }
  331.         super.stopAITask();
  332.     }
  333.  
  334.     /**
  335.      * Set the Intention of this L2CharacterAI and create an AI Task executed every 1s (call onEvtThink method) for this L2Attackable.<br>
  336.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : If actor _knowPlayer isn't EMPTY, AI_INTENTION_IDLE will be change in AI_INTENTION_ACTIVE</B></FONT>
  337.      * @param intention The new Intention to set to the AI
  338.      * @param arg0 The first parameter of the Intention
  339.      * @param arg1 The second parameter of the Intention
  340.      */
  341.     @Override
  342.     synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
  343.     {
  344.         if ((intention == AI_INTENTION_IDLE) || (intention == AI_INTENTION_ACTIVE))
  345.         {
  346.             // Check if actor is not dead
  347.             L2Attackable npc = getActiveChar();
  348.             if (!npc.isAlikeDead())
  349.             {
  350.                 // If its _knownPlayer isn't empty set the Intention to AI_INTENTION_ACTIVE
  351.                 if (!npc.getKnownList().getKnownPlayers().isEmpty())
  352.                 {
  353.                     intention = AI_INTENTION_ACTIVE;
  354.                 }
  355.                 else
  356.                 {
  357.                     if (npc.getSpawn() != null)
  358.                     {
  359.                         final int range = Config.MAX_DRIFT_RANGE;
  360.                         if (!npc.isInsideRadius(npc.getSpawn().getLocx(), npc.getSpawn().getLocy(), npc.getSpawn().getLocz(), range + range, true, false))
  361.                         {
  362.                             intention = AI_INTENTION_ACTIVE;
  363.                         }
  364.                     }
  365.                 }
  366.             }
  367.  
  368.             if (intention == AI_INTENTION_IDLE)
  369.             {
  370.                 // Set the Intention of this L2AttackableAI to AI_INTENTION_IDLE
  371.                 super.changeIntention(AI_INTENTION_IDLE, null, null);
  372.  
  373.                 // Stop AI task and detach AI from NPC
  374.                 if (_aiTask != null)
  375.                 {
  376.                     _aiTask.cancel(true);
  377.                     _aiTask = null;
  378.                 }
  379.  
  380.                 // Cancel the AI
  381.                 _accessor.detachAI();
  382.  
  383.                 return;
  384.             }
  385.         }
  386.  
  387.         // Set the Intention of this L2AttackableAI to intention
  388.         super.changeIntention(intention, arg0, arg1);
  389.  
  390.         // If not idle - create an AI task (schedule onEvtThink repeatedly)
  391.         startAITask();
  392.     }
  393.  
  394.     /**
  395.      * Manage the Attack Intention : Stop current Attack (if necessary), Calculate attack timeout, Start a new Attack and Launch Think Event.
  396.      * @param target The L2Character to attack
  397.      */
  398.     @Override
  399.     protected void onIntentionAttack(L2Character target)
  400.     {
  401.         // Calculate the attack timeout
  402.         _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getInstance().getGameTicks();
  403.  
  404.         // self and buffs
  405.         if ((lastBuffTick + 30) < GameTimeController.getInstance().getGameTicks())
  406.         {
  407.             for (L2Skill sk : _skillrender.getBuffSkills())
  408.             {
  409.                 if (cast(sk))
  410.                 {
  411.                     break;
  412.                 }
  413.             }
  414.             lastBuffTick = GameTimeController.getInstance().getGameTicks();
  415.         }
  416.  
  417.         // Manage the Attack Intention : Stop current Attack (if necessary), Start a new Attack and Launch Think Event
  418.         super.onIntentionAttack(target);
  419.     }
  420.  
  421.     private void thinkCast()
  422.     {
  423.         if (checkTargetLost(getCastTarget()))
  424.         {
  425.             setCastTarget(null);
  426.             return;
  427.         }
  428.         if (maybeMoveToPawn(getCastTarget(), _actor.getMagicalAttackRange(_skill)))
  429.         {
  430.             return;
  431.         }
  432.         clientStopMoving(null);
  433.         setIntention(AI_INTENTION_ACTIVE);
  434.         _accessor.doCast(_skill);
  435.     }
  436.  
  437.     /**
  438.      * Manage AI standard thinks of a L2Attackable (called by onEvtThink). <B><U> Actions</U> :</B>
  439.      * <ul>
  440.      * <li>Update every 1s the _globalAggro counter to come close to 0</li>
  441.      * <li>If the actor is Aggressive and can attack, add all autoAttackable L2Character in its Aggro Range to its _aggroList, chose a target and order to attack it</li>
  442.      * <li>If the actor is a L2GuardInstance that can't attack, order to it to return to its home location</li>
  443.      * <li>If the actor is a L2MonsterInstance that can't attack, order to it to random walk (1/100)</li>
  444.      * </ul>
  445.      */
  446.     private void thinkActive()
  447.     {
  448.         L2Attackable npc = getActiveChar();
  449.  
  450.         // Update every 1s the _globalAggro counter to come close to 0
  451.         if (_globalAggro != 0)
  452.         {
  453.             if (_globalAggro < 0)
  454.             {
  455.                 _globalAggro++;
  456.             }
  457.             else
  458.             {
  459.                 _globalAggro--;
  460.             }
  461.         }
  462.  
  463.         // Add all autoAttackable L2Character in L2Attackable Aggro Range to its _aggroList with 0 damage and 1 hate
  464.         // A L2Attackable isn't aggressive during 10s after its spawn because _globalAggro is set to -10
  465.         if (_globalAggro >= 0)
  466.         {
  467.             // Get all visible objects inside its Aggro Range
  468.             Collection<L2Object> objs = npc.getKnownList().getKnownObjects().values();
  469.  
  470.             for (L2Object obj : objs)
  471.             {
  472.                 if (!(obj instanceof L2Character) || (obj instanceof L2StaticObjectInstance))
  473.                 {
  474.                     continue;
  475.                 }
  476.                 L2Character target = (L2Character) obj;
  477.  
  478.                 /*
  479.                  * Check to see if this is a festival mob spawn. If it is, then check to see if the aggro trigger is a festival participant...if so, move to attack it.
  480.                  */
  481.                 if ((npc instanceof L2FestivalMonsterInstance) && (obj instanceof L2PcInstance))
  482.                 {
  483.                     L2PcInstance targetPlayer = (L2PcInstance) obj;
  484.  
  485.                     if (!(targetPlayer.isFestivalParticipant()))
  486.                     {
  487.                         continue;
  488.                     }
  489.                 }
  490.  
  491.                 // TODO: The AI Script ought to handle aggro behaviors in onSee. Once implemented, aggro behaviors ought
  492.                 // to be removed from here. (Fulminus)
  493.                 // For each L2Character check if the target is autoattackable
  494.                 if (autoAttackCondition(target)) // check aggression
  495.                 {
  496.                     // Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
  497.                     int hating = npc.getHating(target);
  498.  
  499.                     // Add the attacker to the L2Attackable _aggroList with 0 damage and 1 hate
  500.                     if (hating == 0)
  501.                     {
  502.                         npc.addDamageHate(target, 0, 0);
  503.                     }
  504.                 }
  505.             }
  506.  
  507.             // Chose a target from its aggroList
  508.             L2Character hated;
  509.             if (npc.isConfused())
  510.             {
  511.                 hated = getAttackTarget(); // effect handles selection
  512.             }
  513.             else
  514.             {
  515.                 hated = npc.getMostHated();
  516.             }
  517.  
  518.             // Order to the L2Attackable to attack the target
  519.             if ((hated != null) && !npc.isCoreAIDisabled())
  520.             {
  521.                 // Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
  522.                 int aggro = npc.getHating(hated);
  523.  
  524.                 if ((aggro + _globalAggro) > 0)
  525.                 {
  526.                     // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
  527.                     if (!npc.isRunning())
  528.                     {
  529.                         npc.setRunning();
  530.                     }
  531.  
  532.                     // Set the AI Intention to AI_INTENTION_ATTACK
  533.                     setIntention(CtrlIntention.AI_INTENTION_ATTACK, hated);
  534.                 }
  535.  
  536.                 return;
  537.             }
  538.         }
  539.  
  540.         // Chance to forget attackers after some time
  541.         if ((npc.getCurrentHp() == npc.getMaxHp()) && (npc.getCurrentMp() == npc.getMaxMp()) && !npc.getAttackByList().isEmpty() && (Rnd.nextInt(500) == 0))
  542.         {
  543.             npc.clearAggroList();
  544.             npc.getAttackByList().clear();
  545.             if (npc instanceof L2MonsterInstance)
  546.             {
  547.                 if (((L2MonsterInstance) npc).hasMinions())
  548.                 {
  549.                     ((L2MonsterInstance) npc).getMinionList().deleteReusedMinions();
  550.                 }
  551.             }
  552.         }
  553.  
  554.         // Check if the actor is a L2GuardInstance
  555.         if (npc instanceof L2GuardInstance)
  556.         {
  557.             // Order to the L2GuardInstance to return to its home location because there's no target to attack
  558.             // ((L2GuardInstance) npc).returnHome();
  559.         }
  560.  
  561.         // If this is a festival monster, then it remains in the same location.
  562.         if (npc instanceof L2FestivalMonsterInstance)
  563.         {
  564.             return;
  565.         }
  566.  
  567.         // Check if the mob should not return to spawn point
  568.         if (!npc.canReturnToSpawnPoint())
  569.         {
  570.             return;
  571.         }
  572.  
  573.         // Minions following leader
  574.         final L2Character leader = npc.getLeader();
  575.         if ((leader != null) && !leader.isAlikeDead())
  576.         {
  577.             final int offset;
  578.             final int minRadius = 30;
  579.  
  580.             if (npc.isRaidMinion())
  581.             {
  582.                 offset = 500; // for Raids - need correction
  583.             }
  584.             else
  585.             {
  586.                 offset = 200; // for normal minions - need correction :)
  587.             }
  588.  
  589.             if (leader.isRunning())
  590.             {
  591.                 npc.setRunning();
  592.             }
  593.             else
  594.             {
  595.                 npc.setWalking();
  596.             }
  597.  
  598.             if (npc.getPlanDistanceSq(leader) > (offset * offset))
  599.             {
  600.                 int x1, y1, z1;
  601.                 x1 = Rnd.get(minRadius * 2, offset * 2); // x
  602.                 y1 = Rnd.get(x1, offset * 2); // distance
  603.                 y1 = (int) Math.sqrt((y1 * y1) - (x1 * x1)); // y
  604.                 if (x1 > (offset + minRadius))
  605.                 {
  606.                     x1 = (leader.getX() + x1) - offset;
  607.                 }
  608.                 else
  609.                 {
  610.                     x1 = (leader.getX() - x1) + minRadius;
  611.                 }
  612.                 if (y1 > (offset + minRadius))
  613.                 {
  614.                     y1 = (leader.getY() + y1) - offset;
  615.                 }
  616.                 else
  617.                 {
  618.                     y1 = (leader.getY() - y1) + minRadius;
  619.                 }
  620.  
  621.                 z1 = leader.getZ();
  622.                 // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
  623.                 moveTo(x1, y1, z1);
  624.                 return;
  625.             }
  626.             else if (Rnd.nextInt(RANDOM_WALK_RATE) == 0)
  627.             {
  628.                 for (L2Skill sk : _skillrender.getBuffSkills())
  629.                 {
  630.                     if (cast(sk))
  631.                     {
  632.                         return;
  633.                     }
  634.                 }
  635.             }
  636.         }
  637.         // Order to the L2MonsterInstance to random walk (1/100)
  638.         else if ((npc.getSpawn() != null) && (Rnd.nextInt(RANDOM_WALK_RATE) == 0) && !npc.isNoRndWalk())
  639.         {
  640.             int x1, y1, z1;
  641.             final int range = Config.MAX_DRIFT_RANGE;
  642.  
  643.             for (L2Skill sk : _skillrender.getBuffSkills())
  644.             {
  645.                 if (cast(sk))
  646.                 {
  647.                     return;
  648.                 }
  649.             }
  650.  
  651.             // If NPC with random coord in territory
  652.             if ((npc.getSpawn().getLocx() == 0) && (npc.getSpawn().getLocy() == 0))
  653.             {
  654.                 // Calculate a destination point in the spawn area
  655.                 int p[] = TerritoryTable.getInstance().getRandomPoint(npc.getSpawn().getLocation());
  656.                 x1 = p[0];
  657.                 y1 = p[1];
  658.                 z1 = p[2];
  659.  
  660.                 // Calculate the distance between the current position of the L2Character and the target (x,y)
  661.                 double distance2 = npc.getPlanDistanceSq(x1, y1);
  662.  
  663.                 if (distance2 > ((range + range) * (range + range)))
  664.                 {
  665.                     npc.setisReturningToSpawnPoint(true);
  666.                     float delay = (float) Math.sqrt(distance2) / range;
  667.                     x1 = npc.getX() + (int) ((x1 - npc.getX()) / delay);
  668.                     y1 = npc.getY() + (int) ((y1 - npc.getY()) / delay);
  669.                 }
  670.  
  671.                 // If NPC with random fixed coord, don't move (unless needs to return to spawnpoint)
  672.                 if ((TerritoryTable.getInstance().getProcMax(npc.getSpawn().getLocation()) > 0) && !npc.isReturningToSpawnPoint())
  673.                 {
  674.                     return;
  675.                 }
  676.             }
  677.             else
  678.             {
  679.                 // If NPC with fixed coord
  680.                 x1 = npc.getSpawn().getLocx();
  681.                 y1 = npc.getSpawn().getLocy();
  682.                 z1 = npc.getSpawn().getLocz();
  683.  
  684.                 if (!npc.isInsideRadius(x1, y1, range, false))
  685.                 {
  686.                     npc.setisReturningToSpawnPoint(true);
  687.                 }
  688.                 else
  689.                 {
  690.                     x1 = Rnd.nextInt(range * 2); // x
  691.                     y1 = Rnd.get(x1, range * 2); // distance
  692.                     y1 = (int) Math.sqrt((y1 * y1) - (x1 * x1)); // y
  693.                     x1 += npc.getSpawn().getLocx() - range;
  694.                     y1 += npc.getSpawn().getLocy() - range;
  695.                     z1 = npc.getZ();
  696.                 }
  697.             }
  698.  
  699.             // _log.debug("Current pos ("+getX()+", "+getY()+"), moving to ("+x1+", "+y1+").");
  700.             // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
  701.             moveTo(x1, y1, z1);
  702.         }
  703.     }
  704.  
  705.     /**
  706.      * Manage AI attack thinks of a L2Attackable (called by onEvtThink). <B><U> Actions</U> :</B>
  707.      * <ul>
  708.      * <li>Update the attack timeout if actor is running</li>
  709.      * <li>If target is dead or timeout is expired, stop this attack and set the Intention to AI_INTENTION_ACTIVE</li>
  710.      * <li>Call all L2Object of its Faction inside the Faction Range</li>
  711.      * <li>Chose a target and order to attack it with magic skill or physical attack</li>
  712.      * </ul>
  713.      * TODO: Manage casting rules to healer mobs (like Ant Nurses)
  714.      */
  715.     private void thinkAttack()
  716.     {
  717.         final L2Attackable npc = getActiveChar();
  718.         if (npc.isCastingNow())
  719.         {
  720.             return;
  721.         }
  722.  
  723.         L2Character originalAttackTarget = getAttackTarget();
  724.         // Check if target is dead or if timeout is expired to stop this attack
  725.         if ((originalAttackTarget == null) || originalAttackTarget.isAlikeDead() || (_attackTimeout < GameTimeController.getInstance().getGameTicks()))
  726.         {
  727.             // Stop hating this target after the attack timeout or if target is dead
  728.             if (originalAttackTarget != null)
  729.             {
  730.                 npc.stopHating(originalAttackTarget);
  731.             }
  732.  
  733.             // Set the AI Intention to AI_INTENTION_ACTIVE
  734.             setIntention(AI_INTENTION_ACTIVE);
  735.  
  736.             npc.setWalking();
  737.             return;
  738.         }
  739.  
  740.         final int collision = npc.getTemplate().getCollisionRadius();
  741.  
  742.         // Handle all L2Object of its Faction inside the Faction Range
  743.  
  744.         String faction_id = getActiveChar().getFactionId();
  745.         if ((faction_id != null) && !faction_id.isEmpty())
  746.         {
  747.             int factionRange = npc.getClanRange() + collision;
  748.             // Go through all L2Object that belong to its faction
  749.             Collection<L2Object> objs = npc.getKnownList().getKnownObjects().values();
  750.  
  751.             try
  752.             {
  753.                 for (L2Object obj : objs)
  754.                 {
  755.                     if (obj instanceof L2Npc)
  756.                     {
  757.                         L2Npc called = (L2Npc) obj;
  758.  
  759.                         // Handle SevenSigns mob Factions
  760.                         final String npcfaction = called.getFactionId();
  761.                         if ((npcfaction == null) || npcfaction.isEmpty())
  762.                         {
  763.                             continue;
  764.                         }
  765.  
  766.                         boolean sevenSignFaction = false;
  767.  
  768.                         // TODO: Unhardcode this by AI scripts (DrHouse)
  769.                         // Catacomb mobs should assist lilim and nephilim other than dungeon
  770.                         if ("c_dungeon_clan".equals(faction_id) && ("c_dungeon_lilim".equals(npcfaction) || "c_dungeon_nephi".equals(npcfaction)))
  771.                         {
  772.                             sevenSignFaction = true;
  773.                         }
  774.                         // Lilim mobs should assist other Lilim and catacomb mobs
  775.                         else if ("c_dungeon_lilim".equals(faction_id) && "c_dungeon_clan".equals(npcfaction))
  776.                         {
  777.                             sevenSignFaction = true;
  778.                         }
  779.                         // Nephilim mobs should assist other Nephilim and catacomb mobs
  780.                         else if ("c_dungeon_nephi".equals(faction_id) && "c_dungeon_clan".equals(npcfaction))
  781.                         {
  782.                             sevenSignFaction = true;
  783.                         }
  784.  
  785.                         if (!faction_id.equals(npcfaction) && !sevenSignFaction)
  786.                         {
  787.                             continue;
  788.                         }
  789.  
  790.                         // Check if the L2Object is inside the Faction Range of the actor
  791.                         if (npc.isInsideRadius(called, factionRange, true, false) && called.hasAI())
  792.                         {
  793.                             if ((Math.abs(originalAttackTarget.getZ() - called.getZ()) < 600) && npc.getAttackByList().contains(originalAttackTarget) && ((called.getAI()._intention == CtrlIntention.AI_INTENTION_IDLE) || (called.getAI()._intention == CtrlIntention.AI_INTENTION_ACTIVE)) && (called.getInstanceId() == npc.getInstanceId()))
  794.                                 // && GeoData.getInstance().canSeeTarget(called, npc))
  795.                             {
  796.                                 if (originalAttackTarget.isPlayable())
  797.                                 {
  798.                                     List<Quest> quests = called.getTemplate().getEventQuests(QuestEventType.ON_FACTION_CALL);
  799.                                     if ((quests != null) && !quests.isEmpty())
  800.                                     {
  801.                                         L2PcInstance player = originalAttackTarget.getActingPlayer();
  802.                                         boolean isSummon = originalAttackTarget.isSummon();
  803.                                         for (Quest quest : quests)
  804.                                         {
  805.                                             quest.notifyFactionCall(called, getActiveChar(), player, isSummon);
  806.                                         }
  807.                                     }
  808.                                 }
  809.                                 else if ((called instanceof L2Attackable) && (getAttackTarget() != null) && (called.getAI()._intention != CtrlIntention.AI_INTENTION_ATTACK))
  810.                                 {
  811.                                     ((L2Attackable) called).addDamageHate(getAttackTarget(), 0, npc.getHating(getAttackTarget()));
  812.                                     called.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, getAttackTarget());
  813.                                 }
  814.                             }
  815.                         }
  816.                     }
  817.                 }
  818.             }
  819.             catch (NullPointerException e)
  820.             {
  821.                 _log.warning(getClass().getSimpleName() + ": thinkAttack() faction call failed: " + e.getMessage());
  822.             }
  823.         }
  824.  
  825.         if (npc.isCoreAIDisabled())
  826.         {
  827.             return;
  828.         }
  829.  
  830.         // Initialize data
  831.         L2Character mostHate = npc.getMostHated();
  832.         if (mostHate == null)
  833.         {
  834.             setIntention(AI_INTENTION_ACTIVE);
  835.             return;
  836.         }
  837.  
  838.         setAttackTarget(mostHate);
  839.         npc.setTarget(mostHate);
  840.  
  841.         final int combinedCollision = collision + mostHate.getTemplate().getCollisionRadius();
  842.  
  843.         if (!_skillrender.getSuicideSkills().isEmpty() && ((int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100) < 30))
  844.         {
  845.             final L2Skill skill = _skillrender.getSuicideSkills().get(Rnd.nextInt(_skillrender.getSuicideSkills().size()));
  846.             if (Util.checkIfInRange(skill.getAffectRange(), getActiveChar(), mostHate, false) && (Rnd.get(100) < Rnd.get(npc.getMinSkillChance(), npc.getMaxSkillChance())))
  847.             {
  848.                 if (cast(skill))
  849.                 {
  850.                     return;
  851.                 }
  852.  
  853.                 for (L2Skill sk : _skillrender.getSuicideSkills())
  854.                 {
  855.                     if (cast(sk))
  856.                     {
  857.                         return;
  858.                     }
  859.                 }
  860.             }
  861.         }
  862.         // BICHOS JUNTOS
  863.         // ------------------------------------------------------
  864.         // In case many mobs are trying to hit from same place, move a bit,
  865.         // circling around the target
  866.         // Note from Gnacik:
  867.         // On l2js because of that sometimes mobs don't attack player only running
  868.         // around player without any sense, so decrease chance for now
  869.         if (!npc.isMovementDisabled() && (Rnd.nextInt(100) <= 30))
  870.         {
  871.             for (L2Object nearby : npc.getKnownList().getKnownObjects().values())
  872.             {
  873.                 if ((nearby instanceof L2Attackable) && npc.isInsideRadius(nearby, collision, false, false) && (nearby != mostHate))
  874.                 {
  875.                     int newX = combinedCollision + Rnd.get(40);
  876.                     if (Rnd.nextBoolean())
  877.                     {
  878.                         newX = mostHate.getX() + newX;
  879.                     }
  880.                     else
  881.                     {
  882.                         newX = mostHate.getX() - newX;
  883.                     }
  884.                     int newY = combinedCollision + Rnd.get(40);
  885.                     if (Rnd.nextBoolean())
  886.                     {
  887.                         newY = mostHate.getY() + newY;
  888.                     }
  889.                     else
  890.                     {
  891.                         newY = mostHate.getY() - newY;
  892.                     }
  893.  
  894.                     if (!npc.isInsideRadius(newX, newY, collision, false))
  895.                     {
  896.                         int newZ = npc.getZ() + 30;
  897.                         if ((Config.GEODATA == 0) || GeoData.getInstance().canMoveFromToTarget(npc.getX(), npc.getY(), npc.getZ(), newX, newY, newZ, npc.getInstanceId()))
  898.                         {
  899.                             moveTo(newX, newY, newZ);
  900.                         }
  901.                     }
  902.                     return;
  903.                 }
  904.             }
  905.         }
  906.         // Dodge if its needed
  907.         if (!npc.isMovementDisabled() && (npc.getCanDodge() > 0))
  908.         {
  909.             if (Rnd.get(100) <= npc.getCanDodge())
  910.             {
  911.                 // Micht: kepping this one otherwise we should do 2 sqrt
  912.                 double distance2 = npc.getPlanDistanceSq(mostHate.getX(), mostHate.getY());
  913.                 if (Math.sqrt(distance2) <= (60 + combinedCollision))
  914.                 {
  915.                     int posX = npc.getX();
  916.                     int posY = npc.getY();
  917.                     int posZ = npc.getZ() + 30;
  918.  
  919.                     if (originalAttackTarget.getX() < posX)
  920.                     {
  921.                         posX = posX + 300;
  922.                     }
  923.                     else
  924.                     {
  925.                         posX = posX - 300;
  926.                     }
  927.  
  928.                     if (originalAttackTarget.getY() < posY)
  929.                     {
  930.                         posY = posY + 300;
  931.                     }
  932.                     else
  933.                     {
  934.                         posY = posY - 300;
  935.                     }
  936.  
  937.                     if ((Config.GEODATA == 0) || GeoData.getInstance().canMoveFromToTarget(npc.getX(), npc.getY(), npc.getZ(), posX, posY, posZ, npc.getInstanceId()))
  938.                     {
  939.                         setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(posX, posY, posZ, 0));
  940.                     }
  941.                     return;
  942.                 }
  943.             }
  944.         }
  945.  
  946.         // ------------------------------------------------------------------------------
  947.         // BOSS/Raid Minion Target Reconsider
  948.         if (npc.isRaid() || npc.isRaidMinion())
  949.         {
  950.             chaostime++;
  951.             if (npc instanceof L2RaidBossInstance)
  952.             {
  953.                 if (!((L2MonsterInstance) npc).hasMinions())
  954.                 {
  955.                     if (chaostime > Config.RAID_CHAOS_TIME)
  956.                     {
  957.                         if (Rnd.get(100) <= (100 - ((npc.getCurrentHp() * 100) / npc.getMaxHp())))
  958.                         {
  959.                             aggroReconsider();
  960.                             chaostime = 0;
  961.                             return;
  962.                         }
  963.                     }
  964.                 }
  965.                 else
  966.                 {
  967.                     if (chaostime > Config.RAID_CHAOS_TIME)
  968.                     {
  969.                         if (Rnd.get(100) <= (100 - ((npc.getCurrentHp() * 200) / npc.getMaxHp())))
  970.                         {
  971.                             aggroReconsider();
  972.                             chaostime = 0;
  973.                             return;
  974.                         }
  975.                     }
  976.                 }
  977.             }
  978.             else if (npc instanceof L2GrandBossInstance)
  979.             {
  980.                 if (chaostime > Config.GRAND_CHAOS_TIME)
  981.                 {
  982.                     double chaosRate = 100 - ((npc.getCurrentHp() * 300) / npc.getMaxHp());
  983.                     if (((chaosRate <= 10) && (Rnd.get(100) <= 10)) || ((chaosRate > 10) && (Rnd.get(100) <= chaosRate)))
  984.                     {
  985.                         aggroReconsider();
  986.                         chaostime = 0;
  987.                         return;
  988.                     }
  989.                 }
  990.             }
  991.             else
  992.             {
  993.                 if (chaostime > Config.MINION_CHAOS_TIME)
  994.                 {
  995.                     if (Rnd.get(100) <= (100 - ((npc.getCurrentHp() * 200) / npc.getMaxHp())))
  996.                     {
  997.                         aggroReconsider();
  998.                         chaostime = 0;
  999.                         return;
  1000.                     }
  1001.                 }
  1002.             }
  1003.         }
  1004.  
  1005.         if (!_skillrender.getGeneralskills().isEmpty())
  1006.         {
  1007.             // -------------------------------------------------------------------------------
  1008.             // Heal Condition
  1009.             if (!_skillrender.getHealSkills().isEmpty())
  1010.             {
  1011.                 double percentage = (npc.getCurrentHp() / npc.getMaxHp()) * 100;
  1012.                 if (npc.isMinion())
  1013.                 {
  1014.                     L2Character leader = npc.getLeader();
  1015.                     if ((leader != null) && !leader.isDead() && (Rnd.get(100) > ((leader.getCurrentHp() / leader.getMaxHp()) * 100)))
  1016.                     {
  1017.                         for (L2Skill sk : _skillrender.getHealSkills())
  1018.                         {
  1019.                             if (sk.getTargetType() == L2TargetType.SELF)
  1020.                             {
  1021.                                 continue;
  1022.                             }
  1023.                             if (!checkSkillCastConditions(sk))
  1024.                             {
  1025.                                 continue;
  1026.                             }
  1027.                             if (!Util.checkIfInRange((sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius()), npc, leader, false) && !isParty(sk) && !npc.isMovementDisabled())
  1028.                             {
  1029.                                 moveToPawn(leader, sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius());
  1030.                                 return;
  1031.                             }
  1032.                             if (GeoData.getInstance().canSeeTarget(npc, leader))
  1033.                             {
  1034.                                 clientStopMoving(null);
  1035.                                 npc.setTarget(leader);
  1036.                                 clientStopMoving(null);
  1037.                                 npc.doCast(sk);
  1038.                                 return;
  1039.                             }
  1040.                         }
  1041.                     }
  1042.                 }
  1043.                 if (Rnd.get(100) < ((100 - percentage) / 3))
  1044.                 {
  1045.                     for (L2Skill sk : _skillrender.getHealSkills())
  1046.                     {
  1047.                         if (!checkSkillCastConditions(sk))
  1048.                         {
  1049.                             continue;
  1050.                         }
  1051.                         clientStopMoving(null);
  1052.                         npc.setTarget(npc);
  1053.                         npc.doCast(sk);
  1054.                         return;
  1055.                     }
  1056.                 }
  1057.                 for (L2Skill sk : _skillrender.getHealSkills())
  1058.                 {
  1059.                     if (!checkSkillCastConditions(sk))
  1060.                     {
  1061.                         continue;
  1062.                     }
  1063.                     if (sk.getTargetType() == L2TargetType.ONE)
  1064.                     {
  1065.                         for (L2Character obj : npc.getKnownList().getKnownCharactersInRadius(sk.getCastRange() + collision))
  1066.                         {
  1067.                             if (!(obj instanceof L2Attackable) || obj.isDead())
  1068.                             {
  1069.                                 continue;
  1070.                             }
  1071.  
  1072.                             L2Attackable targets = ((L2Attackable) obj);
  1073.                             if ((npc.getFactionId() != null) && !npc.getFactionId().equals(targets.getFactionId()))
  1074.                             {
  1075.                                 continue;
  1076.                             }
  1077.                             percentage = (targets.getCurrentHp() / targets.getMaxHp()) * 100;
  1078.                             if (Rnd.get(100) < ((100 - percentage) / 10))
  1079.                             {
  1080.                                 if (GeoData.getInstance().canSeeTarget(npc, targets))
  1081.                                 {
  1082.                                     clientStopMoving(null);
  1083.                                     npc.setTarget(obj);
  1084.                                     npc.doCast(sk);
  1085.                                     return;
  1086.                                 }
  1087.                             }
  1088.                         }
  1089.                     }
  1090.                     if (isParty(sk))
  1091.                     {
  1092.                         clientStopMoving(null);
  1093.                         npc.doCast(sk);
  1094.                         return;
  1095.                     }
  1096.                 }
  1097.             }
  1098.             // -------------------------------------------------------------------------------
  1099.             // Res Skill Condition
  1100.             if (!_skillrender.getResSkills().isEmpty())
  1101.             {
  1102.                 if (npc.isMinion())
  1103.                 {
  1104.                     L2Character leader = npc.getLeader();
  1105.                     if ((leader != null) && leader.isDead())
  1106.                     {
  1107.                         for (L2Skill sk : _skillrender.getResSkills())
  1108.                         {
  1109.                             if (sk.getTargetType() == L2TargetType.SELF)
  1110.                             {
  1111.                                 continue;
  1112.                             }
  1113.                             if (!checkSkillCastConditions(sk))
  1114.                             {
  1115.                                 continue;
  1116.                             }
  1117.                             if (!Util.checkIfInRange((sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius()), npc, leader, false) && !isParty(sk) && !npc.isMovementDisabled())
  1118.                             {
  1119.                                 moveToPawn(leader, sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius());
  1120.                                 return;
  1121.                             }
  1122.                             if (GeoData.getInstance().canSeeTarget(npc, leader))
  1123.                             {
  1124.                                 clientStopMoving(null);
  1125.                                 npc.setTarget(leader);
  1126.                                 npc.doCast(sk);
  1127.                                 return;
  1128.                             }
  1129.                         }
  1130.                     }
  1131.                 }
  1132.                 for (L2Skill sk : _skillrender.getResSkills())
  1133.                 {
  1134.                     if (!checkSkillCastConditions(sk))
  1135.                     {
  1136.                         continue;
  1137.                     }
  1138.                     if (sk.getTargetType() == L2TargetType.ONE)
  1139.                     {
  1140.                         for (L2Character obj : npc.getKnownList().getKnownCharactersInRadius(sk.getCastRange() + collision))
  1141.                         {
  1142.                             if (!(obj instanceof L2Attackable) || !obj.isDead())
  1143.                             {
  1144.                                 continue;
  1145.                             }
  1146.  
  1147.                             L2Attackable targets = ((L2Attackable) obj);
  1148.                             if ((npc.getFactionId() != null) && !npc.getFactionId().equals(targets.getFactionId()))
  1149.                             {
  1150.                                 continue;
  1151.                             }
  1152.                             if (Rnd.get(100) < 10)
  1153.                             {
  1154.                                 if (GeoData.getInstance().canSeeTarget(npc, targets))
  1155.                                 {
  1156.                                     clientStopMoving(null);
  1157.                                     npc.setTarget(obj);
  1158.                                     npc.doCast(sk);
  1159.                                     return;
  1160.                                 }
  1161.                             }
  1162.                         }
  1163.                     }
  1164.                     if (isParty(sk))
  1165.                     {
  1166.                         clientStopMoving(null);
  1167.                         L2Object target = getAttackTarget();
  1168.                         npc.setTarget(npc);
  1169.                         npc.doCast(sk);
  1170.                         npc.setTarget(target);
  1171.                         return;
  1172.                     }
  1173.                 }
  1174.             }
  1175.         }
  1176.  
  1177.         double dist = Math.sqrt(npc.getPlanDistanceSq(mostHate.getX(), mostHate.getY()));
  1178.         int dist2 = (int) dist - collision;
  1179.         int range = npc.getPhysicalAttackRange() + combinedCollision;
  1180.         if (mostHate.isMoving())
  1181.         {
  1182.             range = range + 50;
  1183.             if (npc.isMoving())
  1184.             {
  1185.                 range = range + 50;
  1186.             }
  1187.         }
  1188.  
  1189.         // -------------------------------------------------------------------------------
  1190.         // Immobilize Condition
  1191.         if ((npc.isMovementDisabled() && ((dist > range) || mostHate.isMoving())) || ((dist > range) && mostHate.isMoving()))
  1192.         {
  1193.             movementDisable();
  1194.             return;
  1195.         }
  1196.  
  1197.         setTimepass(0);
  1198.         // --------------------------------------------------------------------------------
  1199.         // Skill Use
  1200.         if (!_skillrender.getGeneralskills().isEmpty())
  1201.         {
  1202.             if (Rnd.get(100) < Rnd.get(npc.getMinSkillChance(), npc.getMaxSkillChance()))
  1203.             {
  1204.                 L2Skill skills = _skillrender.getGeneralskills().get(Rnd.nextInt(_skillrender.getGeneralskills().size()));
  1205.                 if (cast(skills))
  1206.                 {
  1207.                     return;
  1208.                 }
  1209.                 for (L2Skill sk : _skillrender.getGeneralskills())
  1210.                 {
  1211.                     if (cast(sk))
  1212.                     {
  1213.                         return;
  1214.                     }
  1215.                 }
  1216.             }
  1217.  
  1218.             // --------------------------------------------------------------------------------
  1219.             // Long/Short Range skill usage.
  1220.             if (npc.hasLSkill() || npc.hasSSkill())
  1221.             {
  1222.                 final List<L2Skill> shortRangeSkills = shortRangeSkillRender();
  1223.                 if (!shortRangeSkills.isEmpty() && npc.hasSSkill() && (dist2 <= 150) && (Rnd.get(100) <= npc.getSSkillChance()))
  1224.                 {
  1225.                     final L2Skill shortRangeSkill = shortRangeSkills.get(Rnd.get(shortRangeSkills.size()));
  1226.                     if ((shortRangeSkill != null) && cast(shortRangeSkill))
  1227.                     {
  1228.                         return;
  1229.                     }
  1230.                     for (L2Skill sk : shortRangeSkills)
  1231.                     {
  1232.                         if ((sk != null) && cast(sk))
  1233.                         {
  1234.                             return;
  1235.                         }
  1236.                     }
  1237.                 }
  1238.  
  1239.                 final List<L2Skill> longRangeSkills = longRangeSkillRender();
  1240.                 if (!longRangeSkills.isEmpty() && npc.hasLSkill() && (dist2 > 150) && (Rnd.get(100) <= npc.getLSkillChance()))
  1241.                 {
  1242.                     final L2Skill longRangeSkill = longRangeSkills.get(Rnd.get(longRangeSkills.size()));
  1243.                     if ((longRangeSkill != null) && cast(longRangeSkill))
  1244.                     {
  1245.                         return;
  1246.                     }
  1247.                     for (L2Skill sk : longRangeSkills)
  1248.                     {
  1249.                         if ((sk != null) && cast(sk))
  1250.                         {
  1251.                             return;
  1252.                         }
  1253.                     }
  1254.                 }
  1255.             }
  1256.         }
  1257.  
  1258.         // --------------------------------------------------------------------------------
  1259.         // Starts Melee or Primary Skill
  1260.         if ((dist2 > range) || !GeoData.getInstance().canSeeTarget(npc, mostHate))
  1261.         {
  1262.             if (npc.isMovementDisabled())
  1263.             {
  1264.                 targetReconsider();
  1265.             }
  1266.             else if (getAttackTarget() != null)
  1267.             {
  1268.                 if (getAttackTarget().isMoving())
  1269.                 {
  1270.                     range -= 100;
  1271.                 }
  1272.                 if (range < 5)
  1273.                 {
  1274.                     range = 5;
  1275.                 }
  1276.                 moveToPawn(getAttackTarget(), range);
  1277.             }
  1278.             return;
  1279.         }
  1280.  
  1281.         melee(npc.getPrimarySkillId());
  1282.     }
  1283.  
  1284.     private void melee(int type)
  1285.     {
  1286.         if (type != 0)
  1287.         {
  1288.             switch (type)
  1289.             {
  1290.                 case -1:
  1291.                 {
  1292.                     if (_skillrender.getGeneralskills() != null)
  1293.                     {
  1294.                         for (L2Skill sk : _skillrender.getGeneralskills())
  1295.                         {
  1296.                             if (cast(sk))
  1297.                             {
  1298.                                 return;
  1299.                             }
  1300.                         }
  1301.                     }
  1302.                     break;
  1303.                 }
  1304.                 case 1:
  1305.                 {
  1306.                     for (L2Skill sk : _skillrender.getAtkSkills())
  1307.                     {
  1308.                         if (cast(sk))
  1309.                         {
  1310.                             return;
  1311.                         }
  1312.                     }
  1313.                     break;
  1314.                 }
  1315.                 default:
  1316.                 {
  1317.                     for (L2Skill sk : _skillrender.getGeneralskills())
  1318.                     {
  1319.                         if (sk.getId() == getActiveChar().getPrimarySkillId())
  1320.                         {
  1321.                             if (cast(sk))
  1322.                             {
  1323.                                 return;
  1324.                             }
  1325.                         }
  1326.                     }
  1327.                 }
  1328.                 break;
  1329.             }
  1330.         }
  1331.  
  1332.         _accessor.doAttack(getAttackTarget());
  1333.     }
  1334.  
  1335.     private boolean cast(L2Skill sk)
  1336.     {
  1337.         if (sk == null)
  1338.         {
  1339.             return false;
  1340.         }
  1341.  
  1342.         final L2Attackable caster = getActiveChar();
  1343.  
  1344.         if (caster.isCastingNow() && !sk.isSimultaneousCast())
  1345.         {
  1346.             return false;
  1347.         }
  1348.  
  1349.         if (!checkSkillCastConditions(sk))
  1350.         {
  1351.             return false;
  1352.         }
  1353.         if (getAttackTarget() == null)
  1354.         {
  1355.             if (caster.getMostHated() != null)
  1356.             {
  1357.                 setAttackTarget(caster.getMostHated());
  1358.             }
  1359.         }
  1360.         L2Character attackTarget = getAttackTarget();
  1361.         if (attackTarget == null)
  1362.         {
  1363.             return false;
  1364.         }
  1365.         double dist = Math.sqrt(caster.getPlanDistanceSq(attackTarget.getX(), attackTarget.getY()));
  1366.         double dist2 = dist - attackTarget.getTemplate().getCollisionRadius();
  1367.         double range = caster.getPhysicalAttackRange() + caster.getTemplate().getCollisionRadius() + attackTarget.getTemplate().getCollisionRadius();
  1368.         double srange = sk.getCastRange() + caster.getTemplate().getCollisionRadius();
  1369.         if (attackTarget.isMoving())
  1370.         {
  1371.             dist2 = dist2 - 30;
  1372.         }
  1373.  
  1374.         switch (sk.getSkillType())
  1375.         {
  1376.             case BUFF:
  1377.             {
  1378.                 if (caster.getFirstEffect(sk) == null)
  1379.                 {
  1380.                     clientStopMoving(null);
  1381.                     // L2Object target = attackTarget;
  1382.                     caster.setTarget(caster);
  1383.                     caster.doCast(sk);
  1384.                     // _actor.setTarget(target);
  1385.                     return true;
  1386.                 }
  1387.                 // ----------------------------------------
  1388.                 // If actor already have buff, start looking at others same faction mob to cast
  1389.                 if (sk.getTargetType() == L2TargetType.SELF)
  1390.                 {
  1391.                     return false;
  1392.                 }
  1393.                 if (sk.getTargetType() == L2TargetType.ONE)
  1394.                 {
  1395.                     L2Character target = effectTargetReconsider(sk, true);
  1396.                     if (target != null)
  1397.                     {
  1398.                         clientStopMoving(null);
  1399.                         L2Object targets = attackTarget;
  1400.                         caster.setTarget(target);
  1401.                         caster.doCast(sk);
  1402.                         caster.setTarget(targets);
  1403.                         return true;
  1404.                     }
  1405.                 }
  1406.                 if (canParty(sk))
  1407.                 {
  1408.                     clientStopMoving(null);
  1409.                     L2Object targets = attackTarget;
  1410.                     caster.setTarget(caster);
  1411.                     caster.doCast(sk);
  1412.                     caster.setTarget(targets);
  1413.                     return true;
  1414.                 }
  1415.                 break;
  1416.             }
  1417.             case RESURRECT:
  1418.             {
  1419.                 if (!isParty(sk))
  1420.                 {
  1421.                     if (caster.isMinion() && (sk.getTargetType() != L2TargetType.SELF))
  1422.                     {
  1423.                         L2Character leader = caster.getLeader();
  1424.                         if ((leader != null) && leader.isDead())
  1425.                         {
  1426.                             if (!Util.checkIfInRange((sk.getCastRange() + caster.getTemplate().getCollisionRadius() + leader.getTemplate().getCollisionRadius()), caster, leader, false) && !isParty(sk) && !caster.isMovementDisabled())
  1427.                             {
  1428.                                 moveToPawn(leader, sk.getCastRange() + caster.getTemplate().getCollisionRadius() + leader.getTemplate().getCollisionRadius());
  1429.                             }
  1430.                         }
  1431.                         if (GeoData.getInstance().canSeeTarget(caster, leader))
  1432.                         {
  1433.                             clientStopMoving(null);
  1434.                             caster.setTarget(leader);
  1435.                             caster.doCast(sk);
  1436.                             return true;
  1437.                         }
  1438.                     }
  1439.  
  1440.                     for (L2Character obj : caster.getKnownList().getKnownCharactersInRadius(sk.getCastRange() + caster.getTemplate().getCollisionRadius()))
  1441.                     {
  1442.                         if (!(obj instanceof L2Attackable) || !obj.isDead())
  1443.                         {
  1444.                             continue;
  1445.                         }
  1446.  
  1447.                         L2Attackable targets = ((L2Attackable) obj);
  1448.                         if ((caster.getFactionId() != null) && !caster.getFactionId().equals(targets.getFactionId()))
  1449.                         {
  1450.                             continue;
  1451.                         }
  1452.                         if (Rnd.get(100) < 10)
  1453.                         {
  1454.                             if (GeoData.getInstance().canSeeTarget(caster, targets))
  1455.                             {
  1456.                                 clientStopMoving(null);
  1457.                                 caster.setTarget(obj);
  1458.                                 caster.doCast(sk);
  1459.                                 return true;
  1460.                             }
  1461.                         }
  1462.                     }
  1463.                 }
  1464.                 else if (isParty(sk))
  1465.                 {
  1466.                     for (L2Character obj : caster.getKnownList().getKnownCharactersInRadius(sk.getAffectRange() + caster.getTemplate().getCollisionRadius()))
  1467.                     {
  1468.                         if (!(obj instanceof L2Attackable))
  1469.                         {
  1470.                             continue;
  1471.                         }
  1472.                         L2Npc targets = ((L2Npc) obj);
  1473.                         if ((caster.getFactionId() != null) && caster.getFactionId().equals(targets.getFactionId()))
  1474.                         {
  1475.                             if ((obj.getCurrentHp() < obj.getMaxHp()) && (Rnd.get(100) <= 20))
  1476.                             {
  1477.                                 clientStopMoving(null);
  1478.                                 caster.setTarget(caster);
  1479.                                 caster.doCast(sk);
  1480.                                 return true;
  1481.                             }
  1482.                         }
  1483.                     }
  1484.                 }
  1485.                 break;
  1486.             }
  1487.             case DEBUFF:
  1488.             case POISON:
  1489.             case DOT:
  1490.             case MDOT:
  1491.             case BLEED:
  1492.             {
  1493.                 if (GeoData.getInstance().canSeeTarget(caster, attackTarget) && !canAOE(sk) && !attackTarget.isDead() && (dist2 <= srange))
  1494.                 {
  1495.                     if (attackTarget.getFirstEffect(sk) == null)
  1496.                     {
  1497.                         clientStopMoving(null);
  1498.                         caster.doCast(sk);
  1499.                         return true;
  1500.                     }
  1501.                 }
  1502.                 else if (canAOE(sk))
  1503.                 {
  1504.                     if ((sk.getTargetType() == L2TargetType.AURA) || (sk.getTargetType() == L2TargetType.BEHIND_AURA) || (sk.getTargetType() == L2TargetType.FRONT_AURA) || (sk.getTargetType() == L2TargetType.AURA_CORPSE_MOB))
  1505.                     {
  1506.                         clientStopMoving(null);
  1507.                         // L2Object target = attackTarget;
  1508.                         // _actor.setTarget(_actor);
  1509.                         caster.doCast(sk);
  1510.                         // _actor.setTarget(target);
  1511.                         return true;
  1512.                     }
  1513.                     if (((sk.getTargetType() == L2TargetType.AREA) || (sk.getTargetType() == L2TargetType.BEHIND_AREA) || (sk.getTargetType() == L2TargetType.FRONT_AREA)) && GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
  1514.                     {
  1515.                         clientStopMoving(null);
  1516.                         caster.doCast(sk);
  1517.                         return true;
  1518.                     }
  1519.                 }
  1520.                 else if (sk.getTargetType() == L2TargetType.ONE)
  1521.                 {
  1522.                     L2Character target = effectTargetReconsider(sk, false);
  1523.                     if (target != null)
  1524.                     {
  1525.                         clientStopMoving(null);
  1526.                         caster.doCast(sk);
  1527.                         return true;
  1528.                     }
  1529.                 }
  1530.                 break;
  1531.             }
  1532.             case SLEEP:
  1533.             {
  1534.                 if (sk.getTargetType() == L2TargetType.ONE)
  1535.                 {
  1536.                     if (!attackTarget.isDead() && (dist2 <= srange))
  1537.                     {
  1538.                         if ((dist2 > range) || attackTarget.isMoving())
  1539.                         {
  1540.                             if (attackTarget.getFirstEffect(sk) == null)
  1541.                             {
  1542.                                 clientStopMoving(null);
  1543.                                 // _actor.setTarget(attackTarget);
  1544.                                 caster.doCast(sk);
  1545.                                 return true;
  1546.                             }
  1547.                         }
  1548.                     }
  1549.  
  1550.                     L2Character target = effectTargetReconsider(sk, false);
  1551.                     if (target != null)
  1552.                     {
  1553.                         clientStopMoving(null);
  1554.                         caster.doCast(sk);
  1555.                         return true;
  1556.                     }
  1557.                 }
  1558.                 else if (canAOE(sk))
  1559.                 {
  1560.                     if ((sk.getTargetType() == L2TargetType.AURA) || (sk.getTargetType() == L2TargetType.BEHIND_AURA) || (sk.getTargetType() == L2TargetType.FRONT_AURA))
  1561.                     {
  1562.                         clientStopMoving(null);
  1563.                         // L2Object target = attackTarget;
  1564.                         // _actor.setTarget(_actor);
  1565.                         caster.doCast(sk);
  1566.                         // _actor.setTarget(target);
  1567.                         return true;
  1568.                     }
  1569.                     if (((sk.getTargetType() == L2TargetType.AREA) || (sk.getTargetType() == L2TargetType.BEHIND_AREA) || (sk.getTargetType() == L2TargetType.FRONT_AREA)) && GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
  1570.                     {
  1571.                         clientStopMoving(null);
  1572.                         caster.doCast(sk);
  1573.                         return true;
  1574.                     }
  1575.                 }
  1576.                 break;
  1577.             }
  1578.             case ROOT:
  1579.             case STUN:
  1580.             case PARALYZE:
  1581.             case MUTE:
  1582.             case FEAR:
  1583.             {
  1584.                 if (GeoData.getInstance().canSeeTarget(caster, attackTarget) && !canAOE(sk) && (dist2 <= srange))
  1585.                 {
  1586.                     if (attackTarget.getFirstEffect(sk) == null)
  1587.                     {
  1588.                         clientStopMoving(null);
  1589.                         caster.doCast(sk);
  1590.                         return true;
  1591.                     }
  1592.                 }
  1593.                 else if (canAOE(sk))
  1594.                 {
  1595.                     if ((sk.getTargetType() == L2TargetType.AURA) || (sk.getTargetType() == L2TargetType.BEHIND_AURA) || (sk.getTargetType() == L2TargetType.FRONT_AURA))
  1596.                     {
  1597.                         clientStopMoving(null);
  1598.                         // L2Object target = attackTarget;
  1599.                         // _actor.setTarget(_actor);
  1600.                         caster.doCast(sk);
  1601.                         // _actor.setTarget(target);
  1602.                         return true;
  1603.                     }
  1604.                     if (((sk.getTargetType() == L2TargetType.AREA) || (sk.getTargetType() == L2TargetType.BEHIND_AREA) || (sk.getTargetType() == L2TargetType.FRONT_AREA)) && GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
  1605.                     {
  1606.                         clientStopMoving(null);
  1607.                         caster.doCast(sk);
  1608.                         return true;
  1609.                     }
  1610.                 }
  1611.                 else if (sk.getTargetType() == L2TargetType.ONE)
  1612.                 {
  1613.                     L2Character target = effectTargetReconsider(sk, false);
  1614.                     if (target != null)
  1615.                     {
  1616.                         clientStopMoving(null);
  1617.                         caster.doCast(sk);
  1618.                         return true;
  1619.                     }
  1620.                 }
  1621.                 break;
  1622.             }
  1623.             case PDAM:
  1624.             case MDAM:
  1625.             case BLOW:
  1626.             case DRAIN:
  1627.             case CHARGEDAM:
  1628.             case FATAL:
  1629.             case DEATHLINK:
  1630.             case MANADAM:
  1631.             case CPDAMPERCENT:
  1632.             {
  1633.                 if (!canAura(sk))
  1634.                 {
  1635.                     if (GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
  1636.                     {
  1637.                         clientStopMoving(null);
  1638.                         caster.doCast(sk);
  1639.                         return true;
  1640.                     }
  1641.  
  1642.                     L2Character target = skillTargetReconsider(sk);
  1643.                     if (target != null)
  1644.                     {
  1645.                         clientStopMoving(null);
  1646.                         L2Object targets = attackTarget;
  1647.                         caster.setTarget(target);
  1648.                         caster.doCast(sk);
  1649.                         caster.setTarget(targets);
  1650.                         return true;
  1651.                     }
  1652.                 }
  1653.                 else
  1654.                 {
  1655.                     clientStopMoving(null);
  1656.                     caster.doCast(sk);
  1657.                     return true;
  1658.                 }
  1659.                 break;
  1660.             }
  1661.             default:
  1662.             {
  1663.                 if (sk.hasEffectType(L2EffectType.CANCEL, L2EffectType.CANCEL_ALL, L2EffectType.NEGATE))
  1664.                 {
  1665.                     // decrease cancel probability
  1666.                     if (Rnd.get(50) != 0)
  1667.                     {
  1668.                         return true;
  1669.                     }
  1670.  
  1671.                     if (sk.getTargetType() == L2TargetType.ONE)
  1672.                     {
  1673.                         if ((attackTarget.getFirstEffect(L2EffectType.BUFF) != null) && GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
  1674.                         {
  1675.                             clientStopMoving(null);
  1676.                             // L2Object target = attackTarget;
  1677.                             // _actor.setTarget(_actor);
  1678.                             caster.doCast(sk);
  1679.                             // _actor.setTarget(target);
  1680.                             return true;
  1681.                         }
  1682.                         L2Character target = effectTargetReconsider(sk, false);
  1683.                         if (target != null)
  1684.                         {
  1685.                             clientStopMoving(null);
  1686.                             L2Object targets = attackTarget;
  1687.                             caster.setTarget(target);
  1688.                             caster.doCast(sk);
  1689.                             caster.setTarget(targets);
  1690.                             return true;
  1691.                         }
  1692.                     }
  1693.                     else if (canAOE(sk))
  1694.                     {
  1695.                         if (((sk.getTargetType() == L2TargetType.AURA) || (sk.getTargetType() == L2TargetType.BEHIND_AURA) || (sk.getTargetType() == L2TargetType.FRONT_AURA)) && GeoData.getInstance().canSeeTarget(caster, attackTarget))
  1696.  
  1697.                         {
  1698.                             clientStopMoving(null);
  1699.                             // L2Object target = attackTarget;
  1700.                             // _actor.setTarget(_actor);
  1701.                             caster.doCast(sk);
  1702.                             // _actor.setTarget(target);
  1703.                             return true;
  1704.                         }
  1705.                         else if (((sk.getTargetType() == L2TargetType.AREA) || (sk.getTargetType() == L2TargetType.BEHIND_AREA) || (sk.getTargetType() == L2TargetType.FRONT_AREA)) && GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
  1706.                         {
  1707.                             clientStopMoving(null);
  1708.                             caster.doCast(sk);
  1709.                             return true;
  1710.                         }
  1711.                     }
  1712.                 }
  1713.                 if (sk.hasEffectType(L2EffectType.HEAL, L2EffectType.HEAL_PERCENT))
  1714.                 {
  1715.                     double percentage = (caster.getCurrentHp() / caster.getMaxHp()) * 100;
  1716.                     if (caster.isMinion() && (sk.getTargetType() != L2TargetType.SELF))
  1717.                     {
  1718.                         L2Character leader = caster.getLeader();
  1719.                         if ((leader != null) && !leader.isDead() && (Rnd.get(100) > ((leader.getCurrentHp() / leader.getMaxHp()) * 100)))
  1720.                         {
  1721.                             if (!Util.checkIfInRange((sk.getCastRange() + caster.getTemplate().getCollisionRadius() + leader.getTemplate().getCollisionRadius()), caster, leader, false) && !isParty(sk) && !caster.isMovementDisabled())
  1722.                             {
  1723.                                 moveToPawn(leader, sk.getCastRange() + caster.getTemplate().getCollisionRadius() + leader.getTemplate().getCollisionRadius());
  1724.                             }
  1725.                             if (GeoData.getInstance().canSeeTarget(caster, leader))
  1726.                             {
  1727.                                 clientStopMoving(null);
  1728.                                 caster.setTarget(leader);
  1729.                                 caster.doCast(sk);
  1730.                                 return true;
  1731.                             }
  1732.                         }
  1733.                     }
  1734.                     if (Rnd.get(100) < ((100 - percentage) / 3))
  1735.                     {
  1736.                         clientStopMoving(null);
  1737.                         caster.setTarget(caster);
  1738.                         caster.doCast(sk);
  1739.                         return true;
  1740.                     }
  1741.  
  1742.                     if (sk.getTargetType() == L2TargetType.ONE)
  1743.                     {
  1744.                         for (L2Character obj : caster.getKnownList().getKnownCharactersInRadius(sk.getCastRange() + caster.getTemplate().getCollisionRadius()))
  1745.                         {
  1746.                             if (!(obj instanceof L2Attackable) || obj.isDead())
  1747.                             {
  1748.                                 continue;
  1749.                             }
  1750.  
  1751.                             L2Attackable targets = ((L2Attackable) obj);
  1752.                             if ((caster.getFactionId() != null) && !caster.getFactionId().equals(targets.getFactionId()))
  1753.                             {
  1754.                                 continue;
  1755.                             }
  1756.                             percentage = (targets.getCurrentHp() / targets.getMaxHp()) * 100;
  1757.                             if (Rnd.get(100) < ((100 - percentage) / 10))
  1758.                             {
  1759.                                 if (GeoData.getInstance().canSeeTarget(caster, targets))
  1760.                                 {
  1761.                                     clientStopMoving(null);
  1762.                                     caster.setTarget(obj);
  1763.                                     caster.doCast(sk);
  1764.                                     return true;
  1765.                                 }
  1766.                             }
  1767.                         }
  1768.                     }
  1769.                     if (isParty(sk))
  1770.                     {
  1771.                         for (L2Character obj : caster.getKnownList().getKnownCharactersInRadius(sk.getAffectRange() + caster.getTemplate().getCollisionRadius()))
  1772.                         {
  1773.                             if (!(obj instanceof L2Attackable))
  1774.                             {
  1775.                                 continue;
  1776.                             }
  1777.                             L2Npc targets = ((L2Npc) obj);
  1778.                             if ((caster.getFactionId() != null) && targets.getFactionId().equals(caster.getFactionId()))
  1779.                             {
  1780.                                 if ((obj.getCurrentHp() < obj.getMaxHp()) && (Rnd.get(100) <= 20))
  1781.                                 {
  1782.                                     clientStopMoving(null);
  1783.                                     caster.setTarget(caster);
  1784.                                     caster.doCast(sk);
  1785.                                     return true;
  1786.                                 }
  1787.                             }
  1788.                         }
  1789.                     }
  1790.                 }
  1791.                 if (!canAura(sk))
  1792.                 {
  1793.  
  1794.                     if (GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
  1795.                     {
  1796.                         clientStopMoving(null);
  1797.                         caster.doCast(sk);
  1798.                         return true;
  1799.                     }
  1800.  
  1801.                     L2Character target = skillTargetReconsider(sk);
  1802.                     if (target != null)
  1803.                     {
  1804.                         clientStopMoving(null);
  1805.                         L2Object targets = attackTarget;
  1806.                         caster.setTarget(target);
  1807.                         caster.doCast(sk);
  1808.                         caster.setTarget(targets);
  1809.                         return true;
  1810.                     }
  1811.                 }
  1812.                 else
  1813.                 {
  1814.                     clientStopMoving(null);
  1815.                     // L2Object targets = attackTarget;
  1816.                     // _actor.setTarget(_actor);
  1817.                     caster.doCast(sk);
  1818.                     // _actor.setTarget(targets);
  1819.                     return true;
  1820.                 }
  1821.             }
  1822.             break;
  1823.         }
  1824.  
  1825.         return false;
  1826.     }
  1827.  
  1828.     /**
  1829.      * This AI task will start when ACTOR cannot move and attack range larger than distance
  1830.      */
  1831.     private void movementDisable()
  1832.     {
  1833.         final L2Attackable npc = getActiveChar();
  1834.         double dist = 0;
  1835.         double dist2 = 0;
  1836.         int range = 0;
  1837.         try
  1838.         {
  1839.             if (npc.getTarget() == null)
  1840.             {
  1841.                 npc.setTarget(getAttackTarget());
  1842.             }
  1843.             dist = Math.sqrt(npc.getPlanDistanceSq(getAttackTarget().getX(), getAttackTarget().getY()));
  1844.             dist2 = dist - npc.getTemplate().getCollisionRadius();
  1845.             range = npc.getPhysicalAttackRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius();
  1846.             if (getAttackTarget().isMoving())
  1847.             {
  1848.                 dist = dist - 30;
  1849.                 if (npc.isMoving())
  1850.                 {
  1851.                     dist = dist - 50;
  1852.                 }
  1853.             }
  1854.  
  1855.             // Check if activeChar has any skill
  1856.             if (!_skillrender.getGeneralskills().isEmpty())
  1857.             {
  1858.                 // -------------------------------------------------------------
  1859.                 // Try to stop the target or disable the target as priority
  1860.                 int random = Rnd.get(100);
  1861.                 if (!_skillrender.getImmobiliseSkills().isEmpty() && !getAttackTarget().isImmobilized() && (random < 2))
  1862.                 {
  1863.                     for (L2Skill sk : _skillrender.getImmobiliseSkills())
  1864.                     {
  1865.                         if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
  1866.                         {
  1867.                             continue;
  1868.                         }
  1869.                         if (!GeoData.getInstance().canSeeTarget(npc, getAttackTarget()))
  1870.                         {
  1871.                             continue;
  1872.                         }
  1873.                         if (getAttackTarget().getFirstEffect(sk) == null)
  1874.                         {
  1875.                             clientStopMoving(null);
  1876.                             // L2Object target = getAttackTarget();
  1877.                             // _actor.setTarget(_actor);
  1878.                             npc.doCast(sk);
  1879.                             // _actor.setTarget(target);
  1880.                             return;
  1881.                         }
  1882.                     }
  1883.                 }
  1884.                 // -------------------------------------------------------------
  1885.                 // Same as Above, but with Mute/FEAR etc....
  1886.                 if (!_skillrender.getCostOverTimeSkills().isEmpty() && (random < 5))
  1887.                 {
  1888.                     for (L2Skill sk : _skillrender.getCostOverTimeSkills())
  1889.                     {
  1890.                         if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
  1891.                         {
  1892.                             continue;
  1893.                         }
  1894.                         if (!GeoData.getInstance().canSeeTarget(npc, getAttackTarget()))
  1895.                         {
  1896.                             continue;
  1897.                         }
  1898.                         if (getAttackTarget().getFirstEffect(sk) == null)
  1899.                         {
  1900.                             clientStopMoving(null);
  1901.                             // L2Object target = getAttackTarget();
  1902.                             // _actor.setTarget(_actor);
  1903.                             npc.doCast(sk);
  1904.                             // _actor.setTarget(target);
  1905.                             return;
  1906.                         }
  1907.                     }
  1908.                 }
  1909.                 // -------------------------------------------------------------
  1910.                 if (!_skillrender.getDebuffSkills().isEmpty() && (random < 8))
  1911.                 {
  1912.                     for (L2Skill sk : _skillrender.getDebuffSkills())
  1913.                     {
  1914.                         if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
  1915.                         {
  1916.                             continue;
  1917.                         }
  1918.                         if (!GeoData.getInstance().canSeeTarget(npc, getAttackTarget()))
  1919.                         {
  1920.                             continue;
  1921.                         }
  1922.                         if (getAttackTarget().getFirstEffect(sk) == null)
  1923.                         {
  1924.                             clientStopMoving(null);
  1925.                             // L2Object target = getAttackTarget();
  1926.                             // _actor.setTarget(_actor);
  1927.                             npc.doCast(sk);
  1928.                             // _actor.setTarget(target);
  1929.                             return;
  1930.                         }
  1931.                     }
  1932.                 }
  1933.                 // -------------------------------------------------------------
  1934.                 // Some side effect skill like CANCEL or NEGATE
  1935.                 if (!_skillrender.getNegativeSkills().isEmpty() && (random < 9))
  1936.                 {
  1937.                     for (L2Skill sk : _skillrender.getNegativeSkills())
  1938.                     {
  1939.                         if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
  1940.                         {
  1941.                             continue;
  1942.                         }
  1943.                         if (!GeoData.getInstance().canSeeTarget(npc, getAttackTarget()))
  1944.                         {
  1945.                             continue;
  1946.                         }
  1947.                         if (getAttackTarget().getFirstEffect(L2EffectType.BUFF) != null)
  1948.                         {
  1949.                             clientStopMoving(null);
  1950.                             // L2Object target = getAttackTarget();
  1951.                             // _actor.setTarget(_actor);
  1952.                             npc.doCast(sk);
  1953.                             // _actor.setTarget(target);
  1954.                             return;
  1955.                         }
  1956.                     }
  1957.                 }
  1958.                 // -------------------------------------------------------------
  1959.                 // Start ATK SKILL when nothing can be done
  1960.                 if (!_skillrender.getAtkSkills().isEmpty() && (npc.isMovementDisabled() || (npc.getAiType() == AIType.MAGE) || (npc.getAiType() == AIType.HEALER)))
  1961.                 {
  1962.                     for (L2Skill sk : _skillrender.getAtkSkills())
  1963.                     {
  1964.                         if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
  1965.                         {
  1966.                             continue;
  1967.                         }
  1968.                         if (!GeoData.getInstance().canSeeTarget(npc, getAttackTarget()))
  1969.                         {
  1970.                             continue;
  1971.                         }
  1972.                         clientStopMoving(null);
  1973.                         // L2Object target = getAttackTarget();
  1974.                         // _actor.setTarget(_actor);
  1975.                         npc.doCast(sk);
  1976.                         // _actor.setTarget(target);
  1977.                         return;
  1978.                     }
  1979.                 }
  1980.                 // -------------------------------------------------------------
  1981.                 // if there is no ATK skill to use, then try Universal skill
  1982.                 // @formatter:off
  1983.                 /*
  1984.                 for(L2Skill sk:_skillrender.getUniversalSkills())
  1985.                 {
  1986.                     if(sk.getMpConsume()>=_actor.getCurrentMp()
  1987.                             || _actor.isSkillDisabled(sk.getId())
  1988.                             ||(sk.getCastRange()+ _actor.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius() <= dist2 && !canAura(sk))
  1989.                             ||(sk.isMagic()&&_actor.isMuted())
  1990.                             ||(!sk.isMagic()&&_actor.isPhysicalMuted()))
  1991.                     {
  1992.                         continue;
  1993.                     }
  1994.                     if(!GeoData.getInstance().canSeeTarget(_actor,getAttackTarget()))
  1995.                         continue;
  1996.                     clientStopMoving(null);
  1997.                     L2Object target = getAttackTarget();
  1998.                     //_actor.setTarget(_actor);
  1999.                     _actor.doCast(sk);
  2000.                     //_actor.setTarget(target);
  2001.                     return;
  2002.                 }
  2003.                  */
  2004.                 // @formatter:on
  2005.             }
  2006.             // timepass = timepass + 1;
  2007.             if (npc.isMovementDisabled())
  2008.             {
  2009.                 // timepass = 0;
  2010.                 targetReconsider();
  2011.  
  2012.                 return;
  2013.             }
  2014.             // else if(timepass>=5)
  2015.             // {
  2016.             // timepass = 0;
  2017.             // AggroReconsider();
  2018.             // return;
  2019.             // }
  2020.  
  2021.             if ((dist > range) || !GeoData.getInstance().canSeeTarget(npc, getAttackTarget()))
  2022.             {
  2023.                 if (getAttackTarget().isMoving())
  2024.                 {
  2025.                     range -= 100;
  2026.                 }
  2027.                 if (range < 5)
  2028.                 {
  2029.                     range = 5;
  2030.                 }
  2031.                 moveToPawn(getAttackTarget(), range);
  2032.                 return;
  2033.  
  2034.             }
  2035.  
  2036.             melee(npc.getPrimarySkillId());
  2037.         }
  2038.         catch (NullPointerException e)
  2039.         {
  2040.             setIntention(AI_INTENTION_ACTIVE);
  2041.             _log.warning(getClass().getSimpleName() + ": " + this + " - failed executing movementDisable(): " + e.getMessage());
  2042.             return;
  2043.         }
  2044.     }
  2045.  
  2046.     /**
  2047.      * @param skill the skill to check.
  2048.      * @return {@code true} if the skill is available for casting {@code false} otherwise.
  2049.      */
  2050.     private boolean checkSkillCastConditions(L2Skill skill)
  2051.     {
  2052.         // Not enough MP.
  2053.         if (skill.getMpConsume() >= getActiveChar().getCurrentMp())
  2054.         {
  2055.             return false;
  2056.         }
  2057.         // Character is in "skill disabled" mode.
  2058.         if (getActiveChar().isSkillDisabled(skill))
  2059.         {
  2060.             return false;
  2061.         }
  2062.         // If is a static skill and magic skill and character is muted or is a physical skill muted and character is physically muted.
  2063.         if (!skill.isStatic() && ((skill.isMagic() && getActiveChar().isMuted()) || getActiveChar().isPhysicalMuted()))
  2064.         {
  2065.             return false;
  2066.         }
  2067.         return true;
  2068.     }
  2069.  
  2070.     private L2Character effectTargetReconsider(L2Skill sk, boolean positive)
  2071.     {
  2072.         if (sk == null)
  2073.         {
  2074.             return null;
  2075.         }
  2076.         L2Attackable actor = getActiveChar();
  2077.         if (!sk.hasEffectType(L2EffectType.CANCEL, L2EffectType.CANCEL_ALL, L2EffectType.NEGATE))
  2078.         {
  2079.             if (!positive)
  2080.             {
  2081.                 double dist = 0;
  2082.                 double dist2 = 0;
  2083.                 int range = 0;
  2084.  
  2085.                 for (L2Character obj : actor.getAttackByList())
  2086.                 {
  2087.                     if ((obj == null) || obj.isDead() || !GeoData.getInstance().canSeeTarget(actor, obj) || (obj == getAttackTarget()))
  2088.                     {
  2089.                         continue;
  2090.                     }
  2091.                     try
  2092.                     {
  2093.                         actor.setTarget(getAttackTarget());
  2094.                         dist = Math.sqrt(actor.getPlanDistanceSq(obj.getX(), obj.getY()));
  2095.                         dist2 = dist - actor.getTemplate().getCollisionRadius();
  2096.                         range = sk.getCastRange() + actor.getTemplate().getCollisionRadius() + obj.getTemplate().getCollisionRadius();
  2097.                         if (obj.isMoving())
  2098.                         {
  2099.                             dist2 = dist2 - 70;
  2100.                         }
  2101.                     }
  2102.                     catch (NullPointerException e)
  2103.                     {
  2104.                         continue;
  2105.                     }
  2106.                     if (dist2 <= range)
  2107.                     {
  2108.                         if (getAttackTarget().getFirstEffect(sk) == null)
  2109.                         {
  2110.                             return obj;
  2111.                         }
  2112.                     }
  2113.                 }
  2114.  
  2115.                 // ----------------------------------------------------------------------
  2116.                 // If there is nearby Target with aggro, start going on random target that is attackable
  2117.                 for (L2Character obj : actor.getKnownList().getKnownCharactersInRadius(range))
  2118.                 {
  2119.                     if (obj.isDead() || !GeoData.getInstance().canSeeTarget(actor, obj))
  2120.                     {
  2121.                         continue;
  2122.                     }
  2123.                     try
  2124.                     {
  2125.                         actor.setTarget(getAttackTarget());
  2126.                         dist = Math.sqrt(actor.getPlanDistanceSq(obj.getX(), obj.getY()));
  2127.                         dist2 = dist;
  2128.                         range = sk.getCastRange() + actor.getTemplate().getCollisionRadius() + obj.getTemplate().getCollisionRadius();
  2129.                         if (obj.isMoving())
  2130.                         {
  2131.                             dist2 = dist2 - 70;
  2132.                         }
  2133.                     }
  2134.                     catch (NullPointerException e)
  2135.                     {
  2136.                         continue;
  2137.                     }
  2138.                     if (obj instanceof L2Attackable)
  2139.                     {
  2140.                         if ((actor.getEnemyClan() != null) && actor.getEnemyClan().equals(((L2Attackable) obj).getClan()))
  2141.                         {
  2142.                             if (dist2 <= range)
  2143.                             {
  2144.                                 if (getAttackTarget().getFirstEffect(sk) == null)
  2145.                                 {
  2146.                                     return obj;
  2147.                                 }
  2148.                             }
  2149.                         }
  2150.                     }
  2151.                     if ((obj instanceof L2PcInstance) || (obj instanceof L2Summon))
  2152.                     {
  2153.                         if (dist2 <= range)
  2154.                         {
  2155.                             if (getAttackTarget().getFirstEffect(sk) == null)
  2156.                             {
  2157.                                 return obj;
  2158.                             }
  2159.                         }
  2160.                     }
  2161.                 }
  2162.             }
  2163.             else if (positive)
  2164.             {
  2165.                 double dist = 0;
  2166.                 double dist2 = 0;
  2167.                 int range = 0;
  2168.                 for (L2Character obj : actor.getKnownList().getKnownCharactersInRadius(range))
  2169.                 {
  2170.                     if (!(obj instanceof L2Attackable) || obj.isDead() || !GeoData.getInstance().canSeeTarget(actor, obj))
  2171.                     {
  2172.                         continue;
  2173.                     }
  2174.  
  2175.                     L2Attackable targets = ((L2Attackable) obj);
  2176.                     if ((actor.getFactionId() != null) && !actor.getFactionId().equals(targets.getFactionId()))
  2177.                     {
  2178.                         continue;
  2179.                     }
  2180.  
  2181.                     try
  2182.                     {
  2183.                         actor.setTarget(getAttackTarget());
  2184.                         dist = Math.sqrt(actor.getPlanDistanceSq(obj.getX(), obj.getY()));
  2185.                         dist2 = dist - actor.getTemplate().getCollisionRadius();
  2186.                         range = sk.getCastRange() + actor.getTemplate().getCollisionRadius() + obj.getTemplate().getCollisionRadius();
  2187.                         if (obj.isMoving())
  2188.                         {
  2189.                             dist2 = dist2 - 70;
  2190.                         }
  2191.                     }
  2192.                     catch (NullPointerException e)
  2193.                     {
  2194.                         continue;
  2195.                     }
  2196.                     if (dist2 <= range)
  2197.                     {
  2198.                         if (obj.getFirstEffect(sk) == null)
  2199.                         {
  2200.                             return obj;
  2201.                         }
  2202.                     }
  2203.                 }
  2204.             }
  2205.         }
  2206.         else
  2207.         {
  2208.             double dist = 0;
  2209.             double dist2 = 0;
  2210.             int range = 0;
  2211.             range = sk.getCastRange() + actor.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius();
  2212.             for (L2Character obj : actor.getKnownList().getKnownCharactersInRadius(range))
  2213.             {
  2214.                 if ((obj == null) || obj.isDead() || !GeoData.getInstance().canSeeTarget(actor, obj))
  2215.                 {
  2216.                     continue;
  2217.                 }
  2218.                 try
  2219.                 {
  2220.                     actor.setTarget(getAttackTarget());
  2221.                     dist = Math.sqrt(actor.getPlanDistanceSq(obj.getX(), obj.getY()));
  2222.                     dist2 = dist - actor.getTemplate().getCollisionRadius();
  2223.                     range = sk.getCastRange() + actor.getTemplate().getCollisionRadius() + obj.getTemplate().getCollisionRadius();
  2224.                     if (obj.isMoving())
  2225.                     {
  2226.                         dist2 = dist2 - 70;
  2227.                     }
  2228.                 }
  2229.                 catch (NullPointerException e)
  2230.                 {
  2231.                     continue;
  2232.                 }
  2233.                 if (obj instanceof L2Attackable)
  2234.                 {
  2235.                     if ((actor.getEnemyClan() != null) && actor.getEnemyClan().equals(((L2Attackable) obj).getClan()))
  2236.                     {
  2237.                         if (dist2 <= range)
  2238.                         {
  2239.                             if (getAttackTarget().getFirstEffect(L2EffectType.BUFF) != null)
  2240.                             {
  2241.                                 return obj;
  2242.                             }
  2243.                         }
  2244.                     }
  2245.                 }
  2246.                 if ((obj instanceof L2PcInstance) || (obj instanceof L2Summon))
  2247.                 {
  2248.  
  2249.                     if (dist2 <= range)
  2250.                     {
  2251.                         if (getAttackTarget().getFirstEffect(L2EffectType.BUFF) != null)
  2252.                         {
  2253.                             return obj;
  2254.                         }
  2255.                     }
  2256.                 }
  2257.             }
  2258.         }
  2259.         return null;
  2260.     }
  2261.  
  2262.     private L2Character skillTargetReconsider(L2Skill sk)
  2263.     {
  2264.         double dist = 0;
  2265.         double dist2 = 0;
  2266.         int range = 0;
  2267.         L2Attackable actor = getActiveChar();
  2268.         if (actor.getHateList() != null)
  2269.         {
  2270.             for (L2Character obj : actor.getHateList())
  2271.             {
  2272.                 if ((obj == null) || !GeoData.getInstance().canSeeTarget(actor, obj) || obj.isDead())
  2273.                 {
  2274.                     continue;
  2275.                 }
  2276.                 try
  2277.                 {
  2278.                     actor.setTarget(getAttackTarget());
  2279.                     dist = Math.sqrt(actor.getPlanDistanceSq(obj.getX(), obj.getY()));
  2280.                     dist2 = dist - actor.getTemplate().getCollisionRadius();
  2281.                     range = sk.getCastRange() + actor.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius();
  2282.                     // if(obj.isMoving())
  2283.                     // dist2 = dist2 - 40;
  2284.                 }
  2285.                 catch (NullPointerException e)
  2286.                 {
  2287.                     continue;
  2288.                 }
  2289.                 if (dist2 <= range)
  2290.                 {
  2291.                     return obj;
  2292.                 }
  2293.             }
  2294.         }
  2295.  
  2296.         if (!(actor instanceof L2GuardInstance))
  2297.         {
  2298.             Collection<L2Object> objs = actor.getKnownList().getKnownObjects().values();
  2299.             for (L2Object target : objs)
  2300.             {
  2301.                 try
  2302.                 {
  2303.                     actor.setTarget(getAttackTarget());
  2304.                     dist = Math.sqrt(actor.getPlanDistanceSq(target.getX(), target.getY()));
  2305.                     dist2 = dist;
  2306.                     range = sk.getCastRange() + actor.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius();
  2307.                     // if(obj.isMoving())
  2308.                     // dist2 = dist2 - 40;
  2309.                 }
  2310.                 catch (NullPointerException e)
  2311.                 {
  2312.                     continue;
  2313.                 }
  2314.                 L2Character obj = null;
  2315.                 if (target instanceof L2Character)
  2316.                 {
  2317.                     obj = (L2Character) target;
  2318.                 }
  2319.                 if ((obj == null) || !GeoData.getInstance().canSeeTarget(actor, obj) || (dist2 > range))
  2320.                 {
  2321.                     continue;
  2322.                 }
  2323.                 if (obj instanceof L2PcInstance)
  2324.                 {
  2325.                     return obj;
  2326.  
  2327.                 }
  2328.                 if (obj instanceof L2Attackable)
  2329.                 {
  2330.                     if ((actor.getEnemyClan() != null) && actor.getEnemyClan().equals(((L2Attackable) obj).getClan()))
  2331.                     {
  2332.                         return obj;
  2333.                     }
  2334.                     if (actor.getIsChaos() != 0)
  2335.                     {
  2336.                         if ((((L2Attackable) obj).getFactionId() != null) && ((L2Attackable) obj).getFactionId().equals(actor.getFactionId()))
  2337.                         {
  2338.                             continue;
  2339.                         }
  2340.  
  2341.                         return obj;
  2342.                     }
  2343.                 }
  2344.                 if (obj instanceof L2Summon)
  2345.                 {
  2346.                     return obj;
  2347.                 }
  2348.             }
  2349.         }
  2350.         return null;
  2351.     }
  2352.  
  2353.     private void targetReconsider()
  2354.     {
  2355.         double dist = 0;
  2356.         double dist2 = 0;
  2357.         int range = 0;
  2358.         L2Attackable actor = getActiveChar();
  2359.         L2Character MostHate = actor.getMostHated();
  2360.         if (actor.getHateList() != null)
  2361.         {
  2362.             for (L2Character obj : actor.getHateList())
  2363.             {
  2364.                 if ((obj == null) || !GeoData.getInstance().canSeeTarget(actor, obj) || obj.isDead() || (obj != MostHate) || (obj == actor))
  2365.                 {
  2366.                     continue;
  2367.                 }
  2368.                 try
  2369.                 {
  2370.                     dist = Math.sqrt(actor.getPlanDistanceSq(obj.getX(), obj.getY()));
  2371.                     dist2 = dist - actor.getTemplate().getCollisionRadius();
  2372.                     range = actor.getPhysicalAttackRange() + actor.getTemplate().getCollisionRadius() + obj.getTemplate().getCollisionRadius();
  2373.                     if (obj.isMoving())
  2374.                     {
  2375.                         dist2 = dist2 - 70;
  2376.                     }
  2377.                 }
  2378.                 catch (NullPointerException e)
  2379.                 {
  2380.                     continue;
  2381.                 }
  2382.  
  2383.                 if (dist2 <= range)
  2384.                 {
  2385.                     if (MostHate != null)
  2386.                     {
  2387.                         actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2388.                     }
  2389.                     else
  2390.                     {
  2391.                         actor.addDamageHate(obj, 0, 2000);
  2392.                     }
  2393.                     actor.setTarget(obj);
  2394.                     setAttackTarget(obj);
  2395.                     return;
  2396.                 }
  2397.             }
  2398.         }
  2399.         if (!(actor instanceof L2GuardInstance))
  2400.         {
  2401.             Collection<L2Object> objs = actor.getKnownList().getKnownObjects().values();
  2402.             for (L2Object target : objs)
  2403.             {
  2404.                 L2Character obj = null;
  2405.                 if (target instanceof L2Character)
  2406.                 {
  2407.                     obj = (L2Character) target;
  2408.                 }
  2409.  
  2410.                 if ((obj == null) || !GeoData.getInstance().canSeeTarget(actor, obj) || obj.isDead() || (obj != MostHate) || (obj == actor) || (obj == getAttackTarget()))
  2411.                 {
  2412.                     continue;
  2413.                 }
  2414.                 if (obj instanceof L2PcInstance)
  2415.                 {
  2416.                     if (MostHate != null)
  2417.                     {
  2418.                         actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2419.                     }
  2420.                     else
  2421.                     {
  2422.                         actor.addDamageHate(obj, 0, 2000);
  2423.                     }
  2424.                     actor.setTarget(obj);
  2425.                     setAttackTarget(obj);
  2426.  
  2427.                 }
  2428.                 else if (obj instanceof L2Attackable)
  2429.                 {
  2430.                     if ((actor.getEnemyClan() != null) && actor.getEnemyClan().equals(((L2Attackable) obj).getClan()))
  2431.                     {
  2432.                         actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2433.                         actor.setTarget(obj);
  2434.                     }
  2435.                     if (actor.getIsChaos() != 0)
  2436.                     {
  2437.                         if ((((L2Attackable) obj).getFactionId() != null) && ((L2Attackable) obj).getFactionId().equals(actor.getFactionId()))
  2438.                         {
  2439.                             continue;
  2440.                         }
  2441.  
  2442.                         if (MostHate != null)
  2443.                         {
  2444.                             actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2445.                         }
  2446.                         else
  2447.                         {
  2448.                             actor.addDamageHate(obj, 0, 2000);
  2449.                         }
  2450.                         actor.setTarget(obj);
  2451.                         setAttackTarget(obj);
  2452.                     }
  2453.                 }
  2454.                 else if (obj instanceof L2Summon)
  2455.                 {
  2456.                     if (MostHate != null)
  2457.                     {
  2458.                         actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2459.                     }
  2460.                     else
  2461.                     {
  2462.                         actor.addDamageHate(obj, 0, 2000);
  2463.                     }
  2464.                     actor.setTarget(obj);
  2465.                     setAttackTarget(obj);
  2466.                 }
  2467.             }
  2468.         }
  2469.     }
  2470.  
  2471.     private void aggroReconsider()
  2472.     {
  2473.         L2Attackable actor = getActiveChar();
  2474.         L2Character MostHate = actor.getMostHated();
  2475.         if (actor.getHateList() != null)
  2476.         {
  2477.  
  2478.             int rand = Rnd.get(actor.getHateList().size());
  2479.             int count = 0;
  2480.             for (L2Character obj : actor.getHateList())
  2481.             {
  2482.                 if (count < rand)
  2483.                 {
  2484.                     count++;
  2485.                     continue;
  2486.                 }
  2487.  
  2488.                 if ((obj == null) || !GeoData.getInstance().canSeeTarget(actor, obj) || obj.isDead() || (obj == getAttackTarget()) || (obj == actor))
  2489.                 {
  2490.                     continue;
  2491.                 }
  2492.  
  2493.                 try
  2494.                 {
  2495.                     actor.setTarget(getAttackTarget());
  2496.                 }
  2497.                 catch (NullPointerException e)
  2498.                 {
  2499.                     continue;
  2500.                 }
  2501.                 if (MostHate != null)
  2502.                 {
  2503.                     actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2504.                 }
  2505.                 else
  2506.                 {
  2507.                     actor.addDamageHate(obj, 0, 2000);
  2508.                 }
  2509.                 actor.setTarget(obj);
  2510.                 setAttackTarget(obj);
  2511.                 return;
  2512.             }
  2513.         }
  2514.  
  2515.         if (!(actor instanceof L2GuardInstance))
  2516.         {
  2517.             Collection<L2Object> objs = actor.getKnownList().getKnownObjects().values();
  2518.             for (L2Object target : objs)
  2519.             {
  2520.                 L2Character obj = null;
  2521.                 if (target instanceof L2Character)
  2522.                 {
  2523.                     obj = (L2Character) target;
  2524.                 }
  2525.                 else
  2526.                 {
  2527.                     continue;
  2528.                 }
  2529.  
  2530.                 if (!GeoData.getInstance().canSeeTarget(actor, obj) || obj.isDead() || (obj != MostHate) || (obj == actor))
  2531.                 {
  2532.                     continue;
  2533.                 }
  2534.                 if (obj instanceof L2PcInstance)
  2535.                 {
  2536.                     if ((MostHate != null) && !MostHate.isDead())
  2537.                     {
  2538.                         actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2539.                     }
  2540.                     else
  2541.                     {
  2542.                         actor.addDamageHate(obj, 0, 2000);
  2543.                     }
  2544.                     actor.setTarget(obj);
  2545.                     setAttackTarget(obj);
  2546.                 }
  2547.                 else if (obj instanceof L2Attackable)
  2548.                 {
  2549.                     if ((actor.getEnemyClan() != null) && actor.getEnemyClan().equals(((L2Attackable) obj).getClan()))
  2550.                     {
  2551.                         if (MostHate != null)
  2552.                         {
  2553.                             actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2554.                         }
  2555.                         else
  2556.                         {
  2557.                             actor.addDamageHate(obj, 0, 2000);
  2558.                         }
  2559.                         actor.setTarget(obj);
  2560.                     }
  2561.                     if (actor.getIsChaos() != 0)
  2562.                     {
  2563.                         if ((((L2Attackable) obj).getFactionId() != null) && ((L2Attackable) obj).getFactionId().equals(actor.getFactionId()))
  2564.                         {
  2565.                             continue;
  2566.                         }
  2567.  
  2568.                         if (MostHate != null)
  2569.                         {
  2570.                             actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2571.                         }
  2572.                         else
  2573.                         {
  2574.                             actor.addDamageHate(obj, 0, 2000);
  2575.                         }
  2576.                         actor.setTarget(obj);
  2577.                         setAttackTarget(obj);
  2578.                     }
  2579.                 }
  2580.                 else if (obj instanceof L2Summon)
  2581.                 {
  2582.                     if (MostHate != null)
  2583.                     {
  2584.                         actor.addDamageHate(obj, 0, actor.getHating(MostHate));
  2585.                     }
  2586.                     else
  2587.                     {
  2588.                         actor.addDamageHate(obj, 0, 2000);
  2589.                     }
  2590.                     actor.setTarget(obj);
  2591.                     setAttackTarget(obj);
  2592.                 }
  2593.             }
  2594.         }
  2595.     }
  2596.  
  2597.     private List<L2Skill> longRangeSkillRender()
  2598.     {
  2599.         longRangeSkills = _skillrender.getLongRangeSkills();
  2600.         if (longRangeSkills.isEmpty())
  2601.         {
  2602.             longRangeSkills = getActiveChar().getLongRangeSkill();
  2603.         }
  2604.         return longRangeSkills;
  2605.     }
  2606.  
  2607.     private List<L2Skill> shortRangeSkillRender()
  2608.     {
  2609.         shortRangeSkills = _skillrender.getShortRangeSkills();
  2610.         if (shortRangeSkills.isEmpty())
  2611.         {
  2612.             shortRangeSkills = getActiveChar().getShortRangeSkill();
  2613.         }
  2614.         return shortRangeSkills;
  2615.     }
  2616.  
  2617.     /**
  2618.      * Manage AI thinking actions of a L2Attackable.
  2619.      */
  2620.     @Override
  2621.     protected void onEvtThink()
  2622.     {
  2623.         // Check if the actor can't use skills and if a thinking action isn't already in progress
  2624.         if (_thinking || getActiveChar().isAllSkillsDisabled())
  2625.         {
  2626.             return;
  2627.         }
  2628.  
  2629.         // Start thinking action
  2630.         _thinking = true;
  2631.  
  2632.         try
  2633.         {
  2634.             // Manage AI thinks of a L2Attackable
  2635.             switch (getIntention())
  2636.             {
  2637.                 case AI_INTENTION_ACTIVE:
  2638.                     thinkActive();
  2639.                     break;
  2640.                 case AI_INTENTION_ATTACK:
  2641.                     thinkAttack();
  2642.                     break;
  2643.                 case AI_INTENTION_CAST:
  2644.                     thinkCast();
  2645.                     break;
  2646.             }
  2647.         }
  2648.         catch (Exception e)
  2649.         {
  2650.             _log.warning(getClass().getSimpleName() + ": " + this + " -  onEvtThink() failed: " + e.getMessage());
  2651.         }
  2652.         finally
  2653.         {
  2654.             // Stop thinking action
  2655.             _thinking = false;
  2656.         }
  2657.     }
  2658.  
  2659.     /**
  2660.      * Launch actions corresponding to the Event Attacked.<br>
  2661.      * <B><U> Actions</U> :</B>
  2662.      * <ul>
  2663.      * <li>Init the attack : Calculate the attack timeout, Set the _globalAggro to 0, Add the attacker to the actor _aggroList</li>
  2664.      * <li>Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance</li>
  2665.      * <li>Set the Intention to AI_INTENTION_ATTACK</li>
  2666.      * </ul>
  2667.      * @param attacker The L2Character that attacks the actor
  2668.      */
  2669.     @Override
  2670.     protected void onEvtAttacked(L2Character attacker)
  2671.     {
  2672.         L2Attackable me = getActiveChar();
  2673.  
  2674.         // Calculate the attack timeout
  2675.         _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getInstance().getGameTicks();
  2676.  
  2677.         // Set the _globalAggro to 0 to permit attack even just after spawn
  2678.         if (_globalAggro < 0)
  2679.         {
  2680.             _globalAggro = 0;
  2681.         }
  2682.  
  2683.         // Add the attacker to the _aggroList of the actor
  2684.         me.addDamageHate(attacker, 0, 1);
  2685.  
  2686.         // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
  2687.         if (!me.isRunning())
  2688.         {
  2689.             me.setRunning();
  2690.         }
  2691.  
  2692.         // Set the Intention to AI_INTENTION_ATTACK
  2693.         if (getIntention() != AI_INTENTION_ATTACK)
  2694.         {
  2695.             setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
  2696.         }
  2697.         else if (me.getMostHated() != getAttackTarget())
  2698.         {
  2699.             setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
  2700.         }
  2701.  
  2702.         if (me instanceof L2MonsterInstance)
  2703.         {
  2704.             L2MonsterInstance master = (L2MonsterInstance) me;
  2705.  
  2706.             if (master.hasMinions())
  2707.             {
  2708.                 master.getMinionList().onAssist(me, attacker);
  2709.             }
  2710.  
  2711.             master = master.getLeader();
  2712.             if ((master != null) && master.hasMinions())
  2713.             {
  2714.                 master.getMinionList().onAssist(me, attacker);
  2715.             }
  2716.         }
  2717.  
  2718.         super.onEvtAttacked(attacker);
  2719.     }
  2720.  
  2721.     /**
  2722.      * Launch actions corresponding to the Event Aggression.<br>
  2723.      * <B><U> Actions</U> :</B>
  2724.      * <ul>
  2725.      * <li>Add the target to the actor _aggroList or update hate if already present</li>
  2726.      * <li>Set the actor Intention to AI_INTENTION_ATTACK (if actor is L2GuardInstance check if it isn't too far from its home location)</li>
  2727.      * </ul>
  2728.      * @param aggro The value of hate to add to the actor against the target
  2729.      */
  2730.     @Override
  2731.     protected void onEvtAggression(L2Character target, int aggro)
  2732.     {
  2733.         L2Attackable me = getActiveChar();
  2734.  
  2735.         if (target != null)
  2736.         {
  2737.             // Add the target to the actor _aggroList or update hate if already present
  2738.             me.addDamageHate(target, 0, aggro);
  2739.  
  2740.             // Set the actor AI Intention to AI_INTENTION_ATTACK
  2741.             if (getIntention() != CtrlIntention.AI_INTENTION_ATTACK)
  2742.             {
  2743.                 // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
  2744.                 if (!me.isRunning())
  2745.                 {
  2746.                     me.setRunning();
  2747.                 }
  2748.  
  2749.                 setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
  2750.             }
  2751.  
  2752.             if (me instanceof L2MonsterInstance)
  2753.             {
  2754.                 L2MonsterInstance master = (L2MonsterInstance) me;
  2755.  
  2756.                 if (master.hasMinions())
  2757.                 {
  2758.                     master.getMinionList().onAssist(me, target);
  2759.                 }
  2760.  
  2761.                 master = master.getLeader();
  2762.                 if ((master != null) && master.hasMinions())
  2763.                 {
  2764.                     master.getMinionList().onAssist(me, target);
  2765.                 }
  2766.             }
  2767.         }
  2768.     }
  2769.  
  2770.     @Override
  2771.     protected void onIntentionActive()
  2772.     {
  2773.         // Cancel attack timeout
  2774.         _attackTimeout = Integer.MAX_VALUE;
  2775.         super.onIntentionActive();
  2776.     }
  2777.  
  2778.     public void setGlobalAggro(int value)
  2779.     {
  2780.         _globalAggro = value;
  2781.     }
  2782.  
  2783.     /**
  2784.      * @param TP The timepass to set.
  2785.      */
  2786.     public void setTimepass(int TP)
  2787.     {
  2788.         timepass = TP;
  2789.     }
  2790.  
  2791.     /**
  2792.      * @return Returns the timepass.
  2793.      */
  2794.     public int getTimepass()
  2795.     {
  2796.         return timepass;
  2797.     }
  2798.  
  2799.     public L2Attackable getActiveChar()
  2800.     {
  2801.         return (L2Attackable) _actor;
  2802.     }
  2803. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement