L2CharacterAI.java 52 KB

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