Axelut

Frintezza aCis 401

Sep 23rd, 2023
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ### Eclipse Workspace Patch 1.0
  2. #P aCis
  3. diff --git aCis_data/data/html/default/29061.htm aCis_data/data/html/default/29061.htm
  4. new file mode 100644
  5. index 0000000..ab9388d
  6. --- /dev/null
  7. +++ aCis_data/data/html/default/29061.htm
  8. @@ -0,0 +1,3 @@
  9. +<html><body>Teleportation Cubic:<br>
  10. +<a action="bypass -h npc_%objectId%_Quest GrandBossTeleporter">Exit the Last Imperial Tomb</a><br>
  11. +</body></html>
  12. diff --git aCis_data/data/html/default/32011.htm aCis_data/data/html/default/32011.htm
  13. index 2341448..1c7c641 100644
  14. --- aCis_data/data/html/default/32011.htm
  15. +++ aCis_data/data/html/default/32011.htm
  16. @@ -1,7 +1,7 @@
  17. <html><body>
  18. I feel an invisible barrier... Some sort of Magic Force Field has been put in place...<br>
  19. ...? The guide of the Imperial mausoleum seems to have something to say.<br><br>
  20. -<a action="bypass -h npc_%objectId%_Quest FinalEmperialTomb">Enter the Magic Force Field</a><br>
  21. +<a action="bypass -h npc_%objectId%_Quest GrandBossTeleporter">Enter the Magic Force Field</a><br>
  22. <a action="bypass -h npc_%objectId%_Chat 1">Listen to Imperial Tomb Guide</a><br>
  23. <a action="bypass -h npc_%objectId%_Quest">Quest</a>
  24. </body></html>
  25. \ No newline at end of file
  26. diff --git aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-01.htm aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-01.htm
  27. new file mode 100644
  28. index 0000000..ef3f436
  29. --- /dev/null
  30. +++ aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-01.htm
  31. @@ -0,0 +1,2 @@
  32. +<html><body>There is nothing beyond the Magic Force Field. Come back later.<br>(You may not enter because Frintezza is not inside the Imperial Tomb.)
  33. +</body></html>
  34. \ No newline at end of file
  35. diff --git aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-02.htm aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-02.htm
  36. new file mode 100644
  37. index 0000000..7904d4e
  38. --- /dev/null
  39. +++ aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-02.htm
  40. @@ -0,0 +1,3 @@
  41. +<html><body>There is big battle beyond the Magic Force Field. Come back later.<br>
  42. +(You may not enter becouse someone is already in a battle with Frintezza.)
  43. +</body></html>
  44. \ No newline at end of file
  45. diff --git aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-03.htm aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-03.htm
  46. new file mode 100644
  47. index 0000000..2e5ec6f
  48. --- /dev/null
  49. +++ aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-03.htm
  50. @@ -0,0 +1 @@
  51. +<html><body>No reaction. Contact must be initiated by the Command Channel Leader.</body></html>
  52. \ No newline at end of file
  53. diff --git aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-04.htm aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-04.htm
  54. new file mode 100644
  55. index 0000000..9fd5d88
  56. --- /dev/null
  57. +++ aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-04.htm
  58. @@ -0,0 +1 @@
  59. +<html><body>Your command channel needs to have at least 2 parties and a maximum of 5.</body></html>
  60. \ No newline at end of file
  61. diff --git aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-05.htm aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-05.htm
  62. new file mode 100644
  63. index 0000000..1c29d9e
  64. --- /dev/null
  65. +++ aCis_data/data/html/script/teleport/GrandBossTeleporter/32011-05.htm
  66. @@ -0,0 +1 @@
  67. +<html><body>You dont have required item.</body></html>
  68. \ No newline at end of file
  69. diff --git aCis_data/data/xml/items/8100-8199.xml aCis_data/data/xml/items/8100-8199.xml
  70. index 79540e3..eafa3ac 100644
  71. --- aCis_data/data/xml/items/8100-8199.xml
  72. +++ aCis_data/data/xml/items/8100-8199.xml
  73. @@ -1566,6 +1566,7 @@
  74. <set name="material" val="GOLD" />
  75. <set name="weight" val="3" />
  76. <set name="is_stackable" val="true" />
  77. + <set name="handler" val="ItemSkills" />
  78. <set name="item_skill" val="2234-1" />
  79. </item>
  80. <item id="8193" type="EtcItem" name="Fisherman's Potion - Green">
  81. diff --git aCis_data/data/xml/items/8500-8599.xml aCis_data/data/xml/items/8500-8599.xml
  82. index 95d3e27..ae2dcf5 100644
  83. --- aCis_data/data/xml/items/8500-8599.xml
  84. +++ aCis_data/data/xml/items/8500-8599.xml
  85. @@ -549,6 +549,7 @@
  86. <set name="material" val="GOLD" />
  87. <set name="weight" val="3" />
  88. <set name="is_stackable" val="true" />
  89. + <set name="handler" val="ItemSkills" />
  90. <set name="item_skill" val="2276-1" />
  91. </item>
  92. <item id="8557" type="Armor" name="Blue Party Hat">
  93. diff --git aCis_data/data/xml/npcs/29000-29999.xml aCis_data/data/xml/npcs/29000-29999.xml
  94. index 40f963f..a8f62b3 100644
  95. --- aCis_data/data/xml/npcs/29000-29999.xml
  96. +++ aCis_data/data/xml/npcs/29000-29999.xml
  97. @@ -2317,7 +2317,7 @@
  98. </skills>
  99. </npc>
  100. <npc id="29045" name="Frintezza" title="">
  101. - <set name="level" val="90"/>
  102. + <set name="level" val="85"/>
  103. <set name="radius" val="45"/>
  104. <set name="height" val="42.7"/>
  105. <set name="rHand" val="0"/>
  106. @@ -2338,7 +2338,7 @@
  107. <set name="str" val="60"/>
  108. <set name="int" val="76"/>
  109. <set name="dex" val="73"/>
  110. - <set name="wit" val="70"/>
  111. + <set name="wit" val="30"/>
  112. <set name="con" val="57"/>
  113. <set name="men" val="80"/>
  114. <set name="corpseTime" val="7"/>
  115. @@ -2352,7 +2352,7 @@
  116. </skills>
  117. </npc>
  118. <npc id="29046" name="Scarlet van Halisha" title="">
  119. - <set name="level" val="85"/>
  120. + <set name="level" val="80"/>
  121. <set name="radius" val="45"/>
  122. <set name="height" val="90.7"/>
  123. <set name="rHand" val="8204"/>
  124. @@ -2387,7 +2387,7 @@
  125. </skills>
  126. </npc>
  127. <npc id="29047" name="Scarlet van Halisha" title="">
  128. - <set name="level" val="90"/>
  129. + <set name="level" val="85"/>
  130. <set name="radius" val="92"/>
  131. <set name="height" val="112.8"/>
  132. <set name="rHand" val="8222"/>
  133. diff --git aCis_data/data/xml/scripts.xml aCis_data/data/xml/scripts.xml
  134. index 3e38b21..e44c739 100644
  135. --- aCis_data/data/xml/scripts.xml
  136. +++ aCis_data/data/xml/scripts.xml
  137. @@ -366,7 +366,7 @@
  138. <script path="script.ai.boss.Benom"/>
  139. <script path="script.ai.boss.Core"/>
  140. <script path="script.ai.boss.DrChaos"/>
  141. -<!-- <script path="script.ai.boss.Frintezza"/> -->
  142. + <script path="script.ai.boss.Frintezza"/>
  143. <script path="script.ai.boss.Gordon"/>
  144. <!-- <script path="script.ai.boss.IceFairySirra"/> -->
  145. <script path="script.ai.boss.Orfen"/>
  146. diff --git aCis_data/data/xml/skills/5000-5099.xml aCis_data/data/xml/skills/5000-5099.xml
  147. index b958bd0..d268c96 100644
  148. --- aCis_data/data/xml/skills/5000-5099.xml
  149. +++ aCis_data/data/xml/skills/5000-5099.xml
  150. @@ -104,22 +104,25 @@
  151. <set name="target" val="SELF" />
  152. </skill>
  153. <skill id="5008" levels="5" name="Frintezza's Songs">
  154. - <table name="#aggroPoints"> 100 100 100 0 0 </table>
  155. + <table name="#aggroPoints"> 100 100 110 0 0 </table>
  156. <table name="#isDebuff"> false false false true true </table>
  157. <table name="#isMagic"> true false false true true </table>
  158. <table name="#power"> 3 0 0 10 10 </table>
  159. - <table name="#skillType"> HEAL_PERCENT DUMMY BUFF DEBUFF STUN </table>
  160. + <table name="#skillType"> HEAL_PERCENT BUFF BUFF DEBUFF STUN </table>
  161. <table name="#stackOrder"> 0 0 1 1 1 </table>
  162. <table name="#stackType"> none none ultimate_buff heal_effect_down stun </table>
  163. <table name="#attackAndSpeed"> 1 1 1.2 1 1 </table>
  164. - <table name="#time"> 0 0 5 5 5 </table>
  165. + <table name="#time"> 0 30 30 15 8 </table>
  166. <table name="#gainHp"> 1 1 1 0.5 1 </table>
  167. <table name="#lvlDepend"> 0 0 0 1 1 </table>
  168. - <table name="#effectname1"> Buff Buff Buff Buff Stun </table>
  169. - <table name="#effectname2"> Buff Buff Buff Buff Cancel </table>
  170. + <table name="#effectname1"> Buff Buff Buff Debuff DanceStun </table><!-- EffectDanceStun.java -->
  171. + <table name="#effectname2"> Buff Buff Buff Buff Stun </table>
  172. <table name="#effectPower"> 0 0 0 0 20 </table>
  173. - <table name="#effectType"> BUFF BUFF BUFF BUFF CANCEL </table>
  174. + <table name="#effectType"> BUFF BUFF BUFF DEBUFF STUN </table>
  175. + <table name="#effectRange"> 6000 6000 6000 -1 -1 </table>
  176. <table name="#maxNegated"> 0 0 0 0 10 </table>
  177. + <table name="#target"> SELF SELF SELF AURA AURA </table>
  178. + <table name="#skillRadius"> -1 -1 -1 8000 8000 </table>
  179. <set name="aggroPoints" val="#aggroPoints" />
  180. <set name="isDebuff" val="#isDebuff" />
  181. <set name="isMagic" val="#isMagic" />
  182. @@ -127,9 +130,11 @@
  183. <set name="magicLvl" val="85" />
  184. <set name="maxNegated" val="#maxNegated" />
  185. <set name="operateType" val="ACTIVE" />
  186. + <set name="effectRange" val="#effectRange" />
  187. <set name="power" val="#power" />
  188. <set name="skillType" val="#skillType" />
  189. - <set name="target" val="SELF" />
  190. + <set name="target" val="#target" />
  191. + <set name="skillRadius" val="#skillRadius" />
  192. <for>
  193. <effect name="#effectname1" time="#time" val="0" stackOrder="1" stackType="#stackType">
  194. <mul stat="pAtk" val="#attackAndSpeed" />
  195. @@ -139,7 +144,7 @@
  196. <add stat="runSpd" val="#attackAndSpeed" />
  197. <mul stat="gainHp" val="#gainHp" />
  198. </effect>
  199. - <effect name="#effectname2" noicon="1" val="0" effectPower="#effectPower" effectType="#effectType" />
  200. + <effect name="#effectname2" val="0" effectPower="#effectPower" effectType="#effectType" />
  201. </for>
  202. </skill>
  203. <skill id="5009" levels="1" name="Frintezza's Ghostly Fighter">
  204. @@ -170,6 +175,8 @@
  205. <skill id="5011" levels="1" name="Frintezza's Bomber Ghost">
  206. <set name="element" val="DARK" />
  207. <set name="hitTime" val="1000" />
  208. + <set name="coolTime" val="2000" />
  209. + <set name="isMagic" val="false" />
  210. <set name="isSuicideAttack" val="true" />
  211. <set name="magicLvl" val="85" />
  212. <set name="operateType" val="ACTIVE" />
  213. @@ -223,12 +230,14 @@
  214. <set name="target" val="FRONT_AREA" />
  215. </skill>
  216. <skill id="5015" levels="6" name="Frintezza's Daemon Charge">
  217. + <table name="#baseCritRate"> 10 12 12 10 12 12 </table>
  218. <table name="#coolTime"> 0 0 0 1500 1500 1500 </table>
  219. <table name="#radius"> 400 500 700 400 500 700 </table>
  220. <table name="#power"> 48761 52970 68074 48761 52970 68074 </table>
  221. - <set name="castRange" val="150" />
  222. + <set name="baseCritRate" val="#baseCritRate" />
  223. + <set name="castRange" val="250" />
  224. <set name="coolTime" val="#coolTime" />
  225. - <set name="effectRange" val="650" />
  226. + <set name="effectRange" val="925" />
  227. <set name="element" val="DARK" />
  228. <set name="flyRadius" val="#radius" />
  229. <set name="flyType" val="CHARGE" />
  230. @@ -239,6 +248,10 @@
  231. <set name="skillRadius" val="#radius" />
  232. <set name="skillType" val="PDAM" />
  233. <set name="target" val="FRONT_AREA" />
  234. + <set name="flyCourse" val="180" />
  235. + <for>
  236. + <effect self="1" name="Warp" val="0" noicon="1" />
  237. + </for>
  238. </skill>
  239. <skill id="5016" levels="1" name="Yoke of Scarlet">
  240. <set name="castRange" val="500" />
  241. @@ -254,7 +267,7 @@
  242. <set name="skillType" val="PARALYZE" />
  243. <set name="target" val="AREA" />
  244. <for>
  245. - <effect name="Paralyze" time="20" val="0" abnormal="floatroot" stackOrder="1" stackType="paralyze" />
  246. + <effect name="FloatStun" time="15" val="0" stackOrder="1" stackType="stun" abnormal="floatroot" effectPower="80" effectType="STUN" />
  247. </for>
  248. </skill>
  249. <skill id="5017" levels="1" name="Frintezza's Daemon Morph">
  250. @@ -278,6 +291,7 @@
  251. <set name="coolTime" val="1000" />
  252. <set name="element" val="DARK" />
  253. <set name="hitTime" val="7000" />
  254. + <set name="isMagic" val="false" />
  255. <set name="magicLvl" val="85" />
  256. <set name="operateType" val="ACTIVE" />
  257. <set name="power" val="#power" />
  258. diff --git aCis_data/data/xml/zones/BossZone.xml aCis_data/data/xml/zones/BossZone.xml
  259. index 8dddd01..e620733 100644
  260. --- aCis_data/data/xml/zones/BossZone.xml
  261. +++ aCis_data/data/xml/zones/BossZone.xml
  262. @@ -109,12 +109,10 @@
  263. <node x="26846" y="-8117"/>
  264. <node x="28231" y="-8163"/>
  265. </zone>
  266. - <zone id="110012" shape="NPoly" minZ="-5200" maxZ="-4680"><!-- Frintezza -->
  267. - <stat name="InvadeTime" val="1800000"/>
  268. - <node x="172031" y="-90127"/>
  269. - <node x="176428" y="-90089"/>
  270. - <node x="176428" y="-74051"/>
  271. - <node x="172057" y="-74108"/>
  272. + <zone id="110012" shape="Cuboid" minZ="-5150" maxZ="-4000"><!-- Frintezza -->
  273. + <stat name="InvadeTime" val="1800000" />
  274. + <node x="172176" y="-74106" />
  275. + <node x="176284" y="-90033" />
  276. </zone>
  277. <zone id="110013" shape="NPoly" minZ="-5136" maxZ="864"><!-- Ice Fairy 1 -->
  278. <stat name="InvadeTime" val="1800000"/>
  279. diff --git aCis_data/data/xml/zones/ScriptZone.xml aCis_data/data/xml/zones/ScriptZone.xml
  280. index e0dbb43..8962e1b 100644
  281. --- aCis_data/data/xml/zones/ScriptZone.xml
  282. +++ aCis_data/data/xml/zones/ScriptZone.xml
  283. @@ -22,4 +22,8 @@
  284. <node x="88759" y="-108195"/>
  285. <node x="88677" y="-108275"/>
  286. </zone>
  287. + <zone id="100004" shape="Cuboid" minZ="-5140" maxZ="-2319"> <!-- Frintezza.java# Frintezza's Concert Hall -->
  288. + <node x="172176" y="-86081" />
  289. + <node x="176284" y="-90033" />
  290. + </zone>
  291. </list>
  292. \ No newline at end of file
  293. diff --git aCis_game/java/net/sf/l2j/gameserver/handler/chathandlers/ChatAll.java aCis_game/java/net/sf/l2j/gameserver/handler/chathandlers/ChatAll.java
  294. index a707ce5..28c1129 100644
  295. --- aCis_game/java/net/sf/l2j/gameserver/handler/chathandlers/ChatAll.java
  296. +++ aCis_game/java/net/sf/l2j/gameserver/handler/chathandlers/ChatAll.java
  297. @@ -1,5 +1,6 @@
  298. package net.sf.l2j.gameserver.handler.chathandlers;
  299.  
  300. +import net.sf.l2j.gameserver.data.xml.ScriptData;
  301. import net.sf.l2j.gameserver.enums.FloodProtector;
  302. import net.sf.l2j.gameserver.enums.SayType;
  303. import net.sf.l2j.gameserver.handler.IChatHandler;
  304. @@ -18,7 +19,14 @@
  305. {
  306. if (!player.getClient().performAction(FloodProtector.GLOBAL_CHAT))
  307. return;
  308. -
  309. +
  310. + if (player.isGM())
  311. + if (text.equalsIgnoreCase(".frintezza"))
  312. + {
  313. + ScriptData.getInstance().getQuest("Frintezza").startQuestTimer("start", null, null, 1000);
  314. + return;
  315. + }
  316. +
  317. final CreatureSay cs = new CreatureSay(player, type, text);
  318. for (Player knownPlayer : player.getKnownTypeInRadius(Player.class, 1250))
  319. knownPlayer.sendPacket(cs);
  320. diff --git aCis_game/java/net/sf/l2j/gameserver/model/actor/Npc.java aCis_game/java/net/sf/l2j/gameserver/model/actor/Npc.java
  321. index 23723ee..728cf87 100644
  322. --- aCis_game/java/net/sf/l2j/gameserver/model/actor/Npc.java
  323. +++ aCis_game/java/net/sf/l2j/gameserver/model/actor/Npc.java
  324. @@ -1486,4 +1486,15 @@
  325. {
  326. startRandomAnimationTimer();
  327. }
  328. + private boolean isFlying = false;
  329. + @Override
  330. + public boolean isFlying()
  331. + {
  332. + return isFlying;
  333. + }
  334. +
  335. + public void setIsFlying(boolean a)
  336. + {
  337. + isFlying = a;
  338. + }
  339. }
  340. \ No newline at end of file
  341. diff --git aCis_game/java/net/sf/l2j/gameserver/scripting/script/ai/boss/Frintezza.java aCis_game/java/net/sf/l2j/gameserver/scripting/script/ai/boss/Frintezza.java
  342. new file mode 100644
  343. index 0000000..472c122
  344. --- /dev/null
  345. +++ aCis_game/java/net/sf/l2j/gameserver/scripting/script/ai/boss/Frintezza.java
  346. @@ -0,0 +1,1167 @@
  347. +package net.sf.l2j.gameserver.scripting.script.ai.boss;
  348. +
  349. +import java.util.List;
  350. +import java.util.Map;
  351. +import java.util.concurrent.ConcurrentHashMap;
  352. +import java.util.concurrent.CopyOnWriteArrayList;
  353. +
  354. +import net.sf.l2j.commons.data.StatSet;
  355. +import net.sf.l2j.commons.math.MathUtil;
  356. +import net.sf.l2j.commons.random.Rnd;
  357. +
  358. +import net.sf.l2j.Config;
  359. +import net.sf.l2j.gameserver.data.manager.GrandBossManager;
  360. +import net.sf.l2j.gameserver.data.manager.ZoneManager;
  361. +import net.sf.l2j.gameserver.data.xml.DoorData;
  362. +import net.sf.l2j.gameserver.enums.SayType;
  363. +import net.sf.l2j.gameserver.enums.skills.FlyType;
  364. +import net.sf.l2j.gameserver.model.actor.Creature;
  365. +import net.sf.l2j.gameserver.model.actor.Npc;
  366. +import net.sf.l2j.gameserver.model.actor.Player;
  367. +import net.sf.l2j.gameserver.model.actor.instance.GrandBoss;
  368. +import net.sf.l2j.gameserver.model.actor.instance.Monster;
  369. +import net.sf.l2j.gameserver.model.holder.IntIntHolder;
  370. +import net.sf.l2j.gameserver.model.location.Location;
  371. +import net.sf.l2j.gameserver.model.zone.type.BossZone;
  372. +import net.sf.l2j.gameserver.model.zone.type.ScriptZone;
  373. +import net.sf.l2j.gameserver.network.SystemMessageId;
  374. +import net.sf.l2j.gameserver.network.serverpackets.AbstractNpcInfo.NpcInfo;
  375. +import net.sf.l2j.gameserver.network.serverpackets.CreatureSay;
  376. +import net.sf.l2j.gameserver.network.serverpackets.Earthquake;
  377. +import net.sf.l2j.gameserver.network.serverpackets.ExShowScreenMessage;
  378. +import net.sf.l2j.gameserver.network.serverpackets.ExShowScreenMessage.SMPOS;
  379. +import net.sf.l2j.gameserver.network.serverpackets.FlyToLocation;
  380. +import net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket;
  381. +import net.sf.l2j.gameserver.network.serverpackets.MagicSkillCanceled;
  382. +import net.sf.l2j.gameserver.network.serverpackets.MagicSkillUse;
  383. +import net.sf.l2j.gameserver.network.serverpackets.NpcSay;
  384. +import net.sf.l2j.gameserver.network.serverpackets.SocialAction;
  385. +import net.sf.l2j.gameserver.network.serverpackets.SpecialCamera;
  386. +import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  387. +import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
  388. +import net.sf.l2j.gameserver.scripting.script.ai.AttackableAIScript;
  389. +import net.sf.l2j.gameserver.skills.AbstractEffect;
  390. +import net.sf.l2j.gameserver.skills.L2Skill;
  391. +
  392. +public class Frintezza extends AttackableAIScript
  393. +{
  394. + private static final ScriptZone FRINTEZZA_LAIR = ZoneManager.getInstance().getZoneById(100004, ScriptZone.class);
  395. + private static final BossZone lastImperialTomp = ZoneManager.getInstance().getZoneById(110012, BossZone.class);
  396. +
  397. + public static final int FRINTEZZA = 29045;
  398. + private static final int SCARLET1 = 29046;
  399. + private static final int SCARLET2 = 29047;
  400. +
  401. + private static final int ALARM_DEVICE = 18328;
  402. + private static final int CHOIR_CAPTAIN = 18334;
  403. + private static final int CHOIR_PRAYER = 18339;
  404. +
  405. + // Frintezza Status Tracking :
  406. + public static final byte DORMANT = 0; // No one has entered yet. Entry is unlocked
  407. + public static final byte WAITING = 1; // Someone has entered, triggering a 35 minute window for additional people to enter before he unleashes his attack. Entry is unlocked
  408. + public static final byte FIGHTING = 2; // Frintezza is engaged in battle, annihilating his foes. Entry is locked
  409. + public static final byte DEAD = 3; // Frintezza has been killed. Entry is locked
  410. +
  411. + private Player _actualVictim; // Actual target of Scarlet.
  412. + private static long _lastAttackTime = 0;
  413. + private static int _killMobs = 0;
  414. +
  415. + private static GrandBoss scarlet, frintezza;
  416. +
  417. + private final List<Npc> _dummys = new CopyOnWriteArrayList<>();
  418. + private final List<Monster> demons = new CopyOnWriteArrayList<>();
  419. + private final Map<Monster, Integer> portraits = new ConcurrentHashMap<>();
  420. + private final List<Npc> _mobs = new CopyOnWriteArrayList<>();
  421. +
  422. + //features unconfirmed retail
  423. + // Cinematic initial and Alarm Device open doors
  424. + private static boolean not_confirmed = true;
  425. +
  426. + // Skills
  427. + private static final int DEWDROP_OF_DESTRUCTION_SKILL_ID = 2276;
  428. + private static final int BREAKING_ARROW_SKILL_ID = 2234;
  429. + private static final IntIntHolder Bomber_Ghost = new IntIntHolder(5011, 1);
  430. +
  431. + private L2Skill songEffect = null;
  432. + private static int[][] scarletSkills;
  433. +
  434. + // Items
  435. + //private static final int FRINTEZZA_SCROLL = 8073; // Frintezza's Magic Force Field Removal Scroll.
  436. + //http://legacy.lineage2.com/news/chronicle5_07.html
  437. + private static final int DEWDROP_OF_DESTRUCTION = 8556; // Dewdrop of Destruction
  438. + // Clicking the Dewdrop of Destruction will make the portrait disappear. It will disappear when one enters the Last Imperial Sepulcher.
  439. + private static final int BREAKING_ARROW = 8192; // Breaking Arrow
  440. + // Double-click the arrow to temporarily stop Frintezza's musical performance. This gets deleted when one enters the Tomb of the Last Emperor.
  441. +
  442. + protected static final int[][] PORTRAIT_GHOST =
  443. + {
  444. + {29048, 175833, -87165, -5126, 35048, 175833, -87165, -5100, 35048},
  445. + {29048, 172634, -87165, -5126, 57730, 172634, -87165, -5100, 57730},
  446. + {29049, 175876, -88713, -5126, 28205, 175876, -88713, -5100, 28205},
  447. + {29049, 172608, -88702, -5126, 64817, 172608, -88702, -5100, 64817}
  448. + };
  449. +
  450. + protected static final int[][] DUMMY_SPAWNS =
  451. + {
  452. + {29052, 174240, -89805, -5022, 16048},
  453. + {29052, 174232, -88020, -5110, 16384},
  454. + {29052, 172450, -87890, -5100, 16048},
  455. + {29052, 176012, -87890, -5100, 16048},
  456. + {29053, 174232, -88020, -5110, 16384}
  457. + };
  458. +
  459. + private static final int[][] ROOM1_SPAWN =
  460. + {
  461. + { 18328,172894,-76019,-5107,243 },
  462. + { 18328,174095,-77279,-5107,16216 },
  463. + { 18328,174111,-74833,-5107,49043 },
  464. + { 18328,175344,-76042,-5107,32847 },
  465. + { 18330,173489,-76227,-5134,63565 },
  466. + { 18330,173498,-75724,-5107,58498 },
  467. + { 18330,174365,-76745,-5107,22424 },
  468. + { 18330,174570,-75584,-5107,31968 },
  469. + { 18330,174613,-76179,-5107,31471 },
  470. + { 18332,173620,-75981,-5107,4588 },
  471. + { 18332,173630,-76340,-5107,62454 },
  472. + { 18332,173755,-75613,-5107,57892 },
  473. + { 18332,173823,-76688,-5107,2411 },
  474. + { 18332,174000,-75411,-5107,54718 },
  475. + { 18332,174487,-75555,-5107,33861 },
  476. + { 18332,174517,-76471,-5107,21893 },
  477. + { 18332,174576,-76122,-5107,31176 },
  478. + { 18332,174600,-75841,-5134,35927 }
  479. + };
  480. + // Hall Keeper Captain
  481. + private static final int[][] ROOM1_CAPTAIN =
  482. + {
  483. + { 18329,173481,-76043,-5107,61312 },
  484. + { 18329,173539,-75678,-5107,59524 },
  485. + { 18329,173584,-76386,-5107,3041 },
  486. + { 18329,173773,-75420,-5107,51115 },
  487. + { 18329,173777,-76650,-5107,12588 },
  488. + { 18329,174585,-76510,-5107,21704 },
  489. + { 18329,174623,-75571,-5107,40141 },
  490. + { 18329,174744,-76240,-5107,29202 },
  491. + { 18329,174769,-75895,-5107,29572 }
  492. + };
  493. + // Hall Keeper Suicidal Soldier
  494. + private static final int[][] ROOM1_SUICIDAL_SOLDIER =
  495. + {
  496. + { 18333,173861,-76011,-5107,383 },
  497. + { 18333,173872,-76461,-5107,8041 },
  498. + { 18333,173898,-75668,-5107,51856 },
  499. + { 18333,174422,-75689,-5107,42878 },
  500. + { 18333,174460,-76355,-5107,27311 },
  501. + { 18333,174483,-76041,-5107,30947 }
  502. + };
  503. + // Hall Keeper Guard
  504. + private static final int[][] ROOM1_GUARD =
  505. + {
  506. + { 18331,173515,-76184,-5107,6971 },
  507. + { 18331,173516,-75790,-5134,3142 },
  508. + { 18331,173696,-76675,-5107,6757 },
  509. + { 18331,173766,-75502,-5134,60827 },
  510. + { 18331,174473,-75321,-5107,37147 },
  511. + { 18331,174493,-76505,-5107,34503 },
  512. + { 18331,174568,-75654,-5134,41661 },
  513. + { 18331,174584,-76263,-5107,31729 }
  514. + };
  515. + // Dark Choir Player
  516. + private static final int[][] ROOM2_SPAWN =
  517. + {
  518. + { 18339,173892,-81592,-5123,50849 },
  519. + { 18339,173958,-81820,-5123,7459 },
  520. + { 18339,174128,-81805,-5150,21495 },
  521. + { 18339,174245,-81566,-5123,41760 }
  522. + };
  523. + private static final int[][] ROOM2_SPAWN2 =
  524. + {
  525. + { 18334,173264,-81529,-5072,1646 },
  526. + { 18334,173265,-81656,-5072,441 },
  527. + { 18334,173267,-81889,-5072,0 },
  528. + { 18334,173271,-82015,-5072,65382 },
  529. + { 18334,174867,-81655,-5073,32537 },
  530. + { 18334,174868,-81890,-5073,32768 },
  531. + { 18334,174869,-81485,-5073,32315 },
  532. + { 18334,174871,-82017,-5073,33007 },
  533. + { 18335,173074,-80817,-5107,8353 },
  534. + { 18335,173128,-82702,-5107,5345 },
  535. + { 18335,173181,-82544,-5107,65135 },
  536. + { 18335,173191,-80981,-5107,6947 },
  537. + { 18335,174859,-80889,-5134,24103 },
  538. + { 18335,174924,-82666,-5107,38710 },
  539. + { 18335,174947,-80733,-5107,22449 },
  540. + { 18335,175096,-82724,-5107,42205 },
  541. + { 18336,173435,-80512,-5107,65215 },
  542. + { 18336,173440,-82948,-5107,417 },
  543. + { 18336,173443,-83120,-5107,1094 },
  544. + { 18336,173463,-83064,-5107,286 },
  545. + { 18336,173465,-80453,-5107,174 },
  546. + { 18336,173465,-83006,-5107,2604 },
  547. + { 18336,173468,-82889,-5107,316 },
  548. + { 18336,173469,-80570,-5107,65353 },
  549. + { 18336,173469,-80628,-5107,166 },
  550. + { 18336,173492,-83121,-5107,394 },
  551. + { 18336,173493,-80683,-5107,0 },
  552. + { 18336,173497,-80510,-5134,417 },
  553. + { 18336,173499,-82947,-5107,0 },
  554. + { 18336,173521,-83063,-5107,316 },
  555. + { 18336,173523,-82889,-5107,128 },
  556. + { 18336,173524,-80627,-5134,65027 },
  557. + { 18336,173524,-83007,-5107,0 },
  558. + { 18336,173526,-80452,-5107,64735 },
  559. + { 18336,173527,-80569,-5134,65062 },
  560. + { 18336,174602,-83122,-5107,33104 },
  561. + { 18336,174604,-82949,-5107,33184 },
  562. + { 18336,174609,-80514,-5107,33234 },
  563. + { 18336,174609,-80684,-5107,32851 },
  564. + { 18336,174629,-80627,-5107,33346 },
  565. + { 18336,174632,-80570,-5107,32896 },
  566. + { 18336,174632,-83066,-5107,32768 },
  567. + { 18336,174635,-82893,-5107,33594 },
  568. + { 18336,174636,-80456,-5107,32065 },
  569. + { 18336,174639,-83008,-5107,33057 },
  570. + { 18336,174660,-80512,-5107,33057 },
  571. + { 18336,174661,-83121,-5107,32768 },
  572. + { 18336,174663,-82948,-5107,32768 },
  573. + { 18336,174664,-80685,-5107,32676 },
  574. + { 18336,174687,-83008,-5107,32520 },
  575. + { 18336,174691,-83066,-5107,32961 },
  576. + { 18336,174692,-80455,-5107,33202 },
  577. + { 18336,174692,-80571,-5107,32768 },
  578. + { 18336,174693,-80630,-5107,32994 },
  579. + { 18336,174693,-82889,-5107,32622 },
  580. + { 18337,172837,-82382,-5107,58363 },
  581. + { 18337,172867,-81123,-5107,64055 },
  582. + { 18337,172883,-82495,-5107,64764 },
  583. + { 18337,172916,-81033,-5107,7099 },
  584. + { 18337,172940,-82325,-5107,58998 },
  585. + { 18337,172946,-82435,-5107,58038 },
  586. + { 18337,172971,-81198,-5107,14768 },
  587. + { 18337,172992,-81091,-5107,9438 },
  588. + { 18337,173032,-82365,-5107,59041 },
  589. + { 18337,173064,-81125,-5107,5827 },
  590. + { 18337,175014,-81173,-5107,26398 },
  591. + { 18337,175061,-82374,-5107,43290 },
  592. + { 18337,175096,-81080,-5107,24719 },
  593. + { 18337,175169,-82453,-5107,37672 },
  594. + { 18337,175172,-80972,-5107,32315 },
  595. + { 18337,175174,-82328,-5107,41760 },
  596. + { 18337,175197,-81157,-5107,27617 },
  597. + { 18337,175245,-82547,-5107,40275 },
  598. + { 18337,175249,-81075,-5107,28435 },
  599. + { 18337,175292,-82432,-5107,42225 },
  600. + { 18338,173014,-82628,-5107,11874 },
  601. + { 18338,173033,-80920,-5107,10425 },
  602. + { 18338,173095,-82520,-5107,49152 },
  603. + { 18338,173115,-80986,-5107,9611 },
  604. + { 18338,173144,-80894,-5107,5345 },
  605. + { 18338,173147,-82602,-5107,51316 },
  606. + { 18338,174912,-80825,-5107,24270 },
  607. + { 18338,174935,-80899,-5107,18061 },
  608. + { 18338,175016,-82697,-5107,39533 },
  609. + { 18338,175041,-80834,-5107,25420 },
  610. + { 18338,175071,-82549,-5107,39163 },
  611. + { 18338,175154,-82619,-5107,36345 }
  612. + };
  613. +
  614. + public Frintezza()
  615. + {
  616. + super("ai/boss");
  617. +
  618. + StatSet info = GrandBossManager.getInstance().getStatSet(FRINTEZZA);
  619. + if (GrandBossManager.getInstance().getBossStatus(FRINTEZZA) == DEAD)
  620. + {
  621. + long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
  622. + if (temp > 0)
  623. + startQuestTimer("frintezza_unlock", null, null, temp);
  624. + else
  625. + GrandBossManager.getInstance().setBossStatus(FRINTEZZA, DORMANT);
  626. + }
  627. + else if (GrandBossManager.getInstance().getBossStatus(FRINTEZZA) != DORMANT)
  628. + GrandBossManager.getInstance().setBossStatus(FRINTEZZA, DORMANT);
  629. + }
  630. +
  631. + @Override
  632. + protected void registerNpcs()
  633. + {
  634. + addAttackId(SCARLET1, SCARLET2, FRINTEZZA, 29048, 29049);
  635. + addSpawnId(FRINTEZZA, SCARLET1, SCARLET2, ALARM_DEVICE, CHOIR_CAPTAIN);
  636. + addKillId(SCARLET2, 29048, 29049, 29050, 29051, ALARM_DEVICE, 18329, 18330, 18331, 18332, 18333, CHOIR_CAPTAIN, 18335, 18336, 18337, 18338, CHOIR_PRAYER);
  637. + addSkillSeeId(29050, 29051);
  638. + addSpellFinishedId(FRINTEZZA, 29050, 29051);
  639. + addExitZoneId(100004);
  640. + }
  641. +
  642. + @Override
  643. + public String onSpawn(Npc npc)
  644. + {
  645. + switch(npc.getNpcId())
  646. + {
  647. + case ALARM_DEVICE:
  648. + case CHOIR_CAPTAIN:
  649. + if (not_confirmed)
  650. + lastImperialTomp.broadcastPacket(new NpcSay(npc.getObjectId(), SayType.SHOUT, npc.getNpcId() == ALARM_DEVICE ? "Intruders! Sound the alarm!" : "How dare you ruin the performance of the Dark Choir... Unforgivable!"));
  651. + npc.setIsImmobilized(true);
  652. + npc.disableCoreAi(true);
  653. + break;
  654. + case FRINTEZZA:
  655. + case SCARLET1:
  656. + case SCARLET2:
  657. + npc.disableCoreAi(true);
  658. + break;
  659. + }
  660. + return super.onSpawn(npc);
  661. + }
  662. +
  663. + @Override
  664. + public String onTimer(String event, Npc npc, Player player)
  665. + {
  666. + if (event.equalsIgnoreCase("start"))
  667. + {
  668. + broadcastPacket(new Earthquake(getKnownInside(), 45, 27, false));
  669. + clean(WAITING);
  670. + dropTimers();
  671. + startQuestTimer("beginning", null, null, 4000);
  672. + }
  673. + else if (event.equalsIgnoreCase("beginning")) //TODO: beginning
  674. + {
  675. + startQuestTimer("camera_00", null, null, 29000);
  676. + startQuestTimer("camera_01", null, null, 30000);
  677. + startQuestTimer("camera_02", null, null, 31000); //100
  678. + startQuestTimer("camera_03", null, null, 37500); //6500
  679. + startQuestTimer("camera_04", null, null, 38400); //900
  680. + startQuestTimer("camera_05", null, null, 42400); //4000 ex - cam5b
  681. + startQuestTimer("camera_06", null, null, 43750); //1350
  682. + startQuestTimer("camera_07", null, null, 51750); //7000
  683. + startQuestTimer("camera_08", null, null, 52150); //1000
  684. + startQuestTimer("camera_09", null, null, 54150); //2000
  685. + startQuestTimer("camera_10", null, null, 58650); //4500
  686. + startQuestTimer("camera_11", null, null, 59350); //700
  687. + startQuestTimer("camera_12", null, null, 60650); //1300 -15
  688. + startQuestTimer("camera_13", null, null, 62150); //1500 -16
  689. + startQuestTimer("camera_14", null, null, 69650); //7500 -17
  690. + startQuestTimer("camera_15", null, null, 79150); //9500 -16 //79350//200
  691. + startQuestTimer("camera_16", null, null, 81750); //2400 //81550 //81150
  692. + startQuestTimer("camera_17", null, null, 84150); //5000
  693. + startQuestTimer("camera_18", null, null, 84850); //6300 -85450 -throw_up
  694. + startQuestTimer("camera_19", null, null, 87650); //3500
  695. + startQuestTimer("camera_20", null, null, 89650); //2000
  696. + startQuestTimer("camera_21", null, null, 92650); //3000
  697. + startQuestTimer("camera_22", null, null, 94650); //2000
  698. + }
  699. + else if (event.equalsIgnoreCase("despawn"))
  700. + {
  701. + if (GrandBossManager.getInstance().getBossStatus(FRINTEZZA) == FIGHTING && (System.currentTimeMillis() - _lastAttackTime) >= 900000)
  702. + {
  703. + clean(DORMANT);
  704. + dropTimers();
  705. + }
  706. + }
  707. + else if (event.equalsIgnoreCase("camera_00")) //TODO: camera 00
  708. + {
  709. + for (int[] loc : DUMMY_SPAWNS)
  710. + {
  711. + Npc dummy = addSpawn(loc[0], loc[1], loc[2], loc[3], loc[4], false, 62650, false);
  712. + dummy.setIsImmobilized(true);
  713. + dummy.setIsParalyzed(true);
  714. + dummy.disableCoreAi(true);
  715. + _dummys.add(dummy);
  716. + }
  717. + _dummys.get(2).setIsFlying(true);
  718. + _dummys.get(3).setIsFlying(true);
  719. + _dummys.get(1).setCollisionHeight(600);
  720. + setPrepareRoom(true);
  721. + }
  722. + else if (event.equalsIgnoreCase("camera_01"))
  723. + {
  724. + GrandBossManager.getInstance().setBossStatus(FRINTEZZA, FIGHTING);
  725. + frintezza = (GrandBoss) addSpawn(FRINTEZZA, 174240, -89805, -5022, 16048, false, 0, false);
  726. + frintezza.setInvul(true);
  727. + frintezza.decayMe();
  728. + }
  729. + else if (event.equalsIgnoreCase("camera_02"))
  730. + {
  731. + for (int[] ghosts : PORTRAIT_GHOST)
  732. + {
  733. + Monster demon = (Monster) addSpawn(ghosts[0] + 2, ghosts[5], ghosts[6], ghosts[7], ghosts[8], false, 0, false);
  734. + demon.setIsImmobilized(true);
  735. + demon.disableAllSkills();
  736. + demons.add(demon);
  737. + }
  738. + frintezza.spawnMe();
  739. + _dummys.get(1).decayMe();
  740. + broadcastPacket(new NpcInfo(_dummys.get(1), null));
  741. + GrandBossManager.getInstance().addBoss(frintezza);
  742. + broadcastPacket(new SpecialCamera(_dummys.get(1).getObjectId(), 0, 75, -89, 0, 100, 0, 0, 1, 0), new SpecialCamera(_dummys.get(1).getObjectId(), 0, 75, -89, 0, 100, 0, 0, 1, 0), new ValidateLocation(frintezza), new SpecialCamera(_dummys.get(1).getObjectId(), 300, 90, -10, 6500, 7000, 0, 0, 1, 0));
  743. + }
  744. + else if (event.equalsIgnoreCase("camera_03"))
  745. + broadcastPacket(new SpecialCamera(_dummys.get(0).getObjectId(), 1800, 90, 8, 6500, 7000, 0, 0, 1, 0));
  746. + else if (event.equalsIgnoreCase("camera_04"))
  747. + broadcastPacket(new SpecialCamera(_dummys.get(0).getObjectId(), 140, 90, 10, 2500, 4500, 0, 0, 1, 0));
  748. + else if (event.equalsIgnoreCase("camera_05"))
  749. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 40, 75, -10, 0, 1000, 0, 0, 1, 0), new SpecialCamera(frintezza.getObjectId(), 40, 75, -10, 0, 12000, 0, 0, 1, 0));
  750. + else if (event.equalsIgnoreCase("camera_06"))
  751. + broadcastPacket(new SocialAction(frintezza, 2));
  752. + else if (event.equalsIgnoreCase("camera_07"))
  753. + {}//broadcastPacket(new SocialAction(demons.get(1), 1), new SocialAction(demons.get(3), 1)); // TODO: 1 y 3
  754. + else if (event.equalsIgnoreCase("camera_08"))
  755. + {
  756. + broadcastPacket(new SocialAction(demons.get(1), 1), new SocialAction(demons.get(3), 1), new SocialAction(demons.get(0), 1), new SocialAction(demons.get(2), 1));
  757. + _dummys.get(2).instantTeleportTo(172450, -87890, -5100, 0);
  758. + _dummys.get(3).instantTeleportTo(176012, -87890, -5100, 0);
  759. + boolean locX = getKnownInside().getX() < 174232;
  760. + broadcastPacket(new SpecialCamera(_dummys.get(locX ? 2 : 3).getObjectId(), 1000, locX ? 118 : 62, 0, 0, 1000, 0, 0, 1, 0), new SpecialCamera(_dummys.get(locX ? 2 : 3).getObjectId(), 1000, locX ? 118 : 62, 0, 0, 10000, 0, 0, 1, 0));
  761. + }
  762. + else if (event.equalsIgnoreCase("camera_09"))
  763. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 240, 90, 0, 0, 1000, 0, 0, 1, 0), new SpecialCamera(frintezza.getObjectId(), 240, 90, 25, 5500, 10000, 0, 0, 1, 0), new SocialAction(frintezza, 3));
  764. + else if (event.equalsIgnoreCase("camera_10"))
  765. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 100, 195, 35, 0, 10000, 0, 0, 1, 0));
  766. + else if (event.equalsIgnoreCase("camera_11"))
  767. + {
  768. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 100, 195, 35, 0, 10000, 0, 0, 1, 0));
  769. + if (not_confirmed)
  770. + playFrintezzaMelody();
  771. + }
  772. + else if (event.equalsIgnoreCase("camera_12"))
  773. + {
  774. + scarlet = (GrandBoss) addSpawn(SCARLET1, 174232, -88020, -5110, 16384, false, 0, true);
  775. + scarlet.setRightHandItemId(8204);
  776. + scarlet.decayMe();
  777. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 120, 180, 45, 1500, 10000, 0, 0, 1, 0));
  778. + if (!not_confirmed)
  779. + playFrintezzaMelody();
  780. + }
  781. + else if (event.equalsIgnoreCase("camera_13"))
  782. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 520, 135, 45, 8000, 10000, 0, 0, 1, 0));
  783. + else if (event.equalsIgnoreCase("camera_14"))
  784. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 1500, 110, 25, 10000, 13000, 0, 0, 1, 0));
  785. + else if (event.equalsIgnoreCase("camera_15"))
  786. + broadcastPacket(new SpecialCamera(_dummys.get(1).getObjectId(), 930, 160, -20, 0, 1000, 0, 0, 1, 0), new MagicSkillUse(_dummys.get(4), _dummys.get(4), 5004, 1, 5800, 0), new SpecialCamera(_dummys.get(1).getObjectId(), 600, 180, -25, 0, 10000, 0, 0, 1, 0));
  787. + else if (event.equalsIgnoreCase("camera_16"))
  788. + scarlet.spawnMe();
  789. + else if (event.equalsIgnoreCase("camera_17"))
  790. + broadcastPacket(new SocialAction(_dummys.get(4), 3), new SpecialCamera(_dummys.get(4).getObjectId(), 800, 180, 10, 1000, 10000, 0, 0, 1, 0));
  791. + else if (event.equalsIgnoreCase("camera_18")) // TODO: throw_up
  792. + throwUp(_dummys.get(4), 500, SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT).addSkillName(5004, 1));
  793. + else if (event.equalsIgnoreCase("camera_19"))
  794. + broadcastPacket(new SpecialCamera(_dummys.get(4).getObjectId(), 300, 60, 8, 0, 10000, 0, 0, 1, 0));
  795. + else if (event.equalsIgnoreCase("camera_20"))
  796. + broadcastPacket(new SpecialCamera(scarlet.getObjectId(), 500, 90, 10, 1000, 5000, 0, 0, 1, 0), new SpecialCamera(scarlet.getObjectId(), 500, 90, 10, 3000, 5000, 0, 0, 1, 0));
  797. + else if (event.equalsIgnoreCase("camera_21"))
  798. + {
  799. + for (int i = 0; i < PORTRAIT_GHOST.length; i++)
  800. + {
  801. + Monster portrait = (Monster) addSpawn(PORTRAIT_GHOST[i][0], PORTRAIT_GHOST[i][1], PORTRAIT_GHOST[i][2], PORTRAIT_GHOST[i][3], PORTRAIT_GHOST[i][4], false, 0, false);
  802. + //portrait.setIsFlying(true);
  803. + portrait.setIsImmobilized(true);
  804. + portrait.disableCoreAi(true);
  805. + portraits.put(portrait, i);
  806. + }
  807. + if (!_dummys.isEmpty())
  808. + {
  809. + for (Npc n : _dummys)
  810. + deleteNpc(n);
  811. + _dummys.clear();
  812. + }
  813. + }
  814. + else if (event.equalsIgnoreCase("camera_22")) //TODO: camera_22
  815. + {
  816. + roomTasks();
  817. + setPrepareRoom(false);
  818. + frintezza.setInvul(false);
  819. + startQuestTimerAtFixedRate("spawn_minion", null, null, 20000);
  820. + }
  821. + else if (event.equalsIgnoreCase("spawn_minion")) //TODO: spawn_minion
  822. + {
  823. + if (frintezza != null && !frintezza.isDead() && !portraits.isEmpty())
  824. + {
  825. + if (!frintezza.isInvul())
  826. + for (int i : portraits.values())
  827. + {
  828. + if (demons.size() > 24)
  829. + break;
  830. + Monster demon = (Monster) addSpawn(PORTRAIT_GHOST[i][0] + 2, PORTRAIT_GHOST[i][5], PORTRAIT_GHOST[i][6], PORTRAIT_GHOST[i][7], PORTRAIT_GHOST[i][8], false, 0, false);
  831. + demon.setMinion(true);
  832. + demon.forceRunStance();
  833. + demons.add(demon);
  834. + demon.disableSkill(Bomber_Ghost.getSkill(), -1); // Bomb
  835. + startQuestTimer("action", demon, null, 200);
  836. + }
  837. + }
  838. + else
  839. + cancelQuestTimers("spawn_minion");
  840. + }
  841. + else if (event.equalsIgnoreCase("end_camera"))
  842. + npc.setInvul(false);
  843. + else if (event.equalsIgnoreCase("first_morph_01")) //TODO: first_morph
  844. + {
  845. + npc.stopSkillEffects(5008);
  846. + setPrepareRoom(true);
  847. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 250, calcCameraAngle(npc), 12, 2000, 15000, 0, 0, 1, 0));
  848. + }
  849. + else if (event.equalsIgnoreCase("first_morph_02"))
  850. + {
  851. + broadcastPacket(new SocialAction(npc, 1));
  852. + npc.setRightHandItemId(7903);
  853. + }
  854. + else if (event.equalsIgnoreCase("first_morph_03"))
  855. + daemonMorph(npc, 1);
  856. + else if (event.equalsIgnoreCase("second_morph_01"))
  857. + {
  858. + setPrepareRoom(true);
  859. + broadcastPacket(new SocialAction(frintezza, 4));
  860. + }
  861. + else if (event.equalsIgnoreCase("second_morph_02"))
  862. + {
  863. + broadcastPacket(new SpecialCamera(frintezza.getObjectId(), 250, 120, 15, 0, 1000, 0, 0, 1, 0), new SpecialCamera(frintezza.getObjectId(), 250, 120, 15, 0, 10000, 0, 0, 1, 0));
  864. + npc.setIsImmobilized(true);
  865. + }
  866. + else if (event.equalsIgnoreCase("second_morph_03"))
  867. + {
  868. + playFrintezzaMelody();
  869. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 500, 70, 15, 3000, 10000, 0, 0, 1, 0));
  870. + }
  871. + else if (event.equalsIgnoreCase("second_morph_04"))
  872. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 2500, 90, 12, 6000, 10000, 0, 0, 1, 0));
  873. + else if (event.equalsIgnoreCase("second_morph_05"))
  874. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 250, calcCameraAngle(npc), 12, 0, 1000, 0, 0, 1, 0), new SpecialCamera(npc.getObjectId(), 250, calcCameraAngle(npc), 12, 0, 10000, 0, 0, 1, 0));
  875. + else if (event.equalsIgnoreCase("second_morph_06"))
  876. + {
  877. + npc.doDie(npc);
  878. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 450, calcCameraAngle(npc), 14, 8000, 8000, 0, 0, 1, 0));
  879. + scarlet = null;
  880. + }
  881. + else if (event.equalsIgnoreCase("second_morph_07"))
  882. + deleteNpc(npc);
  883. + else if (event.equalsIgnoreCase("second_morph_08"))
  884. + {
  885. + scarlet = (GrandBoss) addSpawn(SCARLET2, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0, false);
  886. + broadcastPacket(new SpecialCamera(scarlet.getObjectId(), 450, calcCameraAngle(npc), 12, 500, 14000, 0, 0, 1, 0));
  887. + }
  888. + else if (event.equalsIgnoreCase("second_morph_09"))
  889. + daemonMorph(scarlet, 2);
  890. + else if (event.equalsIgnoreCase("start_room"))
  891. + setPrepareRoom(false);
  892. + else if (event.equalsIgnoreCase("die_01")) //TODO: die_01
  893. + npc.doDie(npc);
  894. + else if (event.equalsIgnoreCase("die_02"))
  895. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 100, 120, 5, 0, 7000, 0, 0, 1, 0), new SpecialCamera(npc.getObjectId(), 100, 90, 5, 5000, 15000, 0, 0, 1, 0));
  896. + else if (event.equalsIgnoreCase("die_03"))
  897. + {
  898. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 900, 90, 25, 7000, 10000, 0, 0, 1, 0));
  899. + addSpawn(29061, 174232, -88020, -5114, 16384, false, 900000, false);
  900. + startQuestTimer("remove_players", null, null, 900000);
  901. + }
  902. + else if (event.equalsIgnoreCase("die_04"))
  903. + {
  904. + cancelQuestTimers("spawn_minion");
  905. + clean(DEAD);
  906. + long respawnTime = (long) Config.SPAWN_INTERVAL_FRINTEZZA + Rnd.get(-Config.RANDOM_SPAWN_TIME_FRINTEZZA, Config.RANDOM_SPAWN_TIME_FRINTEZZA);
  907. + respawnTime *= 3600000;
  908. + startQuestTimer("frintezza_unlock", npc, null, respawnTime);
  909. + // also save the respawn time so that the info is maintained past reboots
  910. + StatSet info = GrandBossManager.getInstance().getStatSet(FRINTEZZA);
  911. + info.set("respawn_time", System.currentTimeMillis() + respawnTime);
  912. + GrandBossManager.getInstance().setStatSet(FRINTEZZA, info);
  913. + }
  914. + else if (event.equalsIgnoreCase("songs_play")) //TODO: play song
  915. + callSongAI();
  916. + else if (event.equalsIgnoreCase("skill_task")) //TODO: skill_task
  917. + {
  918. + if (npc.isInvul() || npc.getCast().isCastingNow() || npc.isDead() || frintezza.isInvul())
  919. + return super.onTimer(event, npc, player);
  920. +
  921. + final L2Skill skill = getRandomSkill();
  922. + int rnd = Rnd.get(10);
  923. +
  924. + if (_actualVictim == null || _actualVictim.isDead() || !npc.knows(_actualVictim) || npc.getScriptValue() != 1 && !npc.isMoving() || rnd == 0 && npc.isMoving())
  925. + _actualVictim = getRandomPlayer(npc);
  926. + if (_actualVictim == null)
  927. + return super.onTimer(event, npc, player);
  928. +
  929. + int range = skill.getCastRange();
  930. + if (_actualVictim.isMoving())
  931. + range = range * 80 / 100;
  932. + if (MathUtil.checkIfInRange((int) (range + npc.getCollisionRadius()), npc, _actualVictim, true))
  933. + {
  934. + npc.getAI().tryToIdle(); //.getAI().setIntention(CtrlIntention.IDLE);
  935. + npc.getAI().tryToCast(_actualVictim, skill); // npc.doCast(skill); npc.setTarget(_actualVictim);
  936. + npc.setScriptValue(0);
  937. + if (rnd < 0) // 90% he decides to reconsiders his new target.
  938. + _actualVictim = null;
  939. + }
  940. + else
  941. + {
  942. + npc.forceRunStance();
  943. + npc.setScriptValue(1);
  944. + npc.getAI().tryToMoveTo(new Location(_actualVictim.getX(), _actualVictim.getY(), _actualVictim.getZ()), null);//npc.getAI().setIntention(CtrlIntention.FOLLOW, _actualVictim, null);
  945. + }
  946. + }
  947. + else if (event.equalsIgnoreCase("songs_effect"))
  948. + {
  949. + if (scarlet == null || frintezza == null || scarlet.isDead() || scarlet.isInvul() || frintezza.isDead() || frintezza.isInvul() || songEffect == null)
  950. + return super.onTimer(event, npc, player);
  951. +
  952. + if (frintezza.getScriptValue() == 1)
  953. + frintezza.getCast().doCast(songEffect, songEffect.getLevel() < 4 ? getKnownInside() : scarlet, null);
  954. + else
  955. + cancelQuestTimers("songs_effect");
  956. + }
  957. + else if (event.equalsIgnoreCase("end_song")) // Stop effect song
  958. + npc.setScriptValue(3);
  959. + else if (event.equalsIgnoreCase("timeNextSong")) // BreakingArrow - time next song
  960. + npc.setScriptValue(0);
  961. + else if (event.equalsIgnoreCase("action"))
  962. + broadcastPacket(new SocialAction(npc, 1));
  963. + else if (event.equalsIgnoreCase("frintezza_unlock"))
  964. + GrandBossManager.getInstance().setBossStatus(FRINTEZZA, DORMANT);
  965. + else if (event.equalsIgnoreCase("waiting"))
  966. + {
  967. + startQuestTimer("close", npc, null, 2700);
  968. + startQuestTimer("beginning", null, null, 3000);//_LastImperialTomp.broadcastPacket(new Earthquake(174232, -88020, -5116, 45, 27));
  969. + for (Creature cha : lastImperialTomp.getKnownTypeInside(Player.class))
  970. + if (cha instanceof Player)
  971. + cha.broadcastPacket(new Earthquake(cha, 45, 27, false)); //174232, -88020, -5116, 45, 27));
  972. + }
  973. + else if (event.equalsIgnoreCase("room1_spawn"))
  974. + for (int[] loc : ROOM1_SPAWN)
  975. + _mobs.add(addSpawn(loc[0], loc[1], loc[2], loc[3], loc[4], false, 0, false));
  976. + else if (event.equalsIgnoreCase("room1_spawn2"))
  977. + for (int[] loc : ROOM1_CAPTAIN)
  978. + _mobs.add(addSpawn(loc[0], loc[1], loc[2], loc[3], loc[4], false, 0, false));
  979. + else if (event.equalsIgnoreCase("room1_spawn3"))
  980. + for (int[] loc : ROOM1_SUICIDAL_SOLDIER)
  981. + _mobs.add(addSpawn(loc[0], loc[1], loc[2], loc[3], loc[4], false, 0, false));
  982. + else if (event.equalsIgnoreCase("room1_spawn4"))
  983. + for (int[] loc : ROOM1_GUARD)
  984. + _mobs.add(addSpawn(loc[0], loc[1], loc[2], loc[3], loc[4], false, 0, false));
  985. + else if (event.equalsIgnoreCase("room2_spawn"))
  986. + for (int[] loc : ROOM2_SPAWN)
  987. + _mobs.add(addSpawn(loc[0], loc[1], loc[2], loc[3], loc[4], false, 0, false));
  988. + else if (event.equalsIgnoreCase("room2_spawn2"))
  989. + for (int[] loc : ROOM2_SPAWN2)
  990. + _mobs.add(addSpawn(loc[0], loc[1], loc[2], loc[3], loc[4], false, 0, false));
  991. + else if (event.equalsIgnoreCase("mobs_del"))
  992. + {
  993. + for (Npc mob : _mobs)
  994. + if (mob != null)
  995. + mob.deleteMe();
  996. + _mobs.clear();
  997. + }
  998. + else if (event.equalsIgnoreCase("clean"))
  999. + _killMobs = 0;
  1000. + else if (event.equalsIgnoreCase("close"))
  1001. + {
  1002. + for (int i = 25150051; i <= 25150058; i++)
  1003. + openCloseDoor(false, i);
  1004. +
  1005. + for (int i = 25150061; i <= 25150070; i++)
  1006. + openCloseDoor(false, i);
  1007. +
  1008. + openCloseDoor(false, 25150042, 25150043, 25150045, 25150046);
  1009. + }
  1010. + else if (event.equalsIgnoreCase("enter"))
  1011. + {
  1012. + startQuestTimer("clean", null, null, 100);
  1013. + startQuestTimer("close", null, null, 100);
  1014. + startQuestTimer("room1_spawn", null, null, 4000);
  1015. + startQuestTimer("room_final", null, null, 2100000); // 35min
  1016. + }
  1017. + else if (event.equalsIgnoreCase("room_final"))
  1018. + {
  1019. + lastImperialTomp.broadcastPacket(new CreatureSay(npc.getObjectId(), SayType.SHOUT, npc.getName(), "Exceeded his time limit, challenge failed!"));
  1020. + startQuestTimer("remove_players", null, null, 0);
  1021. +
  1022. + cancelQuestTimers("waiting");
  1023. + startQuestTimer("clean", null, null, 1000);
  1024. + startQuestTimer("close", null, null, 1000);
  1025. + startQuestTimer("mobs_del", null, null, 1000);
  1026. +
  1027. + GrandBossManager.getInstance().setBossStatus(Frintezza.FRINTEZZA, Frintezza.DORMANT);
  1028. + }
  1029. + else if (event.equalsIgnoreCase("remove_players"))
  1030. + lastImperialTomp.oustAllPlayers();
  1031. +
  1032. + return super.onTimer(event, npc, player);
  1033. + }
  1034. +
  1035. + private static void playFrintezzaMelody()
  1036. + {
  1037. + // frintezza.getCast().doCast(Frintezza_Melody.getSkill(), frintezza, null); // frintezza.getAI().tryToCast(frintezza, Frintezza_Melody.getSkill());
  1038. + L2Skill skill = new IntIntHolder(5006, 1).getSkill(); // If tryToCast or doCast is used in the last acis, it looks like a speen run, Frintezza's casting stats are wrong?
  1039. + broadcastPacket(new MagicSkillUse(frintezza, frintezza, skill.getId(), skill.getLevel(), skill.getHitTime(), skill.getReuseDelay()));
  1040. + }
  1041. +
  1042. + private void callSongAI()
  1043. + {
  1044. + if (frintezza == null || frintezza.isDead() || frintezza.isInvul() || frintezza.getScriptValue() == 1)
  1045. + return;
  1046. + else if (frintezza.getScriptValue() == 0)
  1047. + {
  1048. + boolean isRequiem = getState() == 3 && scarlet != null && scarlet.getStatus().getHp() < scarlet.getStatus().getMaxHp() * 0.6 && 100 < Rnd.get(80);
  1049. + // new song play
  1050. + int rnd = Rnd.get(100);
  1051. + for (FrintezzaSong song : FRINTEZZA_SONG_LIST)
  1052. + {
  1053. + int songLvl = song.skill.getSkill().getLevel();
  1054. + if (rnd < song.chance || isRequiem && songLvl == 1)
  1055. + {
  1056. + L2Skill dummySkill = song.skill.getSkill();
  1057. + songEffect = song.effectSkill.getSkill();
  1058. + int hitTime = dummySkill.getHitTime();
  1059. + broadcastPacket(new ExShowScreenMessage(1, -1, SMPOS.TOP_CENTER, false, 0, 0, 0, true, 4000, false, song.songName));
  1060. + broadcastPacket(new MagicSkillUse(frintezza, frintezza, dummySkill.getId(), songLvl, hitTime, dummySkill.getReuseDelay()));
  1061. + startQuestTimer("songs_effect", scarlet, null, 10000);
  1062. + startQuestTimer("endSong", frintezza, null, hitTime);
  1063. + startQuestTimer("timeNextSong", frintezza, null, hitTime + Rnd.get(10000, 15000)/*Rnd.get(30000, 120000)*/);
  1064. + frintezza.setScriptValue(1);
  1065. + return;
  1066. + }
  1067. + }
  1068. + }
  1069. + else if (frintezza.getScriptValue() == 2)
  1070. + {
  1071. + frintezza.setScriptValue(3);
  1072. + startQuestTimer("timeNextSong", frintezza, null, Rnd.get(30000, 120000));
  1073. + }
  1074. + }
  1075. +
  1076. + @Override
  1077. + public String onAttack(Npc npc, Creature attacker, int damage, L2Skill skill)
  1078. + {
  1079. + if (GrandBossManager.getInstance().getBossStatus(FRINTEZZA) != FIGHTING || npc.isInvul())
  1080. + return null;
  1081. +
  1082. + if (!FRINTEZZA_LAIR.isInsideZone(attacker))
  1083. + {
  1084. + attacker.teleportTo(150037 + Rnd.get(500), -57720 + Rnd.get(500), -2976, 0);
  1085. + return null;
  1086. + }
  1087. + if (npc.getNpcId() != FRINTEZZA && !FRINTEZZA_LAIR.isInsideZone(npc) || npc.getX() < 171932 || npc.getX() > 176532 || npc.getY() < -90320 || npc.getY() > -85720 || npc.getZ() < -5130)
  1088. + {
  1089. + npc.enableAllSkills();
  1090. + npc.setIsImmobilized(false);
  1091. + npc.teleportTo(174232, -88020, -5116, 0);
  1092. + return null;
  1093. + }
  1094. +
  1095. + switch (npc.getNpcId())
  1096. + {
  1097. + // When Dewdrop of Destruction is used on Portraits they suicide.
  1098. + case 29048:
  1099. + case 29049:
  1100. + if (skill != null && (skill.getId() == DEWDROP_OF_DESTRUCTION_SKILL_ID))
  1101. + if (attacker.getTarget() == npc)
  1102. + npc.doDie(attacker);
  1103. + break;
  1104. + case 29050:
  1105. + case 29051:
  1106. + double hp = npc.getStatus().getHp();
  1107. + double mm = npc.getStatus().getMaxHp() * 0.10;
  1108. + if (hp >= mm && hp - damage > 0 && hp - damage < mm)
  1109. + npc.enableSkill(Bomber_Ghost.getSkill());
  1110. + break;
  1111. + case FRINTEZZA:
  1112. + if (skill != null && skill.getId() == BREAKING_ARROW_SKILL_ID)
  1113. + {
  1114. + npc.setScriptValue(2);
  1115. + npc.abortAll(true);
  1116. + npc.getAI().tryToIdle();
  1117. + getKnownInside().stopSkillEffects(5008);
  1118. + if (scarlet != null)
  1119. + scarlet.stopSkillEffects(5008);
  1120. + broadcastPacket(new MagicSkillCanceled(frintezza.getObjectId()));
  1121. + }
  1122. + npc.getStatus().setHp(npc.getStatus().getMaxHp(), true);
  1123. + break;
  1124. + case SCARLET1:
  1125. + synchronized (this)
  1126. + {
  1127. + taskCameraMorph(getState(), npc);
  1128. + break;
  1129. + }
  1130. + }
  1131. + _lastAttackTime = System.currentTimeMillis();
  1132. + return super.onAttack(npc, attacker, damage, skill);
  1133. + }
  1134. +
  1135. + @Override
  1136. + public String onSpellFinished(Npc npc, Player player, L2Skill skill)
  1137. + {
  1138. + if (skill.isSuicideAttack() && npc.getNpcId() != FRINTEZZA)
  1139. + this.onKill(npc, null);
  1140. + return super.onSpellFinished(npc, player, skill);
  1141. + }
  1142. +
  1143. + @Override
  1144. + public String onKill(Npc npc, Creature killer)
  1145. + {
  1146. + int StatusBoss = GrandBossManager.getInstance().getBossStatus(FRINTEZZA);
  1147. + if (StatusBoss == FIGHTING)
  1148. + {
  1149. + if (npc.getNpcId() == SCARLET2)
  1150. + taskCameraMorph(getState(), npc);
  1151. + if (portraits.containsKey(npc))
  1152. + portraits.remove(npc);
  1153. + if (demons.contains(npc))
  1154. + demons.remove(npc);
  1155. + return null;
  1156. + }
  1157. + else if (StatusBoss == WAITING)
  1158. + {
  1159. + switch(npc.getNpcId())
  1160. + {
  1161. + case 18329:
  1162. + case 18330:
  1163. + case 18331:
  1164. + case 18332:
  1165. + case 18333:
  1166. + if (Rnd.get(100) < 10)
  1167. + killer.getInventory().addItem("Quest", DEWDROP_OF_DESTRUCTION, 1, null, null);
  1168. + break;
  1169. + case ALARM_DEVICE:
  1170. + if (Rnd.get(100) < 33)
  1171. + killer.getInventory().addItem("Quest", DEWDROP_OF_DESTRUCTION, 1, null, null);
  1172. + _killMobs++;
  1173. +
  1174. + if (not_confirmed)
  1175. + if (_killMobs <= 3 && Rnd.get(100) < _killMobs * 5) // 5% chance first alarm, 10% in the second alarm
  1176. + for (int i = 25150051; i <= 25150058; i++)
  1177. + openCloseDoor(true, i);
  1178. + if (_killMobs == 1)
  1179. + startQuestTimer("room1_spawn2", npc, null, 200);
  1180. + if (_killMobs == 2)
  1181. + startQuestTimer("room1_spawn3", npc, null, 200);
  1182. + if (_killMobs == 3)
  1183. + startQuestTimer("room1_spawn4", npc, null, 200);
  1184. + if (_killMobs == 4)
  1185. + {
  1186. + for (int i = 25150051; i <= 25150058; i++)
  1187. + openCloseDoor(true, i);
  1188. + startQuestTimer("mobs_del", npc, null, 100);
  1189. + startQuestTimer("room2_spawn", npc, null, 200);
  1190. +
  1191. + openCloseDoor(true, 25150042, 25150043); //, 25150045, 25150046
  1192. + }
  1193. + break;
  1194. + case 18339:
  1195. + if (_killMobs <= 6)
  1196. + _killMobs++;
  1197. + if (_killMobs == 6)
  1198. + {
  1199. + openCloseDoor(false, 25150042, 25150043, 25150045, 25150046);
  1200. + for (int i = 25150061; i <= 25150070; i++)
  1201. + openCloseDoor(true, i);
  1202. +
  1203. + startQuestTimer("room2_spawn2", npc, null, 1000);
  1204. + }
  1205. + break;
  1206. + case 18334:
  1207. + if (Rnd.get(100) < 33)
  1208. + killer.getInventory().addItem("Quest", BREAKING_ARROW, 1, null, null); // Breaking Arrow
  1209. + if (_killMobs <= 14)
  1210. + _killMobs++;
  1211. + if (_killMobs == 14)
  1212. + {
  1213. + startQuestTimer("mobs_del", npc, null, 100);
  1214. +
  1215. + openCloseDoor(true, 25150045, 25150046);
  1216. + startQuestTimer("waiting", npc, null, Config.WAIT_TIME_FRINTEZZA * 3);
  1217. + cancelQuestTimers("room_final");
  1218. + startQuestTimer("clean", npc, null, 1000);
  1219. + }
  1220. + break;
  1221. + }
  1222. + return null;
  1223. + }
  1224. + return super.onKill(npc, killer);
  1225. + }
  1226. +
  1227. + private static void openCloseDoor(boolean open, int... doorIds)
  1228. + {
  1229. + for (int doorId : doorIds)
  1230. + if (open)
  1231. + DoorData.getInstance().getDoor(doorId).openMe();
  1232. + else
  1233. + DoorData.getInstance().getDoor(doorId).closeMe();
  1234. + }
  1235. +
  1236. + private static L2Skill getRandomSkill() //TODO: getRandomSkill()
  1237. + {
  1238. + int[][] FIRST_SCARLET_SKILLS =
  1239. + {
  1240. + { 5014, 1, 100}, // Frintezza's Daemon Attack 1
  1241. + { 5015, 1, 5 }, // Frintezza's Daemon Charge 1
  1242. + { 5015, 4, 5 }, // Frintezza's Daemon Charge 4
  1243. + };
  1244. + int[][] SECOND_SCARLET_SKILLS =
  1245. + {
  1246. + { 5014, 2, 100}, // Frintezza's Daemon Attack
  1247. + { 5015, 2, 5 }, // Frintezza's Daemon Charge 2
  1248. + { 5015, 5, 5 }, // Frintezza's Daemon Charge 5
  1249. + { 5018, 1, 10 }, // Frintezza's Daemon Field 1
  1250. + { 5016, 1, 10 }, // Yoke of Scarlet
  1251. + };
  1252. + int[][] THIRD_SCARLET_SKILLS =
  1253. + {
  1254. + { 5014, 3, 100}, // Frintezza's Daemon Attack
  1255. + { 5015, 3, 5 }, // Frintezza's Daemon Charge 3
  1256. + { 5015, 6, 5 }, // Frintezza's Daemon Charge 6
  1257. + { 5018, 2, 10 }, // Frintezza's Daemon Field 2
  1258. + { 5019, 1, 10 }, // Frintezza's Daemon Drain
  1259. + { 5016, 1, 10 }, // Yoke of Scarlet
  1260. + };
  1261. + int skillLvl = getState();
  1262. + if (skillLvl == 1)
  1263. + scarletSkills = FIRST_SCARLET_SKILLS;
  1264. + else if (skillLvl == 2)
  1265. + scarletSkills = SECOND_SCARLET_SKILLS;
  1266. + else if (skillLvl == 3)
  1267. + scarletSkills = THIRD_SCARLET_SKILLS;
  1268. +
  1269. + int rnd = Rnd.get(100);
  1270. + for (int i = scarletSkills.length; --i >= 0;)
  1271. + {
  1272. + int[] sk = scarletSkills[i];
  1273. + int chance = sk[2];
  1274. + if ((rnd -= chance) <= 0)
  1275. + return new IntIntHolder(sk[0], sk[1]).getSkill();
  1276. + }
  1277. + return null;
  1278. + }
  1279. +
  1280. + private static int calcCameraAngle(Creature npc)
  1281. + {
  1282. + final int heading = npc.getHeading();
  1283. + return Math.abs((heading < 32768 ? 180 : 540) - (int)(heading / 182.044444444));
  1284. + }
  1285. +
  1286. + private static void throwUp(Creature attacker, final double range, SystemMessage msg)
  1287. + {
  1288. + final int mx = attacker.getX(), my = attacker.getY();
  1289. + for (Creature target : FRINTEZZA_LAIR.getKnownTypeInside(Creature.class))//.getCharactersInside())
  1290. + {
  1291. + if (target == attacker)
  1292. + continue;
  1293. + if (target instanceof Npc && ((Npc) target).getNpcId() >= 29045 && ((Npc) target).getNpcId() <= 29053)
  1294. + continue;
  1295. + double dx = target.getX() - mx;
  1296. + double dy = target.getY() - my;
  1297. + if (dx == 0 && dy == 0)
  1298. + dx = dy = range / 2;
  1299. + double aa = range / Math.sqrt(dx * dx + dy * dy);
  1300. + if (aa > 1.0)
  1301. + {
  1302. + int x = mx + (int) (dx * aa);
  1303. + int y = my + (int) (dy * aa);
  1304. + int z = target.getZ();
  1305. +
  1306. + target.abortAll(true); //cha.abortAttack(); //cha.abortCast();
  1307. + target.getAI().tryToIdle(); //target.getAI().setIntention(CtrlIntention.IDLE);
  1308. +
  1309. + target.broadcastPacket(new FlyToLocation(target, x, y, z, FlyType.THROW_UP));
  1310. + target.setXYZ(x, y, z);
  1311. + target.getPosition().setHeading(MathUtil.calculateHeadingFrom(x, y, mx, my));
  1312. + target.broadcastPacket(new ValidateLocation(target));
  1313. + if (msg != null)
  1314. + target.sendPacket(msg);
  1315. + if (target instanceof Player)
  1316. + ((Player) target).standUp();
  1317. + }
  1318. + }
  1319. + }
  1320. +
  1321. + private static class FrintezzaSong
  1322. + {
  1323. + public IntIntHolder skill;
  1324. + public IntIntHolder effectSkill;
  1325. + public String songName;
  1326. + public int chance;
  1327. +
  1328. + public FrintezzaSong(IntIntHolder sk, IntIntHolder esk, String sn, int ch)
  1329. + {
  1330. + skill = sk;
  1331. + effectSkill = esk;
  1332. + songName = sn;
  1333. + chance = ch;
  1334. + }
  1335. + }
  1336. +
  1337. + private final FrintezzaSong[] FRINTEZZA_SONG_LIST =
  1338. + {
  1339. + new FrintezzaSong(new IntIntHolder(5007, 1), new IntIntHolder(5008, 1), "Requiem of Hatred", 5),
  1340. + new FrintezzaSong(new IntIntHolder(5007, 2), new IntIntHolder(5008, 2), "Rondo of Solitude", 50),
  1341. + new FrintezzaSong(new IntIntHolder(5007, 3), new IntIntHolder(5008, 3), "Frenetic Toccata", 70),
  1342. + new FrintezzaSong(new IntIntHolder(5007, 4), new IntIntHolder(5008, 4), "Fugue of Jubilation", 90),
  1343. + new FrintezzaSong(new IntIntHolder(5007, 5), new IntIntHolder(5008, 5), "Hypnotic Mazurka", 100),
  1344. + };
  1345. +
  1346. + private static void broadcastPacket(L2GameServerPacket... packets)
  1347. + {
  1348. + for (L2GameServerPacket packet : packets)
  1349. + FRINTEZZA_LAIR.broadcastPacket(packet);
  1350. + }
  1351. +
  1352. + private void daemonMorph(Npc npc, int stage)
  1353. + {
  1354. + npc.setCollisionHeight(stage == 1 ? 110 : 130);
  1355. + broadcastPacket(new SocialAction(npc, stage == 1 ? 4 : 2));
  1356. + final IntIntHolder Daemon_Morph = new IntIntHolder(5017, 1);
  1357. + npc.getCast().doCast(Daemon_Morph.getSkill(), npc, null);
  1358. + broadcastPacket(new NpcInfo(npc, null));
  1359. + roomTasks();
  1360. + }
  1361. +
  1362. + private void setPrepareRoom(boolean move)
  1363. + {
  1364. + for (Creature cha : FRINTEZZA_LAIR.getKnownTypeInside(Creature.class))
  1365. + {
  1366. + if (cha != null)
  1367. + {
  1368. + if (frintezza != cha || frintezza == null)
  1369. + cha.setInvul(move);
  1370. + if (move)
  1371. + {
  1372. + cha.getAI().tryToIdle();
  1373. + cha.abortAll(true);
  1374. + if (frintezza != null)
  1375. + {
  1376. + if (move)
  1377. + cha.setInvul(true);
  1378. + dropTimers();
  1379. + frintezza.setScriptValue(1);
  1380. + broadcastPacket(new MagicSkillCanceled(frintezza.getObjectId()));
  1381. + }
  1382. + }
  1383. + if (!(cha instanceof GrandBoss))
  1384. + {
  1385. + if (move)
  1386. + {
  1387. + cha.disableAllSkills();
  1388. + if (cha instanceof Monster)
  1389. + cha.forceRunStance();//cha.setRunning(true);
  1390. + }
  1391. + else
  1392. + cha.enableAllSkills();
  1393. + cha.setIsImmobilized(move);
  1394. + cha.setIsParalyzed(move);
  1395. + }
  1396. + }
  1397. + }
  1398. + }
  1399. +
  1400. + private void roomTasks()
  1401. + {
  1402. + _lastAttackTime = System.currentTimeMillis();
  1403. + startQuestTimerAtFixedRate("songs_play", frintezza, null, 5000);
  1404. + startQuestTimerAtFixedRate("skill_task", scarlet, null, 2500);
  1405. + startQuestTimerAtFixedRate("spawn_minion", null, null, 20000);
  1406. + startQuestTimer("despawn", scarlet, null, 60000);
  1407. + frintezza.setScriptValue(0);
  1408. + }
  1409. +
  1410. + private static void deleteNpc(Npc... npcs)
  1411. + {
  1412. + for (Npc npc : npcs)
  1413. + {
  1414. + if (npc != null)
  1415. + npc.deleteMe();
  1416. + npc = null;
  1417. + }
  1418. + }
  1419. +
  1420. + private void clean(int status)
  1421. + {
  1422. + if (!demons.isEmpty())
  1423. + for (Npc mobs : demons)
  1424. + deleteNpc(mobs);
  1425. + if (!portraits.isEmpty())
  1426. + for (Monster portrait : portraits.keySet())
  1427. + deleteNpc(portrait);
  1428. + deleteNpc(scarlet, frintezza);
  1429. + demons.clear();
  1430. + portraits.clear();
  1431. + GrandBossManager.getInstance().setBossStatus(FRINTEZZA, status);
  1432. +
  1433. + _lastAttackTime = 0;
  1434. + songEffect = null;
  1435. + }
  1436. +
  1437. + private static int getState()
  1438. + {
  1439. + final IntIntHolder Daemon_Morph = new IntIntHolder(5017, 1);
  1440. + if (scarlet != null)
  1441. + {
  1442. + if (scarlet.getNpcId() == SCARLET2)
  1443. + return 3;
  1444. + AbstractEffect[] effects = scarlet.getAllEffects();
  1445. + if (effects.length != 0)
  1446. + for (AbstractEffect e : effects)
  1447. + if (e.getSkill() == Daemon_Morph.getSkill())
  1448. + return 2;
  1449. + return 1;
  1450. + }
  1451. + return 0;
  1452. + }
  1453. +
  1454. + private void dropTimers()
  1455. + {
  1456. + cancelQuestTimers("despawn");
  1457. + cancelQuestTimers("spawn_minion");
  1458. + cancelQuestTimers("skill_task");
  1459. + cancelQuestTimers("songs_play");
  1460. + cancelQuestTimers("songs_effect");
  1461. + cancelQuestTimers("end_song");
  1462. + cancelQuestTimers("timeNextSong");
  1463. + }
  1464. +
  1465. + private void taskCameraMorph(int state, Npc npc)
  1466. + {
  1467. + if (frintezza.isInvul())
  1468. + return;
  1469. + final double hpRatio = npc.getStatus().getHp() / npc.getStatus().getMaxHp();
  1470. + if (state == 1 && hpRatio < 0.75)
  1471. + {
  1472. + setPrepareRoom(true);
  1473. + startQuestTimer("first_morph_01", npc, null, 1100);
  1474. + startQuestTimer("first_morph_02", npc, null, 4100);
  1475. + startQuestTimer("first_morph_03", npc, null, 8100);
  1476. + startQuestTimer("start_room", npc, null, 11100);
  1477. + startQuestTimer("end_camera", frintezza, null, 14100);
  1478. + }
  1479. + else if (state == 2 && hpRatio < 0.5)
  1480. + {
  1481. + setPrepareRoom(true);
  1482. + startQuestTimer("second_morph_01", npc, null, 2000);
  1483. + startQuestTimer("second_morph_02", npc, null, 2100);
  1484. + startQuestTimer("second_morph_03", frintezza, null, 6300);
  1485. + startQuestTimer("second_morph_04", frintezza, null, 9300);
  1486. + startQuestTimer("second_morph_05", npc, null, 12300);
  1487. + startQuestTimer("second_morph_06", npc, null, 12800);
  1488. + startQuestTimer("second_morph_07", npc, null, 19050);
  1489. + startQuestTimer("second_morph_08", npc, null, 20000);
  1490. + startQuestTimer("second_morph_09", npc, null, 28100);
  1491. + startQuestTimer("start_room", npc, null, 34100);
  1492. + startQuestTimer("end_camera", frintezza, null, 37100);
  1493. + }
  1494. + if (state == 3 && npc.getNpcId() == SCARLET2)
  1495. + {
  1496. + setPrepareRoom(true);
  1497. + broadcastPacket(new SpecialCamera(npc.getObjectId(), 300, calcCameraAngle(npc) - 180, 5, 0, 7000, 0, 0, 1, 0), new SpecialCamera(npc.getObjectId(), 200, calcCameraAngle(npc), 85, 4000, 10000, 0, 0, 1, 0));
  1498. + startQuestTimer("die_01", frintezza, null, 7400);
  1499. + startQuestTimer("die_02", frintezza, null, 7500);
  1500. + startQuestTimer("die_03", frintezza, null, 14500);
  1501. + startQuestTimer("die_04", frintezza, null, 22500);
  1502. + startQuestTimer("start_room", frintezza, null, 21500);
  1503. + }
  1504. + }
  1505. +
  1506. + private static Creature getKnownInside()
  1507. + {
  1508. + for (Creature ch : FRINTEZZA_LAIR.getKnownTypeInside(Creature.class))
  1509. + if (ch instanceof Player)
  1510. + return ch;
  1511. + return null;
  1512. + }
  1513. +}
  1514. \ No newline at end of file
  1515. diff --git aCis_game/java/net/sf/l2j/gameserver/scripting/script/teleport/GrandBossTeleporter.java aCis_game/java/net/sf/l2j/gameserver/scripting/script/teleport/GrandBossTeleporter.java
  1516. index cee8e32..c6de41b 100644
  1517. --- aCis_game/java/net/sf/l2j/gameserver/scripting/script/teleport/GrandBossTeleporter.java
  1518. +++ aCis_game/java/net/sf/l2j/gameserver/scripting/script/teleport/GrandBossTeleporter.java
  1519. @@ -12,11 +12,14 @@
  1520. import net.sf.l2j.gameserver.data.xml.ScriptData;
  1521. import net.sf.l2j.gameserver.model.actor.Npc;
  1522. import net.sf.l2j.gameserver.model.actor.Player;
  1523. +import net.sf.l2j.gameserver.model.group.CommandChannel;
  1524. +import net.sf.l2j.gameserver.model.group.Party;
  1525. import net.sf.l2j.gameserver.model.location.Location;
  1526. import net.sf.l2j.gameserver.model.zone.type.BossZone;
  1527. import net.sf.l2j.gameserver.scripting.Quest;
  1528. import net.sf.l2j.gameserver.scripting.script.ai.boss.Antharas;
  1529. import net.sf.l2j.gameserver.scripting.script.ai.boss.Baium;
  1530. +import net.sf.l2j.gameserver.scripting.script.ai.boss.Frintezza;
  1531. import net.sf.l2j.gameserver.scripting.script.ai.boss.Sailren;
  1532. import net.sf.l2j.gameserver.scripting.script.ai.boss.Valakas;
  1533.  
  1534. @@ -47,6 +50,18 @@
  1535. new Location(115488, 22096, -5168)
  1536. };
  1537.  
  1538. + private static final Location[] FRINTEZZA_IN =
  1539. + {
  1540. + new Location(174102, -76039, -5105),
  1541. + new Location(173235, -76884, -5105),
  1542. + new Location(175003, -76933, -5105),
  1543. + new Location(174196, -76190, -5105),
  1544. + new Location(174013, -76120, -5105),
  1545. + new Location(173263, -75161, -5105)
  1546. + };
  1547. +
  1548. + private static final Location FRINTEZZA_OUT = new Location(150037, -57720, -2976);
  1549. +
  1550. private static final Location SAILREN_IN = new Location(27333, -6835, -1970);
  1551. private static final Location[] SAILREN_OUT =
  1552. {
  1553. @@ -62,7 +77,7 @@
  1554. super(-1, "teleport");
  1555.  
  1556. addFirstTalkId(29055, 31862);
  1557. - addTalkId(13001, 29055, 31859, 31384, 31385, 31540, 31686, 31687, 31759, 31862, 32107, 32109);
  1558. + addTalkId(13001, 29055, 31859, 31384, 31385, 31540, 31686, 31687, 31759, 31862, 32107, 32109, 32011, 29061);
  1559. }
  1560.  
  1561. @Override
  1562. @@ -169,6 +184,10 @@
  1563. htmltext = "13001-03.htm";
  1564. }
  1565. break;
  1566. +
  1567. + case 29061:
  1568. + player.teleportTo(FRINTEZZA_OUT.getX() + Rnd.get(500), FRINTEZZA_OUT.getY() + Rnd.get(500), FRINTEZZA_OUT.getZ(), 0);
  1569. + break;
  1570.  
  1571. case 31859:
  1572. player.teleportTo(79800 + Rnd.get(600), 151200 + Rnd.get(1100), -3534, 0);
  1573. @@ -232,7 +251,88 @@
  1574. case 31759:
  1575. player.teleportTo(150037, -57720, -2976, 250);
  1576. break;
  1577. -
  1578. +
  1579. + case 32011:
  1580. + status = GrandBossManager.getInstance().getBossStatus(Frintezza.FRINTEZZA);
  1581. + if (status == Frintezza.DORMANT)
  1582. + {
  1583. + final BossZone tomb = ZoneManager.getInstance().getZoneById(110012, BossZone.class);
  1584. + if (player.isGM())
  1585. + {
  1586. + ScriptData.getInstance().getQuest("Frintezza").startQuestTimer("enter", null, player, 1000);
  1587. + GrandBossManager.getInstance().setBossStatus(Frintezza.FRINTEZZA, Frintezza.WAITING);
  1588. + byte locCycle = 0;
  1589. + final List<Player> party = player.getParty().getMembers();
  1590. + if (player.getParty() != null)
  1591. + {
  1592. + for (Player member : party)
  1593. + {
  1594. + if (tomb != null)
  1595. + {
  1596. + tomb.allowPlayerEntry(member, 30);
  1597. + member.teleportTo(FRINTEZZA_IN[locCycle], 100);
  1598. + }
  1599. + locCycle++;
  1600. + if (locCycle >= 6)
  1601. + locCycle = 1;
  1602. + }
  1603. + }
  1604. + else
  1605. + player.teleportTo(FRINTEZZA_IN[locCycle], 100);
  1606. + break;
  1607. + }
  1608. + if ((!player.isInParty() || !player.getParty().isLeader(player)) || (player.getParty().getCommandChannel() == null) || (player.getParty().getCommandChannel().getLeader() != player))
  1609. + htmltext = "32011-03.htm";
  1610. + else if (player.getParty().getCommandChannel().getParties().size() < 2 || player.getParty().getCommandChannel().getParties().size() > 5)
  1611. + htmltext = "32011-04.htm";
  1612. + else
  1613. + {
  1614. + if (!player.destroyItemByItemId("Quest", 8073, 1, player, true))
  1615. + return "32011-05.htm";
  1616. +
  1617. + byte locCycle = 0;
  1618. + ScriptData.getInstance().getQuest("Frintezza").startQuestTimer("enter", null, player, 1000);
  1619. + GrandBossManager.getInstance().setBossStatus(Frintezza.FRINTEZZA, Frintezza.WAITING);
  1620. +
  1621. + if (player.getParty() != null)
  1622. + {
  1623. + CommandChannel CommandChannel = player.getParty().getCommandChannel();
  1624. + if (CommandChannel != null)
  1625. + for (Party party : CommandChannel.getParties())
  1626. + {
  1627. + if (party == null)
  1628. + continue;
  1629. + for (Player member : party.getMembers())
  1630. + {
  1631. + if (member == null || member.getStatus().getLevel() < 74 || !MathUtil.checkIfInRange(700, npc, member, true))
  1632. + continue;
  1633. + if (CommandChannel.getMembersCount() > 45)
  1634. + {
  1635. + member.sendMessage("The number of challenges have been full, so can not enter.");
  1636. + break;
  1637. + }
  1638. +
  1639. + if (tomb != null)
  1640. + {
  1641. + tomb.allowPlayerEntry(member, 30);
  1642. + member.teleportTo(FRINTEZZA_IN[locCycle], 100);
  1643. + }
  1644. + member.destroyItemByItemId(getName(), 8556, member.getInventory().getItemCount(8556, -1), null, true);
  1645. + member.destroyItemByItemId(getName(), 8192, member.getInventory().getItemCount(8192, -1), null, true);
  1646. + }
  1647. + locCycle++;
  1648. + if (locCycle >= 6)
  1649. + locCycle = 1;
  1650. + }
  1651. + }
  1652. + }
  1653. + }
  1654. + if (status == Frintezza.DEAD)
  1655. + htmltext = "32011-01.htm";
  1656. + else
  1657. + htmltext = "32011-02.htm";
  1658. + break;
  1659. +
  1660. case 32107:
  1661. player.teleportTo(Rnd.get(SAILREN_OUT), 100);
  1662. break;
  1663. diff --git aCis_game/java/net/sf/l2j/gameserver/skills/effects/EffectDanceStun.java aCis_game/java/net/sf/l2j/gameserver/skills/effects/EffectDanceStun.java
  1664. new file mode 100644
  1665. index 0000000..8a6a80a
  1666. --- /dev/null
  1667. +++ aCis_game/java/net/sf/l2j/gameserver/skills/effects/EffectDanceStun.java
  1668. @@ -0,0 +1,74 @@
  1669. +/*
  1670. + * This program is free software: you can redistribute it and/or modify it under
  1671. + * the terms of the GNU General Public License as published by the Free Software
  1672. + * Foundation, either version 3 of the License, or (at your option) any later
  1673. + * version.
  1674. + *
  1675. + * This program is distributed in the hope that it will be useful, but WITHOUT
  1676. + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  1677. + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  1678. + * details.
  1679. + *
  1680. + * You should have received a copy of the GNU General Public License along with
  1681. + * this program. If not, see <http://www.gnu.org/licenses/>.
  1682. + */
  1683. +package net.sf.l2j.gameserver.skills.effects;
  1684. +
  1685. +import net.sf.l2j.gameserver.enums.skills.AbnormalEffect;
  1686. +import net.sf.l2j.gameserver.enums.skills.EffectType;
  1687. +import net.sf.l2j.gameserver.model.actor.Creature;
  1688. +import net.sf.l2j.gameserver.skills.AbstractEffect;
  1689. +import net.sf.l2j.gameserver.skills.L2Skill;
  1690. +
  1691. +/**
  1692. + * Copy from http://www.l2jserver.com/forum/viewtopic.php?f=69&t=13999
  1693. + * @author KKnD
  1694. + */
  1695. +public class EffectDanceStun extends AbstractEffect
  1696. +{
  1697. + public EffectDanceStun(EffectTemplate template, L2Skill skill, Creature effected, Creature effector)
  1698. + {
  1699. + super(template, skill, effected, effector);
  1700. + }
  1701. +
  1702. + @Override
  1703. + public EffectType getEffectType()
  1704. + {
  1705. + return EffectType.STUN;
  1706. + }
  1707. +
  1708. + /** Notify started */
  1709. + @Override
  1710. + public boolean onStart()
  1711. + {
  1712. + if (getEffected().isStunned() || getEffected().isImmobilized())
  1713. + return false;
  1714. + int e = getEffected().getAbnormalEffect();
  1715. + if ((e & AbnormalEffect.FLOATING_ROOT.getMask()) != 0 || (e & AbnormalEffect.DANCE_STUNNED.getMask()) != 0)
  1716. + return false;
  1717. +
  1718. + // Abort attack, cast and move.
  1719. + getEffected().abortAll(false);
  1720. +
  1721. + getEffected().startAbnormalEffect(AbnormalEffect.DANCE_STUNNED);
  1722. + getEffected().setIsImmobilized(true);
  1723. + getEffected().disableAllSkills();
  1724. + return true;
  1725. + }
  1726. +
  1727. + /** Notify exited */
  1728. + @Override
  1729. + public void onExit()
  1730. + {
  1731. + getEffected().stopAbnormalEffect(AbnormalEffect.DANCE_STUNNED);
  1732. + getEffected().setIsImmobilized(false);
  1733. + getEffected().enableAllSkills();
  1734. + }
  1735. +
  1736. + @Override
  1737. + public boolean onActionTime()
  1738. + {
  1739. + // just stop this effect
  1740. + return false;
  1741. + }
  1742. +}
  1743. \ No newline at end of file
  1744. diff --git aCis_game/java/net/sf/l2j/gameserver/skills/effects/EffectFloatStun.java aCis_game/java/net/sf/l2j/gameserver/skills/effects/EffectFloatStun.java
  1745. new file mode 100644
  1746. index 0000000..221b06e
  1747. --- /dev/null
  1748. +++ aCis_game/java/net/sf/l2j/gameserver/skills/effects/EffectFloatStun.java
  1749. @@ -0,0 +1,59 @@
  1750. +package net.sf.l2j.gameserver.skills.effects;
  1751. +
  1752. +import net.sf.l2j.gameserver.enums.skills.AbnormalEffect;
  1753. +import net.sf.l2j.gameserver.enums.skills.EffectType;
  1754. +import net.sf.l2j.gameserver.model.actor.Creature;
  1755. +import net.sf.l2j.gameserver.skills.AbstractEffect;
  1756. +import net.sf.l2j.gameserver.skills.L2Skill;
  1757. +
  1758. +/**
  1759. + * Copy from EffectDanceStun.java
  1760. + */
  1761. +public class EffectFloatStun extends AbstractEffect
  1762. +{
  1763. + public EffectFloatStun(EffectTemplate template, L2Skill skill, Creature effected, Creature effector)
  1764. + {
  1765. + super(template, skill, effected, effector);
  1766. + }
  1767. +
  1768. + @Override
  1769. + public EffectType getEffectType()
  1770. + {
  1771. + return EffectType.STUN;
  1772. + }
  1773. +
  1774. + @Override
  1775. + public boolean onStart()
  1776. + {
  1777. + if (getEffected().isStunned() || getEffected().isImmobilized())
  1778. + return false;
  1779. + int e = getEffected().getAbnormalEffect();
  1780. + if ((e & AbnormalEffect.FLOATING_ROOT.getMask()) != 0 || (e & AbnormalEffect.DANCE_STUNNED.getMask()) != 0)
  1781. + return false;
  1782. +
  1783. + // Abort attack, cast and move.
  1784. + getEffected().abortAll(false);
  1785. +
  1786. + getEffected().getAI().tryToIdle();
  1787. +
  1788. + getEffected().startAbnormalEffect(AbnormalEffect.FLOATING_ROOT);
  1789. + getEffected().setIsImmobilized(true);
  1790. + getEffected().disableAllSkills();
  1791. + return true;
  1792. + }
  1793. +
  1794. + @Override
  1795. + public void onExit()
  1796. + {
  1797. + getEffected().stopAbnormalEffect(AbnormalEffect.FLOATING_ROOT);
  1798. + getEffected().setIsImmobilized(false);
  1799. + getEffected().enableAllSkills();
  1800. + }
  1801. +
  1802. + @Override
  1803. + public boolean onActionTime()
  1804. + {
  1805. + // just stop this effect
  1806. + return false;
  1807. + }
  1808. +}
  1809. \ No newline at end of file
  1810.  
Add Comment
Please, Sign In to add comment