L2CharacterAI.java 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665
  1. /*
  2. * Copyright (C) 2004-2015 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. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
  21. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
  22. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
  23. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
  24. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
  25. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
  26. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_MOVE_TO;
  27. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
  28. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
  29. import java.util.ArrayList;
  30. import java.util.List;
  31. import com.l2jserver.Config;
  32. import com.l2jserver.gameserver.GameTimeController;
  33. import com.l2jserver.gameserver.GeoData;
  34. import com.l2jserver.gameserver.ThreadPoolManager;
  35. import com.l2jserver.gameserver.enums.ItemLocation;
  36. import com.l2jserver.gameserver.instancemanager.WalkingManager;
  37. import com.l2jserver.gameserver.model.L2Object;
  38. import com.l2jserver.gameserver.model.Location;
  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.instance.L2DoorInstance;
  44. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  45. import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
  46. import com.l2jserver.gameserver.model.effects.L2EffectType;
  47. import com.l2jserver.gameserver.model.events.EventDispatcher;
  48. import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcMoveFinished;
  49. import com.l2jserver.gameserver.model.interfaces.ILocational;
  50. import com.l2jserver.gameserver.model.items.L2Weapon;
  51. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  52. import com.l2jserver.gameserver.model.items.type.WeaponType;
  53. import com.l2jserver.gameserver.model.skills.Skill;
  54. import com.l2jserver.gameserver.model.skills.targets.L2TargetType;
  55. import com.l2jserver.gameserver.network.SystemMessageId;
  56. import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
  57. import com.l2jserver.gameserver.network.serverpackets.AutoAttackStop;
  58. import com.l2jserver.gameserver.taskmanager.AttackStanceTaskManager;
  59. import com.l2jserver.gameserver.util.Util;
  60. import com.l2jserver.util.Rnd;
  61. /**
  62. * This class manages AI of L2Character.<br>
  63. * L2CharacterAI :
  64. * <ul>
  65. * <li>L2AttackableAI</li>
  66. * <li>L2DoorAI</li>
  67. * <li>L2PlayerAI</li>
  68. * <li>L2SummonAI</li>
  69. * </ul>
  70. */
  71. public class L2CharacterAI extends AbstractAI
  72. {
  73. public static class IntentionCommand
  74. {
  75. protected final CtrlIntention _crtlIntention;
  76. protected final Object _arg0, _arg1;
  77. protected IntentionCommand(CtrlIntention pIntention, Object pArg0, Object pArg1)
  78. {
  79. _crtlIntention = pIntention;
  80. _arg0 = pArg0;
  81. _arg1 = pArg1;
  82. }
  83. public CtrlIntention getCtrlIntention()
  84. {
  85. return _crtlIntention;
  86. }
  87. }
  88. protected static final int FEAR_RANGE = 500;
  89. /**
  90. * Cast Task
  91. * @author Zoey76
  92. */
  93. public static class CastTask implements Runnable
  94. {
  95. private final L2Character _activeChar;
  96. private final L2Object _target;
  97. private final Skill _skill;
  98. public CastTask(L2Character actor, Skill skill, L2Object target)
  99. {
  100. _activeChar = actor;
  101. _target = target;
  102. _skill = skill;
  103. }
  104. @Override
  105. public void run()
  106. {
  107. if (_activeChar.isAttackingNow())
  108. {
  109. _activeChar.abortAttack();
  110. }
  111. _activeChar.getAI().changeIntentionToCast(_skill, _target);
  112. }
  113. }
  114. /**
  115. * Constructor of L2CharacterAI.
  116. * @param creature the creature
  117. */
  118. public L2CharacterAI(L2Character creature)
  119. {
  120. super(creature);
  121. }
  122. public IntentionCommand getNextIntention()
  123. {
  124. return null;
  125. }
  126. @Override
  127. protected void onEvtAttacked(L2Character attacker)
  128. {
  129. if ((attacker instanceof L2Attackable) && !attacker.isCoreAIDisabled())
  130. {
  131. clientStartAutoAttack();
  132. }
  133. }
  134. /**
  135. * Manage the Idle Intention : Stop Attack, Movement and Stand Up the actor.<br>
  136. * <B><U> Actions</U> :</B>
  137. * <ul>
  138. * <li>Set the AI Intention to AI_INTENTION_IDLE</li>
  139. * <li>Init cast and attack target</li>
  140. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  141. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  142. * <li>Stand up the actor server side AND client side by sending Server->Client packet ChangeWaitType (broadcast)</li>
  143. * </ul>
  144. */
  145. @Override
  146. protected void onIntentionIdle()
  147. {
  148. // Set the AI Intention to AI_INTENTION_IDLE
  149. changeIntention(AI_INTENTION_IDLE, null, null);
  150. // Init cast and attack target
  151. setCastTarget(null);
  152. setAttackTarget(null);
  153. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  154. clientStopMoving(null);
  155. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  156. clientStopAutoAttack();
  157. }
  158. /**
  159. * Manage the Active Intention : Stop Attack, Movement and Launch Think Event.<br>
  160. * <B><U> Actions</U> : <I>if the Intention is not already Active</I></B>
  161. * <ul>
  162. * <li>Set the AI Intention to AI_INTENTION_ACTIVE</li>
  163. * <li>Init cast and attack target</li>
  164. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  165. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  166. * <li>Launch the Think Event</li>
  167. * </ul>
  168. */
  169. @Override
  170. protected void onIntentionActive()
  171. {
  172. // Check if the Intention is not already Active
  173. if (getIntention() != AI_INTENTION_ACTIVE)
  174. {
  175. // Set the AI Intention to AI_INTENTION_ACTIVE
  176. changeIntention(AI_INTENTION_ACTIVE, null, null);
  177. // Init cast and attack target
  178. setCastTarget(null);
  179. setAttackTarget(null);
  180. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  181. clientStopMoving(null);
  182. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  183. clientStopAutoAttack();
  184. // Also enable random animations for this L2Character if allowed
  185. // This is only for mobs - town npcs are handled in their constructor
  186. if (_actor instanceof L2Attackable)
  187. {
  188. ((L2Npc) _actor).startRandomAnimationTimer();
  189. }
  190. // Launch the Think Event
  191. onEvtThink();
  192. }
  193. }
  194. /**
  195. * Manage the Rest Intention.<br>
  196. * <B><U> Actions</U> : </B>
  197. * <ul>
  198. * <li>Set the AI Intention to AI_INTENTION_IDLE</li>
  199. * </ul>
  200. */
  201. @Override
  202. protected void onIntentionRest()
  203. {
  204. // Set the AI Intention to AI_INTENTION_IDLE
  205. setIntention(AI_INTENTION_IDLE);
  206. }
  207. /**
  208. * Manage the Attack Intention : Stop current Attack (if necessary), Start a new Attack and Launch Think Event.<br>
  209. * <B><U> Actions</U> : </B>
  210. * <ul>
  211. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  212. * <li>Set the Intention of this AI to AI_INTENTION_ATTACK</li>
  213. * <li>Set or change the AI attack target</li>
  214. * <li>Start the actor Auto Attack client side by sending Server->Client packet AutoAttackStart (broadcast)</li>
  215. * <li>Launch the Think Event</li>
  216. * </ul>
  217. * <B><U> Overridden in</U> :</B>
  218. * <ul>
  219. * <li>L2AttackableAI : Calculate attack timeout</li>
  220. * </ul>
  221. */
  222. @Override
  223. protected void onIntentionAttack(L2Character target)
  224. {
  225. if (target == null)
  226. {
  227. clientActionFailed();
  228. return;
  229. }
  230. if (getIntention() == AI_INTENTION_REST)
  231. {
  232. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  233. clientActionFailed();
  234. return;
  235. }
  236. if (_actor.isAllSkillsDisabled() || _actor.isCastingNow() || _actor.isAfraid())
  237. {
  238. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  239. clientActionFailed();
  240. return;
  241. }
  242. // Check if the Intention is already AI_INTENTION_ATTACK
  243. if (getIntention() == AI_INTENTION_ATTACK)
  244. {
  245. // Check if the AI already targets the L2Character
  246. if (getAttackTarget() != target)
  247. {
  248. // Set the AI attack target (change target)
  249. setAttackTarget(target);
  250. stopFollow();
  251. // Launch the Think Event
  252. notifyEvent(CtrlEvent.EVT_THINK);
  253. }
  254. else
  255. {
  256. clientActionFailed(); // else client freezes until cancel target
  257. }
  258. }
  259. else
  260. {
  261. // Set the Intention of this AbstractAI to AI_INTENTION_ATTACK
  262. changeIntention(AI_INTENTION_ATTACK, target, null);
  263. // Set the AI attack target
  264. setAttackTarget(target);
  265. stopFollow();
  266. // Launch the Think Event
  267. notifyEvent(CtrlEvent.EVT_THINK);
  268. }
  269. }
  270. /**
  271. * Manage the Cast Intention : Stop current Attack, Init the AI in order to cast and Launch Think Event.<br>
  272. * <B><U> Actions</U> : </B>
  273. * <ul>
  274. * <li>Set the AI cast target</li>
  275. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  276. * <li>Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor</li>
  277. * <li>Set the AI skill used by INTENTION_CAST</li>
  278. * <li>Set the Intention of this AI to AI_INTENTION_CAST</li>
  279. * <li>Launch the Think Event</li>
  280. * </ul>
  281. */
  282. @Override
  283. protected void onIntentionCast(Skill skill, L2Object target)
  284. {
  285. if ((getIntention() == AI_INTENTION_REST) && skill.isMagic())
  286. {
  287. clientActionFailed();
  288. _actor.setIsCastingNow(false);
  289. return;
  290. }
  291. if (_actor.getBowAttackEndTime() > GameTimeController.getInstance().getGameTicks())
  292. {
  293. ThreadPoolManager.getInstance().scheduleGeneral(new CastTask(_actor, skill, target), (_actor.getBowAttackEndTime() - GameTimeController.getInstance().getGameTicks()) * GameTimeController.MILLIS_IN_TICK);
  294. }
  295. else
  296. {
  297. changeIntentionToCast(skill, target);
  298. }
  299. }
  300. protected void changeIntentionToCast(Skill skill, L2Object target)
  301. {
  302. // Set the AI cast target
  303. setCastTarget((L2Character) target);
  304. // Set the AI skill used by INTENTION_CAST
  305. _skill = skill;
  306. // Change the Intention of this AbstractAI to AI_INTENTION_CAST
  307. changeIntention(AI_INTENTION_CAST, skill, target);
  308. // Launch the Think Event
  309. notifyEvent(CtrlEvent.EVT_THINK);
  310. }
  311. /**
  312. * Manage the Move To Intention : Stop current Attack and Launch a Move to Location Task.<br>
  313. * <B><U> Actions</U> : </B>
  314. * <ul>
  315. * <li>Stop the actor auto-attack server side AND client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  316. * <li>Set the Intention of this AI to AI_INTENTION_MOVE_TO</li>
  317. * <li>Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)</li>
  318. * </ul>
  319. */
  320. @Override
  321. protected void onIntentionMoveTo(Location loc)
  322. {
  323. if (getIntention() == AI_INTENTION_REST)
  324. {
  325. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  326. clientActionFailed();
  327. return;
  328. }
  329. if (_actor.isAllSkillsDisabled() || _actor.isCastingNow())
  330. {
  331. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  332. clientActionFailed();
  333. return;
  334. }
  335. // Set the Intention of this AbstractAI to AI_INTENTION_MOVE_TO
  336. changeIntention(AI_INTENTION_MOVE_TO, loc, null);
  337. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  338. clientStopAutoAttack();
  339. // Abort the attack of the L2Character and send Server->Client ActionFailed packet
  340. _actor.abortAttack();
  341. // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
  342. moveTo(loc.getX(), loc.getY(), loc.getZ());
  343. }
  344. /**
  345. * Manage the Follow Intention : Stop current Attack and Launch a Follow Task.<br>
  346. * <B><U> Actions</U> : </B>
  347. * <ul>
  348. * <li>Stop the actor auto-attack server side AND client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  349. * <li>Set the Intention of this AI to AI_INTENTION_FOLLOW</li>
  350. * <li>Create and Launch an AI Follow Task to execute every 1s</li>
  351. * </ul>
  352. */
  353. @Override
  354. protected void onIntentionFollow(L2Character target)
  355. {
  356. if (getIntention() == AI_INTENTION_REST)
  357. {
  358. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  359. clientActionFailed();
  360. return;
  361. }
  362. if (_actor.isAllSkillsDisabled() || _actor.isCastingNow())
  363. {
  364. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  365. clientActionFailed();
  366. return;
  367. }
  368. if (_actor.isMovementDisabled())
  369. {
  370. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  371. clientActionFailed();
  372. return;
  373. }
  374. // Dead actors can`t follow
  375. if (_actor.isDead())
  376. {
  377. clientActionFailed();
  378. return;
  379. }
  380. // do not follow yourself
  381. if (_actor == target)
  382. {
  383. clientActionFailed();
  384. return;
  385. }
  386. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  387. clientStopAutoAttack();
  388. // Set the Intention of this AbstractAI to AI_INTENTION_FOLLOW
  389. changeIntention(AI_INTENTION_FOLLOW, target, null);
  390. // Create and Launch an AI Follow Task to execute every 1s
  391. startFollow(target);
  392. }
  393. /**
  394. * Manage the PickUp Intention : Set the pick up target and Launch a Move To Pawn Task (offset=20).<br>
  395. * <B><U> Actions</U> : </B>
  396. * <ul>
  397. * <li>Set the AI pick up target</li>
  398. * <li>Set the Intention of this AI to AI_INTENTION_PICK_UP</li>
  399. * <li>Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)</li>
  400. * </ul>
  401. */
  402. @Override
  403. protected void onIntentionPickUp(L2Object object)
  404. {
  405. if (getIntention() == AI_INTENTION_REST)
  406. {
  407. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  408. clientActionFailed();
  409. return;
  410. }
  411. if (_actor.isAllSkillsDisabled() || _actor.isCastingNow())
  412. {
  413. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  414. clientActionFailed();
  415. return;
  416. }
  417. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  418. clientStopAutoAttack();
  419. if ((object instanceof L2ItemInstance) && (((L2ItemInstance) object).getItemLocation() != ItemLocation.VOID))
  420. {
  421. return;
  422. }
  423. // Set the Intention of this AbstractAI to AI_INTENTION_PICK_UP
  424. changeIntention(AI_INTENTION_PICK_UP, object, null);
  425. // Set the AI pick up target
  426. setTarget(object);
  427. if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug
  428. {
  429. _log.warn("Object in coords 0,0 - using a temporary fix");
  430. object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
  431. }
  432. // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
  433. moveToPawn(object, 20);
  434. }
  435. /**
  436. * Manage the Interact Intention : Set the interact target and Launch a Move To Pawn Task (offset=60).<br>
  437. * <B><U> Actions</U> : </B>
  438. * <ul>
  439. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  440. * <li>Set the AI interact target</li>
  441. * <li>Set the Intention of this AI to AI_INTENTION_INTERACT</li>
  442. * <li>Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)</li>
  443. * </ul>
  444. */
  445. @Override
  446. protected void onIntentionInteract(L2Object object)
  447. {
  448. if (getIntention() == AI_INTENTION_REST)
  449. {
  450. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  451. clientActionFailed();
  452. return;
  453. }
  454. if (_actor.isAllSkillsDisabled() || _actor.isCastingNow())
  455. {
  456. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  457. clientActionFailed();
  458. return;
  459. }
  460. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  461. clientStopAutoAttack();
  462. if (getIntention() != AI_INTENTION_INTERACT)
  463. {
  464. // Set the Intention of this AbstractAI to AI_INTENTION_INTERACT
  465. changeIntention(AI_INTENTION_INTERACT, object, null);
  466. // Set the AI interact target
  467. setTarget(object);
  468. // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
  469. moveToPawn(object, 60);
  470. }
  471. }
  472. /**
  473. * Do nothing.
  474. */
  475. @Override
  476. protected void onEvtThink()
  477. {
  478. // do nothing
  479. }
  480. /**
  481. * Do nothing.
  482. */
  483. @Override
  484. protected void onEvtAggression(L2Character target, int aggro)
  485. {
  486. // do nothing
  487. }
  488. /**
  489. * Launch actions corresponding to the Event Stunned then onAttacked Event.<br>
  490. * <B><U> Actions</U> :</B>
  491. * <ul>
  492. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  493. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  494. * <li>Break an attack and send Server->Client ActionFailed packet and a System Message to the L2Character</li>
  495. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character</li>
  496. * <li>Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode)</li>
  497. * </ul>
  498. */
  499. @Override
  500. protected void onEvtStunned(L2Character attacker)
  501. {
  502. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  503. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  504. if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(_actor))
  505. {
  506. AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  507. }
  508. // Stop Server AutoAttack also
  509. setAutoAttacking(false);
  510. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  511. clientStopMoving(null);
  512. // Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode)
  513. onEvtAttacked(attacker);
  514. }
  515. @Override
  516. protected void onEvtParalyzed(L2Character attacker)
  517. {
  518. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  519. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  520. if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(_actor))
  521. {
  522. AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  523. }
  524. // Stop Server AutoAttack also
  525. setAutoAttacking(false);
  526. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  527. clientStopMoving(null);
  528. // Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode)
  529. onEvtAttacked(attacker);
  530. }
  531. /**
  532. * Launch actions corresponding to the Event Sleeping.<br>
  533. * <B><U> Actions</U> :</B>
  534. * <ul>
  535. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  536. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  537. * <li>Break an attack and send Server->Client ActionFailed packet and a System Message to the L2Character</li>
  538. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character</li>
  539. * </ul>
  540. */
  541. @Override
  542. protected void onEvtSleeping(L2Character attacker)
  543. {
  544. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  545. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  546. if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(_actor))
  547. {
  548. AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  549. }
  550. // stop Server AutoAttack also
  551. setAutoAttacking(false);
  552. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  553. clientStopMoving(null);
  554. }
  555. /**
  556. * Launch actions corresponding to the Event Rooted.<br>
  557. * <B><U> Actions</U> :</B>
  558. * <ul>
  559. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  560. * <li>Launch actions corresponding to the Event onAttacked</li>
  561. * </ul>
  562. */
  563. @Override
  564. protected void onEvtRooted(L2Character attacker)
  565. {
  566. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  567. // _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  568. // if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(_actor))
  569. // AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  570. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  571. clientStopMoving(null);
  572. // Launch actions corresponding to the Event onAttacked
  573. onEvtAttacked(attacker);
  574. }
  575. /**
  576. * Launch actions corresponding to the Event Confused.<br>
  577. * <B><U> Actions</U> :</B>
  578. * <ul>
  579. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  580. * <li>Launch actions corresponding to the Event onAttacked</li>
  581. * </ul>
  582. */
  583. @Override
  584. protected void onEvtConfused(L2Character attacker)
  585. {
  586. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  587. clientStopMoving(null);
  588. // Launch actions corresponding to the Event onAttacked
  589. onEvtAttacked(attacker);
  590. }
  591. /**
  592. * Launch actions corresponding to the Event Muted.<br>
  593. * <B><U> Actions</U> :</B>
  594. * <ul>
  595. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character</li>
  596. * </ul>
  597. */
  598. @Override
  599. protected void onEvtMuted(L2Character attacker)
  600. {
  601. // Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character
  602. onEvtAttacked(attacker);
  603. }
  604. /**
  605. * Do nothing.
  606. */
  607. @Override
  608. protected void onEvtEvaded(L2Character attacker)
  609. {
  610. // do nothing
  611. }
  612. /**
  613. * Launch actions corresponding to the Event ReadyToAct.<br>
  614. * <B><U> Actions</U> :</B>
  615. * <ul>
  616. * <li>Launch actions corresponding to the Event Think</li>
  617. * </ul>
  618. */
  619. @Override
  620. protected void onEvtReadyToAct()
  621. {
  622. // Launch actions corresponding to the Event Think
  623. onEvtThink();
  624. }
  625. /**
  626. * Do nothing.
  627. */
  628. @Override
  629. protected void onEvtUserCmd(Object arg0, Object arg1)
  630. {
  631. // do nothing
  632. }
  633. /**
  634. * Launch actions corresponding to the Event Arrived.<br>
  635. * <B><U> Actions</U> :</B>
  636. * <ul>
  637. * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
  638. * <li>Launch actions corresponding to the Event Think</li>
  639. * </ul>
  640. */
  641. @Override
  642. protected void onEvtArrived()
  643. {
  644. _actor.revalidateZone(true);
  645. if (_actor.moveToNextRoutePoint())
  646. {
  647. return;
  648. }
  649. if (_actor instanceof L2Attackable)
  650. {
  651. ((L2Attackable) _actor).setisReturningToSpawnPoint(false);
  652. }
  653. clientStoppedMoving();
  654. if (_actor instanceof L2Npc)
  655. {
  656. L2Npc npc = (L2Npc) _actor;
  657. WalkingManager.getInstance().onArrived(npc); // Walking Manager support
  658. // Notify to scripts
  659. EventDispatcher.getInstance().notifyEventAsync(new OnNpcMoveFinished(npc), npc);
  660. }
  661. // If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE
  662. if (getIntention() == AI_INTENTION_MOVE_TO)
  663. {
  664. setIntention(AI_INTENTION_ACTIVE);
  665. }
  666. // Launch actions corresponding to the Event Think
  667. onEvtThink();
  668. }
  669. /**
  670. * Launch actions corresponding to the Event ArrivedRevalidate.<br>
  671. * <B><U> Actions</U> :</B>
  672. * <ul>
  673. * <li>Launch actions corresponding to the Event Think</li>
  674. * </ul>
  675. */
  676. @Override
  677. protected void onEvtArrivedRevalidate()
  678. {
  679. // Launch actions corresponding to the Event Think
  680. onEvtThink();
  681. }
  682. /**
  683. * Launch actions corresponding to the Event ArrivedBlocked.<br>
  684. * <B><U> Actions</U> :</B>
  685. * <ul>
  686. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  687. * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
  688. * <li>Launch actions corresponding to the Event Think</li>
  689. * </ul>
  690. */
  691. @Override
  692. protected void onEvtArrivedBlocked(Location blocked_at_loc)
  693. {
  694. // If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE
  695. if ((getIntention() == AI_INTENTION_MOVE_TO) || (getIntention() == AI_INTENTION_CAST))
  696. {
  697. setIntention(AI_INTENTION_ACTIVE);
  698. }
  699. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  700. clientStopMoving(blocked_at_loc);
  701. // Launch actions corresponding to the Event Think
  702. onEvtThink();
  703. }
  704. /**
  705. * Launch actions corresponding to the Event ForgetObject.<br>
  706. * <B><U> Actions</U> :</B>
  707. * <ul>
  708. * <li>If the object was targeted and the Intention was AI_INTENTION_INTERACT or AI_INTENTION_PICK_UP, set the Intention to AI_INTENTION_ACTIVE</li>
  709. * <li>If the object was targeted to attack, stop the auto-attack, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
  710. * <li>If the object was targeted to cast, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
  711. * <li>If the object was targeted to follow, stop the movement, cancel AI Follow Task and set the Intention to AI_INTENTION_ACTIVE</li>
  712. * <li>If the targeted object was the actor , cancel AI target, stop AI Follow Task, stop the movement and set the Intention to AI_INTENTION_IDLE</li>
  713. * </ul>
  714. */
  715. @Override
  716. protected void onEvtForgetObject(L2Object object)
  717. {
  718. // If the object was targeted and the Intention was AI_INTENTION_INTERACT or AI_INTENTION_PICK_UP, set the Intention to AI_INTENTION_ACTIVE
  719. if (getTarget() == object)
  720. {
  721. setTarget(null);
  722. if ((getIntention() == AI_INTENTION_INTERACT) || (getIntention() == AI_INTENTION_PICK_UP))
  723. {
  724. setIntention(AI_INTENTION_ACTIVE);
  725. }
  726. }
  727. // Check if the object was targeted to attack
  728. if (getAttackTarget() == object)
  729. {
  730. // Cancel attack target
  731. setAttackTarget(null);
  732. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  733. setIntention(AI_INTENTION_ACTIVE);
  734. }
  735. // Check if the object was targeted to cast
  736. if (getCastTarget() == object)
  737. {
  738. // Cancel cast target
  739. setCastTarget(null);
  740. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  741. setIntention(AI_INTENTION_ACTIVE);
  742. }
  743. // Check if the object was targeted to follow
  744. if (getFollowTarget() == object)
  745. {
  746. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  747. clientStopMoving(null);
  748. // Stop an AI Follow Task
  749. stopFollow();
  750. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  751. setIntention(AI_INTENTION_ACTIVE);
  752. }
  753. // Check if the targeted object was the actor
  754. if (_actor == object)
  755. {
  756. // Cancel AI target
  757. setTarget(null);
  758. setAttackTarget(null);
  759. setCastTarget(null);
  760. // Stop an AI Follow Task
  761. stopFollow();
  762. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  763. clientStopMoving(null);
  764. // Set the Intention of this AbstractAI to AI_INTENTION_IDLE
  765. changeIntention(AI_INTENTION_IDLE, null, null);
  766. }
  767. }
  768. /**
  769. * Launch actions corresponding to the Event Cancel.<br>
  770. * <B><U> Actions</U> :</B>
  771. * <ul>
  772. * <li>Stop an AI Follow Task</li>
  773. * <li>Launch actions corresponding to the Event Think</li>
  774. * </ul>
  775. */
  776. @Override
  777. protected void onEvtCancel()
  778. {
  779. _actor.abortCast();
  780. // Stop an AI Follow Task
  781. stopFollow();
  782. if (!AttackStanceTaskManager.getInstance().hasAttackStanceTask(_actor))
  783. {
  784. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  785. }
  786. // Launch actions corresponding to the Event Think
  787. onEvtThink();
  788. }
  789. /**
  790. * Launch actions corresponding to the Event Dead.<br>
  791. * <B><U> Actions</U> :</B>
  792. * <ul>
  793. * <li>Stop an AI Follow Task</li>
  794. * <li>Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)</li>
  795. * </ul>
  796. */
  797. @Override
  798. protected void onEvtDead()
  799. {
  800. // Stop an AI Tasks
  801. stopAITask();
  802. // Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)
  803. clientNotifyDead();
  804. if (!(_actor instanceof L2Playable))
  805. {
  806. _actor.setWalking();
  807. }
  808. }
  809. /**
  810. * Launch actions corresponding to the Event Fake Death.<br>
  811. * <B><U> Actions</U> :</B>
  812. * <ul>
  813. * <li>Stop an AI Follow Task</li>
  814. * </ul>
  815. */
  816. @Override
  817. protected void onEvtFakeDeath()
  818. {
  819. // Stop an AI Follow Task
  820. stopFollow();
  821. // Stop the actor movement and send Server->Client packet StopMove/StopRotation (broadcast)
  822. clientStopMoving(null);
  823. // Init AI
  824. _intention = AI_INTENTION_IDLE;
  825. setTarget(null);
  826. setCastTarget(null);
  827. setAttackTarget(null);
  828. }
  829. /**
  830. * Do nothing.
  831. */
  832. @Override
  833. protected void onEvtFinishCasting()
  834. {
  835. // do nothing
  836. }
  837. @Override
  838. protected void onEvtAfraid(L2Character effector, boolean start)
  839. {
  840. double radians = Math.toRadians(start ? Util.calculateAngleFrom(effector, _actor) : Util.convertHeadingToDegree(_actor.getHeading()));
  841. int posX = (int) (_actor.getX() + (FEAR_RANGE * Math.cos(radians)));
  842. int posY = (int) (_actor.getY() + (FEAR_RANGE * Math.sin(radians)));
  843. int posZ = _actor.getZ();
  844. if (!_actor.isPet())
  845. {
  846. _actor.setRunning();
  847. }
  848. // If pathfinding enabled the creature will go to the defined destination (retail like).
  849. // Otherwise it will go to the nearest obstacle.
  850. final Location destination;
  851. if (Config.PATHFINDING > 0)
  852. {
  853. destination = new Location(posX, posY, posZ, _actor.getInstanceId());
  854. }
  855. else
  856. {
  857. destination = GeoData.getInstance().moveCheck(_actor.getX(), _actor.getY(), _actor.getZ(), posX, posY, posZ, _actor.getInstanceId());
  858. }
  859. setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
  860. }
  861. protected boolean maybeMoveToPosition(ILocational worldPosition, int offset)
  862. {
  863. if (worldPosition == null)
  864. {
  865. _log.warn("maybeMoveToPosition: worldPosition == NULL!");
  866. return false;
  867. }
  868. if (offset < 0)
  869. {
  870. return false; // skill radius -1
  871. }
  872. if (!_actor.isInsideRadius(worldPosition, offset + _actor.getTemplate().getCollisionRadius(), false, false))
  873. {
  874. if (_actor.isMovementDisabled())
  875. {
  876. return true;
  877. }
  878. if (!_actor.isRunning() && !(this instanceof L2PlayerAI) && !(this instanceof L2SummonAI))
  879. {
  880. _actor.setRunning();
  881. }
  882. stopFollow();
  883. int x = _actor.getX();
  884. int y = _actor.getY();
  885. double dx = worldPosition.getX() - x;
  886. double dy = worldPosition.getY() - y;
  887. double dist = Math.sqrt((dx * dx) + (dy * dy));
  888. double sin = dy / dist;
  889. double cos = dx / dist;
  890. dist -= offset - 5;
  891. x += (int) (dist * cos);
  892. y += (int) (dist * sin);
  893. moveTo(x, y, worldPosition.getZ());
  894. return true;
  895. }
  896. if (getFollowTarget() != null)
  897. {
  898. stopFollow();
  899. }
  900. return false;
  901. }
  902. /**
  903. * Manage the Move to Pawn action in function of the distance and of the Interact area.<br>
  904. * <B><U> Actions</U> :</B>
  905. * <ul>
  906. * <li>Get the distance between the current position of the L2Character and the target (x,y)</li>
  907. * <li>If the distance > offset+20, move the actor (by running) to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)</li>
  908. * <li>If the distance <= offset+20, Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  909. * </ul>
  910. * <B><U> Example of use </U> :</B>
  911. * <ul>
  912. * <li>L2PLayerAI, L2SummonAI</li>
  913. * </ul>
  914. * @param target The targeted L2Object
  915. * @param offset The Interact area radius
  916. * @return True if a movement must be done
  917. */
  918. protected boolean maybeMoveToPawn(L2Object target, int offset)
  919. {
  920. // Get the distance between the current position of the L2Character and the target (x,y)
  921. if (target == null)
  922. {
  923. _log.warn("maybeMoveToPawn: target == NULL!");
  924. return false;
  925. }
  926. if (offset < 0)
  927. {
  928. return false; // skill radius -1
  929. }
  930. offset += _actor.getTemplate().getCollisionRadius();
  931. if (target instanceof L2Character)
  932. {
  933. offset += ((L2Character) target).getTemplate().getCollisionRadius();
  934. }
  935. if (!_actor.isInsideRadius(target, offset, false, false))
  936. {
  937. // Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
  938. if (getFollowTarget() != null)
  939. {
  940. // allow larger hit range when the target is moving (check is run only once per second)
  941. if (!_actor.isInsideRadius(target, offset + 100, false, false))
  942. {
  943. return true;
  944. }
  945. stopFollow();
  946. return false;
  947. }
  948. if (_actor.isMovementDisabled())
  949. {
  950. // If player is trying attack target but he cannot move to attack target
  951. // change his intention to idle
  952. if (_actor.getAI().getIntention() == CtrlIntention.AI_INTENTION_ATTACK)
  953. {
  954. _actor.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
  955. }
  956. return true;
  957. }
  958. // while flying there is no move to cast
  959. if ((_actor.getAI().getIntention() == CtrlIntention.AI_INTENTION_CAST) && (_actor instanceof L2PcInstance) && _actor.isTransformed())
  960. {
  961. if (!_actor.getTransformation().isCombat())
  962. {
  963. _actor.sendPacket(SystemMessageId.DIST_TOO_FAR_CASTING_STOPPED);
  964. _actor.sendPacket(ActionFailed.STATIC_PACKET);
  965. return true;
  966. }
  967. }
  968. // If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
  969. if (!_actor.isRunning() && !(this instanceof L2PlayerAI) && !(this instanceof L2SummonAI))
  970. {
  971. _actor.setRunning();
  972. }
  973. stopFollow();
  974. if ((target instanceof L2Character) && !(target instanceof L2DoorInstance))
  975. {
  976. if (((L2Character) target).isMoving())
  977. {
  978. offset -= 100;
  979. }
  980. if (offset < 5)
  981. {
  982. offset = 5;
  983. }
  984. startFollow((L2Character) target, offset);
  985. }
  986. else
  987. {
  988. // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
  989. moveToPawn(target, offset);
  990. }
  991. return true;
  992. }
  993. if (getFollowTarget() != null)
  994. {
  995. stopFollow();
  996. }
  997. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  998. // clientStopMoving(null);
  999. return false;
  1000. }
  1001. /**
  1002. * Modify current Intention and actions if the target is lost or dead.<br>
  1003. * <B><U> Actions</U> : <I>If the target is lost or dead</I></B>
  1004. * <ul>
  1005. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  1006. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  1007. * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li>
  1008. * </ul>
  1009. * <B><U> Example of use </U> :</B>
  1010. * <ul>
  1011. * <li>L2PLayerAI, L2SummonAI</li>
  1012. * </ul>
  1013. * @param target The targeted L2Object
  1014. * @return True if the target is lost or dead (false if fakedeath)
  1015. */
  1016. protected boolean checkTargetLostOrDead(L2Character target)
  1017. {
  1018. if ((target == null) || target.isAlikeDead())
  1019. {
  1020. // check if player is fakedeath
  1021. if ((target instanceof L2PcInstance) && ((L2PcInstance) target).isFakeDeath())
  1022. {
  1023. target.stopFakeDeath(true);
  1024. return false;
  1025. }
  1026. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  1027. setIntention(AI_INTENTION_ACTIVE);
  1028. return true;
  1029. }
  1030. return false;
  1031. }
  1032. /**
  1033. * Modify current Intention and actions if the target is lost.<br>
  1034. * <B><U> Actions</U> : <I>If the target is lost</I></B>
  1035. * <ul>
  1036. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  1037. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  1038. * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li>
  1039. * </ul>
  1040. * <B><U> Example of use </U> :</B>
  1041. * <ul>
  1042. * <li>L2PLayerAI, L2SummonAI</li>
  1043. * </ul>
  1044. * @param target The targeted L2Object
  1045. * @return True if the target is lost
  1046. */
  1047. protected boolean checkTargetLost(L2Object target)
  1048. {
  1049. // check if player is fakedeath
  1050. if (target instanceof L2PcInstance)
  1051. {
  1052. L2PcInstance target2 = (L2PcInstance) target; // convert object to chara
  1053. if (target2.isFakeDeath())
  1054. {
  1055. target2.stopFakeDeath(true);
  1056. return false;
  1057. }
  1058. }
  1059. if (target == null)
  1060. {
  1061. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  1062. setIntention(AI_INTENTION_ACTIVE);
  1063. return true;
  1064. }
  1065. if ((_actor != null) && (_skill != null) && _skill.isBad() && (_skill.getAffectRange() > 0) && !GeoData.getInstance().canSeeTarget(_actor, target))
  1066. {
  1067. setIntention(AI_INTENTION_ACTIVE);
  1068. return true;
  1069. }
  1070. return false;
  1071. }
  1072. protected class SelfAnalysis
  1073. {
  1074. public boolean isMage = false;
  1075. public boolean isBalanced;
  1076. public boolean isArcher = false;
  1077. public boolean isHealer = false;
  1078. public boolean isFighter = false;
  1079. public boolean cannotMoveOnLand = false;
  1080. public List<Skill> generalSkills = new ArrayList<>();
  1081. public List<Skill> buffSkills = new ArrayList<>();
  1082. public int lastBuffTick = 0;
  1083. public List<Skill> debuffSkills = new ArrayList<>();
  1084. public int lastDebuffTick = 0;
  1085. public List<Skill> cancelSkills = new ArrayList<>();
  1086. public List<Skill> healSkills = new ArrayList<>();
  1087. // public List<L2Skill> trickSkills = new ArrayList<>();
  1088. public List<Skill> generalDisablers = new ArrayList<>();
  1089. public List<Skill> sleepSkills = new ArrayList<>();
  1090. public List<Skill> rootSkills = new ArrayList<>();
  1091. public List<Skill> muteSkills = new ArrayList<>();
  1092. public List<Skill> resurrectSkills = new ArrayList<>();
  1093. public boolean hasHealOrResurrect = false;
  1094. public boolean hasLongRangeSkills = false;
  1095. public boolean hasLongRangeDamageSkills = false;
  1096. public int maxCastRange = 0;
  1097. public SelfAnalysis()
  1098. {
  1099. }
  1100. public void init()
  1101. {
  1102. switch (((L2NpcTemplate) _actor.getTemplate()).getAIType())
  1103. {
  1104. case FIGHTER:
  1105. isFighter = true;
  1106. break;
  1107. case MAGE:
  1108. isMage = true;
  1109. break;
  1110. case CORPSE:
  1111. case BALANCED:
  1112. isBalanced = true;
  1113. break;
  1114. case ARCHER:
  1115. isArcher = true;
  1116. break;
  1117. case HEALER:
  1118. isHealer = true;
  1119. break;
  1120. default:
  1121. isFighter = true;
  1122. break;
  1123. }
  1124. // water movement analysis
  1125. if (_actor.isNpc())
  1126. {
  1127. switch (_actor.getId())
  1128. {
  1129. case 20314: // great white shark
  1130. case 20849: // Light Worm
  1131. cannotMoveOnLand = true;
  1132. break;
  1133. default:
  1134. cannotMoveOnLand = false;
  1135. break;
  1136. }
  1137. }
  1138. // skill analysis
  1139. for (Skill sk : _actor.getAllSkills())
  1140. {
  1141. if (sk.isPassive())
  1142. {
  1143. continue;
  1144. }
  1145. int castRange = sk.getCastRange();
  1146. boolean hasLongRangeDamageSkill = false;
  1147. if (sk.isContinuous())
  1148. {
  1149. if (!sk.isDebuff())
  1150. {
  1151. buffSkills.add(sk);
  1152. }
  1153. else
  1154. {
  1155. debuffSkills.add(sk);
  1156. }
  1157. continue;
  1158. }
  1159. if (sk.hasEffectType(L2EffectType.DISPEL, L2EffectType.DISPEL_BY_SLOT))
  1160. {
  1161. cancelSkills.add(sk);
  1162. }
  1163. else if (sk.hasEffectType(L2EffectType.HEAL))
  1164. {
  1165. healSkills.add(sk);
  1166. hasHealOrResurrect = true;
  1167. }
  1168. else if (sk.hasEffectType(L2EffectType.SLEEP))
  1169. {
  1170. sleepSkills.add(sk);
  1171. }
  1172. else if (sk.hasEffectType(L2EffectType.STUN, L2EffectType.PARALYZE))
  1173. {
  1174. // hardcoding petrification until improvements are made to
  1175. // EffectTemplate... petrification is totally different for
  1176. // AI than paralyze
  1177. switch (sk.getId())
  1178. {
  1179. case 367:
  1180. case 4111:
  1181. case 4383:
  1182. case 4616:
  1183. case 4578:
  1184. sleepSkills.add(sk);
  1185. break;
  1186. default:
  1187. generalDisablers.add(sk);
  1188. break;
  1189. }
  1190. }
  1191. else if (sk.hasEffectType(L2EffectType.ROOT))
  1192. {
  1193. rootSkills.add(sk);
  1194. }
  1195. else if (sk.hasEffectType(L2EffectType.FEAR))
  1196. {
  1197. debuffSkills.add(sk);
  1198. }
  1199. else if (sk.hasEffectType(L2EffectType.MUTE))
  1200. {
  1201. muteSkills.add(sk);
  1202. }
  1203. else if (sk.hasEffectType(L2EffectType.RESURRECTION))
  1204. {
  1205. resurrectSkills.add(sk);
  1206. hasHealOrResurrect = true;
  1207. }
  1208. else
  1209. {
  1210. generalSkills.add(sk);
  1211. hasLongRangeDamageSkill = true;
  1212. }
  1213. if (castRange > 70)
  1214. {
  1215. hasLongRangeSkills = true;
  1216. if (hasLongRangeDamageSkill)
  1217. {
  1218. hasLongRangeDamageSkills = true;
  1219. }
  1220. }
  1221. if (castRange > maxCastRange)
  1222. {
  1223. maxCastRange = castRange;
  1224. }
  1225. }
  1226. // Because of missing skills, some mages/balanced cannot play like mages
  1227. if (!hasLongRangeDamageSkills && isMage)
  1228. {
  1229. isBalanced = true;
  1230. isMage = false;
  1231. isFighter = false;
  1232. }
  1233. if (!hasLongRangeSkills && (isMage || isBalanced))
  1234. {
  1235. isBalanced = false;
  1236. isMage = false;
  1237. isFighter = true;
  1238. }
  1239. if (generalSkills.isEmpty() && isMage)
  1240. {
  1241. isBalanced = true;
  1242. isMage = false;
  1243. }
  1244. }
  1245. }
  1246. protected class TargetAnalysis
  1247. {
  1248. public L2Character character;
  1249. public boolean isMage;
  1250. public boolean isBalanced;
  1251. public boolean isArcher;
  1252. public boolean isFighter;
  1253. public boolean isCanceled;
  1254. public boolean isSlower;
  1255. public boolean isMagicResistant;
  1256. public TargetAnalysis()
  1257. {
  1258. }
  1259. public void update(L2Character target)
  1260. {
  1261. // update status once in 4 seconds
  1262. if ((target == character) && (Rnd.nextInt(100) > 25))
  1263. {
  1264. return;
  1265. }
  1266. character = target;
  1267. if (target == null)
  1268. {
  1269. return;
  1270. }
  1271. isMage = false;
  1272. isBalanced = false;
  1273. isArcher = false;
  1274. isFighter = false;
  1275. isCanceled = false;
  1276. if (target.getMAtk(null, null) > (1.5 * target.getPAtk(null)))
  1277. {
  1278. isMage = true;
  1279. }
  1280. else if (((target.getPAtk(null) * 0.8) < target.getMAtk(null, null)) || ((target.getMAtk(null, null) * 0.8) > target.getPAtk(null)))
  1281. {
  1282. isBalanced = true;
  1283. }
  1284. else
  1285. {
  1286. L2Weapon weapon = target.getActiveWeaponItem();
  1287. if ((weapon != null) && ((weapon.getItemType() == WeaponType.BOW) || (weapon.getItemType() == WeaponType.CROSSBOW)))
  1288. {
  1289. isArcher = true;
  1290. }
  1291. else
  1292. {
  1293. isFighter = true;
  1294. }
  1295. }
  1296. if (target.getRunSpeed() < (_actor.getRunSpeed() - 3))
  1297. {
  1298. isSlower = true;
  1299. }
  1300. else
  1301. {
  1302. isSlower = false;
  1303. }
  1304. if ((target.getMDef(null, null) * 1.2) > _actor.getMAtk(null, null))
  1305. {
  1306. isMagicResistant = true;
  1307. }
  1308. else
  1309. {
  1310. isMagicResistant = false;
  1311. }
  1312. if (target.getBuffCount() < 4)
  1313. {
  1314. isCanceled = true;
  1315. }
  1316. }
  1317. }
  1318. public boolean canAura(Skill sk)
  1319. {
  1320. if ((sk.getTargetType() == L2TargetType.AURA) || (sk.getTargetType() == L2TargetType.BEHIND_AURA) || (sk.getTargetType() == L2TargetType.FRONT_AURA) || (sk.getTargetType() == L2TargetType.AURA_CORPSE_MOB))
  1321. {
  1322. for (L2Object target : _actor.getKnownList().getKnownCharactersInRadius(sk.getAffectRange()))
  1323. {
  1324. if (target == getAttackTarget())
  1325. {
  1326. return true;
  1327. }
  1328. }
  1329. }
  1330. return false;
  1331. }
  1332. public boolean canAOE(Skill sk)
  1333. {
  1334. if (sk.hasEffectType(L2EffectType.DISPEL, L2EffectType.DISPEL_BY_SLOT))
  1335. {
  1336. if ((sk.getTargetType() == L2TargetType.AURA) || (sk.getTargetType() == L2TargetType.BEHIND_AURA) || (sk.getTargetType() == L2TargetType.FRONT_AURA) || (sk.getTargetType() == L2TargetType.AURA_CORPSE_MOB))
  1337. {
  1338. boolean cancast = true;
  1339. for (L2Character target : _actor.getKnownList().getKnownCharactersInRadius(sk.getAffectRange()))
  1340. {
  1341. if (!GeoData.getInstance().canSeeTarget(_actor, target))
  1342. {
  1343. continue;
  1344. }
  1345. if (target instanceof L2Attackable)
  1346. {
  1347. L2Npc actors = ((L2Npc) _actor);
  1348. if (!actors.isChaos())
  1349. {
  1350. continue;
  1351. }
  1352. }
  1353. if (target.isAffectedBySkill(sk.getId()))
  1354. {
  1355. cancast = false;
  1356. }
  1357. }
  1358. if (cancast)
  1359. {
  1360. return true;
  1361. }
  1362. }
  1363. else if ((sk.getTargetType() == L2TargetType.AREA) || (sk.getTargetType() == L2TargetType.BEHIND_AREA) || (sk.getTargetType() == L2TargetType.FRONT_AREA))
  1364. {
  1365. boolean cancast = true;
  1366. for (L2Character target : getAttackTarget().getKnownList().getKnownCharactersInRadius(sk.getAffectRange()))
  1367. {
  1368. if (!GeoData.getInstance().canSeeTarget(_actor, target) || (target == null))
  1369. {
  1370. continue;
  1371. }
  1372. if (target instanceof L2Attackable)
  1373. {
  1374. L2Npc actors = ((L2Npc) _actor);
  1375. if (!actors.isChaos())
  1376. {
  1377. continue;
  1378. }
  1379. }
  1380. if (!target.getEffectList().isEmpty())
  1381. {
  1382. cancast = true;
  1383. }
  1384. }
  1385. if (cancast)
  1386. {
  1387. return true;
  1388. }
  1389. }
  1390. }
  1391. else
  1392. {
  1393. if ((sk.getTargetType() == L2TargetType.AURA) || (sk.getTargetType() == L2TargetType.BEHIND_AURA) || (sk.getTargetType() == L2TargetType.FRONT_AURA) || (sk.getTargetType() == L2TargetType.AURA_CORPSE_MOB))
  1394. {
  1395. boolean cancast = false;
  1396. for (L2Character target : _actor.getKnownList().getKnownCharactersInRadius(sk.getAffectRange()))
  1397. {
  1398. if (!GeoData.getInstance().canSeeTarget(_actor, target))
  1399. {
  1400. continue;
  1401. }
  1402. if (target instanceof L2Attackable)
  1403. {
  1404. L2Npc actors = ((L2Npc) _actor);
  1405. if (!actors.isChaos())
  1406. {
  1407. continue;
  1408. }
  1409. }
  1410. if (!target.getEffectList().isEmpty())
  1411. {
  1412. cancast = true;
  1413. }
  1414. }
  1415. if (cancast)
  1416. {
  1417. return true;
  1418. }
  1419. }
  1420. else if ((sk.getTargetType() == L2TargetType.AREA) || (sk.getTargetType() == L2TargetType.BEHIND_AREA) || (sk.getTargetType() == L2TargetType.FRONT_AREA))
  1421. {
  1422. boolean cancast = true;
  1423. for (L2Character target : getAttackTarget().getKnownList().getKnownCharactersInRadius(sk.getAffectRange()))
  1424. {
  1425. if (!GeoData.getInstance().canSeeTarget(_actor, target))
  1426. {
  1427. continue;
  1428. }
  1429. if (target instanceof L2Attackable)
  1430. {
  1431. L2Npc actors = ((L2Npc) _actor);
  1432. if (!actors.isChaos())
  1433. {
  1434. continue;
  1435. }
  1436. }
  1437. if (target.isAffectedBySkill(sk.getId()))
  1438. {
  1439. cancast = false;
  1440. }
  1441. }
  1442. if (cancast)
  1443. {
  1444. return true;
  1445. }
  1446. }
  1447. }
  1448. return false;
  1449. }
  1450. public boolean canParty(Skill sk)
  1451. {
  1452. if (sk.getTargetType() == L2TargetType.PARTY)
  1453. {
  1454. int count = 0;
  1455. int ccount = 0;
  1456. for (L2Character target : _actor.getKnownList().getKnownCharactersInRadius(sk.getAffectRange()))
  1457. {
  1458. if (!(target instanceof L2Attackable) || !GeoData.getInstance().canSeeTarget(_actor, target))
  1459. {
  1460. continue;
  1461. }
  1462. L2Npc targets = ((L2Npc) target);
  1463. L2Npc actors = ((L2Npc) _actor);
  1464. if (targets.isInMyClan(actors))
  1465. {
  1466. count++;
  1467. if (target.isAffectedBySkill(sk.getId()))
  1468. {
  1469. ccount++;
  1470. }
  1471. }
  1472. }
  1473. if (ccount < count)
  1474. {
  1475. return true;
  1476. }
  1477. }
  1478. return false;
  1479. }
  1480. public boolean isParty(Skill sk)
  1481. {
  1482. return (sk.getTargetType() == L2TargetType.PARTY);
  1483. }
  1484. }