L2CharacterAI.java 49 KB

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