L2CharacterAI.java 52 KB

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