L2CharacterAI.java 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  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. /**
  499. * Launch actions corresponding to the Event Sleeping.<BR><BR>
  500. *
  501. * <B><U> Actions</U> :</B><BR><BR>
  502. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  503. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  504. * <li>Break an attack and send Server->Client ActionFailed packet and a System Message to the L2Character </li>
  505. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li><BR><BR>
  506. *
  507. */
  508. @Override
  509. protected void onEvtSleeping(@SuppressWarnings("unused")
  510. L2Character attacker)
  511. {
  512. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  513. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  514. if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  515. AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  516. // stop Server AutoAttack also
  517. setAutoAttacking(false);
  518. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  519. clientStopMoving(null);
  520. }
  521. /**
  522. * Launch actions corresponding to the Event Rooted.<BR><BR>
  523. *
  524. * <B><U> Actions</U> :</B><BR><BR>
  525. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  526. * <li>Launch actions corresponding to the Event onAttacked</li><BR><BR>
  527. *
  528. */
  529. @Override
  530. protected void onEvtRooted(L2Character attacker)
  531. {
  532. // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
  533. //_actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  534. //if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  535. // AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
  536. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  537. clientStopMoving(null);
  538. // Launch actions corresponding to the Event onAttacked
  539. onEvtAttacked(attacker);
  540. }
  541. /**
  542. * Launch actions corresponding to the Event Confused.<BR><BR>
  543. *
  544. * <B><U> Actions</U> :</B><BR><BR>
  545. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  546. * <li>Launch actions corresponding to the Event onAttacked</li><BR><BR>
  547. *
  548. */
  549. @Override
  550. protected void onEvtConfused(L2Character attacker)
  551. {
  552. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  553. clientStopMoving(null);
  554. // Launch actions corresponding to the Event onAttacked
  555. onEvtAttacked(attacker);
  556. }
  557. /**
  558. * Launch actions corresponding to the Event Muted.<BR><BR>
  559. *
  560. * <B><U> Actions</U> :</B><BR><BR>
  561. * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li><BR><BR>
  562. *
  563. */
  564. @Override
  565. protected void onEvtMuted(L2Character attacker)
  566. {
  567. // Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character
  568. onEvtAttacked(attacker);
  569. }
  570. /**
  571. * Launch actions corresponding to the Event ReadyToAct.<BR><BR>
  572. *
  573. * <B><U> Actions</U> :</B><BR><BR>
  574. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  575. *
  576. */
  577. @Override
  578. protected void onEvtReadyToAct()
  579. {
  580. // Launch actions corresponding to the Event Think
  581. onEvtThink();
  582. }
  583. /**
  584. * Do nothing.<BR><BR>
  585. */
  586. @Override
  587. protected void onEvtUserCmd(@SuppressWarnings("unused")
  588. Object arg0, @SuppressWarnings("unused")
  589. Object arg1)
  590. {
  591. // do nothing
  592. }
  593. /**
  594. * Launch actions corresponding to the Event Arrived.<BR><BR>
  595. *
  596. * <B><U> Actions</U> :</B><BR><BR>
  597. * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
  598. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  599. *
  600. */
  601. @Override
  602. protected void onEvtArrived()
  603. {
  604. // Launch an explore task if necessary
  605. if (_accessor.getActor() instanceof L2PcInstance)
  606. {
  607. if (Config.ACTIVATE_POSITION_RECORDER)
  608. ((L2PcInstance) _accessor.getActor()).explore();
  609. ((L2PcInstance) _accessor.getActor()).revalidateZone(true);
  610. }
  611. else _accessor.getActor().revalidateZone();
  612. if (_accessor.getActor().moveToNextRoutePoint())
  613. return;
  614. if (_accessor.getActor() instanceof L2Attackable)
  615. {
  616. ((L2Attackable)_accessor.getActor()).setisReturningToSpawnPoint(false);
  617. }
  618. clientStoppedMoving();
  619. // If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE
  620. if (getIntention() == AI_INTENTION_MOVE_TO) setIntention(AI_INTENTION_ACTIVE);
  621. // Launch actions corresponding to the Event Think
  622. onEvtThink();
  623. if (_actor instanceof L2BoatInstance)
  624. {
  625. ((L2BoatInstance) _actor).evtArrived();
  626. }
  627. }
  628. /**
  629. * Launch actions corresponding to the Event ArrivedRevalidate.<BR><BR>
  630. *
  631. * <B><U> Actions</U> :</B><BR><BR>
  632. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  633. *
  634. */
  635. @Override
  636. protected void onEvtArrivedRevalidate()
  637. {
  638. // Launch actions corresponding to the Event Think
  639. onEvtThink();
  640. }
  641. /**
  642. * Launch actions corresponding to the Event ArrivedBlocked.<BR><BR>
  643. *
  644. * <B><U> Actions</U> :</B><BR><BR>
  645. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  646. * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
  647. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  648. *
  649. */
  650. @Override
  651. protected void onEvtArrivedBlocked(L2CharPosition blocked_at_pos)
  652. {
  653. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  654. clientStopMoving(blocked_at_pos);
  655. if (Config.ACTIVATE_POSITION_RECORDER
  656. && Universe.getInstance().shouldLog(_accessor.getActor().getObjectId()))
  657. {
  658. if (!_accessor.getActor().isFlying())
  659. Universe.getInstance().registerObstacle(blocked_at_pos.x, blocked_at_pos.y,
  660. blocked_at_pos.z);
  661. if (_accessor.getActor() instanceof L2PcInstance)
  662. ((L2PcInstance) _accessor.getActor()).explore();
  663. }
  664. // If the Intention was AI_INTENTION_MOVE_TO, tet the Intention to AI_INTENTION_ACTIVE
  665. if (getIntention() == AI_INTENTION_MOVE_TO) setIntention(AI_INTENTION_ACTIVE);
  666. // Launch actions corresponding to the Event Think
  667. onEvtThink();
  668. }
  669. /**
  670. * Launch actions corresponding to the Event ForgetObject.<BR><BR>
  671. *
  672. * <B><U> Actions</U> :</B><BR><BR>
  673. * <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>
  674. * <li>If the object was targeted to attack, stop the auto-attack, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
  675. * <li>If the object was targeted to cast, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
  676. * <li>If the object was targeted to follow, stop the movement, cancel AI Follow Task and set the Intention to AI_INTENTION_ACTIVE</li>
  677. * <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>
  678. *
  679. */
  680. @Override
  681. protected void onEvtForgetObject(L2Object object)
  682. {
  683. // If the object was targeted and the Intention was AI_INTENTION_INTERACT or AI_INTENTION_PICK_UP, set the Intention to AI_INTENTION_ACTIVE
  684. if (getTarget() == object)
  685. {
  686. setTarget(null);
  687. if (getIntention() == AI_INTENTION_INTERACT) setIntention(AI_INTENTION_ACTIVE);
  688. else if (getIntention() == AI_INTENTION_PICK_UP) setIntention(AI_INTENTION_ACTIVE);
  689. }
  690. // Check if the object was targeted to attack
  691. if (getAttackTarget() == object)
  692. {
  693. // Cancel attack target
  694. setAttackTarget(null);
  695. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  696. setIntention(AI_INTENTION_ACTIVE);
  697. }
  698. // Check if the object was targeted to cast
  699. if (getCastTarget() == object)
  700. {
  701. // Cancel cast target
  702. setCastTarget(null);
  703. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  704. setIntention(AI_INTENTION_ACTIVE);
  705. }
  706. // Check if the object was targeted to follow
  707. if (getFollowTarget() == object)
  708. {
  709. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  710. clientStopMoving(null);
  711. // Stop an AI Follow Task
  712. stopFollow();
  713. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  714. setIntention(AI_INTENTION_ACTIVE);
  715. }
  716. // Check if the targeted object was the actor
  717. if (_actor == object)
  718. {
  719. // Cancel AI target
  720. setTarget(null);
  721. setAttackTarget(null);
  722. setCastTarget(null);
  723. // Stop an AI Follow Task
  724. stopFollow();
  725. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  726. clientStopMoving(null);
  727. // Set the Intention of this AbstractAI to AI_INTENTION_IDLE
  728. changeIntention(AI_INTENTION_IDLE, null, null);
  729. }
  730. }
  731. /**
  732. * Launch actions corresponding to the Event Cancel.<BR><BR>
  733. *
  734. * <B><U> Actions</U> :</B><BR><BR>
  735. * <li>Stop an AI Follow Task</li>
  736. * <li>Launch actions corresponding to the Event Think</li><BR><BR>
  737. *
  738. */
  739. @Override
  740. protected void onEvtCancel()
  741. {
  742. // Stop an AI Follow Task
  743. stopFollow();
  744. if (!AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
  745. _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
  746. // Launch actions corresponding to the Event Think
  747. onEvtThink();
  748. }
  749. /**
  750. * Launch actions corresponding to the Event Dead.<BR><BR>
  751. *
  752. * <B><U> Actions</U> :</B><BR><BR>
  753. * <li>Stop an AI Follow Task</li>
  754. * <li>Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)</li><BR><BR>
  755. *
  756. */
  757. @Override
  758. protected void onEvtDead()
  759. {
  760. // Stop an AI Follow Task
  761. stopFollow();
  762. // Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)
  763. clientNotifyDead();
  764. if (!(_actor instanceof L2PcInstance))
  765. _actor.setWalking();
  766. }
  767. /**
  768. * Launch actions corresponding to the Event Fake Death.<BR><BR>
  769. *
  770. * <B><U> Actions</U> :</B><BR><BR>
  771. * <li>Stop an AI Follow Task</li>
  772. *
  773. */
  774. @Override
  775. protected void onEvtFakeDeath()
  776. {
  777. // Stop an AI Follow Task
  778. stopFollow();
  779. // Stop the actor movement and send Server->Client packet StopMove/StopRotation (broadcast)
  780. clientStopMoving(null);
  781. // Init AI
  782. _intention = AI_INTENTION_IDLE;
  783. setTarget(null);
  784. setCastTarget(null);
  785. setAttackTarget(null);
  786. }
  787. /**
  788. * Do nothing.<BR><BR>
  789. */
  790. @Override
  791. protected void onEvtFinishCasting()
  792. {
  793. // do nothing
  794. }
  795. protected boolean maybeMoveToPosition(Point3D worldPosition, int offset)
  796. {
  797. if (worldPosition == null)
  798. {
  799. _log.warning("maybeMoveToPosition: worldPosition == NULL!");
  800. return false;
  801. }
  802. if (offset < 0)
  803. return false; // skill radius -1
  804. if (!_actor.isInsideRadius(worldPosition.getX(), worldPosition.getY(), offset + _actor.getTemplate().collisionRadius, false))
  805. {
  806. if (_actor.isMovementDisabled())
  807. return true;
  808. if (!_actor.isRunning() && !(this instanceof L2PlayerAI))
  809. _actor.setRunning();
  810. stopFollow();
  811. int x = _actor.getX();
  812. int y = _actor.getY();
  813. double dx = worldPosition.getX() - x;
  814. double dy = worldPosition.getY() - y;
  815. double dist = Math.sqrt(dx * dx + dy * dy);
  816. double sin = dy / dist;
  817. double cos = dx / dist;
  818. dist -= offset - 5;
  819. x += (int) (dist * cos);
  820. y += (int) (dist * sin);
  821. moveTo(x, y, worldPosition.getZ());
  822. return true;
  823. }
  824. if (getFollowTarget() != null)
  825. stopFollow();
  826. return false;
  827. }
  828. /**
  829. * Manage the Move to Pawn action in function of the distance and of the Interact area.<BR><BR>
  830. *
  831. * <B><U> Actions</U> :</B><BR><BR>
  832. * <li>Get the distance between the current position of the L2Character and the target (x,y)</li>
  833. * <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>
  834. * <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>
  835. *
  836. * <B><U> Example of use </U> :</B><BR><BR>
  837. * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
  838. *
  839. * @param target The targeted L2Object
  840. * @param offset The Interact area radius
  841. *
  842. * @return True if a movement must be done
  843. *
  844. */
  845. protected boolean maybeMoveToPawn(L2Object target, int offset)
  846. {
  847. // Get the distance between the current position of the L2Character and the target (x,y)
  848. if (target == null)
  849. {
  850. _log.warning("maybeMoveToPawn: target == NULL!");
  851. return false;
  852. }
  853. if(offset < 0) return false; // skill radius -1
  854. offset += _actor.getTemplate().collisionRadius;
  855. if (target instanceof L2Character)
  856. offset += ((L2Character)target).getTemplate().collisionRadius;
  857. if (!_actor.isInsideRadius(target, offset, false, false))
  858. {
  859. // Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
  860. if (getFollowTarget() != null) {
  861. // allow larger hit range when the target is moving (check is run only once per second)
  862. if (!_actor.isInsideRadius(target, offset + 100, false, false)) return true;
  863. stopFollow();
  864. return false;
  865. }
  866. if (_actor.isMovementDisabled()) return true;
  867. // If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
  868. if (!_actor.isRunning() && !(this instanceof L2PlayerAI)) _actor.setRunning();
  869. stopFollow();
  870. if ((target instanceof L2Character) && !(target instanceof L2DoorInstance))
  871. {
  872. if (((L2Character)target).isMoving()) offset -= 100;
  873. if (offset < 5) offset = 5;
  874. startFollow((L2Character) target, offset);
  875. }
  876. else
  877. {
  878. // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
  879. moveToPawn(target, offset);
  880. }
  881. return true;
  882. }
  883. if (getFollowTarget() != null) stopFollow();
  884. // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
  885. // clientStopMoving(null);
  886. return false;
  887. }
  888. /**
  889. * Modify current Intention and actions if the target is lost or dead.<BR><BR>
  890. *
  891. * <B><U> Actions</U> : <I>If the target is lost or dead</I></B><BR><BR>
  892. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  893. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  894. * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li><BR><BR>
  895. *
  896. * <B><U> Example of use </U> :</B><BR><BR>
  897. * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
  898. *
  899. * @param target The targeted L2Object
  900. *
  901. * @return True if the target is lost or dead (false if fakedeath)
  902. *
  903. */
  904. protected boolean checkTargetLostOrDead(L2Character target)
  905. {
  906. if (target == null || target.isAlikeDead())
  907. {
  908. //check if player is fakedeath
  909. if (target != null && target.isFakeDeath())
  910. {
  911. target.stopFakeDeath(null);
  912. return false;
  913. }
  914. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  915. setIntention(AI_INTENTION_ACTIVE);
  916. return true;
  917. }
  918. return false;
  919. }
  920. /**
  921. * Modify current Intention and actions if the target is lost.<BR><BR>
  922. *
  923. * <B><U> Actions</U> : <I>If the target is lost</I></B><BR><BR>
  924. * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
  925. * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
  926. * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li><BR><BR>
  927. *
  928. * <B><U> Example of use </U> :</B><BR><BR>
  929. * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
  930. *
  931. * @param target The targeted L2Object
  932. *
  933. * @return True if the target is lost
  934. *
  935. */
  936. protected boolean checkTargetLost(L2Object target)
  937. {
  938. // check if player is fakedeath
  939. if (target instanceof L2PcInstance)
  940. {
  941. L2PcInstance target2 = (L2PcInstance) target; //convert object to chara
  942. if (target2.isFakeDeath())
  943. {
  944. target2.stopFakeDeath(null);
  945. return false;
  946. }
  947. }
  948. if (target == null)
  949. {
  950. // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
  951. setIntention(AI_INTENTION_ACTIVE);
  952. return true;
  953. }
  954. return false;
  955. }
  956. protected class SelfAnalysis
  957. {
  958. public boolean isMage = false;
  959. public boolean isBalanced;
  960. public boolean isArcher = false;
  961. public boolean isFighter = false;
  962. public boolean cannotMoveOnLand = false;
  963. public List<L2Skill> generalSkills = new FastList<L2Skill>();
  964. public List<L2Skill> buffSkills = new FastList<L2Skill>();
  965. public int lastBuffTick = 0;
  966. public List<L2Skill> debuffSkills = new FastList<L2Skill>();
  967. public int lastDebuffTick = 0;
  968. public List<L2Skill> cancelSkills = new FastList<L2Skill>();
  969. public List<L2Skill> healSkills = new FastList<L2Skill>();
  970. //public List<L2Skill> trickSkills = new FastList<L2Skill>();
  971. public List<L2Skill> generalDisablers = new FastList<L2Skill>();
  972. public List<L2Skill> sleepSkills = new FastList<L2Skill>();
  973. public List<L2Skill> rootSkills = new FastList<L2Skill>();
  974. public List<L2Skill> muteSkills = new FastList<L2Skill>();
  975. public List<L2Skill> resurrectSkills = new FastList<L2Skill>();
  976. public boolean hasHealOrResurrect = false;
  977. public boolean hasLongRangeSkills = false;
  978. public boolean hasLongRangeDamageSkills = false;
  979. public int maxCastRange = 0;
  980. public SelfAnalysis()
  981. {
  982. }
  983. public void init()
  984. {
  985. switch (((L2NpcTemplate)_actor.getTemplate()).AI)
  986. {
  987. case FIGHTER:
  988. isFighter = true;
  989. break;
  990. case MAGE:
  991. isMage = true;
  992. break;
  993. case BALANCED:
  994. isBalanced = true;
  995. break;
  996. case ARCHER:
  997. isArcher = true;
  998. break;
  999. default:
  1000. isFighter = true;
  1001. break;
  1002. }
  1003. // water movement analysis
  1004. if (_actor instanceof L2NpcInstance)
  1005. {
  1006. int npcId = ((L2NpcInstance)_actor).getNpcId();
  1007. switch (npcId)
  1008. {
  1009. case 20314: // great white shark
  1010. case 20849: // Light Worm
  1011. cannotMoveOnLand = true;
  1012. break;
  1013. default:
  1014. cannotMoveOnLand = false;
  1015. break;
  1016. }
  1017. }
  1018. // skill analysis
  1019. for (L2Skill sk : _actor.getAllSkills())
  1020. {
  1021. if (sk.isPassive()) continue;
  1022. int castRange = sk.getCastRange();
  1023. boolean hasLongRangeDamageSkill = false;
  1024. switch(sk.getSkillType())
  1025. {
  1026. case HEAL:
  1027. case HEAL_PERCENT:
  1028. case HEAL_STATIC:
  1029. case BALANCE_LIFE:
  1030. case HOT:
  1031. healSkills.add(sk);
  1032. hasHealOrResurrect = true;
  1033. continue; // won't be considered something for fighting
  1034. case BUFF:
  1035. buffSkills.add(sk);
  1036. continue; // won't be considered something for fighting
  1037. case PARALYZE:
  1038. case STUN:
  1039. // hardcoding petrification until improvements are made to
  1040. // EffectTemplate... petrification is totally different for
  1041. // AI than paralyze
  1042. switch(sk.getId())
  1043. {
  1044. case 367: case 4111: case 4383:
  1045. case 4616: case 4578:
  1046. sleepSkills.add(sk);
  1047. break;
  1048. default:
  1049. generalDisablers.add(sk);
  1050. break;
  1051. }
  1052. break;
  1053. case MUTE:
  1054. muteSkills.add(sk);
  1055. break;
  1056. case SLEEP:
  1057. sleepSkills.add(sk);
  1058. break;
  1059. case ROOT:
  1060. rootSkills.add(sk);
  1061. break;
  1062. case FEAR: // could be used as an alternative for healing?
  1063. case CONFUSION:
  1064. // trickSkills.add(sk);
  1065. case DEBUFF:
  1066. debuffSkills.add(sk);
  1067. break;
  1068. case CANCEL:
  1069. case MAGE_BANE:
  1070. case WARRIOR_BANE:
  1071. case NEGATE:
  1072. cancelSkills.add(sk);
  1073. break;
  1074. case RESURRECT:
  1075. resurrectSkills.add(sk);
  1076. hasHealOrResurrect = true;
  1077. break;
  1078. case NOTDONE:
  1079. case COREDONE:
  1080. continue; // won't be considered something for fighting
  1081. default:
  1082. generalSkills.add(sk);
  1083. hasLongRangeDamageSkill = true;
  1084. break;
  1085. }
  1086. if (castRange > 70) {
  1087. hasLongRangeSkills = true;
  1088. if (hasLongRangeDamageSkill)
  1089. hasLongRangeDamageSkills = true;
  1090. }
  1091. if (castRange > maxCastRange) maxCastRange = castRange;
  1092. }
  1093. // Because of missing skills, some mages/balanced cannot play like mages
  1094. if (!hasLongRangeDamageSkills && isMage)
  1095. {
  1096. isBalanced = true;
  1097. isMage = false;
  1098. isFighter = false;
  1099. }
  1100. if (!hasLongRangeSkills && (isMage || isBalanced))
  1101. {
  1102. isBalanced = false;
  1103. isMage = false;
  1104. isFighter = true;
  1105. }
  1106. if (generalSkills.isEmpty() && isMage)
  1107. {
  1108. isBalanced = true;
  1109. isMage = false;
  1110. }
  1111. }
  1112. }
  1113. protected class TargetAnalysis
  1114. {
  1115. public L2Character character;
  1116. public boolean isMage;
  1117. public boolean isBalanced;
  1118. public boolean isArcher;
  1119. public boolean isFighter;
  1120. public boolean isCanceled;
  1121. public boolean isSlower;
  1122. public boolean isMagicResistant;
  1123. public TargetAnalysis()
  1124. {
  1125. }
  1126. public void update(L2Character target)
  1127. {
  1128. // update status once in 4 seconds
  1129. if (target == character && Rnd.nextInt(100) > 25)
  1130. return;
  1131. character = target;
  1132. if (target == null)
  1133. return;
  1134. isMage = false;
  1135. isBalanced = false;
  1136. isArcher = false;
  1137. isFighter = false;
  1138. isCanceled = false;
  1139. if (target.getMAtk(null, null) > 1.5*target.getPAtk(null))
  1140. isMage = true;
  1141. else if (target.getPAtk(null)*0.8 < target.getMAtk(null, null)
  1142. || target.getMAtk(null, null)*0.8 > target.getPAtk(null))
  1143. {
  1144. isBalanced = true;
  1145. }
  1146. else
  1147. {
  1148. L2Weapon weapon = target.getActiveWeaponItem();
  1149. if (weapon != null && (weapon.getItemType() == L2WeaponType.BOW || weapon.getItemType() == L2WeaponType.CROSSBOW))
  1150. isArcher = true;
  1151. else
  1152. isFighter = true;
  1153. }
  1154. if (target.getRunSpeed() < _actor.getRunSpeed()-3)
  1155. isSlower = true;
  1156. else
  1157. isSlower = false;
  1158. if (target.getMDef(null, null)*1.2 > _actor.getMAtk(null, null))
  1159. isMagicResistant = true;
  1160. else
  1161. isMagicResistant = false;
  1162. if (target.getBuffCount() < 4)
  1163. isCanceled = true;
  1164. }
  1165. }
  1166. }