CharEffectList.java 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  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.model;
  16. import java.util.Iterator;
  17. import java.util.List;
  18. import java.util.Map;
  19. import java.util.concurrent.LinkedBlockingQueue;
  20. import java.util.concurrent.atomic.AtomicBoolean;
  21. import java.util.logging.Level;
  22. import java.util.logging.Logger;
  23. import javolution.util.FastList;
  24. import javolution.util.FastMap;
  25. import com.l2jserver.Config;
  26. import com.l2jserver.gameserver.model.actor.L2Character;
  27. import com.l2jserver.gameserver.model.actor.L2Playable;
  28. import com.l2jserver.gameserver.model.actor.L2Summon;
  29. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  30. import com.l2jserver.gameserver.model.olympiad.OlympiadGameManager;
  31. import com.l2jserver.gameserver.model.olympiad.OlympiadGameTask;
  32. import com.l2jserver.gameserver.network.SystemMessageId;
  33. import com.l2jserver.gameserver.network.serverpackets.AbnormalStatusUpdate;
  34. import com.l2jserver.gameserver.network.serverpackets.ExOlympiadSpelledInfo;
  35. import com.l2jserver.gameserver.network.serverpackets.PartySpelled;
  36. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  37. import com.l2jserver.gameserver.templates.skills.L2EffectType;
  38. import com.l2jserver.gameserver.templates.skills.L2SkillType;
  39. public class CharEffectList
  40. {
  41. protected static final Logger _log = Logger.getLogger(CharEffectList.class.getName());
  42. private static final L2Effect[] EMPTY_EFFECTS = new L2Effect[0];
  43. public static final int EFFECT_FLAG_CHARM_OF_COURAGE = 0x1;
  44. public static final int EFFECT_FLAG_CHARM_OF_LUCK = 0x2;
  45. public static final int EFFECT_FLAG_PHOENIX_BLESSING = 0x4;
  46. public static final int EFFECT_FLAG_NOBLESS_BLESSING = 0x8;
  47. public static final int EFFECT_FLAG_SILENT_MOVE = 0x10;
  48. public static final int EFFECT_FLAG_PROTECTION_BLESSING = 0x20;
  49. public static final int EFFECT_FLAG_RELAXING = 0x40;
  50. public static final int EFFECT_FLAG_FEAR = 0x80;
  51. public static final int EFFECT_FLAG_CONFUSED = 0x100;
  52. public static final int EFFECT_FLAG_MUTED = 0x200;
  53. public static final int EFFECT_FLAG_PSYCHICAL_MUTED = 0x400;
  54. //public static final int EFFECT_FLAG_PARALYZE = 2048; //too much abuse in code
  55. public static final int EFFECT_FLAG_PSYCHICAL_ATTACK_MUTED = 0x800;
  56. public static final int EFFECT_FLAG_DISARMED = 0x1000;
  57. public static final int EFFECT_FLAG_ROOTED = 0x2000;
  58. public static final int EFFECT_FLAG_SLEEP = 0x4000;
  59. public static final int EFFECT_FLAG_STUNNED = 0x8000;
  60. public static final int EFFECT_FLAG_BETRAYED = 0x10000;
  61. public static final int EFFECT_FLAG_INVUL = 0x40000;
  62. public static final int EFFECT_FLAG_PARALYZED = 0x80000;
  63. private FastList<L2Effect> _buffs;
  64. private FastList<L2Effect> _debuffs;
  65. // The table containing the List of all stacked effect in progress for each Stack group Identifier
  66. private Map<String, List<L2Effect>> _stackedEffects;
  67. private volatile boolean _hasBuffsRemovedOnAnyAction = false;
  68. private volatile boolean _hasBuffsRemovedOnDamage = false;
  69. private volatile boolean _hasDebuffsRemovedOnDamage = false;
  70. private boolean _queuesInitialized = false;
  71. private LinkedBlockingQueue<L2Effect> _addQueue;
  72. private LinkedBlockingQueue<L2Effect> _removeQueue;
  73. private AtomicBoolean queueLock = new AtomicBoolean();
  74. private int _effectFlags;
  75. // only party icons need to be updated
  76. private boolean _partyOnly = false;
  77. // Owner of this list
  78. private L2Character _owner;
  79. public CharEffectList(L2Character owner)
  80. {
  81. _owner = owner;
  82. }
  83. /**
  84. * Returns all effects affecting stored in this CharEffectList
  85. * @return
  86. */
  87. public final L2Effect[] getAllEffects()
  88. {
  89. // If no effect is active, return EMPTY_EFFECTS
  90. if ( (_buffs == null || _buffs.isEmpty()) && (_debuffs == null || _debuffs.isEmpty()) )
  91. {
  92. return EMPTY_EFFECTS;
  93. }
  94. // Create a copy of the effects
  95. FastList<L2Effect> temp = FastList.newInstance();
  96. // Add all buffs and all debuffs
  97. if (_buffs != null)
  98. {
  99. //synchronized (_buffs)
  100. {
  101. if (!_buffs.isEmpty())
  102. temp.addAll(_buffs);
  103. }
  104. }
  105. if (_debuffs != null)
  106. {
  107. //synchronized (_debuffs)
  108. {
  109. if (!_debuffs.isEmpty())
  110. temp.addAll(_debuffs);
  111. }
  112. }
  113. // Return all effects in an array
  114. L2Effect[] tempArray = new L2Effect[temp.size()];
  115. temp.toArray(tempArray);
  116. FastList.recycle(temp);
  117. return tempArray;
  118. }
  119. /**
  120. * Returns the first effect matching the given EffectType
  121. * @param tp
  122. * @return
  123. */
  124. public final L2Effect getFirstEffect(L2EffectType tp)
  125. {
  126. L2Effect effectNotInUse = null;
  127. if (_buffs != null)
  128. {
  129. //synchronized (_buffs)
  130. {
  131. if (!_buffs.isEmpty())
  132. {
  133. for (L2Effect e: _buffs)
  134. {
  135. if (e == null)
  136. continue;
  137. if (e.getEffectType() == tp)
  138. {
  139. if (e.getInUse())
  140. return e;
  141. else
  142. effectNotInUse = e;
  143. }
  144. }
  145. }
  146. }
  147. }
  148. if (effectNotInUse == null && _debuffs != null)
  149. {
  150. //synchronized (_debuffs)
  151. {
  152. if (!_debuffs.isEmpty())
  153. {
  154. for (L2Effect e: _debuffs)
  155. {
  156. if (e == null)
  157. continue;
  158. if (e.getEffectType() == tp)
  159. {
  160. if (e.getInUse())
  161. return e;
  162. else
  163. effectNotInUse = e;
  164. }
  165. }
  166. }
  167. }
  168. }
  169. return effectNotInUse;
  170. }
  171. /**
  172. * Returns the first effect matching the given L2Skill
  173. * @param skill
  174. * @return
  175. */
  176. public final L2Effect getFirstEffect(L2Skill skill)
  177. {
  178. L2Effect effectNotInUse = null;
  179. if (skill.isDebuff())
  180. {
  181. if (_debuffs == null)
  182. return null;
  183. //synchronized (_debuffs)
  184. {
  185. if (_debuffs.isEmpty())
  186. return null;
  187. for (L2Effect e: _debuffs)
  188. {
  189. if (e == null)
  190. continue;
  191. if (e.getSkill() == skill)
  192. {
  193. if (e.getInUse())
  194. return e;
  195. else
  196. effectNotInUse = e;
  197. }
  198. }
  199. }
  200. return effectNotInUse;
  201. }
  202. else
  203. {
  204. if (_buffs == null)
  205. return null;
  206. //synchronized (_buffs)
  207. {
  208. if (_buffs.isEmpty())
  209. return null;
  210. for (L2Effect e: _buffs)
  211. {
  212. if (e == null)
  213. continue;
  214. if (e.getSkill() == skill)
  215. {
  216. if (e.getInUse())
  217. return e;
  218. else
  219. effectNotInUse = e;
  220. }
  221. }
  222. }
  223. return effectNotInUse;
  224. }
  225. }
  226. /**
  227. * Returns the first effect matching the given skillId
  228. * @param index
  229. * @return
  230. */
  231. public final L2Effect getFirstEffect(int skillId)
  232. {
  233. L2Effect effectNotInUse = null;
  234. if (_buffs != null)
  235. {
  236. //synchronized (_buffs)
  237. {
  238. if (!_buffs.isEmpty())
  239. {
  240. for (L2Effect e: _buffs)
  241. {
  242. if (e == null)
  243. continue;
  244. if (e.getSkill().getId() == skillId)
  245. {
  246. if (e.getInUse())
  247. return e;
  248. else
  249. effectNotInUse = e;
  250. }
  251. }
  252. }
  253. }
  254. }
  255. if (effectNotInUse == null && _debuffs != null)
  256. {
  257. //synchronized (_debuffs)
  258. {
  259. if (!_debuffs.isEmpty())
  260. {
  261. for (L2Effect e: _debuffs)
  262. {
  263. if (e == null)
  264. continue;
  265. if (e.getSkill().getId() == skillId)
  266. {
  267. if (e.getInUse())
  268. return e;
  269. else
  270. effectNotInUse = e;
  271. }
  272. }
  273. }
  274. }
  275. }
  276. return effectNotInUse;
  277. }
  278. /**
  279. * Checks if the given skill stacks with an existing one.
  280. *
  281. * @param checkSkill the skill to be checked
  282. *
  283. * @return Returns whether or not this skill will stack
  284. */
  285. private boolean doesStack(L2Skill checkSkill)
  286. {
  287. if ( (_buffs == null || _buffs.isEmpty()) ||
  288. checkSkill._effectTemplates == null ||
  289. checkSkill._effectTemplates.length < 1 ||
  290. checkSkill._effectTemplates[0].stackType == null ||
  291. "none".equals(checkSkill._effectTemplates[0].stackType))
  292. {
  293. return false;
  294. }
  295. String stackType = checkSkill._effectTemplates[0].stackType;
  296. for (L2Effect e : _buffs)
  297. {
  298. if (e.getStackType() != null && e.getStackType().equals(stackType))
  299. {
  300. return true;
  301. }
  302. }
  303. return false;
  304. }
  305. /**
  306. * Return the number of buffs in this CharEffectList not counting Songs/Dances
  307. * @return
  308. */
  309. public int getBuffCount()
  310. {
  311. if (_buffs == null) return 0;
  312. int buffCount=0;
  313. //synchronized(_buffs)
  314. {
  315. if (_buffs.isEmpty())
  316. return 0;
  317. for (L2Effect e : _buffs)
  318. {
  319. if (e != null && e.getShowIcon() && !e.getSkill().isDance() && !e.getSkill().is7Signs())
  320. {
  321. switch (e.getSkill().getSkillType())
  322. {
  323. case BUFF:
  324. case REFLECT:
  325. case HEAL_PERCENT:
  326. case MANAHEAL_PERCENT:
  327. buffCount++;
  328. }
  329. }
  330. }
  331. }
  332. return buffCount;
  333. }
  334. /**
  335. * Return the number of Songs/Dances in this CharEffectList
  336. * @return
  337. */
  338. public int getDanceCount()
  339. {
  340. if (_buffs == null) return 0;
  341. int danceCount = 0;
  342. //synchronized(_buffs)
  343. {
  344. if (_buffs.isEmpty())
  345. return 0;
  346. for (L2Effect e : _buffs)
  347. {
  348. if (e != null && e.getSkill().isDance() && e.getInUse())
  349. danceCount++;
  350. }
  351. }
  352. return danceCount;
  353. }
  354. /**
  355. * Exits all effects in this CharEffectList
  356. */
  357. public final void stopAllEffects()
  358. {
  359. // Get all active skills effects from this list
  360. L2Effect[] effects = getAllEffects();
  361. // Exit them
  362. for (L2Effect e : effects)
  363. {
  364. if (e != null)
  365. e.exit(true);
  366. }
  367. }
  368. /**
  369. * Exits all effects in this CharEffectList
  370. */
  371. public final void stopAllEffectsExceptThoseThatLastThroughDeath()
  372. {
  373. // Get all active skills effects from this list
  374. L2Effect[] effects = getAllEffects();
  375. // Exit them
  376. for (L2Effect e : effects)
  377. {
  378. if (e != null && !e.getSkill().isStayAfterDeath())
  379. e.exit(true);
  380. }
  381. }
  382. /**
  383. * Exit all toggle-type effects
  384. */
  385. public void stopAllToggles()
  386. {
  387. if (_buffs != null)
  388. {
  389. //synchronized (_buffs)
  390. {
  391. if (!_buffs.isEmpty())
  392. {
  393. for (L2Effect e : _buffs)
  394. if (e != null && e.getSkill().isToggle())
  395. e.exit();
  396. }
  397. }
  398. }
  399. }
  400. /**
  401. * Exit all effects having a specified type
  402. * @param type
  403. */
  404. public final void stopEffects(L2EffectType type)
  405. {
  406. // Go through all active skills effects
  407. FastList<L2Effect> temp = FastList.newInstance();
  408. if (_buffs != null)
  409. {
  410. //synchronized (_buffs)
  411. {
  412. if (!_buffs.isEmpty())
  413. {
  414. for (L2Effect e : _buffs)
  415. // Get active skills effects of the selected type
  416. if (e != null && e.getEffectType() == type)
  417. temp.add(e);
  418. }
  419. }
  420. }
  421. if (_debuffs != null)
  422. {
  423. //synchronized (_debuffs)
  424. {
  425. if (!_debuffs.isEmpty())
  426. {
  427. for (L2Effect e : _debuffs)
  428. // Get active skills effects of the selected type
  429. if (e != null && e.getEffectType() == type)
  430. temp.add(e);
  431. }
  432. }
  433. }
  434. if (!temp.isEmpty())
  435. {
  436. for (L2Effect e : temp)
  437. if (e != null)
  438. e.exit();
  439. }
  440. FastList.recycle(temp);
  441. }
  442. /**
  443. * Exits all effects created by a specific skillId
  444. * @param skillId
  445. */
  446. public final void stopSkillEffects(int skillId)
  447. {
  448. // Go through all active skills effects
  449. FastList<L2Effect> temp = FastList.newInstance();
  450. if (_buffs != null)
  451. {
  452. //synchronized (_buffs)
  453. {
  454. if (!_buffs.isEmpty())
  455. {
  456. for (L2Effect e : _buffs)
  457. if (e != null && e.getSkill().getId() == skillId)
  458. temp.add(e);
  459. }
  460. }
  461. }
  462. if (_debuffs != null)
  463. {
  464. //synchronized (_debuffs)
  465. {
  466. if (!_debuffs.isEmpty())
  467. {
  468. for (L2Effect e : _debuffs)
  469. if (e != null && e.getSkill().getId() == skillId)
  470. temp.add(e);
  471. }
  472. }
  473. }
  474. if (!temp.isEmpty())
  475. {
  476. for (L2Effect e : temp)
  477. if (e != null)
  478. e.exit();
  479. }
  480. FastList.recycle(temp);
  481. }
  482. /**
  483. * Exits all effects created by a specific skill type
  484. * @param skillType skill type
  485. */
  486. public final void stopSkillEffects(L2SkillType skillType, int negateLvl)
  487. {
  488. // Go through all active skills effects
  489. FastList<L2Effect> temp = FastList.newInstance();
  490. if (_buffs != null)
  491. {
  492. //synchronized (_buffs)
  493. {
  494. if (!_buffs.isEmpty())
  495. {
  496. for (L2Effect e : _buffs)
  497. {
  498. if (e != null && (e.getSkill().getSkillType() == skillType || (e.getSkill().getEffectType() != null && e.getSkill().getEffectType() == skillType))
  499. && (negateLvl == -1 || (e.getSkill().getEffectType() != null && e.getSkill().getEffectAbnormalLvl() >= 0 && e.getSkill().getEffectAbnormalLvl() <= negateLvl) || (e.getSkill().getAbnormalLvl() >= 0 && e.getSkill().getAbnormalLvl() <= negateLvl)))
  500. temp.add(e);
  501. }
  502. }
  503. }
  504. }
  505. if (_debuffs != null)
  506. {
  507. //synchronized (_debuffs)
  508. {
  509. if (!_debuffs.isEmpty())
  510. {
  511. for (L2Effect e : _debuffs)
  512. {
  513. if (e != null && (e.getSkill().getSkillType() == skillType || (e.getSkill().getEffectType() != null && e.getSkill().getEffectType() == skillType))
  514. && (negateLvl == -1 || (e.getSkill().getEffectType() != null && e.getSkill().getEffectAbnormalLvl() >= 0 && e.getSkill().getEffectAbnormalLvl() <= negateLvl) || (e.getSkill().getAbnormalLvl() >= 0 && e.getSkill().getAbnormalLvl() <= negateLvl)))
  515. temp.add(e);
  516. }
  517. }
  518. }
  519. }
  520. if (!temp.isEmpty())
  521. {
  522. for (L2Effect e : temp)
  523. if (e != null)
  524. e.exit();
  525. }
  526. FastList.recycle(temp);
  527. }
  528. /**
  529. * Exits all buffs effects of the skills with "removedOnAnyAction" set.
  530. * Called on any action except movement (attack, cast).
  531. */
  532. public void stopEffectsOnAction()
  533. {
  534. if (_hasBuffsRemovedOnAnyAction)
  535. {
  536. if (_buffs != null)
  537. {
  538. //synchronized (_buffs)
  539. {
  540. if (!_buffs.isEmpty())
  541. {
  542. for (L2Effect e : _buffs)
  543. if (e != null && e.getSkill().isRemovedOnAnyActionExceptMove())
  544. e.exit(true);
  545. }
  546. }
  547. }
  548. }
  549. }
  550. public void stopEffectsOnDamage(boolean awake)
  551. {
  552. if (_hasBuffsRemovedOnDamage)
  553. {
  554. if (_buffs != null)
  555. {
  556. //synchronized (_buffs)
  557. {
  558. if (!_buffs.isEmpty())
  559. {
  560. for (L2Effect e : _buffs)
  561. if (e != null
  562. && e.getSkill().isRemovedOnDamage()
  563. && (awake || e.getSkill().getSkillType() != L2SkillType.SLEEP))
  564. e.exit(true);
  565. }
  566. }
  567. }
  568. }
  569. if (_hasDebuffsRemovedOnDamage)
  570. {
  571. if (_debuffs != null)
  572. {
  573. //synchronized (_buffs)
  574. {
  575. if (!_debuffs.isEmpty())
  576. {
  577. for (L2Effect e : _debuffs)
  578. if (e != null
  579. && e.getSkill().isRemovedOnDamage()
  580. && (awake || e.getSkill().getSkillType() != L2SkillType.SLEEP))
  581. e.exit(true);
  582. }
  583. }
  584. }
  585. }
  586. }
  587. public void updateEffectIcons(boolean partyOnly)
  588. {
  589. if (_buffs == null && _debuffs == null)
  590. return;
  591. if (partyOnly)
  592. _partyOnly = true;
  593. queueRunner();
  594. }
  595. public void queueEffect(L2Effect effect, boolean remove)
  596. {
  597. if (effect == null) return;
  598. if (!_queuesInitialized)
  599. init();
  600. if (remove)
  601. _removeQueue.offer(effect);
  602. else
  603. _addQueue.offer(effect);
  604. queueRunner();
  605. }
  606. private synchronized void init()
  607. {
  608. if (_queuesInitialized)
  609. return;
  610. _addQueue = new LinkedBlockingQueue<L2Effect>();
  611. _removeQueue = new LinkedBlockingQueue<L2Effect>();
  612. _queuesInitialized = true;
  613. }
  614. private void queueRunner()
  615. {
  616. if (!queueLock.compareAndSet(false, true))
  617. return;
  618. try
  619. {
  620. L2Effect effect;
  621. do
  622. {
  623. // remove has more priority than add
  624. // so removing all effects from queue first
  625. while ((effect = _removeQueue.poll()) != null)
  626. {
  627. removeEffectFromQueue(effect);
  628. _partyOnly = false;
  629. }
  630. if ((effect = _addQueue.poll()) != null)
  631. {
  632. addEffectFromQueue(effect);
  633. _partyOnly = false;
  634. }
  635. }
  636. while (!_addQueue.isEmpty() || !_removeQueue.isEmpty());
  637. computeEffectFlags();
  638. updateEffectIcons();
  639. }
  640. finally
  641. {
  642. queueLock.set(false);
  643. }
  644. }
  645. protected void removeEffectFromQueue(L2Effect effect)
  646. {
  647. if (effect == null) return;
  648. FastList<L2Effect> effectList;
  649. if (effect.getSkill().isDebuff())
  650. {
  651. if (_debuffs == null)
  652. return;
  653. effectList = _debuffs;
  654. }
  655. else
  656. {
  657. if (_buffs == null)
  658. return;
  659. effectList = _buffs;
  660. }
  661. if ("none".equals(effect.getStackType()))
  662. {
  663. // Remove Func added by this effect from the L2Character Calculator
  664. _owner.removeStatsOwner(effect);
  665. }
  666. else
  667. {
  668. if(_stackedEffects == null) return;
  669. // Get the list of all stacked effects corresponding to the stack type of the L2Effect to add
  670. List<L2Effect> stackQueue = _stackedEffects.get(effect.getStackType());
  671. if (stackQueue == null || stackQueue.isEmpty()) return;
  672. int index = stackQueue.indexOf(effect);
  673. // Remove the effect from the stack group
  674. if (index >= 0)
  675. {
  676. stackQueue.remove(effect);
  677. // Check if the first stacked effect was the effect to remove
  678. if (index == 0)
  679. {
  680. // Remove all its Func objects from the L2Character calculator set
  681. _owner.removeStatsOwner(effect);
  682. // Check if there's another effect in the Stack Group
  683. if (!stackQueue.isEmpty())
  684. {
  685. L2Effect newStackedEffect = listsContains(stackQueue.get(0));
  686. if (newStackedEffect != null)
  687. {
  688. // Set the effect to In Use
  689. if (newStackedEffect.setInUse(true))
  690. // Add its list of Funcs to the Calculator set of the L2Character
  691. _owner.addStatFuncs(newStackedEffect.getStatFuncs());
  692. }
  693. }
  694. }
  695. if (stackQueue.isEmpty())
  696. _stackedEffects.remove(effect.getStackType());
  697. else
  698. // Update the Stack Group table _stackedEffects of the L2Character
  699. _stackedEffects.put(effect.getStackType(), stackQueue);
  700. }
  701. }
  702. // Remove the active skill L2effect from _effects of the L2Character
  703. if (effectList.remove(effect) && _owner instanceof L2PcInstance && effect.getShowIcon())
  704. {
  705. SystemMessage sm;
  706. if (effect.getSkill().isToggle())
  707. {
  708. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_HAS_BEEN_ABORTED);
  709. }
  710. else
  711. {
  712. sm = SystemMessage.getSystemMessage(SystemMessageId.EFFECT_S1_DISAPPEARED);
  713. }
  714. sm.addSkillName(effect);
  715. _owner.sendPacket(sm);
  716. }
  717. }
  718. protected void addEffectFromQueue(L2Effect newEffect)
  719. {
  720. if (newEffect == null) return;
  721. L2Skill newSkill = newEffect.getSkill();
  722. if (newSkill.isDebuff())
  723. {
  724. if (_debuffs == null) _debuffs = new FastList<L2Effect>().shared();
  725. for (L2Effect e : _debuffs)
  726. {
  727. if (e != null
  728. && e.getSkill().getId() == newEffect.getSkill().getId()
  729. && e.getEffectType() == newEffect.getEffectType()
  730. && e.getStackOrder() == newEffect.getStackOrder()
  731. && e.getStackType().equals(newEffect.getStackType()))
  732. {
  733. // Started scheduled timer needs to be canceled.
  734. newEffect.stopEffectTask();
  735. return;
  736. }
  737. }
  738. _debuffs.addLast(newEffect);
  739. }
  740. else
  741. {
  742. if (_buffs == null) _buffs = new FastList<L2Effect>().shared();
  743. for (L2Effect e : _buffs)
  744. {
  745. if (e != null
  746. && e.getSkill().getId() == newEffect.getSkill().getId()
  747. && e.getEffectType() == newEffect.getEffectType()
  748. && e.getStackOrder() == newEffect.getStackOrder()
  749. && e.getStackType().equals(newEffect.getStackType()))
  750. {
  751. e.exit(); // exit this
  752. }
  753. }
  754. // if max buffs, no herb effects are used, even if they would replace one old
  755. if (newEffect.isHerbEffect() && getBuffCount() >= _owner.getMaxBuffCount())
  756. {
  757. newEffect.stopEffectTask();
  758. return;
  759. }
  760. // Remove first buff when buff list is full
  761. if (!doesStack(newSkill) && !newSkill.is7Signs())
  762. {
  763. int effectsToRemove;
  764. if (newSkill.isDance())
  765. {
  766. effectsToRemove = getDanceCount() - Config.DANCES_MAX_AMOUNT;
  767. if (effectsToRemove >= 0)
  768. {
  769. for (L2Effect e : _buffs)
  770. {
  771. if (e == null || !e.getSkill().isDance())
  772. continue;
  773. // get first dance
  774. e.exit();
  775. effectsToRemove--;
  776. if (effectsToRemove < 0)
  777. break;
  778. }
  779. }
  780. }
  781. else
  782. {
  783. effectsToRemove = getBuffCount() - _owner.getMaxBuffCount();
  784. if (effectsToRemove >= 0)
  785. {
  786. switch (newSkill.getSkillType())
  787. {
  788. case BUFF:
  789. case REFLECT:
  790. case HEAL_PERCENT:
  791. case MANAHEAL_PERCENT:
  792. for (L2Effect e : _buffs)
  793. {
  794. if (e == null || e.getSkill().isDance())
  795. continue;
  796. switch (e.getSkill().getSkillType())
  797. {
  798. case BUFF:
  799. case REFLECT:
  800. case HEAL_PERCENT:
  801. case MANAHEAL_PERCENT:
  802. e.exit();
  803. effectsToRemove--;
  804. break; // break switch()
  805. default:
  806. continue; // continue for()
  807. }
  808. if (effectsToRemove < 0)
  809. break; // break for()
  810. }
  811. }
  812. }
  813. }
  814. }
  815. // Icons order: buffs, 7s, toggles, dances
  816. if (newSkill.isDance())
  817. _buffs.addLast(newEffect);
  818. else
  819. {
  820. int pos=0;
  821. if (newSkill.isToggle())
  822. {
  823. // toggle skill - before all dances
  824. for (L2Effect e : _buffs)
  825. {
  826. if (e == null)
  827. continue;
  828. if (e.getSkill().isDance())
  829. break;
  830. pos++;
  831. }
  832. }
  833. else
  834. {
  835. // normal buff - before toggles and 7s and dances
  836. for (L2Effect e : _buffs)
  837. {
  838. if (e == null)
  839. continue;
  840. if (e.getSkill().isToggle() || e.getSkill().is7Signs()
  841. || e.getSkill().isDance())
  842. break;
  843. pos++;
  844. }
  845. }
  846. _buffs.add(pos, newEffect);
  847. }
  848. }
  849. // Check if a stack group is defined for this effect
  850. if ("none".equals(newEffect.getStackType()))
  851. {
  852. // Set this L2Effect to In Use
  853. if (newEffect.setInUse(true))
  854. // Add Funcs of this effect to the Calculator set of the L2Character
  855. _owner.addStatFuncs(newEffect.getStatFuncs());
  856. return;
  857. }
  858. List<L2Effect> stackQueue;
  859. L2Effect effectToAdd = null;
  860. L2Effect effectToRemove = null;
  861. if (_stackedEffects == null) _stackedEffects = new FastMap<String, List<L2Effect>>();
  862. // Get the list of all stacked effects corresponding to the stack type of the L2Effect to add
  863. stackQueue = _stackedEffects.get(newEffect.getStackType());
  864. if (stackQueue != null)
  865. {
  866. int pos = 0;
  867. if (!stackQueue.isEmpty())
  868. {
  869. // Get the first stacked effect of the Stack group selected
  870. effectToRemove = listsContains(stackQueue.get(0));
  871. // Create an Iterator to go through the list of stacked effects in progress on the L2Character
  872. Iterator<L2Effect> queueIterator = stackQueue.iterator();
  873. while (queueIterator.hasNext())
  874. {
  875. if (newEffect.getStackOrder() < queueIterator.next().getStackOrder())
  876. pos++;
  877. else break;
  878. }
  879. // Add the new effect to the Stack list in function of its position in the Stack group
  880. stackQueue.add(pos, newEffect);
  881. // skill.exit() could be used, if the users don't wish to see "effect
  882. // removed" always when a timer goes off, even if the buff isn't active
  883. // any more (has been replaced). but then check e.g. npc hold and raid petrification.
  884. if (Config.EFFECT_CANCELING && !newEffect.isHerbEffect() && stackQueue.size() > 1)
  885. {
  886. if (newSkill.isDebuff())
  887. {
  888. _debuffs.remove(stackQueue.remove(1));
  889. }
  890. else
  891. {
  892. _buffs.remove(stackQueue.remove(1));
  893. }
  894. }
  895. }
  896. else
  897. stackQueue.add(0, newEffect);
  898. }
  899. else
  900. {
  901. stackQueue = new FastList<L2Effect>();
  902. stackQueue.add(0, newEffect);
  903. }
  904. // Update the Stack Group table _stackedEffects of the L2Character
  905. _stackedEffects.put(newEffect.getStackType(), stackQueue);
  906. // Get the first stacked effect of the Stack group selected
  907. if (!stackQueue.isEmpty())
  908. {
  909. effectToAdd = listsContains(stackQueue.get(0));
  910. }
  911. if (effectToRemove != effectToAdd)
  912. {
  913. if (effectToRemove != null)
  914. {
  915. // Remove all Func objects corresponding to this stacked effect from the Calculator set of the L2Character
  916. _owner.removeStatsOwner(effectToRemove);
  917. // Set the L2Effect to Not In Use
  918. effectToRemove.setInUse(false);
  919. }
  920. if (effectToAdd != null)
  921. {
  922. // Set this L2Effect to In Use
  923. if (effectToAdd.setInUse(true))
  924. // Add all Func objects corresponding to this stacked effect to the Calculator set of the L2Character
  925. _owner.addStatFuncs(effectToAdd.getStatFuncs());
  926. }
  927. }
  928. }
  929. protected void updateEffectIcons()
  930. {
  931. if (_owner == null)
  932. return;
  933. if (!(_owner instanceof L2Playable))
  934. {
  935. updateEffectFlags();
  936. return;
  937. }
  938. AbnormalStatusUpdate mi = null;
  939. PartySpelled ps = null;
  940. ExOlympiadSpelledInfo os = null;
  941. if (_owner instanceof L2PcInstance)
  942. {
  943. if (_partyOnly)
  944. _partyOnly = false;
  945. else
  946. mi = new AbnormalStatusUpdate();
  947. if (_owner.isInParty())
  948. ps = new PartySpelled(_owner);
  949. if (((L2PcInstance)_owner).isInOlympiadMode() && ((L2PcInstance)_owner).isOlympiadStart())
  950. os = new ExOlympiadSpelledInfo((L2PcInstance)_owner);
  951. }
  952. else
  953. if (_owner instanceof L2Summon)
  954. ps = new PartySpelled(_owner);
  955. boolean foundRemovedOnAction = false;
  956. boolean foundRemovedOnDamage = false;
  957. if (_buffs != null && !_buffs.isEmpty())
  958. {
  959. //synchronized (_buffs)
  960. {
  961. for (L2Effect e : _buffs)
  962. {
  963. if (e == null)
  964. continue;
  965. if (e.getSkill().isRemovedOnAnyActionExceptMove())
  966. foundRemovedOnAction = true;
  967. if (e.getSkill().isRemovedOnDamage())
  968. foundRemovedOnDamage = true;
  969. if (!e.getShowIcon())
  970. continue;
  971. switch (e.getEffectType())
  972. {
  973. case CHARGE: // handled by EtcStatusUpdate
  974. case SIGNET_GROUND:
  975. continue;
  976. }
  977. if (e.getInUse())
  978. {
  979. if (mi != null)
  980. e.addIcon(mi);
  981. if (ps != null)
  982. e.addPartySpelledIcon(ps);
  983. if (os != null)
  984. e.addOlympiadSpelledIcon(os);
  985. }
  986. }
  987. }
  988. }
  989. _hasBuffsRemovedOnAnyAction = foundRemovedOnAction;
  990. _hasBuffsRemovedOnDamage = foundRemovedOnDamage;
  991. foundRemovedOnDamage = false;
  992. if (_debuffs != null && !_debuffs.isEmpty())
  993. {
  994. //synchronized (_debuffs)
  995. {
  996. for (L2Effect e : _debuffs)
  997. {
  998. if (e == null)
  999. continue;
  1000. if (e.getSkill().isRemovedOnAnyActionExceptMove())
  1001. foundRemovedOnAction = true;
  1002. if (e.getSkill().isRemovedOnDamage())
  1003. foundRemovedOnDamage = true;
  1004. if (!e.getShowIcon())
  1005. continue;
  1006. switch (e.getEffectType())
  1007. {
  1008. case SIGNET_GROUND:
  1009. continue;
  1010. }
  1011. if (e.getInUse())
  1012. {
  1013. if (mi != null)
  1014. e.addIcon(mi);
  1015. if (ps != null)
  1016. e.addPartySpelledIcon(ps);
  1017. if (os != null)
  1018. e.addOlympiadSpelledIcon(os);
  1019. }
  1020. }
  1021. }
  1022. }
  1023. _hasDebuffsRemovedOnDamage = foundRemovedOnDamage;
  1024. if (mi != null)
  1025. _owner.sendPacket(mi);
  1026. if (ps != null)
  1027. {
  1028. if (_owner instanceof L2Summon)
  1029. {
  1030. L2PcInstance summonOwner = ((L2Summon)_owner).getOwner();
  1031. if (summonOwner != null)
  1032. {
  1033. if (summonOwner.isInParty())
  1034. summonOwner.getParty().broadcastToPartyMembers(ps);
  1035. else
  1036. summonOwner.sendPacket(ps);
  1037. }
  1038. }
  1039. else
  1040. if (_owner instanceof L2PcInstance && _owner.isInParty())
  1041. _owner.getParty().broadcastToPartyMembers(ps);
  1042. }
  1043. if (os != null)
  1044. {
  1045. final OlympiadGameTask game = OlympiadGameManager.getInstance().getOlympiadTask(((L2PcInstance)_owner).getOlympiadGameId());
  1046. if (game != null && game.isBattleStarted())
  1047. game.getZone().broadcastPacketToObservers(os);
  1048. }
  1049. }
  1050. protected void updateEffectFlags()
  1051. {
  1052. boolean foundRemovedOnAction = false;
  1053. boolean foundRemovedOnDamage = false;
  1054. if (_buffs != null && !_buffs.isEmpty())
  1055. {
  1056. //synchronized (_buffs)
  1057. {
  1058. for (L2Effect e : _buffs)
  1059. {
  1060. if (e == null)
  1061. continue;
  1062. if (e.getSkill().isRemovedOnAnyActionExceptMove())
  1063. foundRemovedOnAction = true;
  1064. if (e.getSkill().isRemovedOnDamage())
  1065. foundRemovedOnDamage = true;
  1066. }
  1067. }
  1068. }
  1069. _hasBuffsRemovedOnAnyAction = foundRemovedOnAction;
  1070. _hasBuffsRemovedOnDamage = foundRemovedOnDamage;
  1071. foundRemovedOnDamage = false;
  1072. if (_debuffs != null && !_debuffs.isEmpty())
  1073. {
  1074. //synchronized (_debuffs)
  1075. {
  1076. for (L2Effect e : _debuffs)
  1077. {
  1078. if (e == null)
  1079. continue;
  1080. if (e.getSkill().isRemovedOnDamage())
  1081. foundRemovedOnDamage = true;
  1082. }
  1083. }
  1084. }
  1085. _hasDebuffsRemovedOnDamage = foundRemovedOnDamage;
  1086. }
  1087. /**
  1088. * Returns effect if contains in _buffs or _debuffs and null if not found
  1089. * @param effect
  1090. * @return
  1091. */
  1092. private L2Effect listsContains(L2Effect effect)
  1093. {
  1094. if (_buffs != null && !_buffs.isEmpty()&& _buffs.contains(effect))
  1095. return effect;
  1096. if (_debuffs != null && !_debuffs.isEmpty() && _debuffs.contains(effect))
  1097. return effect;
  1098. return null;
  1099. }
  1100. /**
  1101. * Recalculate effect bits flag.<br>
  1102. * Please no concurrency access
  1103. */
  1104. private final void computeEffectFlags()
  1105. {
  1106. int flags = 0;
  1107. if (_buffs != null)
  1108. {
  1109. for (L2Effect e : _buffs)
  1110. {
  1111. if (e == null)
  1112. continue;
  1113. flags |= e.getEffectFlags();
  1114. }
  1115. }
  1116. if (_debuffs != null)
  1117. {
  1118. for (L2Effect e : _debuffs)
  1119. {
  1120. if (e == null)
  1121. continue;
  1122. flags |= e.getEffectFlags();
  1123. }
  1124. }
  1125. _effectFlags = flags;
  1126. }
  1127. /**
  1128. * Check if target is affected with special buff
  1129. * @param bitFlag flag of special buff
  1130. * @return boolean true if affected
  1131. */
  1132. public boolean isAffected(int bitFlag)
  1133. {
  1134. return (_effectFlags & bitFlag) != 0;
  1135. }
  1136. /**
  1137. * Clear and null all queues and lists
  1138. * Use only during delete character from the world.
  1139. */
  1140. public void clear()
  1141. {
  1142. try
  1143. {
  1144. if (_addQueue != null)
  1145. {
  1146. _addQueue.clear();
  1147. _addQueue = null;
  1148. }
  1149. if (_removeQueue != null)
  1150. {
  1151. _removeQueue.clear();
  1152. _removeQueue = null;
  1153. }
  1154. _queuesInitialized = false;
  1155. if (_buffs != null)
  1156. {
  1157. _buffs.clear();
  1158. _buffs = null;
  1159. }
  1160. if (_debuffs != null)
  1161. {
  1162. _debuffs.clear();
  1163. _debuffs = null;
  1164. }
  1165. if (_stackedEffects != null)
  1166. {
  1167. _stackedEffects.clear();
  1168. _stackedEffects = null;
  1169. }
  1170. }
  1171. catch (Exception e)
  1172. {
  1173. _log.log(Level.WARNING, "", e);
  1174. }
  1175. }
  1176. }