L2CharacterAI.java 49 KB

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