L2CharacterAI.java 49 KB

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