L2CharacterAI.java 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  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 net.sf.l2j.gameserver.ai;
  16. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
  17. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
  18. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
  19. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
  20. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
  21. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
  22. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_MOVE_TO;
  23. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
  24. import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
  25. import java.util.List;
  26. import javolution.util.FastList;
  27. import net.sf.l2j.Config;
  28. import net.sf.l2j.gameserver.Universe;
  29. import net.sf.l2j.gameserver.model.L2Attackable;
  30. import net.sf.l2j.gameserver.model.L2CharPosition;
  31. import net.sf.l2j.gameserver.model.L2Character;
  32. import net.sf.l2j.gameserver.model.L2Object;
  33. import net.sf.l2j.gameserver.model.L2Skill;
  34. import net.sf.l2j.gameserver.model.actor.instance.L2BoatInstance;
  35. import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
  36. import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
  37. import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  38. import net.sf.l2j.gameserver.serverpackets.AutoAttackStop;
  39. import net.sf.l2j.gameserver.taskmanager.AttackStanceTaskManager;
  40. import net.sf.l2j.gameserver.templates.L2NpcTemplate;
  41. import net.sf.l2j.gameserver.templates.L2Weapon;
  42. import net.sf.l2j.gameserver.templates.L2WeaponType;
  43. import net.sf.l2j.util.Point3D;
  44. import net.sf.l2j.util.Rnd;
  45. /**
  46. * This class manages AI of L2Character.<BR><BR>
  47. *
  48. * L2CharacterAI :<BR><BR>
  49. * <li>L2AttackableAI</li>
  50. * <li>L2DoorAI</li>
  51. * <li>L2PlayerAI</li>
  52. * <li>L2SummonAI</li><BR><BR>
  53. *
  54. */
  55. public class L2CharacterAI extends AbstractAI
  56. {
  57. class IntentionCommand
  58. {
  59. protected CtrlIntention _crtlIntention;
  60. protected Object _arg0, _arg1;
  61. protected IntentionCommand(CtrlIntention pIntention, Object pArg0, Object pArg1)
  62. {
  63. _crtlIntention = pIntention;
  64. _arg0 = pArg0;
  65. _arg1 = pArg1;
  66. }
  67. }
  68. /**
  69. * Constructor of L2CharacterAI.<BR><BR>
  70. *
  71. * @param accessor The AI accessor of the L2Character
  72. *
  73. */
  74. public L2CharacterAI(L2Character.AIAccessor accessor)
  75. {
  76. super(accessor);
  77. }
  78. public IntentionCommand getNextIntention()
  79. {
  80. return null;
  81. }
  82. @Override
  83. protected void onEvtAttacked(L2Character attacker)
  84. {
  85. clientStartAutoAttack();
  86. }
  87. /**
  88. * Manage the Idle Intention : Stop Attack, Movement and Stand Up the actor.<BR><BR>
  89. *
  90. * <B><U> Actions</U> :</B><BR><BR>
  91. * <li>Set the AI Intention to AI_INTENTION_IDLE </li>
  92. * <li>Init cast and attack target </li>
  93. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
  94. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast) </li>
  95. * <li>Stand up the actor server side AND client side by sending Server->Client packet ChangeWaitType (broadcast) </li><BR><BR>
  96. *
  97. */
  98. @Override
  99. protected void onIntentionIdle()
  100. {
  101. // Set the AI Intention to AI_INTENTION_IDLE
  102. changeIntention(AI_INTENTION_IDLE, null, null);
  103. // Init cast and attack target
  104. setCastTarget(null);
  105. setAttackTarget(null);
  106. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  107. clientStopMoving(null);
  108. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  109. clientStopAutoAttack();
  110. }
  111. /**
  112. * Manage the Active Intention : Stop Attack, Movement and Launch Think Event.<BR><BR>
  113. *
  114. * <B><U> Actions</U> : <I>if the Intention is not already Active</I></B><BR><BR>
  115. * <li>Set the AI Intention to AI_INTENTION_ACTIVE </li>
  116. * <li>Init cast and attack target </li>
  117. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
  118. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast) </li>
  119. * <li>Launch the Think Event </li><BR><BR>
  120. *
  121. */
  122. @Override
  123. protected void onIntentionActive()
  124. {
  125. // Check if the Intention is not already Active
  126. if (getIntention() != AI_INTENTION_ACTIVE)
  127. {
  128. // Set the AI Intention to AI_INTENTION_ACTIVE
  129. changeIntention(AI_INTENTION_ACTIVE, null, null);
  130. // Init cast and attack target
  131. setCastTarget(null);
  132. setAttackTarget(null);
  133. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  134. clientStopMoving(null);
  135. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  136. clientStopAutoAttack();
  137. // Also enable random animations for this L2Character if allowed
  138. // This is only for mobs - town npcs are handled in their constructor
  139. if (_actor instanceof L2Attackable)
  140. ((L2NpcInstance)_actor).startRandomAnimationTimer();
  141. // Launch the Think Event
  142. onEvtThink();
  143. }
  144. }
  145. /**
  146. * Manage the Rest Intention.<BR><BR>
  147. *
  148. * <B><U> Actions</U> : </B><BR><BR>
  149. * <li>Set the AI Intention to AI_INTENTION_IDLE </li><BR><BR>
  150. *
  151. */
  152. @Override
  153. protected void onIntentionRest()
  154. {
  155. // Set the AI Intention to AI_INTENTION_IDLE
  156. setIntention(AI_INTENTION_IDLE);
  157. }
  158. /**
  159. * Manage the Attack Intention : Stop current Attack (if necessary), Start a new Attack and Launch Think Event.<BR><BR>
  160. *
  161. * <B><U> Actions</U> : </B><BR><BR>
  162. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
  163. * <li>Set the Intention of this AI to AI_INTENTION_ATTACK </li>
  164. * <li>Set or change the AI attack target </li>
  165. * <li>Start the actor Auto Attack client side by sending Server->Client packet AutoAttackStart (broadcast) </li>
  166. * <li>Launch the Think Event </li><BR><BR>
  167. *
  168. *
  169. * <B><U> Overridden in</U> :</B><BR><BR>
  170. * <li>L2AttackableAI : Calculate attack timeout</li><BR><BR>
  171. *
  172. */
  173. @Override
  174. protected void onIntentionAttack(L2Character target)
  175. {
  176. if (target == null)
  177. {
  178. clientActionFailed();
  179. return;
  180. }
  181. if (getIntention() == AI_INTENTION_REST)
  182. {
  183. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  184. clientActionFailed();
  185. return;
  186. }
  187. if (_actor.isAllSkillsDisabled() || _actor.isAfraid())
  188. {
  189. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  190. clientActionFailed();
  191. return;
  192. }
  193. // Check if the Intention is already AI_INTENTION_ATTACK
  194. if (getIntention() == AI_INTENTION_ATTACK)
  195. {
  196. // Check if the AI already targets the L2Character
  197. if (getAttackTarget() != target)
  198. {
  199. // Set the AI attack target (change target)
  200. setAttackTarget(target);
  201. stopFollow();
  202. // Launch the Think Event
  203. notifyEvent(CtrlEvent.EVT_THINK, null);
  204. }
  205. else
  206. clientActionFailed(); // else client freezes until cancel target
  207. }
  208. else
  209. {
  210. // Set the Intention of this AbstractAI to AI_INTENTION_ATTACK
  211. changeIntention(AI_INTENTION_ATTACK, target, null);
  212. // Set the AI attack target
  213. setAttackTarget(target);
  214. stopFollow();
  215. // Launch the Think Event
  216. notifyEvent(CtrlEvent.EVT_THINK, null);
  217. }
  218. }
  219. /**
  220. * Manage the Cast Intention : Stop current Attack, Init the AI in order to cast and Launch Think Event.<BR><BR>
  221. *
  222. * <B><U> Actions</U> : </B><BR><BR>
  223. * <li>Set the AI cast target </li>
  224. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
  225. * <li>Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor </li>
  226. * <li>Set the AI skill used by INTENTION_CAST </li>
  227. * <li>Set the Intention of this AI to AI_INTENTION_CAST </li>
  228. * <li>Launch the Think Event </li><BR><BR>
  229. *
  230. */
  231. @Override
  232. protected void onIntentionCast(L2Skill skill, L2Object target)
  233. {
  234. if (getIntention() == AI_INTENTION_REST && skill.isMagic())
  235. {
  236. clientActionFailed();
  237. return;
  238. }
  239. if (_actor.isAllSkillsDisabled())
  240. {
  241. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  242. clientActionFailed();
  243. return;
  244. }
  245. // can't cast if muted
  246. if (_actor.isMuted() && skill.isMagic())
  247. {
  248. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  249. clientActionFailed();
  250. return;
  251. }
  252. // Set the AI cast target
  253. setCastTarget((L2Character) target);
  254. // Stop actions client-side to cast the skill
  255. if (skill.getHitTime() > 50)
  256. {
  257. // Abort the attack of the L2Character and send Server->Client ActionFailed packet
  258. _actor.abortAttack();
  259. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  260. // no need for second ActionFailed packet, abortAttack() already sent it
  261. //clientActionFailed();
  262. }
  263. // Set the AI skill used by INTENTION_CAST
  264. _skill = skill;
  265. // Change the Intention of this AbstractAI to AI_INTENTION_CAST
  266. changeIntention(AI_INTENTION_CAST, skill, target);
  267. // Launch the Think Event
  268. notifyEvent(CtrlEvent.EVT_THINK, null);
  269. }
  270. /**
  271. * Manage the Move To Intention : Stop current Attack and Launch a Move to Location Task.<BR><BR>
  272. *
  273. * <B><U> Actions</U> : </B><BR><BR>
  274. * <li>Stop the actor auto-attack server side AND client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
  275. * <li>Set the Intention of this AI to AI_INTENTION_MOVE_TO </li>
  276. * <li>Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast) </li><BR><BR>
  277. *
  278. */
  279. @Override
  280. protected void onIntentionMoveTo(L2CharPosition pos)
  281. {
  282. if (getIntention() == AI_INTENTION_REST)
  283. {
  284. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  285. clientActionFailed();
  286. return;
  287. }
  288. if (_actor.isAllSkillsDisabled())
  289. {
  290. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  291. clientActionFailed();
  292. return;
  293. }
  294. // Set the Intention of this AbstractAI to AI_INTENTION_MOVE_TO
  295. changeIntention(AI_INTENTION_MOVE_TO, pos, null);
  296. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  297. clientStopAutoAttack();
  298. // Abort the attack of the L2Character and send Server->Client ActionFailed packet
  299. _actor.abortAttack();
  300. // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
  301. moveTo(pos.x, pos.y, pos.z);
  302. }
  303. /* (non-Javadoc)
  304. * @see net.sf.l2j.gameserver.ai.AbstractAI#onIntentionMoveToInABoat(net.sf.l2j.gameserver.model.L2CharPosition, net.sf.l2j.gameserver.model.L2CharPosition)
  305. */
  306. @Override
  307. protected void onIntentionMoveToInABoat(L2CharPosition destination, L2CharPosition origin)
  308. {
  309. if (getIntention() == AI_INTENTION_REST)
  310. {
  311. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  312. clientActionFailed();
  313. return;
  314. }
  315. if (_actor.isAllSkillsDisabled())
  316. {
  317. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  318. clientActionFailed();
  319. return;
  320. }
  321. // Set the Intention of this AbstractAI to AI_INTENTION_MOVE_TO
  322. //
  323. //changeIntention(AI_INTENTION_MOVE_TO, new L2CharPosition(((L2PcInstance)_actor).getBoat().getX() - destination.x, ((L2PcInstance)_actor).getBoat().getY() - destination.y, ((L2PcInstance)_actor).getBoat().getZ() - destination.z, 0) , null);
  324. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  325. clientStopAutoAttack();
  326. // Abort the attack of the L2Character and send Server->Client ActionFailed packet
  327. _actor.abortAttack();
  328. // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
  329. moveToInABoat(destination, origin);
  330. }
  331. /**
  332. * Manage the Follow Intention : Stop current Attack and Launch a Follow Task.<BR><BR>
  333. *
  334. * <B><U> Actions</U> : </B><BR><BR>
  335. * <li>Stop the actor auto-attack server side AND client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
  336. * <li>Set the Intention of this AI to AI_INTENTION_FOLLOW </li>
  337. * <li>Create and Launch an AI Follow Task to execute every 1s </li><BR><BR>
  338. *
  339. */
  340. @Override
  341. protected void onIntentionFollow(L2Character target)
  342. {
  343. if (getIntention() == AI_INTENTION_REST)
  344. {
  345. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  346. clientActionFailed();
  347. return;
  348. }
  349. if (_actor.isAllSkillsDisabled())
  350. {
  351. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  352. clientActionFailed();
  353. return;
  354. }
  355. if (_actor.isImmobilized() || _actor.isRooted())
  356. {
  357. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  358. clientActionFailed();
  359. return;
  360. }
  361. // Dead actors can`t follow
  362. if (_actor.isDead())
  363. {
  364. clientActionFailed();
  365. return;
  366. }
  367. // do not follow yourself
  368. if (_actor == target)
  369. {
  370. clientActionFailed();
  371. return;
  372. }
  373. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  374. clientStopAutoAttack();
  375. // Set the Intention of this AbstractAI to AI_INTENTION_FOLLOW
  376. changeIntention(AI_INTENTION_FOLLOW, target, null);
  377. // Create and Launch an AI Follow Task to execute every 1s
  378. startFollow(target);
  379. }
  380. /**
  381. * Manage the PickUp Intention : Set the pick up target and Launch a Move To Pawn Task (offset=20).<BR><BR>
  382. *
  383. * <B><U> Actions</U> : </B><BR><BR>
  384. * <li>Set the AI pick up target </li>
  385. * <li>Set the Intention of this AI to AI_INTENTION_PICK_UP </li>
  386. * <li>Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast) </li><BR><BR>
  387. *
  388. */
  389. @Override
  390. protected void onIntentionPickUp(L2Object object)
  391. {
  392. if (getIntention() == AI_INTENTION_REST)
  393. {
  394. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  395. clientActionFailed();
  396. return;
  397. }
  398. if (_actor.isAllSkillsDisabled())
  399. {
  400. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  401. clientActionFailed();
  402. return;
  403. }
  404. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  405. clientStopAutoAttack();
  406. // Set the Intention of this AbstractAI to AI_INTENTION_PICK_UP
  407. changeIntention(AI_INTENTION_PICK_UP, object, null);
  408. // Set the AI pick up target
  409. setTarget(object);
  410. if(object.getX() == 0 && object.getY() == 0) // TODO: Find the drop&spawn bug
  411. {
  412. _log.warning("Object in coords 0,0 - using a temporary fix");
  413. object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ()+5);
  414. }
  415. // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
  416. moveToPawn(object, 20);
  417. }
  418. /**
  419. * Manage the Interact Intention : Set the interact target and Launch a Move To Pawn Task (offset=60).<BR><BR>
  420. *
  421. * <B><U> Actions</U> : </B><BR><BR>
  422. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
  423. * <li>Set the AI interact target </li>
  424. * <li>Set the Intention of this AI to AI_INTENTION_INTERACT </li>
  425. * <li>Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast) </li><BR><BR>
  426. *
  427. */
  428. @Override
  429. protected void onIntentionInteract(L2Object object)
  430. {
  431. if (getIntention() == AI_INTENTION_REST)
  432. {
  433. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  434. clientActionFailed();
  435. return;
  436. }
  437. if (_actor.isAllSkillsDisabled())
  438. {
  439. // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
  440. clientActionFailed();
  441. return;
  442. }
  443. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  444. clientStopAutoAttack();
  445. if (getIntention() != AI_INTENTION_INTERACT)
  446. {
  447. // Set the Intention of this AbstractAI to AI_INTENTION_INTERACT
  448. changeIntention(AI_INTENTION_INTERACT, object, null);
  449. // Set the AI interact target
  450. setTarget(object);
  451. // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
  452. moveToPawn(object, 60);
  453. }
  454. }
  455. /**
  456. * Do nothing.<BR><BR>
  457. */
  458. @Override
  459. protected void onEvtThink()
  460. {
  461. // do nothing
  462. }
  463. /**
  464. * Do nothing.<BR><BR>
  465. */
  466. @Override
  467. protected void onEvtAggression(@SuppressWarnings("unused")
  468. L2Character target, @SuppressWarnings("unused")
  469. int aggro)
  470. {
  471. // do nothing
  472. }
  473. /**
  474. * Launch actions corresponding to the Event Stunned then onAttacked Event.<BR><BR>
  475. *
  476. * <B><U> Actions</U> :</B><BR><BR>
  477. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  478. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  479. * <li>Break an attack and send Server->Client ActionFailed packet and a System Message to the L2Character </li>
  480. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li>
  481. * <li>Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode) </li><BR><BR>
  482. *
  483. */
  484. @Override
  485. protected void onEvtStunned(L2Character attacker)
  486. {
  487. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  488. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  489. if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  490. AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  491. // Stop Server AutoAttack also
  492. setAutoAttacking(false);
  493. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  494. clientStopMoving(null);
  495. // Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode)
  496. onEvtAttacked(attacker);
  497. }
  498. @Override
  499. protected void onEvtParalyzed(L2Character attacker)
  500. {
  501. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  502. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  503. if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  504. AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  505. // Stop Server AutoAttack also
  506. setAutoAttacking(false);
  507. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  508. clientStopMoving(null);
  509. // Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode)
  510. onEvtAttacked(attacker);
  511. }
  512. /**
  513. * Launch actions corresponding to the Event Sleeping.<BR><BR>
  514. *
  515. * <B><U> Actions</U> :</B><BR><BR>
  516. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  517. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  518. * <li>Break an attack and send Server->Client ActionFailed packet and a System Message to the L2Character </li>
  519. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li><BR><BR>
  520. *
  521. */
  522. @Override
  523. protected void onEvtSleeping(@SuppressWarnings("unused")
  524. L2Character attacker)
  525. {
  526. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  527. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  528. if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  529. AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  530. // stop Server AutoAttack also
  531. setAutoAttacking(false);
  532. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  533. clientStopMoving(null);
  534. }
  535. /**
  536. * Launch actions corresponding to the Event Rooted.<BR><BR>
  537. *
  538. * <B><U> Actions</U> :</B><BR><BR>
  539. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  540. * <li>Launch actions corresponding to the Event onAttacked</li><BR><BR>
  541. *
  542. */
  543. @Override
  544. protected void onEvtRooted(L2Character attacker)
  545. {
  546. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  547. //_actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  548. //if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  549. // AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  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 Confused.<BR><BR>
  557. *
  558. * <B><U> Actions</U> :</B><BR><BR>
  559. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  560. * <li>Launch actions corresponding to the Event onAttacked</li><BR><BR>
  561. *
  562. */
  563. @Override
  564. protected void onEvtConfused(L2Character attacker)
  565. {
  566. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  567. clientStopMoving(null);
  568. // Launch actions corresponding to the Event onAttacked
  569. onEvtAttacked(attacker);
  570. }
  571. /**
  572. * Launch actions corresponding to the Event Muted.<BR><BR>
  573. *
  574. * <B><U> Actions</U> :</B><BR><BR>
  575. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li><BR><BR>
  576. *
  577. */
  578. @Override
  579. protected void onEvtMuted(L2Character attacker)
  580. {
  581. // Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character
  582. onEvtAttacked(attacker);
  583. }
  584. /**
  585. * Launch actions corresponding to the Event ReadyToAct.<BR><BR>
  586. *
  587. * <B><U> Actions</U> :</B><BR><BR>
  588. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  589. *
  590. */
  591. @Override
  592. protected void onEvtReadyToAct()
  593. {
  594. // Launch actions corresponding to the Event Think
  595. onEvtThink();
  596. }
  597. /**
  598. * Do nothing.<BR><BR>
  599. */
  600. @Override
  601. protected void onEvtUserCmd(@SuppressWarnings("unused")
  602. Object arg0, @SuppressWarnings("unused")
  603. Object arg1)
  604. {
  605. // do nothing
  606. }
  607. /**
  608. * Launch actions corresponding to the Event Arrived.<BR><BR>
  609. *
  610. * <B><U> Actions</U> :</B><BR><BR>
  611. * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
  612. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  613. *
  614. */
  615. @Override
  616. protected void onEvtArrived()
  617. {
  618. // Launch an explore task if necessary
  619. if (_accessor.getActor() instanceof L2PcInstance)
  620. {
  621. if (Config.ACTIVATE_POSITION_RECORDER)
  622. ((L2PcInstance) _accessor.getActor()).explore();
  623. ((L2PcInstance) _accessor.getActor()).revalidateZone(true);
  624. }
  625. else _accessor.getActor().revalidateZone();
  626. if (_accessor.getActor().moveToNextRoutePoint())
  627. return;
  628. if (_accessor.getActor() instanceof L2Attackable)
  629. {
  630. ((L2Attackable)_accessor.getActor()).setisReturningToSpawnPoint(false);
  631. }
  632. clientStoppedMoving();
  633. // If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE
  634. if (getIntention() == AI_INTENTION_MOVE_TO) setIntention(AI_INTENTION_ACTIVE);
  635. // Launch actions corresponding to the Event Think
  636. onEvtThink();
  637. if (_actor instanceof L2BoatInstance)
  638. {
  639. ((L2BoatInstance) _actor).evtArrived();
  640. }
  641. }
  642. /**
  643. * Launch actions corresponding to the Event ArrivedRevalidate.<BR><BR>
  644. *
  645. * <B><U> Actions</U> :</B><BR><BR>
  646. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  647. *
  648. */
  649. @Override
  650. protected void onEvtArrivedRevalidate()
  651. {
  652. // Launch actions corresponding to the Event Think
  653. onEvtThink();
  654. }
  655. /**
  656. * Launch actions corresponding to the Event ArrivedBlocked.<BR><BR>
  657. *
  658. * <B><U> Actions</U> :</B><BR><BR>
  659. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  660. * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
  661. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  662. *
  663. */
  664. @Override
  665. protected void onEvtArrivedBlocked(L2CharPosition blocked_at_pos)
  666. {
  667. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  668. clientStopMoving(blocked_at_pos);
  669. if (Config.ACTIVATE_POSITION_RECORDER
  670. && Universe.getInstance().shouldLog(_accessor.getActor().getObjectId()))
  671. {
  672. if (!_accessor.getActor().isFlying())
  673. Universe.getInstance().registerObstacle(blocked_at_pos.x, blocked_at_pos.y,
  674. blocked_at_pos.z);
  675. if (_accessor.getActor() instanceof L2PcInstance)
  676. ((L2PcInstance) _accessor.getActor()).explore();
  677. }
  678. // If the Intention was AI_INTENTION_MOVE_TO, tet the Intention to AI_INTENTION_ACTIVE
  679. if (getIntention() == AI_INTENTION_MOVE_TO) setIntention(AI_INTENTION_ACTIVE);
  680. // Launch actions corresponding to the Event Think
  681. onEvtThink();
  682. }
  683. /**
  684. * Launch actions corresponding to the Event ForgetObject.<BR><BR>
  685. *
  686. * <B><U> Actions</U> :</B><BR><BR>
  687. * <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>
  688. * <li>If the object was targeted to attack, stop the auto-attack, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
  689. * <li>If the object was targeted to cast, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
  690. * <li>If the object was targeted to follow, stop the movement, cancel AI Follow Task and set the Intention to AI_INTENTION_ACTIVE</li>
  691. * <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>
  692. *
  693. */
  694. @Override
  695. protected void onEvtForgetObject(L2Object object)
  696. {
  697. // If the object was targeted and the Intention was AI_INTENTION_INTERACT or AI_INTENTION_PICK_UP, set the Intention to AI_INTENTION_ACTIVE
  698. if (getTarget() == object)
  699. {
  700. setTarget(null);
  701. if (getIntention() == AI_INTENTION_INTERACT) setIntention(AI_INTENTION_ACTIVE);
  702. else if (getIntention() == AI_INTENTION_PICK_UP) setIntention(AI_INTENTION_ACTIVE);
  703. }
  704. // Check if the object was targeted to attack
  705. if (getAttackTarget() == object)
  706. {
  707. // Cancel attack target
  708. setAttackTarget(null);
  709. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  710. setIntention(AI_INTENTION_ACTIVE);
  711. }
  712. // Check if the object was targeted to cast
  713. if (getCastTarget() == object)
  714. {
  715. // Cancel cast target
  716. setCastTarget(null);
  717. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  718. setIntention(AI_INTENTION_ACTIVE);
  719. }
  720. // Check if the object was targeted to follow
  721. if (getFollowTarget() == object)
  722. {
  723. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  724. clientStopMoving(null);
  725. // Stop an AI Follow Task
  726. stopFollow();
  727. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  728. setIntention(AI_INTENTION_ACTIVE);
  729. }
  730. // Check if the targeted object was the actor
  731. if (_actor == object)
  732. {
  733. // Cancel AI target
  734. setTarget(null);
  735. setAttackTarget(null);
  736. setCastTarget(null);
  737. // Stop an AI Follow Task
  738. stopFollow();
  739. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  740. clientStopMoving(null);
  741. // Set the Intention of this AbstractAI to AI_INTENTION_IDLE
  742. changeIntention(AI_INTENTION_IDLE, null, null);
  743. }
  744. }
  745. /**
  746. * Launch actions corresponding to the Event Cancel.<BR><BR>
  747. *
  748. * <B><U> Actions</U> :</B><BR><BR>
  749. * <li>Stop an AI Follow Task</li>
  750. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  751. *
  752. */
  753. @Override
  754. protected void onEvtCancel()
  755. {
  756. // Stop an AI Follow Task
  757. stopFollow();
  758. if (!AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  759. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  760. // Launch actions corresponding to the Event Think
  761. onEvtThink();
  762. }
  763. /**
  764. * Launch actions corresponding to the Event Dead.<BR><BR>
  765. *
  766. * <B><U> Actions</U> :</B><BR><BR>
  767. * <li>Stop an AI Follow Task</li>
  768. * <li>Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)</li><BR><BR>
  769. *
  770. */
  771. @Override
  772. protected void onEvtDead()
  773. {
  774. // Stop an AI Follow Task
  775. stopFollow();
  776. // Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)
  777. clientNotifyDead();
  778. if (!(_actor instanceof L2PcInstance))
  779. _actor.setWalking();
  780. }
  781. /**
  782. * Launch actions corresponding to the Event Fake Death.<BR><BR>
  783. *
  784. * <B><U> Actions</U> :</B><BR><BR>
  785. * <li>Stop an AI Follow Task</li>
  786. *
  787. */
  788. @Override
  789. protected void onEvtFakeDeath()
  790. {
  791. // Stop an AI Follow Task
  792. stopFollow();
  793. // Stop the actor movement and send Server->Client packet StopMove/StopRotation (broadcast)
  794. clientStopMoving(null);
  795. // Init AI
  796. _intention = AI_INTENTION_IDLE;
  797. setTarget(null);
  798. setCastTarget(null);
  799. setAttackTarget(null);
  800. }
  801. /**
  802. * Do nothing.<BR><BR>
  803. */
  804. @Override
  805. protected void onEvtFinishCasting()
  806. {
  807. // do nothing
  808. }
  809. protected boolean maybeMoveToPosition(Point3D worldPosition, int offset)
  810. {
  811. if (worldPosition == null)
  812. {
  813. _log.warning("maybeMoveToPosition: worldPosition == NULL!");
  814. return false;
  815. }
  816. if (offset < 0)
  817. return false; // skill radius -1
  818. if (!_actor.isInsideRadius(worldPosition.getX(), worldPosition.getY(), offset + _actor.getTemplate().collisionRadius, false))
  819. {
  820. if (_actor.isMovementDisabled())
  821. return true;
  822. if (!_actor.isRunning() && !(this instanceof L2PlayerAI))
  823. _actor.setRunning();
  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. stopFollow();
  840. return false;
  841. }
  842. /**
  843. * Manage the Move to Pawn action in function of the distance and of the Interact area.<BR><BR>
  844. *
  845. * <B><U> Actions</U> :</B><BR><BR>
  846. * <li>Get the distance between the current position of the L2Character and the target (x,y)</li>
  847. * <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>
  848. * <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>
  849. *
  850. * <B><U> Example of use </U> :</B><BR><BR>
  851. * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
  852. *
  853. * @param target The targeted L2Object
  854. * @param offset The Interact area radius
  855. *
  856. * @return True if a movement must be done
  857. *
  858. */
  859. protected boolean maybeMoveToPawn(L2Object target, int offset)
  860. {
  861. // Get the distance between the current position of the L2Character and the target (x,y)
  862. if (target == null)
  863. {
  864. _log.warning("maybeMoveToPawn: target == NULL!");
  865. return false;
  866. }
  867. if(offset < 0) return false; // skill radius -1
  868. offset += _actor.getTemplate().collisionRadius;
  869. if (target instanceof L2Character)
  870. offset += ((L2Character)target).getTemplate().collisionRadius;
  871. if (!_actor.isInsideRadius(target, offset, false, false))
  872. {
  873. // Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
  874. if (getFollowTarget() != null) {
  875. // allow larger hit range when the target is moving (check is run only once per second)
  876. if (!_actor.isInsideRadius(target, offset + 100, false, false)) return true;
  877. stopFollow();
  878. return false;
  879. }
  880. if (_actor.isMovementDisabled()) return true;
  881. // If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
  882. if (!_actor.isRunning() && !(this instanceof L2PlayerAI)) _actor.setRunning();
  883. stopFollow();
  884. if ((target instanceof L2Character) && !(target instanceof L2DoorInstance))
  885. {
  886. if (((L2Character)target).isMoving()) offset -= 100;
  887. if (offset < 5) offset = 5;
  888. startFollow((L2Character) target, offset);
  889. }
  890. else
  891. {
  892. // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
  893. moveToPawn(target, offset);
  894. }
  895. return true;
  896. }
  897. if (getFollowTarget() != null) stopFollow();
  898. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  899. // clientStopMoving(null);
  900. return false;
  901. }
  902. /**
  903. * Modify current Intention and actions if the target is lost or dead.<BR><BR>
  904. *
  905. * <B><U> Actions</U> : <I>If the target is lost or dead</I></B><BR><BR>
  906. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  907. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  908. * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li><BR><BR>
  909. *
  910. * <B><U> Example of use </U> :</B><BR><BR>
  911. * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
  912. *
  913. * @param target The targeted L2Object
  914. *
  915. * @return True if the target is lost or dead (false if fakedeath)
  916. *
  917. */
  918. protected boolean checkTargetLostOrDead(L2Character target)
  919. {
  920. if (target == null || target.isAlikeDead())
  921. {
  922. //check if player is fakedeath
  923. if (target != null && target.isFakeDeath())
  924. {
  925. target.stopFakeDeath(null);
  926. return false;
  927. }
  928. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  929. setIntention(AI_INTENTION_ACTIVE);
  930. return true;
  931. }
  932. return false;
  933. }
  934. /**
  935. * Modify current Intention and actions if the target is lost.<BR><BR>
  936. *
  937. * <B><U> Actions</U> : <I>If the target is lost</I></B><BR><BR>
  938. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  939. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  940. * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li><BR><BR>
  941. *
  942. * <B><U> Example of use </U> :</B><BR><BR>
  943. * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
  944. *
  945. * @param target The targeted L2Object
  946. *
  947. * @return True if the target is lost
  948. *
  949. */
  950. protected boolean checkTargetLost(L2Object target)
  951. {
  952. // check if player is fakedeath
  953. if (target instanceof L2PcInstance)
  954. {
  955. L2PcInstance target2 = (L2PcInstance) target; //convert object to chara
  956. if (target2.isFakeDeath())
  957. {
  958. target2.stopFakeDeath(null);
  959. return false;
  960. }
  961. }
  962. if (target == null)
  963. {
  964. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  965. setIntention(AI_INTENTION_ACTIVE);
  966. return true;
  967. }
  968. return false;
  969. }
  970. protected class SelfAnalysis
  971. {
  972. public boolean isMage = false;
  973. public boolean isBalanced;
  974. public boolean isArcher = false;
  975. public boolean isFighter = false;
  976. public boolean cannotMoveOnLand = false;
  977. public List<L2Skill> generalSkills = new FastList<L2Skill>();
  978. public List<L2Skill> buffSkills = new FastList<L2Skill>();
  979. public int lastBuffTick = 0;
  980. public List<L2Skill> debuffSkills = new FastList<L2Skill>();
  981. public int lastDebuffTick = 0;
  982. public List<L2Skill> cancelSkills = new FastList<L2Skill>();
  983. public List<L2Skill> healSkills = new FastList<L2Skill>();
  984. //public List<L2Skill> trickSkills = new FastList<L2Skill>();
  985. public List<L2Skill> generalDisablers = new FastList<L2Skill>();
  986. public List<L2Skill> sleepSkills = new FastList<L2Skill>();
  987. public List<L2Skill> rootSkills = new FastList<L2Skill>();
  988. public List<L2Skill> muteSkills = new FastList<L2Skill>();
  989. public List<L2Skill> resurrectSkills = new FastList<L2Skill>();
  990. public boolean hasHealOrResurrect = false;
  991. public boolean hasLongRangeSkills = false;
  992. public boolean hasLongRangeDamageSkills = false;
  993. public int maxCastRange = 0;
  994. public SelfAnalysis()
  995. {
  996. }
  997. public void init()
  998. {
  999. switch (((L2NpcTemplate)_actor.getTemplate()).AI)
  1000. {
  1001. case FIGHTER:
  1002. isFighter = true;
  1003. break;
  1004. case MAGE:
  1005. isMage = true;
  1006. break;
  1007. case BALANCED:
  1008. isBalanced = true;
  1009. break;
  1010. case ARCHER:
  1011. isArcher = true;
  1012. break;
  1013. default:
  1014. isFighter = true;
  1015. break;
  1016. }
  1017. // water movement analysis
  1018. if (_actor instanceof L2NpcInstance)
  1019. {
  1020. int npcId = ((L2NpcInstance)_actor).getNpcId();
  1021. switch (npcId)
  1022. {
  1023. case 20314: // great white shark
  1024. case 20849: // Light Worm
  1025. cannotMoveOnLand = true;
  1026. break;
  1027. default:
  1028. cannotMoveOnLand = false;
  1029. break;
  1030. }
  1031. }
  1032. // skill analysis
  1033. for (L2Skill sk : _actor.getAllSkills())
  1034. {
  1035. if (sk.isPassive()) 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: case 4111: case 4383:
  1059. case 4616: case 4578:
  1060. sleepSkills.add(sk);
  1061. break;
  1062. default:
  1063. generalDisablers.add(sk);
  1064. break;
  1065. }
  1066. break;
  1067. case MUTE:
  1068. muteSkills.add(sk);
  1069. break;
  1070. case SLEEP:
  1071. sleepSkills.add(sk);
  1072. break;
  1073. case ROOT:
  1074. rootSkills.add(sk);
  1075. break;
  1076. case FEAR: // could be used as an alternative for healing?
  1077. case CONFUSION:
  1078. // trickSkills.add(sk);
  1079. case DEBUFF:
  1080. debuffSkills.add(sk);
  1081. break;
  1082. case CANCEL:
  1083. case MAGE_BANE:
  1084. case WARRIOR_BANE:
  1085. case NEGATE:
  1086. cancelSkills.add(sk);
  1087. break;
  1088. case RESURRECT:
  1089. resurrectSkills.add(sk);
  1090. hasHealOrResurrect = true;
  1091. break;
  1092. case NOTDONE:
  1093. case COREDONE:
  1094. continue; // won't be considered something for fighting
  1095. default:
  1096. generalSkills.add(sk);
  1097. hasLongRangeDamageSkill = true;
  1098. break;
  1099. }
  1100. if (castRange > 70) {
  1101. hasLongRangeSkills = true;
  1102. if (hasLongRangeDamageSkill)
  1103. hasLongRangeDamageSkills = true;
  1104. }
  1105. if (castRange > maxCastRange) maxCastRange = castRange;
  1106. }
  1107. // Because of missing skills, some mages/balanced cannot play like mages
  1108. if (!hasLongRangeDamageSkills && isMage)
  1109. {
  1110. isBalanced = true;
  1111. isMage = false;
  1112. isFighter = false;
  1113. }
  1114. if (!hasLongRangeSkills && (isMage || isBalanced))
  1115. {
  1116. isBalanced = false;
  1117. isMage = false;
  1118. isFighter = true;
  1119. }
  1120. if (generalSkills.isEmpty() && isMage)
  1121. {
  1122. isBalanced = true;
  1123. isMage = false;
  1124. }
  1125. }
  1126. }
  1127. protected class TargetAnalysis
  1128. {
  1129. public L2Character character;
  1130. public boolean isMage;
  1131. public boolean isBalanced;
  1132. public boolean isArcher;
  1133. public boolean isFighter;
  1134. public boolean isCanceled;
  1135. public boolean isSlower;
  1136. public boolean isMagicResistant;
  1137. public TargetAnalysis()
  1138. {
  1139. }
  1140. public void update(L2Character target)
  1141. {
  1142. // update status once in 4 seconds
  1143. if (target == character && Rnd.nextInt(100) > 25)
  1144. return;
  1145. character = target;
  1146. if (target == null)
  1147. return;
  1148. isMage = false;
  1149. isBalanced = false;
  1150. isArcher = false;
  1151. isFighter = false;
  1152. isCanceled = false;
  1153. if (target.getMAtk(null, null) > 1.5*target.getPAtk(null))
  1154. isMage = true;
  1155. else if (target.getPAtk(null)*0.8 < target.getMAtk(null, null)
  1156. || target.getMAtk(null, null)*0.8 > target.getPAtk(null))
  1157. {
  1158. isBalanced = true;
  1159. }
  1160. else
  1161. {
  1162. L2Weapon weapon = target.getActiveWeaponItem();
  1163. if (weapon != null && (weapon.getItemType() == L2WeaponType.BOW || weapon.getItemType() == L2WeaponType.CROSSBOW))
  1164. isArcher = true;
  1165. else
  1166. isFighter = true;
  1167. }
  1168. if (target.getRunSpeed() < _actor.getRunSpeed()-3)
  1169. isSlower = true;
  1170. else
  1171. isSlower = false;
  1172. if (target.getMDef(null, null)*1.2 > _actor.getMAtk(null, null))
  1173. isMagicResistant = true;
  1174. else
  1175. isMagicResistant = false;
  1176. if (target.getBuffCount() < 4)
  1177. isCanceled = true;
  1178. }
  1179. }
  1180. }