CharEffectList.java 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  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. public static final int EFFECT_FLAG_BLOCK_RESURRECTION = 0x100000;
  64. private FastList<L2Effect> _buffs;
  65. private FastList<L2Effect> _debuffs;
  66. // The table containing the List of all stacked effect in progress for each Stack group Identifier
  67. private Map<String, List<L2Effect>> _stackedEffects;
  68. private volatile boolean _hasBuffsRemovedOnAnyAction = false;
  69. private volatile boolean _hasBuffsRemovedOnDamage = false;
  70. private volatile boolean _hasDebuffsRemovedOnDamage = false;
  71. private boolean _queuesInitialized = false;
  72. private LinkedBlockingQueue<L2Effect> _addQueue;
  73. private LinkedBlockingQueue<L2Effect> _removeQueue;
  74. private AtomicBoolean queueLock = new AtomicBoolean();
  75. private int _effectFlags;
  76. // only party icons need to be updated
  77. private boolean _partyOnly = false;
  78. // Owner of this list
  79. private L2Character _owner;
  80. public CharEffectList(L2Character owner)
  81. {
  82. _owner = owner;
  83. }
  84. /**
  85. * Returns all effects affecting stored in this CharEffectList
  86. * @return
  87. */
  88. public final L2Effect[] getAllEffects()
  89. {
  90. // If no effect is active, return EMPTY_EFFECTS
  91. if ( (_buffs == null || _buffs.isEmpty()) && (_debuffs == null || _debuffs.isEmpty()) )
  92. {
  93. return EMPTY_EFFECTS;
  94. }
  95. // Create a copy of the effects
  96. FastList<L2Effect> temp = FastList.newInstance();
  97. // Add all buffs and all debuffs
  98. if (_buffs != null)
  99. {
  100. //synchronized (_buffs)
  101. {
  102. if (!_buffs.isEmpty())
  103. temp.addAll(_buffs);
  104. }
  105. }
  106. if (_debuffs != null)
  107. {
  108. //synchronized (_debuffs)
  109. {
  110. if (!_debuffs.isEmpty())
  111. temp.addAll(_debuffs);
  112. }
  113. }
  114. // Return all effects in an array
  115. L2Effect[] tempArray = new L2Effect[temp.size()];
  116. temp.toArray(tempArray);
  117. FastList.recycle(temp);
  118. return tempArray;
  119. }
  120. /**
  121. * Returns the first effect matching the given EffectType
  122. * @param tp
  123. * @return
  124. */
  125. public final L2Effect getFirstEffect(L2EffectType tp)
  126. {
  127. L2Effect effectNotInUse = null;
  128. if (_buffs != null)
  129. {
  130. //synchronized (_buffs)
  131. {
  132. if (!_buffs.isEmpty())
  133. {
  134. for (L2Effect e: _buffs)
  135. {
  136. if (e == null)
  137. continue;
  138. if (e.getEffectType() == tp)
  139. {
  140. if (e.getInUse())
  141. return e;
  142. else
  143. effectNotInUse = e;
  144. }
  145. }
  146. }
  147. }
  148. }
  149. if (effectNotInUse == null && _debuffs != null)
  150. {
  151. //synchronized (_debuffs)
  152. {
  153. if (!_debuffs.isEmpty())
  154. {
  155. for (L2Effect e: _debuffs)
  156. {
  157. if (e == null)
  158. continue;
  159. if (e.getEffectType() == tp)
  160. {
  161. if (e.getInUse())
  162. return e;
  163. else
  164. effectNotInUse = e;
  165. }
  166. }
  167. }
  168. }
  169. }
  170. return effectNotInUse;
  171. }
  172. /**
  173. * Returns the first effect matching the given L2Skill
  174. * @param skill
  175. * @return
  176. */
  177. public final L2Effect getFirstEffect(L2Skill skill)
  178. {
  179. L2Effect effectNotInUse = null;
  180. if (skill.isDebuff())
  181. {
  182. if (_debuffs == null)
  183. return null;
  184. //synchronized (_debuffs)
  185. {
  186. if (_debuffs.isEmpty())
  187. return null;
  188. for (L2Effect e: _debuffs)
  189. {
  190. if (e == null)
  191. continue;
  192. if (e.getSkill() == skill)
  193. {
  194. if (e.getInUse())
  195. return e;
  196. else
  197. effectNotInUse = e;
  198. }
  199. }
  200. }
  201. return effectNotInUse;
  202. }
  203. else
  204. {
  205. if (_buffs == null)
  206. return null;
  207. //synchronized (_buffs)
  208. {
  209. if (_buffs.isEmpty())
  210. return null;
  211. for (L2Effect e: _buffs)
  212. {
  213. if (e == null)
  214. continue;
  215. if (e.getSkill() == skill)
  216. {
  217. if (e.getInUse())
  218. return e;
  219. else
  220. effectNotInUse = e;
  221. }
  222. }
  223. }
  224. return effectNotInUse;
  225. }
  226. }
  227. /**
  228. * Returns the first effect matching the given skillId
  229. * @param index
  230. * @return
  231. */
  232. public final L2Effect getFirstEffect(int skillId)
  233. {
  234. L2Effect effectNotInUse = null;
  235. if (_buffs != null)
  236. {
  237. //synchronized (_buffs)
  238. {
  239. if (!_buffs.isEmpty())
  240. {
  241. for (L2Effect e: _buffs)
  242. {
  243. if (e == null)
  244. continue;
  245. if (e.getSkill().getId() == skillId)
  246. {
  247. if (e.getInUse())
  248. return e;
  249. else
  250. effectNotInUse = e;
  251. }
  252. }
  253. }
  254. }
  255. }
  256. if (effectNotInUse == null && _debuffs != null)
  257. {
  258. //synchronized (_debuffs)
  259. {
  260. if (!_debuffs.isEmpty())
  261. {
  262. for (L2Effect e: _debuffs)
  263. {
  264. if (e == null)
  265. continue;
  266. if (e.getSkill().getId() == skillId)
  267. {
  268. if (e.getInUse())
  269. return e;
  270. else
  271. effectNotInUse = e;
  272. }
  273. }
  274. }
  275. }
  276. }
  277. return effectNotInUse;
  278. }
  279. /**
  280. * Checks if the given skill stacks with an existing one.
  281. *
  282. * @param checkSkill the skill to be checked
  283. *
  284. * @return Returns whether or not this skill will stack
  285. */
  286. private boolean doesStack(L2Skill checkSkill)
  287. {
  288. if ( (_buffs == null || _buffs.isEmpty()) ||
  289. checkSkill._effectTemplates == null ||
  290. checkSkill._effectTemplates.length < 1 ||
  291. checkSkill._effectTemplates[0].abnormalType == null ||
  292. "none".equals(checkSkill._effectTemplates[0].abnormalType))
  293. {
  294. return false;
  295. }
  296. String stackType = checkSkill._effectTemplates[0].abnormalType;
  297. for (L2Effect e : _buffs)
  298. {
  299. if (e.getAbnormalType() != null && e.getAbnormalType().equals(stackType))
  300. {
  301. return true;
  302. }
  303. }
  304. return false;
  305. }
  306. /**
  307. * Return the number of buffs in this CharEffectList not counting Songs/Dances
  308. * @return
  309. */
  310. public int getBuffCount()
  311. {
  312. if (_buffs == null) return 0;
  313. int buffCount=0;
  314. //synchronized(_buffs)
  315. {
  316. if (_buffs.isEmpty())
  317. return 0;
  318. for (L2Effect e : _buffs)
  319. {
  320. if (e != null && e.getShowIcon() && !e.getSkill().isDance() && !e.getSkill().is7Signs())
  321. {
  322. switch (e.getSkill().getSkillType())
  323. {
  324. case BUFF:
  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.getAbnormalType()))
  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.getAbnormalType());
  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.getAbnormalType());
  697. else
  698. // Update the Stack Group table _stackedEffects of the L2Character
  699. _stackedEffects.put(effect.getAbnormalType(), 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.getAbnormalLvl() == newEffect.getAbnormalLvl()
  731. && e.getAbnormalType().equals(newEffect.getAbnormalType()))
  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.getAbnormalLvl() == newEffect.getAbnormalLvl()
  749. && e.getAbnormalType().equals(newEffect.getAbnormalType()))
  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 HEAL_PERCENT:
  790. case MANAHEAL_PERCENT:
  791. for (L2Effect e : _buffs)
  792. {
  793. if (e == null || e.getSkill().isDance())
  794. continue;
  795. switch (e.getSkill().getSkillType())
  796. {
  797. case BUFF:
  798. case HEAL_PERCENT:
  799. case MANAHEAL_PERCENT:
  800. e.exit();
  801. effectsToRemove--;
  802. break; // break switch()
  803. default:
  804. continue; // continue for()
  805. }
  806. if (effectsToRemove < 0)
  807. break; // break for()
  808. }
  809. }
  810. }
  811. }
  812. }
  813. // Icons order: buffs, 7s, toggles, dances
  814. if (newSkill.isDance())
  815. _buffs.addLast(newEffect);
  816. else
  817. {
  818. int pos=0;
  819. if (newSkill.isToggle())
  820. {
  821. // toggle skill - before all dances
  822. for (L2Effect e : _buffs)
  823. {
  824. if (e == null)
  825. continue;
  826. if (e.getSkill().isDance())
  827. break;
  828. pos++;
  829. }
  830. }
  831. else
  832. {
  833. // normal buff - before toggles and 7s and dances
  834. for (L2Effect e : _buffs)
  835. {
  836. if (e == null)
  837. continue;
  838. if (e.getSkill().isToggle() || e.getSkill().is7Signs()
  839. || e.getSkill().isDance())
  840. break;
  841. pos++;
  842. }
  843. }
  844. _buffs.add(pos, newEffect);
  845. }
  846. }
  847. // Check if a stack group is defined for this effect
  848. if ("none".equals(newEffect.getAbnormalType()))
  849. {
  850. // Set this L2Effect to In Use
  851. if (newEffect.setInUse(true))
  852. // Add Funcs of this effect to the Calculator set of the L2Character
  853. _owner.addStatFuncs(newEffect.getStatFuncs());
  854. return;
  855. }
  856. List<L2Effect> stackQueue;
  857. L2Effect effectToAdd = null;
  858. L2Effect effectToRemove = null;
  859. if (_stackedEffects == null) _stackedEffects = new FastMap<String, List<L2Effect>>();
  860. // Get the list of all stacked effects corresponding to the stack type of the L2Effect to add
  861. stackQueue = _stackedEffects.get(newEffect.getAbnormalType());
  862. if (stackQueue != null)
  863. {
  864. int pos = 0;
  865. if (!stackQueue.isEmpty())
  866. {
  867. // Get the first stacked effect of the Stack group selected
  868. effectToRemove = listsContains(stackQueue.get(0));
  869. // Create an Iterator to go through the list of stacked effects in progress on the L2Character
  870. Iterator<L2Effect> queueIterator = stackQueue.iterator();
  871. while (queueIterator.hasNext())
  872. {
  873. if (newEffect.getAbnormalLvl() < queueIterator.next().getAbnormalLvl())
  874. pos++;
  875. else break;
  876. }
  877. // Add the new effect to the Stack list in function of its position in the Stack group
  878. stackQueue.add(pos, newEffect);
  879. // skill.exit() could be used, if the users don't wish to see "effect
  880. // removed" always when a timer goes off, even if the buff isn't active
  881. // any more (has been replaced). but then check e.g. npc hold and raid petrification.
  882. if (Config.EFFECT_CANCELING && !newEffect.isHerbEffect() && stackQueue.size() > 1)
  883. {
  884. if (newSkill.isDebuff())
  885. {
  886. _debuffs.remove(stackQueue.remove(1));
  887. }
  888. else
  889. {
  890. _buffs.remove(stackQueue.remove(1));
  891. }
  892. }
  893. }
  894. else
  895. stackQueue.add(0, newEffect);
  896. }
  897. else
  898. {
  899. stackQueue = new FastList<L2Effect>();
  900. stackQueue.add(0, newEffect);
  901. }
  902. // Update the Stack Group table _stackedEffects of the L2Character
  903. _stackedEffects.put(newEffect.getAbnormalType(), stackQueue);
  904. // Get the first stacked effect of the Stack group selected
  905. if (!stackQueue.isEmpty())
  906. {
  907. effectToAdd = listsContains(stackQueue.get(0));
  908. }
  909. if (effectToRemove != effectToAdd)
  910. {
  911. if (effectToRemove != null)
  912. {
  913. // Remove all Func objects corresponding to this stacked effect from the Calculator set of the L2Character
  914. _owner.removeStatsOwner(effectToRemove);
  915. // Set the L2Effect to Not In Use
  916. effectToRemove.setInUse(false);
  917. }
  918. if (effectToAdd != null)
  919. {
  920. // Set this L2Effect to In Use
  921. if (effectToAdd.setInUse(true))
  922. // Add all Func objects corresponding to this stacked effect to the Calculator set of the L2Character
  923. _owner.addStatFuncs(effectToAdd.getStatFuncs());
  924. }
  925. }
  926. }
  927. protected void updateEffectIcons()
  928. {
  929. if (_owner == null)
  930. return;
  931. if (!(_owner instanceof L2Playable))
  932. {
  933. updateEffectFlags();
  934. return;
  935. }
  936. AbnormalStatusUpdate mi = null;
  937. PartySpelled ps = null;
  938. ExOlympiadSpelledInfo os = null;
  939. if (_owner instanceof L2PcInstance)
  940. {
  941. if (_partyOnly)
  942. _partyOnly = false;
  943. else
  944. mi = new AbnormalStatusUpdate();
  945. if (_owner.isInParty())
  946. ps = new PartySpelled(_owner);
  947. if (((L2PcInstance)_owner).isInOlympiadMode() && ((L2PcInstance)_owner).isOlympiadStart())
  948. os = new ExOlympiadSpelledInfo((L2PcInstance)_owner);
  949. }
  950. else
  951. if (_owner instanceof L2Summon)
  952. ps = new PartySpelled(_owner);
  953. boolean foundRemovedOnAction = false;
  954. boolean foundRemovedOnDamage = false;
  955. if (_buffs != null && !_buffs.isEmpty())
  956. {
  957. //synchronized (_buffs)
  958. {
  959. for (L2Effect e : _buffs)
  960. {
  961. if (e == null)
  962. continue;
  963. if (e.getSkill().isRemovedOnAnyActionExceptMove())
  964. foundRemovedOnAction = true;
  965. if (e.getSkill().isRemovedOnDamage())
  966. foundRemovedOnDamage = true;
  967. if (!e.getShowIcon())
  968. continue;
  969. switch (e.getEffectType())
  970. {
  971. case CHARGE: // handled by EtcStatusUpdate
  972. case SIGNET_GROUND:
  973. continue;
  974. }
  975. if (e.getInUse())
  976. {
  977. if (mi != null)
  978. e.addIcon(mi);
  979. if (ps != null)
  980. e.addPartySpelledIcon(ps);
  981. if (os != null)
  982. e.addOlympiadSpelledIcon(os);
  983. }
  984. }
  985. }
  986. }
  987. _hasBuffsRemovedOnAnyAction = foundRemovedOnAction;
  988. _hasBuffsRemovedOnDamage = foundRemovedOnDamage;
  989. foundRemovedOnDamage = false;
  990. if (_debuffs != null && !_debuffs.isEmpty())
  991. {
  992. //synchronized (_debuffs)
  993. {
  994. for (L2Effect e : _debuffs)
  995. {
  996. if (e == null)
  997. continue;
  998. if (e.getSkill().isRemovedOnAnyActionExceptMove())
  999. foundRemovedOnAction = true;
  1000. if (e.getSkill().isRemovedOnDamage())
  1001. foundRemovedOnDamage = true;
  1002. if (!e.getShowIcon())
  1003. continue;
  1004. switch (e.getEffectType())
  1005. {
  1006. case SIGNET_GROUND:
  1007. continue;
  1008. }
  1009. if (e.getInUse())
  1010. {
  1011. if (mi != null)
  1012. e.addIcon(mi);
  1013. if (ps != null)
  1014. e.addPartySpelledIcon(ps);
  1015. if (os != null)
  1016. e.addOlympiadSpelledIcon(os);
  1017. }
  1018. }
  1019. }
  1020. }
  1021. _hasDebuffsRemovedOnDamage = foundRemovedOnDamage;
  1022. if (mi != null)
  1023. _owner.sendPacket(mi);
  1024. if (ps != null)
  1025. {
  1026. if (_owner instanceof L2Summon)
  1027. {
  1028. L2PcInstance summonOwner = ((L2Summon)_owner).getOwner();
  1029. if (summonOwner != null)
  1030. {
  1031. if (summonOwner.isInParty())
  1032. summonOwner.getParty().broadcastToPartyMembers(ps);
  1033. else
  1034. summonOwner.sendPacket(ps);
  1035. }
  1036. }
  1037. else
  1038. if (_owner instanceof L2PcInstance && _owner.isInParty())
  1039. _owner.getParty().broadcastToPartyMembers(ps);
  1040. }
  1041. if (os != null)
  1042. {
  1043. final OlympiadGameTask game = OlympiadGameManager.getInstance().getOlympiadTask(((L2PcInstance)_owner).getOlympiadGameId());
  1044. if (game != null && game.isBattleStarted())
  1045. game.getZone().broadcastPacketToObservers(os);
  1046. }
  1047. }
  1048. protected void updateEffectFlags()
  1049. {
  1050. boolean foundRemovedOnAction = false;
  1051. boolean foundRemovedOnDamage = false;
  1052. if (_buffs != null && !_buffs.isEmpty())
  1053. {
  1054. //synchronized (_buffs)
  1055. {
  1056. for (L2Effect e : _buffs)
  1057. {
  1058. if (e == null)
  1059. continue;
  1060. if (e.getSkill().isRemovedOnAnyActionExceptMove())
  1061. foundRemovedOnAction = true;
  1062. if (e.getSkill().isRemovedOnDamage())
  1063. foundRemovedOnDamage = true;
  1064. }
  1065. }
  1066. }
  1067. _hasBuffsRemovedOnAnyAction = foundRemovedOnAction;
  1068. _hasBuffsRemovedOnDamage = foundRemovedOnDamage;
  1069. foundRemovedOnDamage = false;
  1070. if (_debuffs != null && !_debuffs.isEmpty())
  1071. {
  1072. //synchronized (_debuffs)
  1073. {
  1074. for (L2Effect e : _debuffs)
  1075. {
  1076. if (e == null)
  1077. continue;
  1078. if (e.getSkill().isRemovedOnDamage())
  1079. foundRemovedOnDamage = true;
  1080. }
  1081. }
  1082. }
  1083. _hasDebuffsRemovedOnDamage = foundRemovedOnDamage;
  1084. }
  1085. /**
  1086. * Returns effect if contains in _buffs or _debuffs and null if not found
  1087. * @param effect
  1088. * @return
  1089. */
  1090. private L2Effect listsContains(L2Effect effect)
  1091. {
  1092. if (_buffs != null && !_buffs.isEmpty()&& _buffs.contains(effect))
  1093. return effect;
  1094. if (_debuffs != null && !_debuffs.isEmpty() && _debuffs.contains(effect))
  1095. return effect;
  1096. return null;
  1097. }
  1098. /**
  1099. * Recalculate effect bits flag.<br>
  1100. * Please no concurrency access
  1101. */
  1102. private final void computeEffectFlags()
  1103. {
  1104. int flags = 0;
  1105. if (_buffs != null)
  1106. {
  1107. for (L2Effect e : _buffs)
  1108. {
  1109. if (e == null)
  1110. continue;
  1111. flags |= e.getEffectFlags();
  1112. }
  1113. }
  1114. if (_debuffs != null)
  1115. {
  1116. for (L2Effect e : _debuffs)
  1117. {
  1118. if (e == null)
  1119. continue;
  1120. flags |= e.getEffectFlags();
  1121. }
  1122. }
  1123. _effectFlags = flags;
  1124. }
  1125. /**
  1126. * Check if target is affected with special buff
  1127. * @param bitFlag flag of special buff
  1128. * @return boolean true if affected
  1129. */
  1130. public boolean isAffected(int bitFlag)
  1131. {
  1132. return (_effectFlags & bitFlag) != 0;
  1133. }
  1134. /**
  1135. * Clear and null all queues and lists
  1136. * Use only during delete character from the world.
  1137. */
  1138. public void clear()
  1139. {
  1140. try
  1141. {
  1142. if (_addQueue != null)
  1143. {
  1144. _addQueue.clear();
  1145. _addQueue = null;
  1146. }
  1147. if (_removeQueue != null)
  1148. {
  1149. _removeQueue.clear();
  1150. _removeQueue = null;
  1151. }
  1152. _queuesInitialized = false;
  1153. if (_buffs != null)
  1154. {
  1155. _buffs.clear();
  1156. _buffs = null;
  1157. }
  1158. if (_debuffs != null)
  1159. {
  1160. _debuffs.clear();
  1161. _debuffs = null;
  1162. }
  1163. if (_stackedEffects != null)
  1164. {
  1165. _stackedEffects.clear();
  1166. _stackedEffects = null;
  1167. }
  1168. }
  1169. catch (Exception e)
  1170. {
  1171. _log.log(Level.WARNING, "", e);
  1172. }
  1173. }
  1174. }