From cec597509a617c6f5ec03cea800bad7f1f03bca2 Mon Sep 17 00:00:00 2001
From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com>
Date: Sun, 19 Apr 2020 11:08:17 +0000
Subject: [PATCH] Addition of Etis Van Etina. Source: Liamxroy
---
.../dist/game/config/GrandBoss.ini | 20 +
.../KeucereusAllianceBase/Erda/34319-1.html | 4 +
.../KeucereusAllianceBase/Erda/34319-2.html | 4 +
.../KeucereusAllianceBase/Erda/34319-3.html | 4 +
.../KeucereusAllianceBase/Erda/34319-4.html | 3 +
.../KeucereusAllianceBase/Erda/34319-5.html | 3 +
.../KeucereusAllianceBase/Erda/34319.html | 7 +
.../KeucereusAllianceBase/Erda/Erda.java | 129 +++
.../bosses/EtisVanEtina/ChoirOfDarkness.java | 177 ++++
.../scripts/ai/bosses/EtisVanEtina/Etina.java | 188 +++++
.../ai/bosses/EtisVanEtina/EtisVanEtina.java | 785 ++++++++++++++++++
.../EtisVanEtina/GreatTempleDarkJudge.java | 177 ++++
.../EtisVanEtina/GreatTempleSoulGuide.java | 177 ++++
.../ai/bosses/EtisVanEtina/JudgeOfHeresy.java | 177 ++++
.../scripts/ai/bosses/EtisVanEtina/Kain.java | 187 +++++
.../bosses/EtisVanEtina/LiberatorOfLust.java | 177 ++++
.../bosses/EtisVanEtina/SeekerOfDespair.java | 177 ++++
.../ai/bosses/EtisVanEtina/SoulDestroyer.java | 177 ++++
.../ai/bosses/EtisVanEtina/TempleArchon.java | 177 ++++
.../bosses/EtisVanEtina/TempleDarkWizard.java | 177 ++++
.../EtisVanEtina/TempleFlameMaster.java | 177 ++++
.../bosses/EtisVanEtina/TempleHighPriest.java | 177 ++++
.../spawns/Gracia/KeucereusAllianceBase.xml | 1 +
.../java/org/l2jmobius/Config.java | 12 +
.../dist/game/config/GrandBoss.ini | 19 +
.../KeucereusAllianceBase/Erda/34319-1.html | 4 +
.../KeucereusAllianceBase/Erda/34319-2.html | 4 +
.../KeucereusAllianceBase/Erda/34319-3.html | 4 +
.../KeucereusAllianceBase/Erda/34319-4.html | 3 +
.../KeucereusAllianceBase/Erda/34319-5.html | 3 +
.../KeucereusAllianceBase/Erda/34319.html | 7 +
.../KeucereusAllianceBase/Erda/Erda.java | 129 +++
.../bosses/EtisVanEtina/ChoirOfDarkness.java | 177 ++++
.../scripts/ai/bosses/EtisVanEtina/Etina.java | 188 +++++
.../ai/bosses/EtisVanEtina/EtisVanEtina.java | 785 ++++++++++++++++++
.../EtisVanEtina/GreatTempleDarkJudge.java | 177 ++++
.../EtisVanEtina/GreatTempleSoulGuide.java | 177 ++++
.../ai/bosses/EtisVanEtina/JudgeOfHeresy.java | 177 ++++
.../scripts/ai/bosses/EtisVanEtina/Kain.java | 187 +++++
.../bosses/EtisVanEtina/LiberatorOfLust.java | 177 ++++
.../bosses/EtisVanEtina/SeekerOfDespair.java | 177 ++++
.../ai/bosses/EtisVanEtina/SoulDestroyer.java | 177 ++++
.../ai/bosses/EtisVanEtina/TempleArchon.java | 177 ++++
.../bosses/EtisVanEtina/TempleDarkWizard.java | 177 ++++
.../EtisVanEtina/TempleFlameMaster.java | 177 ++++
.../bosses/EtisVanEtina/TempleHighPriest.java | 177 ++++
.../spawns/Gracia/KeucereusAllianceBase.xml | 1 +
.../java/org/l2jmobius/Config.java | 12 +
.../dist/game/config/GrandBoss.ini | 19 +
.../KeucereusAllianceBase/Erda/34319-1.html | 4 +
.../KeucereusAllianceBase/Erda/34319-2.html | 4 +
.../KeucereusAllianceBase/Erda/34319-3.html | 4 +
.../KeucereusAllianceBase/Erda/34319-4.html | 3 +
.../KeucereusAllianceBase/Erda/34319-5.html | 3 +
.../KeucereusAllianceBase/Erda/34319.html | 7 +
.../KeucereusAllianceBase/Erda/Erda.java | 129 +++
.../bosses/EtisVanEtina/ChoirOfDarkness.java | 177 ++++
.../scripts/ai/bosses/EtisVanEtina/Etina.java | 188 +++++
.../ai/bosses/EtisVanEtina/EtisVanEtina.java | 785 ++++++++++++++++++
.../EtisVanEtina/GreatTempleDarkJudge.java | 177 ++++
.../EtisVanEtina/GreatTempleSoulGuide.java | 177 ++++
.../ai/bosses/EtisVanEtina/JudgeOfHeresy.java | 177 ++++
.../scripts/ai/bosses/EtisVanEtina/Kain.java | 187 +++++
.../bosses/EtisVanEtina/LiberatorOfLust.java | 177 ++++
.../bosses/EtisVanEtina/SeekerOfDespair.java | 177 ++++
.../ai/bosses/EtisVanEtina/SoulDestroyer.java | 177 ++++
.../ai/bosses/EtisVanEtina/TempleArchon.java | 177 ++++
.../bosses/EtisVanEtina/TempleDarkWizard.java | 177 ++++
.../EtisVanEtina/TempleFlameMaster.java | 177 ++++
.../bosses/EtisVanEtina/TempleHighPriest.java | 177 ++++
.../spawns/Gracia/KeucereusAllianceBase.xml | 1 +
.../java/org/l2jmobius/Config.java | 12 +
72 files changed, 9880 insertions(+)
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
create mode 100644 L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/config/GrandBoss.ini b/L2J_Mobius_5.5_EtinasFate/dist/game/config/GrandBoss.ini
index 6b8366025d..2edbdf9e57 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/config/GrandBoss.ini
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/config/GrandBoss.ini
@@ -203,3 +203,23 @@ HeliosMinPlayers = 70
# Minimum players Level for enter to Helios. Retail: 102
HeliosMinPlayerLvl = 99
+
+# ---------------------------------------------------------------------------
+# Etis Van Etina
+# ---------------------------------------------------------------------------
+
+# Interval time of Etis Van Etina. Value is hour. Range 1-480. Retail: 264
+IntervalOfEtinaSpawn = 72
+
+# Random interval. Range 1-192. Retail: 72
+RandomOfEtinaSpawn = 1
+
+# Minimal count of players for enter to Etis Van Etina. Retail: 49
+EtinaMinPlayers = 2
+
+# Maximum count of players for enter to Etis Van Etina. Retail: 112
+EtinaMaxPlayers = 112
+
+# Minimum players Level for enter to Etis Van Etina. Retail: 99
+EtinaMinPlayerLvl = 103
+
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
new file mode 100644
index 0000000000..7024487136
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
@@ -0,0 +1,4 @@
+
Erda:
+On the Etis van Etina there is an attack!
+At this time it's impossible to enter the temple.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
new file mode 100644
index 0000000000..f8fff8d713
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
@@ -0,0 +1,4 @@
+Erda:
+Etis van Etina? You're too late, friend.
+A group of warriors drove him off not long ago.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
new file mode 100644
index 0000000000..4926daed35
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
@@ -0,0 +1,4 @@
+Erda:
+You are overcome by a voice, a voice so powerful you are helpless as it speaks:
+(The players who belong to an association can only enter through the Association Leader.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
new file mode 100644
index 0000000000..3c8b9fc2ac
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
@@ -0,0 +1,3 @@
+Erda:
+(A command channel needs at least minimum: %min% and maximum: %max% members to challenge Etis van Etina.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
new file mode 100644
index 0000000000..3f33bfb866
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
@@ -0,0 +1,3 @@
+Erda:
+(A command channel members level must be minimum: %minlvl% Lvl or higher to challenge Etis van Etina.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
new file mode 100644
index 0000000000..0e5f31ce70
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
@@ -0,0 +1,7 @@
+Erda:
+Thank you. Without your help, we couldn't have won easily.
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
new file mode 100644
index 0000000000..b774fcf6d7
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.areas.KeucereusAllianceBase.Erda;
+
+import java.util.List;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Party;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Erda extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ERDA = 34319;
+ private static final int ETINA_RAID = 29318;
+ // Location
+ private static final Location ENTER_LOC = new Location(-245778, 181088, 2860);
+ private static final Location CAMILLE_LOC = new Location(-245758, 149020, 11838);
+
+ public Erda()
+ {
+ addFirstTalkId(ERDA);
+ addTalkId(ERDA);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ if (event.equals("teleport"))
+ {
+ final int status = GrandBossManager.getInstance().getBossStatus(ETINA_RAID);
+ if (player.isGM())
+ {
+ player.teleToLocation(ENTER_LOC, true);
+ GrandBossManager.getInstance().setBossStatus(ETINA_RAID, 1);
+ }
+ else
+ {
+ if (status == 1)
+ {
+ return "34319-1.html";
+ }
+ if (status == 2)
+ {
+ return "34319-2.html";
+ }
+ if (!player.isInParty())
+ {
+ return "34319-3.html";
+ }
+ final Party party = player.getParty();
+ final boolean isInCC = party.isInCommandChannel();
+ final List members = (isInCC) ? party.getCommandChannel().getMembers() : party.getMembers();
+ final boolean isPartyLeader = (isInCC) ? party.getCommandChannel().isLeader(player) : party.isLeader(player);
+ if (!isPartyLeader)
+ {
+ return "34319-3.html";
+ }
+ if ((members.size() < Config.ETINA_MIN_PLAYERS) || (members.size() > Config.ETINA_MAX_PLAYERS))
+ {
+ final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
+ packet.setHtml(getHtm(player, "34319-4.html"));
+ packet.replace("%min%", Integer.toString(Config.ETINA_MIN_PLAYERS));
+ packet.replace("%max%", Integer.toString(Config.ETINA_MAX_PLAYERS));
+ player.sendPacket(packet);
+ return null;
+ }
+ for (PlayerInstance member : members)
+ {
+ if (member.getLevel() < Config.ETINA_MIN_PLAYER_LVL)
+ {
+ final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
+ packet.setHtml(getHtm(player, "34319-5.html"));
+ packet.replace("%minlvl%", Integer.toString(Config.ETINA_MIN_PLAYER_LVL));
+ player.sendPacket(packet);
+ return null;
+ }
+ }
+ for (PlayerInstance member : members)
+ {
+ if (member.isInsideRadius3D(npc, Config.ALT_PARTY_RANGE))
+ {
+ member.teleToLocation(ENTER_LOC, false);
+ GrandBossManager.getInstance().setBossStatus(ETINA_RAID, 1);
+ }
+ }
+ }
+ }
+ else if (event.equals("tp_inner"))
+ {
+ player.teleToLocation(CAMILLE_LOC, true);
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onFirstTalk(Npc npc, PlayerInstance player)
+ {
+ return "34319.html";
+ }
+
+ public static void main(String[] args)
+ {
+ new Erda();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
new file mode 100644
index 0000000000..b16cd7626e
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class ChoirOfDarkness extends AbstractNpcAI
+{
+ // NPC
+ private static final int CHOIR_OF_DARKNESS = 24078;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private ChoirOfDarkness()
+ {
+ registerMobs(CHOIR_OF_DARKNESS);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == CHOIR_OF_DARKNESS)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new ChoirOfDarkness();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
new file mode 100644
index 0000000000..045a67482c
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
@@ -0,0 +1,188 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Etina extends AbstractNpcAI
+{
+ // Npc
+ private static final int ETINA1 = 29318;
+ private static final int ETINA2 = 29319;
+ // Skills
+ private static final SkillHolder APOCALYPSE_FIRE = new SkillHolder(32001, 1);
+ private static final SkillHolder DEMOLISH_GROUND = new SkillHolder(32002, 1);
+ private static final SkillHolder WALL_OF_VOID = new SkillHolder(32003, 1);
+ private static final SkillHolder FLASH_OF_DARKNESS = new SkillHolder(32007, 1);
+
+ private Etina()
+ {
+ registerMobs(ETINA1, ETINA2);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if ((npc.getId() == ETINA1) || (npc.getId() == ETINA2))
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = WALL_OF_VOID;
+ }
+ else if (getRandom(100) < 30)
+ {
+ skillToCast = DEMOLISH_GROUND;
+ }
+ else if (getRandom(100) < 50)
+ {
+ skillToCast = FLASH_OF_DARKNESS;
+ }
+ else
+ {
+ skillToCast = APOCALYPSE_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new Etina();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
new file mode 100644
index 0000000000..c2be351b76
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
@@ -0,0 +1,785 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.concurrent.ThreadPool;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.Movie;
+import org.l2jmobius.gameserver.enums.TeleportWhereType;
+import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
+import org.l2jmobius.gameserver.instancemanager.MapRegionManager;
+import org.l2jmobius.gameserver.instancemanager.ZoneManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Spawn;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Attackable;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.holders.SpawnHolder;
+import org.l2jmobius.gameserver.model.quest.QuestTimer;
+import org.l2jmobius.gameserver.model.zone.ZoneType;
+import org.l2jmobius.gameserver.model.zone.type.NoRestartZone;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class EtisVanEtina extends AbstractNpcAI
+{
+ // Status
+ private static final int ALIVE = 0;
+ private static final int WAITING = 1;
+ private static final int FIGHTING = 2;
+ private static final int DEAD = 3;
+ // NPCs
+ private static final int ETIS_VAN_ETINA1 = 29318;
+ private static final int ETIS_VAN_ETINA2 = 29319;
+ private static final int KAIN_VAN_HALTER = 29320;
+ // Corridor Mobs
+ private static final int TEMPLE_ARCHON = 24085;
+ private static final int TEMPLE_RAIDER = 24079;
+ private static final int TEMPLE_GUARD_CAPTAIN = 24081;
+ private static final int TEMPLE_ELITE_CAPTAIN = 24082;
+ private static final int TEMPLE_FLAME_MASTER = 24084;
+ private static final int TEMPLE_PASSIONATE_SOLDIER = 24080;
+ private static final int TEMPLE_DARK_WIZARD = 24083;
+ private static final int GREAT_TEMPLE_DECANUS = 24093;
+ private static final int GREAT_TEMPLE_SIEGE_CHARIOT = 24096;
+ private static final int GREAT_TEMPLE_SOUL_GUIDE = 24094;
+ private static final int SOUL_DESTROYER = 24076;
+ private static final int BLIND_BERSERKER = 24075;
+ private static final int SOUL_REAPER = 24074;
+ private static final int JUDGE_OF_HERESY = 24077;
+ private static final int GREAT_TEMPLE_DARK_JUDGE = 24095;
+ private static final int GREAT_TEMPLE_BUTCHER = 24092;
+ private static final int CHOIR_OF_DARKNESS = 24078;
+ private static final int TEMPLE_HIGH_PRIEST = 24086;
+ private static final int CREED_GUARDIAN = 24073;
+ private static final int PARAGON = 24072;
+ //@formatter:off
+ private static final int[] CORRIDOR_MOBS = {24085, 24079, 24081, 24082, 24084, 24080, 24083, 24093, 24096, 24094, 24076, 24075, 24074, 24077, 24095, 24092, 24078, 24086, 24073};
+ //@formatter:on
+ // Minions
+ private static final int MARTYR_OF_GREED = 29321;
+ private static final int LIBERATOR_OF_LUST = 29324;
+ private static final int SEEKER_OF_DESPAIR = 29323;
+ private static final int GUIDE_OF_PRIDE = 29322;
+ // Seals
+ private static final int SEAL_OF_GNOSIS = 19677;
+ private static final int SEAL_OF_STRIFE = 19678;
+ private static final int SEAL_OF_AVARICE = 19679;
+ private static final int SEAL_OF_PUNISHMENT = 19680;
+ private static final int SEAL_OF_AWAKENING = 19681;
+ private static final int SEAL_OF_CALAMITY = 19682;
+ private static final int SEAL_OF_DESTRUCTION = 19683;
+ // Others
+ private static final int BARRICADE = 19724;
+ private static final int DOOR1 = 12230702;
+ private static final int DOOR2 = 12230704;
+ private static final int DOOR3 = 12230802;
+ private static final int DOOR4 = 12230804;
+ // Location
+ private static final Location PARAGON_LOC = new Location(-245757, 187778, 3042);
+ private static final Location ETINA_LOC = new Location(-245765, 194229, 3200);
+ private static final Location KAIN_LOC = new Location(-245766, 192148, 3054);
+ private static final Location SEAL_OF_GNOSIS_LOC = new Location(-246859, 193321, 3045);
+ private static final Location SEAL_OF_STRIFE_LOC = new Location(-246888, 192729, 3045);
+ private static final Location SEAL_OF_AVARICE_LOC = new Location(-246896, 192148, 3045);
+ private static final Location SEAL_OF_PUNISHMENT_LOC = new Location(-244640, 193331, 3044);
+ private static final Location SEAL_OF_AWAKENING_LOC = new Location(-244647, 192739, 3045);
+ private static final Location SEAL_OF_CALAMITY_LOC = new Location(-244641, 192155, 3045);
+ private static final Location SEAL_OF_DESTRUCTION_LOC = new Location(-244640, 191566, 3045);
+
+ private static final int ZONE_ID = 85001;
+ private static final NoRestartZone BOSS_ZONE = ZoneManager.getInstance().getZoneById(ZONE_ID, NoRestartZone.class);
+ // Spawns
+ private static final List SPAWNS_CORRIDOR = new ArrayList<>();
+ static
+ {
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246089, 182518, 2861, 62581, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245778, 182749, 2861, 57797, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245538, 182930, 2861, 34847, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246012, 183159, 2870, 40700, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245798, 183316, 2900, 59692, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245509, 183575, 2950, 59859, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246020, 183718, 2977, 46596, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245913, 182571, 2860, 18939, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245682, 182685, 2860, 59705, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245583, 182903, 2860, 38901, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245949, 183012, 2860, 21081, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245925, 183334, 2904, 10282, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245626, 183509, 2937, 22384, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245682, 182497, 2861, 48877, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245930, 182710, 2861, 44855, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245482, 183005, 2861, 24815, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245874, 183345, 2906, 62359, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245578, 183496, 2935, 58218, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -246033, 183721, 2978, 10200, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245864, 182593, 2860, 39881, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245512, 182948, 2860, 17444, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245987, 183275, 2893, 24335, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -246008, 183765, 2986, 65472, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245595, 183581, 2951, 35910, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245643, 182807, 2860, 52098, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245871, 183166, 2872, 62597, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245615, 183452, 2927, 15114, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245874, 183716, 2977, 38121, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245602, 183883, 3009, 25130, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245923, 182788, 2860, 7524, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245569, 182962, 2860, 45906, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245949, 183312, 2899, 56352, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245651, 183439, 2924, 57404, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -246156, 183790, 2991, 33176, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245587, 183823, 2997, 33966, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245762, 182706, 2860, 46796, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245638, 182913, 2860, 63991, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245867, 183306, 2899, 14493, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245804, 183800, 2993, 47355, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245598, 183551, 2945, 37399, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_DECANUS, -245754, 184113, 3025, 47953, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_SIEGE_CHARIOT, -245762, 184863, 3029, 49151, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_SOUL_GUIDE, -245764, 185502, 3032, 45247, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_DARK_JUDGE, -245753, 186185, 3036, 48708, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_BUTCHER, -245767, 186756, 3039, 47997, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246081, 184205, 3026, 21350, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245571, 184303, 3026, 21662, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246034, 184943, 3029, 981, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245755, 184691, 3028, 11973, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245493, 185001, 3030, 22853, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245770, 185342, 3032, 46786, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246034, 185701, 3033, 38598, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245530, 185713, 3033, 22746, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245772, 186029, 3035, 53127, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246032, 186381, 3037, 57199, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245503, 186312, 3037, 25473, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245905, 186684, 3038, 20419, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245585, 186936, 3041, 25482, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245999, 187393, 3042, 2323, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245435, 187610, 3042, 30564, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245482, 184347, 3027, 5631, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245885, 184457, 3027, 31148, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245604, 184817, 3029, 55428, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245954, 185193, 3031, 56275, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245566, 185624, 3033, 19880, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245882, 185959, 3035, 53078, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245860, 186723, 3039, 50920, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245556, 186293, 3036, 27689, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245524, 187226, 3042, 33041, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245903, 187548, 3042, 10250, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245898, 184129, 3025, 56279, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245720, 184633, 3028, 48934, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245639, 185160, 3031, 57162, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245940, 185549, 3033, 43554, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245635, 185848, 3034, 34721, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245858, 186299, 3036, 60699, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245610, 186904, 3040, 64217, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245394, 187605, 3042, 36104, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -246023, 187593, 3042, 58782, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245659, 184163, 3025, 36852, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245910, 184620, 3028, 43041, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245751, 185242, 3031, 49837, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245519, 185631, 3033, 18471, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245876, 185902, 3034, 46344, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245872, 186422, 3037, 29263, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245609, 186755, 3039, 31045, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245992, 187241, 3042, 24909, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245429, 187640, 3042, 21779, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245434, 184197, 3026, 48401, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245998, 184978, 3030, 45247, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245499, 185745, 3033, 6215, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -246027, 186380, 3037, 56728, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245738, 187327, 3042, 19747, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245765, 184466, 3027, 60537, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245770, 185150, 3030, 50987, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245766, 185731, 3033, 25432, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245761, 186396, 3037, 48080, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245759, 187011, 3041, 23104, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245877, 184118, 3025, 41582, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245627, 184861, 3029, 46344, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245933, 185634, 3033, 58408, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245569, 186351, 3037, 24389, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245920, 186924, 3040, 32558, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245510, 187534, 3042, 27370, false));
+ }
+ private static final List SPAWNS_BARRICADE = new ArrayList<>();
+ static
+ {
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246068, 182171, 2860, 47916, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245523, 182378, 2860, 48500, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246044, 182760, 2860, 48949, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245731, 183026, 2860, 47934, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246044, 183466, 2929, 51168, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245486, 183398, 2916, 47429, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245760, 183696, 2973, 49488, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246034, 183972, 3024, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245484, 183965, 3024, 49075, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245762, 184305, 3026, 48894, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246040, 184694, 3028, 48838, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245478, 184653, 3028, 48932, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245763, 185026, 3030, 49099, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246035, 185335, 3031, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245483, 185328, 3031, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245764, 185620, 3033, 49389, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246035, 185973, 3035, 49208, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245482, 185972, 3035, 49360, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245757, 186296, 3036, 49060, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246038, 186578, 3038, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245481, 186569, 3038, 49041, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245763, 186884, 3040, 48798, false));
+ }
+ private static final List SPAWNS_MINIONS = new ArrayList<>();
+ static
+ {
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ }
+ // Skills
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS = new SkillHolder(32317, 1);
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS_SEAL_N = new SkillHolder(32004, 1);
+ private static final SkillHolder ETINA_REVELATION = new SkillHolder(32014, 2);
+ private static final SkillHolder STIGMA_OF_REVELATION = new SkillHolder(32015, 1);
+ private static final SkillHolder CRY_OF_HOLY_WAR = new SkillHolder(32017, 2);
+ private static final SkillHolder STIGMA_OF_MARTYR = new SkillHolder(32018, 1);
+ private static final SkillHolder UNDEAD_CREATURE = new SkillHolder(32020, 2);
+ private static final SkillHolder ETINA_DIVINE_PUNISHMENT = new SkillHolder(32023, 2);
+ private static final SkillHolder ETINA_OBSERVATION = new SkillHolder(32024, 2);
+ private static final SkillHolder RAGE_OF_THE_OPEN_EYE = new SkillHolder(32026, 2);
+ // Camille -> Horseshoe Trampling, Horizon Bash, Joust Lunge, Call of Etina (summon minions?)
+ // Vars
+ private static long _lastAction;
+ protected ScheduledFuture> _collapseTask;
+ protected ScheduledFuture> _gnosisCastTask;
+ protected ScheduledFuture> _strifeCastTask;
+ protected ScheduledFuture> _avariceCastTask;
+ protected ScheduledFuture> _punishmentCastTask;
+ protected ScheduledFuture> _awakeningCastTask;
+ // summon 5 black holes, that uses skill Explosion of Calamity(32029, 1)
+ protected ScheduledFuture> _calamityCastTask;
+ // summon 5 black holes, that uses skill Cyclone of Chaos(32028, 1)
+ protected ScheduledFuture> _destructionCastTask;
+ private static List _spawns = new ArrayList<>();
+ private static List _barricadeSpawns = new ArrayList<>();
+ private static List _minionSpawns = new ArrayList<>();
+ private Npc _sealOfGnosis;
+ private Npc _sealOfStrife;
+ private Npc _sealOfAvarice;
+ private Npc _sealOfPunishment;
+ private Npc _sealOfAwakening;
+ private Npc _sealOfCalamity;
+ private Npc _sealOfDestruction;
+ private static MonsterInstance _paragon;
+ private static GrandBossInstance _kain;
+ private static GrandBossInstance _etina;
+ private boolean _spawned = false;
+ private boolean _kain30 = false;
+ private boolean _kain60 = false;
+ private boolean _etina80 = false;
+ private boolean _etina15 = false;
+
+ public EtisVanEtina()
+ {
+ addEnterZoneId(ZONE_ID);
+ addExitZoneId(ZONE_ID);
+ addAttackId(CORRIDOR_MOBS);
+ addAttackId(KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+ addKillId(CORRIDOR_MOBS);
+ addKillId(PARAGON, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+
+ // Unlock
+ final StatSet info = GrandBossManager.getInstance().getStatSet(ETIS_VAN_ETINA1);
+ final int status = GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1);
+ if (status == DEAD)
+ {
+ final long time = info.getLong("respawn_time") - System.currentTimeMillis();
+ if (time > 0)
+ {
+ startQuestTimer("unlock_etina", time, null, null);
+ }
+ else
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+ else
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "unlock_etina":
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ break;
+ }
+ case "check_activity_task":
+ {
+ if ((_lastAction + 900000) < System.currentTimeMillis())
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ for (Creature creature : BOSS_ZONE.getCharactersInside())
+ {
+ if (creature != null)
+ {
+ if (creature.isNpc())
+ {
+ creature.deleteMe();
+ }
+ else if (creature.isPlayer())
+ {
+ creature.teleToLocation(MapRegionManager.getInstance().getTeleToLocation(creature, TeleportWhereType.TOWN));
+ }
+ }
+ }
+ startQuestTimer("end_etina", 2000, null, null);
+ }
+ else
+ {
+ startQuestTimer("check_activity_task", 60000, null, null);
+ }
+ break;
+ }
+ case "openInnerDoor":
+ {
+ openDoor(DOOR3, 0);
+ openDoor(DOOR4, 0);
+ startQuestTimer("show_intro_movie", 60000, null, null);
+ break;
+ }
+ case "show_intro_movie":
+ {
+ BOSS_ZONE.getPlayersInside().forEach(p ->
+ {
+ playMovie(p, Movie.SC_INZONE_KAIN_INTRO);
+ });
+ startQuestTimer("spawn_kain", 23000, null, null);
+ break;
+ }
+ case "spawn_kain":
+ {
+ closeDoor(DOOR1, 0);
+ closeDoor(DOOR2, 0);
+ closeDoor(DOOR3, 0);
+ closeDoor(DOOR4, 0);
+ _kain = (GrandBossInstance) addSpawn(KAIN_VAN_HALTER, KAIN_LOC, false, 0, true);
+ _etina = (GrandBossInstance) addSpawn(ETIS_VAN_ETINA1, ETINA_LOC, false, 0, true);
+ _etina.setInvul(true);
+ _etina.setTargetable(false);
+ _etina.setImmobilized(true);
+ BOSS_ZONE.getPlayersInside().forEach(p -> p.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_AND_HIS_APOSTLES_HAVE_APPEARED, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ break;
+ }
+ case "spawnTransformedEtina":
+ {
+ _etina = (GrandBossInstance) addSpawn(ETIS_VAN_ETINA2, KAIN_LOC, false, 0, true);
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ break;
+ }
+ case "cancel_timers":
+ {
+ QuestTimer activityTimer = getQuestTimer("check_activity_task", null, null);
+ if (activityTimer != null)
+ {
+ activityTimer.cancel();
+ }
+
+ QuestTimer forceEnd = getQuestTimer("end_etina", null, null);
+ if (forceEnd != null)
+ {
+ forceEnd.cancel();
+ }
+ break;
+ }
+ case "end_etina":
+ {
+ Clean();
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ protected void Clean()
+ {
+ BOSS_ZONE.getCharactersInside().forEach(mob ->
+ {
+ if (mob.isNpc())
+ {
+ mob.deleteMe();
+ }
+ });
+ if (_gnosisCastTask != null)
+ {
+ _gnosisCastTask.cancel(false);
+ _gnosisCastTask = null;
+ }
+ if (_strifeCastTask != null)
+ {
+ _strifeCastTask.cancel(false);
+ _strifeCastTask = null;
+ }
+ if (_avariceCastTask != null)
+ {
+ _avariceCastTask.cancel(false);
+ _avariceCastTask = null;
+ }
+ if (_punishmentCastTask != null)
+ {
+ _punishmentCastTask.cancel(false);
+ _punishmentCastTask = null;
+ }
+ if (_awakeningCastTask != null)
+ {
+ _awakeningCastTask.cancel(false);
+ _awakeningCastTask = null;
+ }
+ if (_calamityCastTask != null)
+ {
+ _calamityCastTask.cancel(false);
+ _calamityCastTask = null;
+ }
+ if (_destructionCastTask != null)
+ {
+ _destructionCastTask.cancel(false);
+ _destructionCastTask = null;
+ }
+ if (_collapseTask != null)
+ {
+ _collapseTask.cancel(false);
+ _collapseTask = null;
+ }
+ notifyEvent("cancel_timers", null, null);
+ BOSS_ZONE.oustAllPlayers();
+ closeDoor(DOOR1, 0);
+ closeDoor(DOOR2, 0);
+ closeDoor(DOOR3, 0);
+ closeDoor(DOOR4, 0);
+ if (GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1) != DEAD)
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
+ {
+ _lastAction = System.currentTimeMillis();
+ // Anti BUGGERS
+ if (!BOSS_ZONE.isInsideZone(attacker))
+ {
+ attacker.doDie(null);
+ LOGGER.warning(getName() + ": Character: " + attacker.getName() + " attacked: " + npc.getName() + " out of the boss zone!");
+ }
+ if (!BOSS_ZONE.isInsideZone(npc))
+ {
+ Spawn spawn = npc.getSpawn();
+ if (spawn != null)
+ {
+ npc.teleToLocation(spawn.getX(), spawn.getY(), spawn.getZ());
+ }
+ LOGGER.warning(getName() + ": Character: " + attacker.getName() + " attacked: " + npc.getName() + " wich is out of the boss zone!");
+ }
+ if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !_kain30)
+ {
+ _kain30 = true;
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !_kain60)
+ {
+ _kain60 = true;
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ }
+ }
+ else if ((npc.getId() == ETIS_VAN_ETINA1))
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.8)) && !_etina80)
+ {
+ _etina80 = true;
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ _etina.abortCast();
+ _etina.broadcastPacket(new MagicSkillUse(_etina, _etina, CALL_OF_SEVEN_SIGNS.getSkillId(), CALL_OF_SEVEN_SIGNS.getSkillLevel(), 3000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_USES_THE_POWER_OF_THE_SEVEN_SIGNS_TO_SUMMON_ALL_7_SEALS_INSIDE_THE_TEMPLE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ _sealOfGnosis = addSpawn(SEAL_OF_GNOSIS, SEAL_OF_GNOSIS_LOC);
+ _sealOfStrife = addSpawn(SEAL_OF_STRIFE, SEAL_OF_STRIFE_LOC);
+ _sealOfAvarice = addSpawn(SEAL_OF_AVARICE, SEAL_OF_AVARICE_LOC);
+ _sealOfPunishment = addSpawn(SEAL_OF_PUNISHMENT, SEAL_OF_PUNISHMENT_LOC);
+ _sealOfAwakening = addSpawn(SEAL_OF_AWAKENING, SEAL_OF_AWAKENING_LOC);
+ _sealOfCalamity = addSpawn(SEAL_OF_CALAMITY, SEAL_OF_CALAMITY_LOC);
+ _sealOfDestruction = addSpawn(SEAL_OF_DESTRUCTION, SEAL_OF_DESTRUCTION_LOC);
+ _gnosisCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfGnosis.setDisplayEffect(3);
+ _sealOfGnosis.broadcastPacket(new MagicSkillUse(_sealOfGnosis, _sealOfGnosis, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 1, 10000, 0));
+ int rnd = getRandom(BOSS_ZONE.getPlayersInside().size());
+ PlayerInstance member = BOSS_ZONE.getPlayersInside().get(rnd);
+ STIGMA_OF_REVELATION.getSkill().applyEffects(member, member);
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_REVELATION.getSkill().applyEffects(minion, minion);
+ ((Attackable) minion).addDamageHate(member, 0, 999999999);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_GNOSIS_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 10000, 120000);
+ _strifeCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfStrife.setDisplayEffect(3);
+ _sealOfStrife.broadcastPacket(new MagicSkillUse(_sealOfStrife, _sealOfStrife, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 2, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ CRY_OF_HOLY_WAR.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> STIGMA_OF_MARTYR.getSkill().applyEffects(player, player));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_STRIFE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 20000, 120000);
+ _avariceCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfAvarice.setDisplayEffect(3);
+ _sealOfAvarice.broadcastPacket(new MagicSkillUse(_sealOfAvarice, _sealOfAvarice, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 3, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ UNDEAD_CREATURE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_AVARICE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 30000, 120000);
+ _punishmentCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfPunishment.setDisplayEffect(3);
+ _sealOfPunishment.broadcastPacket(new MagicSkillUse(_sealOfPunishment, _sealOfPunishment, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 4, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_DIVINE_PUNISHMENT.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> ETINA_OBSERVATION.getSkill().applyEffects(player, player));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_PUNISHMENT_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 40000, 120000);
+ _awakeningCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfAwakening.setDisplayEffect(3);
+ _sealOfAwakening.broadcastPacket(new MagicSkillUse(_sealOfAwakening, _sealOfAwakening, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 5, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ RAGE_OF_THE_OPEN_EYE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_AWAKENING_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 50000, 120000);
+ _calamityCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfCalamity.setDisplayEffect(3);
+ // TODO: Seal of Calamity skill cast.
+ _sealOfCalamity.broadcastPacket(new MagicSkillUse(_sealOfCalamity, _sealOfCalamity, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 6, 10000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_CALAMITY_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 60000, 120000);
+ _destructionCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfDestruction.setDisplayEffect(3);
+ // TODO: Seal of Destruction skill cast.
+ _sealOfDestruction.broadcastPacket(new MagicSkillUse(_sealOfDestruction, _sealOfDestruction, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 7, 10000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_DESTRUCTION_ACTIVATES_AND_THE_ENTIRE_ETINA_GREAT_TEMPLE_IS_NOW_UNDER_THE_INFLUENCE_OF_THE_SEAL, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 70000, 120000);
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.15)) && !_etina15)
+ {
+ _etina15 = true;
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ // TODO: decrease etina and seals power
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_AND_THE_POWER_OF_SEVEN_SEALS_ARE_WEAKENING, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onEnterZone(Creature character, ZoneType zone)
+ {
+ if (zone.getId() == ZONE_ID)
+ {
+ if (_collapseTask != null)
+ {
+ _collapseTask.cancel(true);
+ _collapseTask = null;
+ }
+ if ((GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1) == WAITING) && !_spawned)
+ {
+ _spawned = true;
+ _spawns.clear();
+ _barricadeSpawns.clear();
+ for (SpawnHolder spawn : SPAWNS_CORRIDOR)
+ {
+ _spawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ for (SpawnHolder spawn : SPAWNS_BARRICADE)
+ {
+ _barricadeSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ _paragon = (MonsterInstance) addSpawn(PARAGON, PARAGON_LOC);
+ _paragon.setInvul(true);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_T_DEFEAT_PARAGON_WHILE_PARAGON_S_MINIONS_ARE_ALIVE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, FIGHTING);
+ _lastAction = System.currentTimeMillis();
+ startQuestTimer("check_activity_task", 60000, null, null, true);
+ }
+ }
+ return super.onEnterZone(character, zone);
+ }
+
+ @Override
+ public String onExitZone(Creature character, ZoneType zone)
+ {
+ if (zone.getId() == ZONE_ID)
+ {
+ if (zone.getPlayersInside().isEmpty())
+ {
+ _collapseTask = ThreadPool.schedule(() -> Clean(), 900000);
+ }
+ }
+ return super.onExitZone(character, zone);
+ }
+
+ @Override
+ public String onKill(Npc npc, PlayerInstance killer, boolean isPet)
+ {
+ if (npc.getId() == ETIS_VAN_ETINA1)
+ {
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_ETIS_VAN_ETINA_TRANS);
+ });
+ startQuestTimer("spawnTransformedEtina", 15000, null, null);
+ }
+ else if (npc.getId() == ETIS_VAN_ETINA2)
+ {
+ notifyEvent("cancel_timers", null, null);
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_ETIS_VAN_ETINA_ENDING);
+ });
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, DEAD);
+ final long respawnTime = (Config.ETINA_SPAWN_INTERVAL + getRandom(-Config.ETINA_SPAWN_RANDOM, Config.ETINA_SPAWN_RANDOM)) * 3600000;
+ final StatSet info = GrandBossManager.getInstance().getStatSet(ETIS_VAN_ETINA1);
+ info.set("respawn_time", System.currentTimeMillis() + respawnTime);
+ GrandBossManager.getInstance().setStatSet(ETIS_VAN_ETINA1, info);
+
+ startQuestTimer("unlock_etina", respawnTime, null, null);
+ startQuestTimer("end_etina", 900000, null, null);
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS, npc.getId()))
+ {
+ _spawns.remove(npc);
+ if (_spawns.isEmpty())
+ {
+ _paragon.setInvul(false);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }
+ }
+ else if (npc.getId() == PARAGON)
+ {
+ openDoor(DOOR1, 0);
+ openDoor(DOOR2, 0);
+ startQuestTimer("openInnerDoor", 30000, null, null);
+ }
+ else if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ minion.doDie(null);
+ }
+ });
+ _etina.setInvul(false);
+ _etina.setImmobilized(false);
+ _etina.setTargetable(true);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_APPROACHES, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ _kain.deleteMe();
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_KAIN_BOSS_ENDING);
+ });
+ }
+ return super.onKill(npc, killer, isPet);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtisVanEtina();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
new file mode 100644
index 0000000000..b66a737f71
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class GreatTempleDarkJudge extends AbstractNpcAI
+{
+ // Npc
+ private static final int GREAT_TEMPLE_DARK_JUDGE = 24095;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private GreatTempleDarkJudge()
+ {
+ registerMobs(GREAT_TEMPLE_DARK_JUDGE);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == GREAT_TEMPLE_DARK_JUDGE)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new GreatTempleDarkJudge();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
new file mode 100644
index 0000000000..ef143e1088
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class GreatTempleSoulGuide extends AbstractNpcAI
+{
+ // Npc
+ private static final int GREAT_TEMPLE_SOUL_GUIDE = 24094;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private GreatTempleSoulGuide()
+ {
+ registerMobs(GREAT_TEMPLE_SOUL_GUIDE);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == GREAT_TEMPLE_SOUL_GUIDE)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new GreatTempleSoulGuide();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
new file mode 100644
index 0000000000..5ba7f93bff
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class JudgeOfHeresy extends AbstractNpcAI
+{
+ // Npc
+ private static final int JUDGE_OF_HERESY = 24077;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private JudgeOfHeresy()
+ {
+ registerMobs(JUDGE_OF_HERESY);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == JUDGE_OF_HERESY)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new JudgeOfHeresy();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
new file mode 100644
index 0000000000..ec40bf98cf
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
@@ -0,0 +1,187 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Kain extends AbstractNpcAI
+{
+ // Npc
+ private static final int KAIN_VAN_HALTER = 29320;
+ // Skills
+ private static final SkillHolder WALL_OF_VOID = new SkillHolder(32003, 1);
+ private static final SkillHolder FLASH_OF_DARKNESS = new SkillHolder(32007, 1);
+ private static final SkillHolder BANE_BLADE = new SkillHolder(32010, 1);
+ private static final SkillHolder SPINNING_SHADOW = new SkillHolder(32011, 1);
+
+ private Kain()
+ {
+ registerMobs(KAIN_VAN_HALTER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = WALL_OF_VOID;
+ }
+ else if (getRandom(100) < 30)
+ {
+ skillToCast = SPINNING_SHADOW;
+ }
+ else if (getRandom(100) < 50)
+ {
+ skillToCast = FLASH_OF_DARKNESS;
+ }
+ else
+ {
+ skillToCast = BANE_BLADE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new Kain();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
new file mode 100644
index 0000000000..3ac3966287
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class LiberatorOfLust extends AbstractNpcAI
+{
+ // Npc
+ private static final int LIBERATOR_OF_LUST = 29324;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private LiberatorOfLust()
+ {
+ registerMobs(LIBERATOR_OF_LUST);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == LIBERATOR_OF_LUST)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new LiberatorOfLust();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
new file mode 100644
index 0000000000..c029102a64
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class SeekerOfDespair extends AbstractNpcAI
+{
+ // Npc
+ private static final int SEEKER_OF_DESPAIR = 29323;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private SeekerOfDespair()
+ {
+ registerMobs(SEEKER_OF_DESPAIR);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == SEEKER_OF_DESPAIR)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new SeekerOfDespair();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
new file mode 100644
index 0000000000..3da99f7d62
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class SoulDestroyer extends AbstractNpcAI
+{
+ // Npc
+ private static final int SOUL_DESTROYER = 24076;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private SoulDestroyer()
+ {
+ registerMobs(SOUL_DESTROYER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == SOUL_DESTROYER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new SoulDestroyer();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
new file mode 100644
index 0000000000..16ad7ae0e5
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleArchon extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_ARCHON = 24085;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private TempleArchon()
+ {
+ registerMobs(TEMPLE_ARCHON);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_ARCHON)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleArchon();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
new file mode 100644
index 0000000000..7a6eacccbc
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleDarkWizard extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_DARK_WIZARD = 24083;
+ // Skills
+ private static final SkillHolder DARK_BREAKER = new SkillHolder(32289, 1);
+ private static final SkillHolder VAMPIRIC_FORCE = new SkillHolder(32294, 1);
+
+ private TempleDarkWizard()
+ {
+ registerMobs(TEMPLE_DARK_WIZARD);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_DARK_WIZARD)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = VAMPIRIC_FORCE;
+ }
+ else
+ {
+ skillToCast = DARK_BREAKER;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleDarkWizard();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
new file mode 100644
index 0000000000..509a7816b5
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleFlameMaster extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_FLAME_MASTER = 24084;
+ // Skills
+ private static final SkillHolder DARK_BREAKER = new SkillHolder(32289, 1);
+ private static final SkillHolder BLOOD_TO_FLESH = new SkillHolder(32302, 1);
+
+ private TempleFlameMaster()
+ {
+ registerMobs(TEMPLE_FLAME_MASTER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_FLAME_MASTER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = BLOOD_TO_FLESH;
+ }
+ else
+ {
+ skillToCast = DARK_BREAKER;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleFlameMaster();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
new file mode 100644
index 0000000000..a7d200da1e
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleHighPriest extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_HIGH_PRIEST = 24086;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private TempleHighPriest()
+ {
+ registerMobs(TEMPLE_HIGH_PRIEST);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_HIGH_PRIEST)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleHighPriest();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
index a7f585c05a..c2e4514976 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
@@ -51,6 +51,7 @@
+
diff --git a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/Config.java b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/Config.java
index 7f9a012e55..fdbfea2135 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/org/l2jmobius/Config.java
@@ -911,6 +911,13 @@ public class Config
public static int RAMONA_SPAWN_RANDOM;
public static int RAMONA_MIN_PLAYER;
+ // Etis van Etina
+ public static int ETINA_SPAWN_INTERVAL;
+ public static int ETINA_SPAWN_RANDOM;
+ public static int ETINA_MIN_PLAYERS;
+ public static int ETINA_MAX_PLAYERS;
+ public static int ETINA_MIN_PLAYER_LVL;
+
// Gracia Seeds Settings
public static int SOD_TIAT_KILL_COUNT;
public static long SOD_STAGE_2_LENGTH;
@@ -2441,6 +2448,11 @@ public class Config
RAMONA_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfRamonaSpawn", 72);
RAMONA_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfRamonaSpawn", 48);
RAMONA_MIN_PLAYER = GrandBossSettings.getInt("RamonaMinPlayers", 7);
+ ETINA_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfEtinaSpawn", 264);
+ ETINA_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfEtinaSpawn", 72);
+ ETINA_MIN_PLAYERS = GrandBossSettings.getInt("EtinaMinPlayers", 49);
+ ETINA_MAX_PLAYERS = GrandBossSettings.getInt("EtinaMaxPlayers", 112);
+ ETINA_MIN_PLAYER_LVL = GrandBossSettings.getInt("EtinaMinPlayerLvl", 103);
// Gracia Seeds
final PropertiesParser GraciaSeedsSettings = new PropertiesParser(GRACIASEEDS_CONFIG_FILE);
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/config/GrandBoss.ini b/L2J_Mobius_6.0_Fafurion/dist/game/config/GrandBoss.ini
index 52fbe3441f..9277083115 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/config/GrandBoss.ini
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/config/GrandBoss.ini
@@ -198,6 +198,25 @@ HeliosMinPlayers = 70
# Minimum players Level for enter to Helios. Retail: 102
HeliosMinPlayerLvl = 99
+# ---------------------------------------------------------------------------
+# Etis Van Etina
+# ---------------------------------------------------------------------------
+
+# Interval time of Etis Van Etina. Value is hour. Range 1-480. Retail: 264
+IntervalOfEtinaSpawn = 72
+
+# Random interval. Range 1-192. Retail: 72
+RandomOfEtinaSpawn = 1
+
+# Minimal count of players for enter to Etis Van Etina. Retail: 49
+EtinaMinPlayers = 2
+
+# Maximum count of players for enter to Etis Van Etina. Retail: 112
+EtinaMaxPlayers = 112
+
+# Minimum players Level for enter to Etis Van Etina. Retail: 99
+EtinaMinPlayerLvl = 103
+
# ---------------------------------------------------------------------------
# Fafurion
# ---------------------------------------------------------------------------
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
new file mode 100644
index 0000000000..7024487136
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
@@ -0,0 +1,4 @@
+Erda:
+On the Etis van Etina there is an attack!
+At this time it's impossible to enter the temple.
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
new file mode 100644
index 0000000000..f8fff8d713
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
@@ -0,0 +1,4 @@
+Erda:
+Etis van Etina? You're too late, friend.
+A group of warriors drove him off not long ago.
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
new file mode 100644
index 0000000000..4926daed35
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
@@ -0,0 +1,4 @@
+Erda:
+You are overcome by a voice, a voice so powerful you are helpless as it speaks:
+(The players who belong to an association can only enter through the Association Leader.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
new file mode 100644
index 0000000000..3c8b9fc2ac
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
@@ -0,0 +1,3 @@
+Erda:
+(A command channel needs at least minimum: %min% and maximum: %max% members to challenge Etis van Etina.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
new file mode 100644
index 0000000000..3f33bfb866
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
@@ -0,0 +1,3 @@
+Erda:
+(A command channel members level must be minimum: %minlvl% Lvl or higher to challenge Etis van Etina.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
new file mode 100644
index 0000000000..0e5f31ce70
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
@@ -0,0 +1,7 @@
+Erda:
+Thank you. Without your help, we couldn't have won easily.
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
new file mode 100644
index 0000000000..b774fcf6d7
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.areas.KeucereusAllianceBase.Erda;
+
+import java.util.List;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Party;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Erda extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ERDA = 34319;
+ private static final int ETINA_RAID = 29318;
+ // Location
+ private static final Location ENTER_LOC = new Location(-245778, 181088, 2860);
+ private static final Location CAMILLE_LOC = new Location(-245758, 149020, 11838);
+
+ public Erda()
+ {
+ addFirstTalkId(ERDA);
+ addTalkId(ERDA);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ if (event.equals("teleport"))
+ {
+ final int status = GrandBossManager.getInstance().getBossStatus(ETINA_RAID);
+ if (player.isGM())
+ {
+ player.teleToLocation(ENTER_LOC, true);
+ GrandBossManager.getInstance().setBossStatus(ETINA_RAID, 1);
+ }
+ else
+ {
+ if (status == 1)
+ {
+ return "34319-1.html";
+ }
+ if (status == 2)
+ {
+ return "34319-2.html";
+ }
+ if (!player.isInParty())
+ {
+ return "34319-3.html";
+ }
+ final Party party = player.getParty();
+ final boolean isInCC = party.isInCommandChannel();
+ final List members = (isInCC) ? party.getCommandChannel().getMembers() : party.getMembers();
+ final boolean isPartyLeader = (isInCC) ? party.getCommandChannel().isLeader(player) : party.isLeader(player);
+ if (!isPartyLeader)
+ {
+ return "34319-3.html";
+ }
+ if ((members.size() < Config.ETINA_MIN_PLAYERS) || (members.size() > Config.ETINA_MAX_PLAYERS))
+ {
+ final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
+ packet.setHtml(getHtm(player, "34319-4.html"));
+ packet.replace("%min%", Integer.toString(Config.ETINA_MIN_PLAYERS));
+ packet.replace("%max%", Integer.toString(Config.ETINA_MAX_PLAYERS));
+ player.sendPacket(packet);
+ return null;
+ }
+ for (PlayerInstance member : members)
+ {
+ if (member.getLevel() < Config.ETINA_MIN_PLAYER_LVL)
+ {
+ final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
+ packet.setHtml(getHtm(player, "34319-5.html"));
+ packet.replace("%minlvl%", Integer.toString(Config.ETINA_MIN_PLAYER_LVL));
+ player.sendPacket(packet);
+ return null;
+ }
+ }
+ for (PlayerInstance member : members)
+ {
+ if (member.isInsideRadius3D(npc, Config.ALT_PARTY_RANGE))
+ {
+ member.teleToLocation(ENTER_LOC, false);
+ GrandBossManager.getInstance().setBossStatus(ETINA_RAID, 1);
+ }
+ }
+ }
+ }
+ else if (event.equals("tp_inner"))
+ {
+ player.teleToLocation(CAMILLE_LOC, true);
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onFirstTalk(Npc npc, PlayerInstance player)
+ {
+ return "34319.html";
+ }
+
+ public static void main(String[] args)
+ {
+ new Erda();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
new file mode 100644
index 0000000000..b16cd7626e
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class ChoirOfDarkness extends AbstractNpcAI
+{
+ // NPC
+ private static final int CHOIR_OF_DARKNESS = 24078;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private ChoirOfDarkness()
+ {
+ registerMobs(CHOIR_OF_DARKNESS);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == CHOIR_OF_DARKNESS)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new ChoirOfDarkness();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
new file mode 100644
index 0000000000..045a67482c
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
@@ -0,0 +1,188 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Etina extends AbstractNpcAI
+{
+ // Npc
+ private static final int ETINA1 = 29318;
+ private static final int ETINA2 = 29319;
+ // Skills
+ private static final SkillHolder APOCALYPSE_FIRE = new SkillHolder(32001, 1);
+ private static final SkillHolder DEMOLISH_GROUND = new SkillHolder(32002, 1);
+ private static final SkillHolder WALL_OF_VOID = new SkillHolder(32003, 1);
+ private static final SkillHolder FLASH_OF_DARKNESS = new SkillHolder(32007, 1);
+
+ private Etina()
+ {
+ registerMobs(ETINA1, ETINA2);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if ((npc.getId() == ETINA1) || (npc.getId() == ETINA2))
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = WALL_OF_VOID;
+ }
+ else if (getRandom(100) < 30)
+ {
+ skillToCast = DEMOLISH_GROUND;
+ }
+ else if (getRandom(100) < 50)
+ {
+ skillToCast = FLASH_OF_DARKNESS;
+ }
+ else
+ {
+ skillToCast = APOCALYPSE_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new Etina();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
new file mode 100644
index 0000000000..c2be351b76
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
@@ -0,0 +1,785 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.concurrent.ThreadPool;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.Movie;
+import org.l2jmobius.gameserver.enums.TeleportWhereType;
+import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
+import org.l2jmobius.gameserver.instancemanager.MapRegionManager;
+import org.l2jmobius.gameserver.instancemanager.ZoneManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Spawn;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Attackable;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.holders.SpawnHolder;
+import org.l2jmobius.gameserver.model.quest.QuestTimer;
+import org.l2jmobius.gameserver.model.zone.ZoneType;
+import org.l2jmobius.gameserver.model.zone.type.NoRestartZone;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class EtisVanEtina extends AbstractNpcAI
+{
+ // Status
+ private static final int ALIVE = 0;
+ private static final int WAITING = 1;
+ private static final int FIGHTING = 2;
+ private static final int DEAD = 3;
+ // NPCs
+ private static final int ETIS_VAN_ETINA1 = 29318;
+ private static final int ETIS_VAN_ETINA2 = 29319;
+ private static final int KAIN_VAN_HALTER = 29320;
+ // Corridor Mobs
+ private static final int TEMPLE_ARCHON = 24085;
+ private static final int TEMPLE_RAIDER = 24079;
+ private static final int TEMPLE_GUARD_CAPTAIN = 24081;
+ private static final int TEMPLE_ELITE_CAPTAIN = 24082;
+ private static final int TEMPLE_FLAME_MASTER = 24084;
+ private static final int TEMPLE_PASSIONATE_SOLDIER = 24080;
+ private static final int TEMPLE_DARK_WIZARD = 24083;
+ private static final int GREAT_TEMPLE_DECANUS = 24093;
+ private static final int GREAT_TEMPLE_SIEGE_CHARIOT = 24096;
+ private static final int GREAT_TEMPLE_SOUL_GUIDE = 24094;
+ private static final int SOUL_DESTROYER = 24076;
+ private static final int BLIND_BERSERKER = 24075;
+ private static final int SOUL_REAPER = 24074;
+ private static final int JUDGE_OF_HERESY = 24077;
+ private static final int GREAT_TEMPLE_DARK_JUDGE = 24095;
+ private static final int GREAT_TEMPLE_BUTCHER = 24092;
+ private static final int CHOIR_OF_DARKNESS = 24078;
+ private static final int TEMPLE_HIGH_PRIEST = 24086;
+ private static final int CREED_GUARDIAN = 24073;
+ private static final int PARAGON = 24072;
+ //@formatter:off
+ private static final int[] CORRIDOR_MOBS = {24085, 24079, 24081, 24082, 24084, 24080, 24083, 24093, 24096, 24094, 24076, 24075, 24074, 24077, 24095, 24092, 24078, 24086, 24073};
+ //@formatter:on
+ // Minions
+ private static final int MARTYR_OF_GREED = 29321;
+ private static final int LIBERATOR_OF_LUST = 29324;
+ private static final int SEEKER_OF_DESPAIR = 29323;
+ private static final int GUIDE_OF_PRIDE = 29322;
+ // Seals
+ private static final int SEAL_OF_GNOSIS = 19677;
+ private static final int SEAL_OF_STRIFE = 19678;
+ private static final int SEAL_OF_AVARICE = 19679;
+ private static final int SEAL_OF_PUNISHMENT = 19680;
+ private static final int SEAL_OF_AWAKENING = 19681;
+ private static final int SEAL_OF_CALAMITY = 19682;
+ private static final int SEAL_OF_DESTRUCTION = 19683;
+ // Others
+ private static final int BARRICADE = 19724;
+ private static final int DOOR1 = 12230702;
+ private static final int DOOR2 = 12230704;
+ private static final int DOOR3 = 12230802;
+ private static final int DOOR4 = 12230804;
+ // Location
+ private static final Location PARAGON_LOC = new Location(-245757, 187778, 3042);
+ private static final Location ETINA_LOC = new Location(-245765, 194229, 3200);
+ private static final Location KAIN_LOC = new Location(-245766, 192148, 3054);
+ private static final Location SEAL_OF_GNOSIS_LOC = new Location(-246859, 193321, 3045);
+ private static final Location SEAL_OF_STRIFE_LOC = new Location(-246888, 192729, 3045);
+ private static final Location SEAL_OF_AVARICE_LOC = new Location(-246896, 192148, 3045);
+ private static final Location SEAL_OF_PUNISHMENT_LOC = new Location(-244640, 193331, 3044);
+ private static final Location SEAL_OF_AWAKENING_LOC = new Location(-244647, 192739, 3045);
+ private static final Location SEAL_OF_CALAMITY_LOC = new Location(-244641, 192155, 3045);
+ private static final Location SEAL_OF_DESTRUCTION_LOC = new Location(-244640, 191566, 3045);
+
+ private static final int ZONE_ID = 85001;
+ private static final NoRestartZone BOSS_ZONE = ZoneManager.getInstance().getZoneById(ZONE_ID, NoRestartZone.class);
+ // Spawns
+ private static final List SPAWNS_CORRIDOR = new ArrayList<>();
+ static
+ {
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246089, 182518, 2861, 62581, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245778, 182749, 2861, 57797, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245538, 182930, 2861, 34847, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246012, 183159, 2870, 40700, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245798, 183316, 2900, 59692, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245509, 183575, 2950, 59859, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246020, 183718, 2977, 46596, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245913, 182571, 2860, 18939, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245682, 182685, 2860, 59705, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245583, 182903, 2860, 38901, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245949, 183012, 2860, 21081, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245925, 183334, 2904, 10282, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245626, 183509, 2937, 22384, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245682, 182497, 2861, 48877, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245930, 182710, 2861, 44855, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245482, 183005, 2861, 24815, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245874, 183345, 2906, 62359, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245578, 183496, 2935, 58218, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -246033, 183721, 2978, 10200, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245864, 182593, 2860, 39881, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245512, 182948, 2860, 17444, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245987, 183275, 2893, 24335, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -246008, 183765, 2986, 65472, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245595, 183581, 2951, 35910, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245643, 182807, 2860, 52098, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245871, 183166, 2872, 62597, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245615, 183452, 2927, 15114, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245874, 183716, 2977, 38121, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245602, 183883, 3009, 25130, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245923, 182788, 2860, 7524, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245569, 182962, 2860, 45906, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245949, 183312, 2899, 56352, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245651, 183439, 2924, 57404, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -246156, 183790, 2991, 33176, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245587, 183823, 2997, 33966, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245762, 182706, 2860, 46796, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245638, 182913, 2860, 63991, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245867, 183306, 2899, 14493, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245804, 183800, 2993, 47355, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245598, 183551, 2945, 37399, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_DECANUS, -245754, 184113, 3025, 47953, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_SIEGE_CHARIOT, -245762, 184863, 3029, 49151, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_SOUL_GUIDE, -245764, 185502, 3032, 45247, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_DARK_JUDGE, -245753, 186185, 3036, 48708, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_BUTCHER, -245767, 186756, 3039, 47997, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246081, 184205, 3026, 21350, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245571, 184303, 3026, 21662, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246034, 184943, 3029, 981, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245755, 184691, 3028, 11973, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245493, 185001, 3030, 22853, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245770, 185342, 3032, 46786, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246034, 185701, 3033, 38598, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245530, 185713, 3033, 22746, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245772, 186029, 3035, 53127, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246032, 186381, 3037, 57199, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245503, 186312, 3037, 25473, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245905, 186684, 3038, 20419, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245585, 186936, 3041, 25482, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245999, 187393, 3042, 2323, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245435, 187610, 3042, 30564, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245482, 184347, 3027, 5631, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245885, 184457, 3027, 31148, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245604, 184817, 3029, 55428, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245954, 185193, 3031, 56275, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245566, 185624, 3033, 19880, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245882, 185959, 3035, 53078, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245860, 186723, 3039, 50920, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245556, 186293, 3036, 27689, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245524, 187226, 3042, 33041, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245903, 187548, 3042, 10250, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245898, 184129, 3025, 56279, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245720, 184633, 3028, 48934, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245639, 185160, 3031, 57162, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245940, 185549, 3033, 43554, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245635, 185848, 3034, 34721, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245858, 186299, 3036, 60699, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245610, 186904, 3040, 64217, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245394, 187605, 3042, 36104, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -246023, 187593, 3042, 58782, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245659, 184163, 3025, 36852, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245910, 184620, 3028, 43041, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245751, 185242, 3031, 49837, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245519, 185631, 3033, 18471, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245876, 185902, 3034, 46344, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245872, 186422, 3037, 29263, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245609, 186755, 3039, 31045, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245992, 187241, 3042, 24909, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245429, 187640, 3042, 21779, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245434, 184197, 3026, 48401, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245998, 184978, 3030, 45247, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245499, 185745, 3033, 6215, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -246027, 186380, 3037, 56728, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245738, 187327, 3042, 19747, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245765, 184466, 3027, 60537, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245770, 185150, 3030, 50987, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245766, 185731, 3033, 25432, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245761, 186396, 3037, 48080, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245759, 187011, 3041, 23104, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245877, 184118, 3025, 41582, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245627, 184861, 3029, 46344, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245933, 185634, 3033, 58408, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245569, 186351, 3037, 24389, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245920, 186924, 3040, 32558, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245510, 187534, 3042, 27370, false));
+ }
+ private static final List SPAWNS_BARRICADE = new ArrayList<>();
+ static
+ {
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246068, 182171, 2860, 47916, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245523, 182378, 2860, 48500, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246044, 182760, 2860, 48949, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245731, 183026, 2860, 47934, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246044, 183466, 2929, 51168, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245486, 183398, 2916, 47429, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245760, 183696, 2973, 49488, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246034, 183972, 3024, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245484, 183965, 3024, 49075, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245762, 184305, 3026, 48894, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246040, 184694, 3028, 48838, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245478, 184653, 3028, 48932, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245763, 185026, 3030, 49099, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246035, 185335, 3031, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245483, 185328, 3031, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245764, 185620, 3033, 49389, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246035, 185973, 3035, 49208, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245482, 185972, 3035, 49360, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245757, 186296, 3036, 49060, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246038, 186578, 3038, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245481, 186569, 3038, 49041, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245763, 186884, 3040, 48798, false));
+ }
+ private static final List SPAWNS_MINIONS = new ArrayList<>();
+ static
+ {
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ }
+ // Skills
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS = new SkillHolder(32317, 1);
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS_SEAL_N = new SkillHolder(32004, 1);
+ private static final SkillHolder ETINA_REVELATION = new SkillHolder(32014, 2);
+ private static final SkillHolder STIGMA_OF_REVELATION = new SkillHolder(32015, 1);
+ private static final SkillHolder CRY_OF_HOLY_WAR = new SkillHolder(32017, 2);
+ private static final SkillHolder STIGMA_OF_MARTYR = new SkillHolder(32018, 1);
+ private static final SkillHolder UNDEAD_CREATURE = new SkillHolder(32020, 2);
+ private static final SkillHolder ETINA_DIVINE_PUNISHMENT = new SkillHolder(32023, 2);
+ private static final SkillHolder ETINA_OBSERVATION = new SkillHolder(32024, 2);
+ private static final SkillHolder RAGE_OF_THE_OPEN_EYE = new SkillHolder(32026, 2);
+ // Camille -> Horseshoe Trampling, Horizon Bash, Joust Lunge, Call of Etina (summon minions?)
+ // Vars
+ private static long _lastAction;
+ protected ScheduledFuture> _collapseTask;
+ protected ScheduledFuture> _gnosisCastTask;
+ protected ScheduledFuture> _strifeCastTask;
+ protected ScheduledFuture> _avariceCastTask;
+ protected ScheduledFuture> _punishmentCastTask;
+ protected ScheduledFuture> _awakeningCastTask;
+ // summon 5 black holes, that uses skill Explosion of Calamity(32029, 1)
+ protected ScheduledFuture> _calamityCastTask;
+ // summon 5 black holes, that uses skill Cyclone of Chaos(32028, 1)
+ protected ScheduledFuture> _destructionCastTask;
+ private static List _spawns = new ArrayList<>();
+ private static List _barricadeSpawns = new ArrayList<>();
+ private static List _minionSpawns = new ArrayList<>();
+ private Npc _sealOfGnosis;
+ private Npc _sealOfStrife;
+ private Npc _sealOfAvarice;
+ private Npc _sealOfPunishment;
+ private Npc _sealOfAwakening;
+ private Npc _sealOfCalamity;
+ private Npc _sealOfDestruction;
+ private static MonsterInstance _paragon;
+ private static GrandBossInstance _kain;
+ private static GrandBossInstance _etina;
+ private boolean _spawned = false;
+ private boolean _kain30 = false;
+ private boolean _kain60 = false;
+ private boolean _etina80 = false;
+ private boolean _etina15 = false;
+
+ public EtisVanEtina()
+ {
+ addEnterZoneId(ZONE_ID);
+ addExitZoneId(ZONE_ID);
+ addAttackId(CORRIDOR_MOBS);
+ addAttackId(KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+ addKillId(CORRIDOR_MOBS);
+ addKillId(PARAGON, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+
+ // Unlock
+ final StatSet info = GrandBossManager.getInstance().getStatSet(ETIS_VAN_ETINA1);
+ final int status = GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1);
+ if (status == DEAD)
+ {
+ final long time = info.getLong("respawn_time") - System.currentTimeMillis();
+ if (time > 0)
+ {
+ startQuestTimer("unlock_etina", time, null, null);
+ }
+ else
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+ else
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "unlock_etina":
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ break;
+ }
+ case "check_activity_task":
+ {
+ if ((_lastAction + 900000) < System.currentTimeMillis())
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ for (Creature creature : BOSS_ZONE.getCharactersInside())
+ {
+ if (creature != null)
+ {
+ if (creature.isNpc())
+ {
+ creature.deleteMe();
+ }
+ else if (creature.isPlayer())
+ {
+ creature.teleToLocation(MapRegionManager.getInstance().getTeleToLocation(creature, TeleportWhereType.TOWN));
+ }
+ }
+ }
+ startQuestTimer("end_etina", 2000, null, null);
+ }
+ else
+ {
+ startQuestTimer("check_activity_task", 60000, null, null);
+ }
+ break;
+ }
+ case "openInnerDoor":
+ {
+ openDoor(DOOR3, 0);
+ openDoor(DOOR4, 0);
+ startQuestTimer("show_intro_movie", 60000, null, null);
+ break;
+ }
+ case "show_intro_movie":
+ {
+ BOSS_ZONE.getPlayersInside().forEach(p ->
+ {
+ playMovie(p, Movie.SC_INZONE_KAIN_INTRO);
+ });
+ startQuestTimer("spawn_kain", 23000, null, null);
+ break;
+ }
+ case "spawn_kain":
+ {
+ closeDoor(DOOR1, 0);
+ closeDoor(DOOR2, 0);
+ closeDoor(DOOR3, 0);
+ closeDoor(DOOR4, 0);
+ _kain = (GrandBossInstance) addSpawn(KAIN_VAN_HALTER, KAIN_LOC, false, 0, true);
+ _etina = (GrandBossInstance) addSpawn(ETIS_VAN_ETINA1, ETINA_LOC, false, 0, true);
+ _etina.setInvul(true);
+ _etina.setTargetable(false);
+ _etina.setImmobilized(true);
+ BOSS_ZONE.getPlayersInside().forEach(p -> p.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_AND_HIS_APOSTLES_HAVE_APPEARED, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ break;
+ }
+ case "spawnTransformedEtina":
+ {
+ _etina = (GrandBossInstance) addSpawn(ETIS_VAN_ETINA2, KAIN_LOC, false, 0, true);
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ break;
+ }
+ case "cancel_timers":
+ {
+ QuestTimer activityTimer = getQuestTimer("check_activity_task", null, null);
+ if (activityTimer != null)
+ {
+ activityTimer.cancel();
+ }
+
+ QuestTimer forceEnd = getQuestTimer("end_etina", null, null);
+ if (forceEnd != null)
+ {
+ forceEnd.cancel();
+ }
+ break;
+ }
+ case "end_etina":
+ {
+ Clean();
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ protected void Clean()
+ {
+ BOSS_ZONE.getCharactersInside().forEach(mob ->
+ {
+ if (mob.isNpc())
+ {
+ mob.deleteMe();
+ }
+ });
+ if (_gnosisCastTask != null)
+ {
+ _gnosisCastTask.cancel(false);
+ _gnosisCastTask = null;
+ }
+ if (_strifeCastTask != null)
+ {
+ _strifeCastTask.cancel(false);
+ _strifeCastTask = null;
+ }
+ if (_avariceCastTask != null)
+ {
+ _avariceCastTask.cancel(false);
+ _avariceCastTask = null;
+ }
+ if (_punishmentCastTask != null)
+ {
+ _punishmentCastTask.cancel(false);
+ _punishmentCastTask = null;
+ }
+ if (_awakeningCastTask != null)
+ {
+ _awakeningCastTask.cancel(false);
+ _awakeningCastTask = null;
+ }
+ if (_calamityCastTask != null)
+ {
+ _calamityCastTask.cancel(false);
+ _calamityCastTask = null;
+ }
+ if (_destructionCastTask != null)
+ {
+ _destructionCastTask.cancel(false);
+ _destructionCastTask = null;
+ }
+ if (_collapseTask != null)
+ {
+ _collapseTask.cancel(false);
+ _collapseTask = null;
+ }
+ notifyEvent("cancel_timers", null, null);
+ BOSS_ZONE.oustAllPlayers();
+ closeDoor(DOOR1, 0);
+ closeDoor(DOOR2, 0);
+ closeDoor(DOOR3, 0);
+ closeDoor(DOOR4, 0);
+ if (GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1) != DEAD)
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
+ {
+ _lastAction = System.currentTimeMillis();
+ // Anti BUGGERS
+ if (!BOSS_ZONE.isInsideZone(attacker))
+ {
+ attacker.doDie(null);
+ LOGGER.warning(getName() + ": Character: " + attacker.getName() + " attacked: " + npc.getName() + " out of the boss zone!");
+ }
+ if (!BOSS_ZONE.isInsideZone(npc))
+ {
+ Spawn spawn = npc.getSpawn();
+ if (spawn != null)
+ {
+ npc.teleToLocation(spawn.getX(), spawn.getY(), spawn.getZ());
+ }
+ LOGGER.warning(getName() + ": Character: " + attacker.getName() + " attacked: " + npc.getName() + " wich is out of the boss zone!");
+ }
+ if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !_kain30)
+ {
+ _kain30 = true;
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !_kain60)
+ {
+ _kain60 = true;
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ }
+ }
+ else if ((npc.getId() == ETIS_VAN_ETINA1))
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.8)) && !_etina80)
+ {
+ _etina80 = true;
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ _etina.abortCast();
+ _etina.broadcastPacket(new MagicSkillUse(_etina, _etina, CALL_OF_SEVEN_SIGNS.getSkillId(), CALL_OF_SEVEN_SIGNS.getSkillLevel(), 3000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_USES_THE_POWER_OF_THE_SEVEN_SIGNS_TO_SUMMON_ALL_7_SEALS_INSIDE_THE_TEMPLE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ _sealOfGnosis = addSpawn(SEAL_OF_GNOSIS, SEAL_OF_GNOSIS_LOC);
+ _sealOfStrife = addSpawn(SEAL_OF_STRIFE, SEAL_OF_STRIFE_LOC);
+ _sealOfAvarice = addSpawn(SEAL_OF_AVARICE, SEAL_OF_AVARICE_LOC);
+ _sealOfPunishment = addSpawn(SEAL_OF_PUNISHMENT, SEAL_OF_PUNISHMENT_LOC);
+ _sealOfAwakening = addSpawn(SEAL_OF_AWAKENING, SEAL_OF_AWAKENING_LOC);
+ _sealOfCalamity = addSpawn(SEAL_OF_CALAMITY, SEAL_OF_CALAMITY_LOC);
+ _sealOfDestruction = addSpawn(SEAL_OF_DESTRUCTION, SEAL_OF_DESTRUCTION_LOC);
+ _gnosisCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfGnosis.setDisplayEffect(3);
+ _sealOfGnosis.broadcastPacket(new MagicSkillUse(_sealOfGnosis, _sealOfGnosis, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 1, 10000, 0));
+ int rnd = getRandom(BOSS_ZONE.getPlayersInside().size());
+ PlayerInstance member = BOSS_ZONE.getPlayersInside().get(rnd);
+ STIGMA_OF_REVELATION.getSkill().applyEffects(member, member);
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_REVELATION.getSkill().applyEffects(minion, minion);
+ ((Attackable) minion).addDamageHate(member, 0, 999999999);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_GNOSIS_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 10000, 120000);
+ _strifeCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfStrife.setDisplayEffect(3);
+ _sealOfStrife.broadcastPacket(new MagicSkillUse(_sealOfStrife, _sealOfStrife, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 2, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ CRY_OF_HOLY_WAR.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> STIGMA_OF_MARTYR.getSkill().applyEffects(player, player));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_STRIFE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 20000, 120000);
+ _avariceCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfAvarice.setDisplayEffect(3);
+ _sealOfAvarice.broadcastPacket(new MagicSkillUse(_sealOfAvarice, _sealOfAvarice, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 3, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ UNDEAD_CREATURE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_AVARICE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 30000, 120000);
+ _punishmentCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfPunishment.setDisplayEffect(3);
+ _sealOfPunishment.broadcastPacket(new MagicSkillUse(_sealOfPunishment, _sealOfPunishment, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 4, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_DIVINE_PUNISHMENT.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> ETINA_OBSERVATION.getSkill().applyEffects(player, player));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_PUNISHMENT_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 40000, 120000);
+ _awakeningCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfAwakening.setDisplayEffect(3);
+ _sealOfAwakening.broadcastPacket(new MagicSkillUse(_sealOfAwakening, _sealOfAwakening, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 5, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ RAGE_OF_THE_OPEN_EYE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_AWAKENING_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 50000, 120000);
+ _calamityCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfCalamity.setDisplayEffect(3);
+ // TODO: Seal of Calamity skill cast.
+ _sealOfCalamity.broadcastPacket(new MagicSkillUse(_sealOfCalamity, _sealOfCalamity, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 6, 10000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_CALAMITY_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 60000, 120000);
+ _destructionCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfDestruction.setDisplayEffect(3);
+ // TODO: Seal of Destruction skill cast.
+ _sealOfDestruction.broadcastPacket(new MagicSkillUse(_sealOfDestruction, _sealOfDestruction, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 7, 10000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_DESTRUCTION_ACTIVATES_AND_THE_ENTIRE_ETINA_GREAT_TEMPLE_IS_NOW_UNDER_THE_INFLUENCE_OF_THE_SEAL, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 70000, 120000);
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.15)) && !_etina15)
+ {
+ _etina15 = true;
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ // TODO: decrease etina and seals power
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_AND_THE_POWER_OF_SEVEN_SEALS_ARE_WEAKENING, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onEnterZone(Creature character, ZoneType zone)
+ {
+ if (zone.getId() == ZONE_ID)
+ {
+ if (_collapseTask != null)
+ {
+ _collapseTask.cancel(true);
+ _collapseTask = null;
+ }
+ if ((GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1) == WAITING) && !_spawned)
+ {
+ _spawned = true;
+ _spawns.clear();
+ _barricadeSpawns.clear();
+ for (SpawnHolder spawn : SPAWNS_CORRIDOR)
+ {
+ _spawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ for (SpawnHolder spawn : SPAWNS_BARRICADE)
+ {
+ _barricadeSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ _paragon = (MonsterInstance) addSpawn(PARAGON, PARAGON_LOC);
+ _paragon.setInvul(true);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_T_DEFEAT_PARAGON_WHILE_PARAGON_S_MINIONS_ARE_ALIVE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, FIGHTING);
+ _lastAction = System.currentTimeMillis();
+ startQuestTimer("check_activity_task", 60000, null, null, true);
+ }
+ }
+ return super.onEnterZone(character, zone);
+ }
+
+ @Override
+ public String onExitZone(Creature character, ZoneType zone)
+ {
+ if (zone.getId() == ZONE_ID)
+ {
+ if (zone.getPlayersInside().isEmpty())
+ {
+ _collapseTask = ThreadPool.schedule(() -> Clean(), 900000);
+ }
+ }
+ return super.onExitZone(character, zone);
+ }
+
+ @Override
+ public String onKill(Npc npc, PlayerInstance killer, boolean isPet)
+ {
+ if (npc.getId() == ETIS_VAN_ETINA1)
+ {
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_ETIS_VAN_ETINA_TRANS);
+ });
+ startQuestTimer("spawnTransformedEtina", 15000, null, null);
+ }
+ else if (npc.getId() == ETIS_VAN_ETINA2)
+ {
+ notifyEvent("cancel_timers", null, null);
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_ETIS_VAN_ETINA_ENDING);
+ });
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, DEAD);
+ final long respawnTime = (Config.ETINA_SPAWN_INTERVAL + getRandom(-Config.ETINA_SPAWN_RANDOM, Config.ETINA_SPAWN_RANDOM)) * 3600000;
+ final StatSet info = GrandBossManager.getInstance().getStatSet(ETIS_VAN_ETINA1);
+ info.set("respawn_time", System.currentTimeMillis() + respawnTime);
+ GrandBossManager.getInstance().setStatSet(ETIS_VAN_ETINA1, info);
+
+ startQuestTimer("unlock_etina", respawnTime, null, null);
+ startQuestTimer("end_etina", 900000, null, null);
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS, npc.getId()))
+ {
+ _spawns.remove(npc);
+ if (_spawns.isEmpty())
+ {
+ _paragon.setInvul(false);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }
+ }
+ else if (npc.getId() == PARAGON)
+ {
+ openDoor(DOOR1, 0);
+ openDoor(DOOR2, 0);
+ startQuestTimer("openInnerDoor", 30000, null, null);
+ }
+ else if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ minion.doDie(null);
+ }
+ });
+ _etina.setInvul(false);
+ _etina.setImmobilized(false);
+ _etina.setTargetable(true);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_APPROACHES, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ _kain.deleteMe();
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_KAIN_BOSS_ENDING);
+ });
+ }
+ return super.onKill(npc, killer, isPet);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtisVanEtina();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
new file mode 100644
index 0000000000..b66a737f71
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class GreatTempleDarkJudge extends AbstractNpcAI
+{
+ // Npc
+ private static final int GREAT_TEMPLE_DARK_JUDGE = 24095;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private GreatTempleDarkJudge()
+ {
+ registerMobs(GREAT_TEMPLE_DARK_JUDGE);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == GREAT_TEMPLE_DARK_JUDGE)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new GreatTempleDarkJudge();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
new file mode 100644
index 0000000000..ef143e1088
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class GreatTempleSoulGuide extends AbstractNpcAI
+{
+ // Npc
+ private static final int GREAT_TEMPLE_SOUL_GUIDE = 24094;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private GreatTempleSoulGuide()
+ {
+ registerMobs(GREAT_TEMPLE_SOUL_GUIDE);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == GREAT_TEMPLE_SOUL_GUIDE)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new GreatTempleSoulGuide();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
new file mode 100644
index 0000000000..5ba7f93bff
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class JudgeOfHeresy extends AbstractNpcAI
+{
+ // Npc
+ private static final int JUDGE_OF_HERESY = 24077;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private JudgeOfHeresy()
+ {
+ registerMobs(JUDGE_OF_HERESY);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == JUDGE_OF_HERESY)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new JudgeOfHeresy();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
new file mode 100644
index 0000000000..ec40bf98cf
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
@@ -0,0 +1,187 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Kain extends AbstractNpcAI
+{
+ // Npc
+ private static final int KAIN_VAN_HALTER = 29320;
+ // Skills
+ private static final SkillHolder WALL_OF_VOID = new SkillHolder(32003, 1);
+ private static final SkillHolder FLASH_OF_DARKNESS = new SkillHolder(32007, 1);
+ private static final SkillHolder BANE_BLADE = new SkillHolder(32010, 1);
+ private static final SkillHolder SPINNING_SHADOW = new SkillHolder(32011, 1);
+
+ private Kain()
+ {
+ registerMobs(KAIN_VAN_HALTER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = WALL_OF_VOID;
+ }
+ else if (getRandom(100) < 30)
+ {
+ skillToCast = SPINNING_SHADOW;
+ }
+ else if (getRandom(100) < 50)
+ {
+ skillToCast = FLASH_OF_DARKNESS;
+ }
+ else
+ {
+ skillToCast = BANE_BLADE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new Kain();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
new file mode 100644
index 0000000000..3ac3966287
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class LiberatorOfLust extends AbstractNpcAI
+{
+ // Npc
+ private static final int LIBERATOR_OF_LUST = 29324;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private LiberatorOfLust()
+ {
+ registerMobs(LIBERATOR_OF_LUST);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == LIBERATOR_OF_LUST)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new LiberatorOfLust();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
new file mode 100644
index 0000000000..c029102a64
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class SeekerOfDespair extends AbstractNpcAI
+{
+ // Npc
+ private static final int SEEKER_OF_DESPAIR = 29323;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private SeekerOfDespair()
+ {
+ registerMobs(SEEKER_OF_DESPAIR);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == SEEKER_OF_DESPAIR)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new SeekerOfDespair();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
new file mode 100644
index 0000000000..3da99f7d62
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class SoulDestroyer extends AbstractNpcAI
+{
+ // Npc
+ private static final int SOUL_DESTROYER = 24076;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private SoulDestroyer()
+ {
+ registerMobs(SOUL_DESTROYER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == SOUL_DESTROYER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new SoulDestroyer();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
new file mode 100644
index 0000000000..16ad7ae0e5
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleArchon extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_ARCHON = 24085;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private TempleArchon()
+ {
+ registerMobs(TEMPLE_ARCHON);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_ARCHON)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleArchon();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
new file mode 100644
index 0000000000..7a6eacccbc
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleDarkWizard extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_DARK_WIZARD = 24083;
+ // Skills
+ private static final SkillHolder DARK_BREAKER = new SkillHolder(32289, 1);
+ private static final SkillHolder VAMPIRIC_FORCE = new SkillHolder(32294, 1);
+
+ private TempleDarkWizard()
+ {
+ registerMobs(TEMPLE_DARK_WIZARD);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_DARK_WIZARD)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = VAMPIRIC_FORCE;
+ }
+ else
+ {
+ skillToCast = DARK_BREAKER;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleDarkWizard();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
new file mode 100644
index 0000000000..509a7816b5
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleFlameMaster extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_FLAME_MASTER = 24084;
+ // Skills
+ private static final SkillHolder DARK_BREAKER = new SkillHolder(32289, 1);
+ private static final SkillHolder BLOOD_TO_FLESH = new SkillHolder(32302, 1);
+
+ private TempleFlameMaster()
+ {
+ registerMobs(TEMPLE_FLAME_MASTER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_FLAME_MASTER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = BLOOD_TO_FLESH;
+ }
+ else
+ {
+ skillToCast = DARK_BREAKER;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleFlameMaster();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
new file mode 100644
index 0000000000..a7d200da1e
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleHighPriest extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_HIGH_PRIEST = 24086;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private TempleHighPriest()
+ {
+ registerMobs(TEMPLE_HIGH_PRIEST);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_HIGH_PRIEST)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleHighPriest();
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
index a7f585c05a..c2e4514976 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
@@ -51,6 +51,7 @@
+
diff --git a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/Config.java b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/Config.java
index fbc39be7e5..4b16ecbe3e 100644
--- a/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_6.0_Fafurion/java/org/l2jmobius/Config.java
@@ -915,6 +915,13 @@ public class Config
public static int RAMONA_SPAWN_RANDOM;
public static int RAMONA_MIN_PLAYER;
+ // Etis van Etina
+ public static int ETINA_SPAWN_INTERVAL;
+ public static int ETINA_SPAWN_RANDOM;
+ public static int ETINA_MIN_PLAYERS;
+ public static int ETINA_MAX_PLAYERS;
+ public static int ETINA_MIN_PLAYER_LVL;
+
// Fafurion
public static int FAFURION_WAIT_TIME;
public static int FAFURION_SPAWN_INTERVAL;
@@ -2478,6 +2485,11 @@ public class Config
RAMONA_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfRamonaSpawn", 72);
RAMONA_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfRamonaSpawn", 48);
RAMONA_MIN_PLAYER = GrandBossSettings.getInt("RamonaMinPlayers", 7);
+ ETINA_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfEtinaSpawn", 264);
+ ETINA_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfEtinaSpawn", 72);
+ ETINA_MIN_PLAYERS = GrandBossSettings.getInt("EtinaMinPlayers", 49);
+ ETINA_MAX_PLAYERS = GrandBossSettings.getInt("EtinaMaxPlayers", 112);
+ ETINA_MIN_PLAYER_LVL = GrandBossSettings.getInt("EtinaMinPlayerLvl", 103);
FAFURION_WAIT_TIME = GrandBossSettings.getInt("FafurionWaitTime", 10);
FAFURION_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfFafurionSpawn", 264);
FAFURION_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfFafurionSpawn", 72);
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/config/GrandBoss.ini b/L2J_Mobius_7.0_PreludeOfWar/dist/game/config/GrandBoss.ini
index 52fbe3441f..9277083115 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/dist/game/config/GrandBoss.ini
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/config/GrandBoss.ini
@@ -198,6 +198,25 @@ HeliosMinPlayers = 70
# Minimum players Level for enter to Helios. Retail: 102
HeliosMinPlayerLvl = 99
+# ---------------------------------------------------------------------------
+# Etis Van Etina
+# ---------------------------------------------------------------------------
+
+# Interval time of Etis Van Etina. Value is hour. Range 1-480. Retail: 264
+IntervalOfEtinaSpawn = 72
+
+# Random interval. Range 1-192. Retail: 72
+RandomOfEtinaSpawn = 1
+
+# Minimal count of players for enter to Etis Van Etina. Retail: 49
+EtinaMinPlayers = 2
+
+# Maximum count of players for enter to Etis Van Etina. Retail: 112
+EtinaMaxPlayers = 112
+
+# Minimum players Level for enter to Etis Van Etina. Retail: 99
+EtinaMinPlayerLvl = 103
+
# ---------------------------------------------------------------------------
# Fafurion
# ---------------------------------------------------------------------------
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
new file mode 100644
index 0000000000..7024487136
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-1.html
@@ -0,0 +1,4 @@
+Erda:
+On the Etis van Etina there is an attack!
+At this time it's impossible to enter the temple.
+
\ No newline at end of file
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
new file mode 100644
index 0000000000..f8fff8d713
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-2.html
@@ -0,0 +1,4 @@
+Erda:
+Etis van Etina? You're too late, friend.
+A group of warriors drove him off not long ago.
+
\ No newline at end of file
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
new file mode 100644
index 0000000000..4926daed35
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-3.html
@@ -0,0 +1,4 @@
+Erda:
+You are overcome by a voice, a voice so powerful you are helpless as it speaks:
+(The players who belong to an association can only enter through the Association Leader.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
new file mode 100644
index 0000000000..3c8b9fc2ac
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-4.html
@@ -0,0 +1,3 @@
+Erda:
+(A command channel needs at least minimum: %min% and maximum: %max% members to challenge Etis van Etina.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
new file mode 100644
index 0000000000..3f33bfb866
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319-5.html
@@ -0,0 +1,3 @@
+Erda:
+(A command channel members level must be minimum: %minlvl% Lvl or higher to challenge Etis van Etina.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
new file mode 100644
index 0000000000..0e5f31ce70
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/34319.html
@@ -0,0 +1,7 @@
+Erda:
+Thank you. Without your help, we couldn't have won easily.
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
new file mode 100644
index 0000000000..b774fcf6d7
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/areas/KeucereusAllianceBase/Erda/Erda.java
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.areas.KeucereusAllianceBase.Erda;
+
+import java.util.List;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Party;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Erda extends AbstractNpcAI
+{
+ // NPCs
+ private static final int ERDA = 34319;
+ private static final int ETINA_RAID = 29318;
+ // Location
+ private static final Location ENTER_LOC = new Location(-245778, 181088, 2860);
+ private static final Location CAMILLE_LOC = new Location(-245758, 149020, 11838);
+
+ public Erda()
+ {
+ addFirstTalkId(ERDA);
+ addTalkId(ERDA);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ if (event.equals("teleport"))
+ {
+ final int status = GrandBossManager.getInstance().getBossStatus(ETINA_RAID);
+ if (player.isGM())
+ {
+ player.teleToLocation(ENTER_LOC, true);
+ GrandBossManager.getInstance().setBossStatus(ETINA_RAID, 1);
+ }
+ else
+ {
+ if (status == 1)
+ {
+ return "34319-1.html";
+ }
+ if (status == 2)
+ {
+ return "34319-2.html";
+ }
+ if (!player.isInParty())
+ {
+ return "34319-3.html";
+ }
+ final Party party = player.getParty();
+ final boolean isInCC = party.isInCommandChannel();
+ final List members = (isInCC) ? party.getCommandChannel().getMembers() : party.getMembers();
+ final boolean isPartyLeader = (isInCC) ? party.getCommandChannel().isLeader(player) : party.isLeader(player);
+ if (!isPartyLeader)
+ {
+ return "34319-3.html";
+ }
+ if ((members.size() < Config.ETINA_MIN_PLAYERS) || (members.size() > Config.ETINA_MAX_PLAYERS))
+ {
+ final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
+ packet.setHtml(getHtm(player, "34319-4.html"));
+ packet.replace("%min%", Integer.toString(Config.ETINA_MIN_PLAYERS));
+ packet.replace("%max%", Integer.toString(Config.ETINA_MAX_PLAYERS));
+ player.sendPacket(packet);
+ return null;
+ }
+ for (PlayerInstance member : members)
+ {
+ if (member.getLevel() < Config.ETINA_MIN_PLAYER_LVL)
+ {
+ final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
+ packet.setHtml(getHtm(player, "34319-5.html"));
+ packet.replace("%minlvl%", Integer.toString(Config.ETINA_MIN_PLAYER_LVL));
+ player.sendPacket(packet);
+ return null;
+ }
+ }
+ for (PlayerInstance member : members)
+ {
+ if (member.isInsideRadius3D(npc, Config.ALT_PARTY_RANGE))
+ {
+ member.teleToLocation(ENTER_LOC, false);
+ GrandBossManager.getInstance().setBossStatus(ETINA_RAID, 1);
+ }
+ }
+ }
+ }
+ else if (event.equals("tp_inner"))
+ {
+ player.teleToLocation(CAMILLE_LOC, true);
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onFirstTalk(Npc npc, PlayerInstance player)
+ {
+ return "34319.html";
+ }
+
+ public static void main(String[] args)
+ {
+ new Erda();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
new file mode 100644
index 0000000000..b16cd7626e
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/ChoirOfDarkness.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class ChoirOfDarkness extends AbstractNpcAI
+{
+ // NPC
+ private static final int CHOIR_OF_DARKNESS = 24078;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private ChoirOfDarkness()
+ {
+ registerMobs(CHOIR_OF_DARKNESS);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == CHOIR_OF_DARKNESS)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new ChoirOfDarkness();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
new file mode 100644
index 0000000000..045a67482c
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Etina.java
@@ -0,0 +1,188 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Etina extends AbstractNpcAI
+{
+ // Npc
+ private static final int ETINA1 = 29318;
+ private static final int ETINA2 = 29319;
+ // Skills
+ private static final SkillHolder APOCALYPSE_FIRE = new SkillHolder(32001, 1);
+ private static final SkillHolder DEMOLISH_GROUND = new SkillHolder(32002, 1);
+ private static final SkillHolder WALL_OF_VOID = new SkillHolder(32003, 1);
+ private static final SkillHolder FLASH_OF_DARKNESS = new SkillHolder(32007, 1);
+
+ private Etina()
+ {
+ registerMobs(ETINA1, ETINA2);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if ((npc.getId() == ETINA1) || (npc.getId() == ETINA2))
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = WALL_OF_VOID;
+ }
+ else if (getRandom(100) < 30)
+ {
+ skillToCast = DEMOLISH_GROUND;
+ }
+ else if (getRandom(100) < 50)
+ {
+ skillToCast = FLASH_OF_DARKNESS;
+ }
+ else
+ {
+ skillToCast = APOCALYPSE_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new Etina();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
new file mode 100644
index 0000000000..c2be351b76
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/EtisVanEtina.java
@@ -0,0 +1,785 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.concurrent.ThreadPool;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.Movie;
+import org.l2jmobius.gameserver.enums.TeleportWhereType;
+import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
+import org.l2jmobius.gameserver.instancemanager.MapRegionManager;
+import org.l2jmobius.gameserver.instancemanager.ZoneManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Spawn;
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Attackable;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
+import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.holders.SpawnHolder;
+import org.l2jmobius.gameserver.model.quest.QuestTimer;
+import org.l2jmobius.gameserver.model.zone.ZoneType;
+import org.l2jmobius.gameserver.model.zone.type.NoRestartZone;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class EtisVanEtina extends AbstractNpcAI
+{
+ // Status
+ private static final int ALIVE = 0;
+ private static final int WAITING = 1;
+ private static final int FIGHTING = 2;
+ private static final int DEAD = 3;
+ // NPCs
+ private static final int ETIS_VAN_ETINA1 = 29318;
+ private static final int ETIS_VAN_ETINA2 = 29319;
+ private static final int KAIN_VAN_HALTER = 29320;
+ // Corridor Mobs
+ private static final int TEMPLE_ARCHON = 24085;
+ private static final int TEMPLE_RAIDER = 24079;
+ private static final int TEMPLE_GUARD_CAPTAIN = 24081;
+ private static final int TEMPLE_ELITE_CAPTAIN = 24082;
+ private static final int TEMPLE_FLAME_MASTER = 24084;
+ private static final int TEMPLE_PASSIONATE_SOLDIER = 24080;
+ private static final int TEMPLE_DARK_WIZARD = 24083;
+ private static final int GREAT_TEMPLE_DECANUS = 24093;
+ private static final int GREAT_TEMPLE_SIEGE_CHARIOT = 24096;
+ private static final int GREAT_TEMPLE_SOUL_GUIDE = 24094;
+ private static final int SOUL_DESTROYER = 24076;
+ private static final int BLIND_BERSERKER = 24075;
+ private static final int SOUL_REAPER = 24074;
+ private static final int JUDGE_OF_HERESY = 24077;
+ private static final int GREAT_TEMPLE_DARK_JUDGE = 24095;
+ private static final int GREAT_TEMPLE_BUTCHER = 24092;
+ private static final int CHOIR_OF_DARKNESS = 24078;
+ private static final int TEMPLE_HIGH_PRIEST = 24086;
+ private static final int CREED_GUARDIAN = 24073;
+ private static final int PARAGON = 24072;
+ //@formatter:off
+ private static final int[] CORRIDOR_MOBS = {24085, 24079, 24081, 24082, 24084, 24080, 24083, 24093, 24096, 24094, 24076, 24075, 24074, 24077, 24095, 24092, 24078, 24086, 24073};
+ //@formatter:on
+ // Minions
+ private static final int MARTYR_OF_GREED = 29321;
+ private static final int LIBERATOR_OF_LUST = 29324;
+ private static final int SEEKER_OF_DESPAIR = 29323;
+ private static final int GUIDE_OF_PRIDE = 29322;
+ // Seals
+ private static final int SEAL_OF_GNOSIS = 19677;
+ private static final int SEAL_OF_STRIFE = 19678;
+ private static final int SEAL_OF_AVARICE = 19679;
+ private static final int SEAL_OF_PUNISHMENT = 19680;
+ private static final int SEAL_OF_AWAKENING = 19681;
+ private static final int SEAL_OF_CALAMITY = 19682;
+ private static final int SEAL_OF_DESTRUCTION = 19683;
+ // Others
+ private static final int BARRICADE = 19724;
+ private static final int DOOR1 = 12230702;
+ private static final int DOOR2 = 12230704;
+ private static final int DOOR3 = 12230802;
+ private static final int DOOR4 = 12230804;
+ // Location
+ private static final Location PARAGON_LOC = new Location(-245757, 187778, 3042);
+ private static final Location ETINA_LOC = new Location(-245765, 194229, 3200);
+ private static final Location KAIN_LOC = new Location(-245766, 192148, 3054);
+ private static final Location SEAL_OF_GNOSIS_LOC = new Location(-246859, 193321, 3045);
+ private static final Location SEAL_OF_STRIFE_LOC = new Location(-246888, 192729, 3045);
+ private static final Location SEAL_OF_AVARICE_LOC = new Location(-246896, 192148, 3045);
+ private static final Location SEAL_OF_PUNISHMENT_LOC = new Location(-244640, 193331, 3044);
+ private static final Location SEAL_OF_AWAKENING_LOC = new Location(-244647, 192739, 3045);
+ private static final Location SEAL_OF_CALAMITY_LOC = new Location(-244641, 192155, 3045);
+ private static final Location SEAL_OF_DESTRUCTION_LOC = new Location(-244640, 191566, 3045);
+
+ private static final int ZONE_ID = 85001;
+ private static final NoRestartZone BOSS_ZONE = ZoneManager.getInstance().getZoneById(ZONE_ID, NoRestartZone.class);
+ // Spawns
+ private static final List SPAWNS_CORRIDOR = new ArrayList<>();
+ static
+ {
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246089, 182518, 2861, 62581, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245778, 182749, 2861, 57797, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245538, 182930, 2861, 34847, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246012, 183159, 2870, 40700, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245798, 183316, 2900, 59692, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -245509, 183575, 2950, 59859, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ARCHON, -246020, 183718, 2977, 46596, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245913, 182571, 2860, 18939, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245682, 182685, 2860, 59705, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245583, 182903, 2860, 38901, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245949, 183012, 2860, 21081, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245925, 183334, 2904, 10282, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_RAIDER, -245626, 183509, 2937, 22384, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245682, 182497, 2861, 48877, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245930, 182710, 2861, 44855, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245482, 183005, 2861, 24815, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245874, 183345, 2906, 62359, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -245578, 183496, 2935, 58218, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_GUARD_CAPTAIN, -246033, 183721, 2978, 10200, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245864, 182593, 2860, 39881, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245512, 182948, 2860, 17444, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245987, 183275, 2893, 24335, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -246008, 183765, 2986, 65472, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_ELITE_CAPTAIN, -245595, 183581, 2951, 35910, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245643, 182807, 2860, 52098, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245871, 183166, 2872, 62597, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245615, 183452, 2927, 15114, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245874, 183716, 2977, 38121, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_FLAME_MASTER, -245602, 183883, 3009, 25130, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245923, 182788, 2860, 7524, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245569, 182962, 2860, 45906, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245949, 183312, 2899, 56352, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245651, 183439, 2924, 57404, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -246156, 183790, 2991, 33176, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_PASSIONATE_SOLDIER, -245587, 183823, 2997, 33966, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245762, 182706, 2860, 46796, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245638, 182913, 2860, 63991, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245867, 183306, 2899, 14493, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245804, 183800, 2993, 47355, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_DARK_WIZARD, -245598, 183551, 2945, 37399, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_DECANUS, -245754, 184113, 3025, 47953, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_SIEGE_CHARIOT, -245762, 184863, 3029, 49151, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_SOUL_GUIDE, -245764, 185502, 3032, 45247, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_DARK_JUDGE, -245753, 186185, 3036, 48708, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(GREAT_TEMPLE_BUTCHER, -245767, 186756, 3039, 47997, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246081, 184205, 3026, 21350, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245571, 184303, 3026, 21662, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246034, 184943, 3029, 981, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245755, 184691, 3028, 11973, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245493, 185001, 3030, 22853, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245770, 185342, 3032, 46786, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246034, 185701, 3033, 38598, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245530, 185713, 3033, 22746, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245772, 186029, 3035, 53127, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -246032, 186381, 3037, 57199, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245503, 186312, 3037, 25473, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245905, 186684, 3038, 20419, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245585, 186936, 3041, 25482, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245999, 187393, 3042, 2323, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_DESTROYER, -245435, 187610, 3042, 30564, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245482, 184347, 3027, 5631, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245885, 184457, 3027, 31148, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245604, 184817, 3029, 55428, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245954, 185193, 3031, 56275, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245566, 185624, 3033, 19880, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245882, 185959, 3035, 53078, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245860, 186723, 3039, 50920, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245556, 186293, 3036, 27689, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245524, 187226, 3042, 33041, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(BLIND_BERSERKER, -245903, 187548, 3042, 10250, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245898, 184129, 3025, 56279, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245720, 184633, 3028, 48934, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245639, 185160, 3031, 57162, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245940, 185549, 3033, 43554, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245635, 185848, 3034, 34721, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245858, 186299, 3036, 60699, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245610, 186904, 3040, 64217, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -245394, 187605, 3042, 36104, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(SOUL_REAPER, -246023, 187593, 3042, 58782, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245659, 184163, 3025, 36852, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245910, 184620, 3028, 43041, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245751, 185242, 3031, 49837, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245519, 185631, 3033, 18471, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245876, 185902, 3034, 46344, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245872, 186422, 3037, 29263, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245609, 186755, 3039, 31045, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245992, 187241, 3042, 24909, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(JUDGE_OF_HERESY, -245429, 187640, 3042, 21779, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245434, 184197, 3026, 48401, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245998, 184978, 3030, 45247, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245499, 185745, 3033, 6215, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -246027, 186380, 3037, 56728, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CHOIR_OF_DARKNESS, -245738, 187327, 3042, 19747, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245765, 184466, 3027, 60537, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245770, 185150, 3030, 50987, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245766, 185731, 3033, 25432, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245761, 186396, 3037, 48080, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(TEMPLE_HIGH_PRIEST, -245759, 187011, 3041, 23104, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245877, 184118, 3025, 41582, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245627, 184861, 3029, 46344, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245933, 185634, 3033, 58408, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245569, 186351, 3037, 24389, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245920, 186924, 3040, 32558, false));
+ SPAWNS_CORRIDOR.add(new SpawnHolder(CREED_GUARDIAN, -245510, 187534, 3042, 27370, false));
+ }
+ private static final List SPAWNS_BARRICADE = new ArrayList<>();
+ static
+ {
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246068, 182171, 2860, 47916, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245523, 182378, 2860, 48500, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246044, 182760, 2860, 48949, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245731, 183026, 2860, 47934, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246044, 183466, 2929, 51168, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245486, 183398, 2916, 47429, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245760, 183696, 2973, 49488, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246034, 183972, 3024, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245484, 183965, 3024, 49075, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245762, 184305, 3026, 48894, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246040, 184694, 3028, 48838, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245478, 184653, 3028, 48932, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245763, 185026, 3030, 49099, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246035, 185335, 3031, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245483, 185328, 3031, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245764, 185620, 3033, 49389, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246035, 185973, 3035, 49208, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245482, 185972, 3035, 49360, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245757, 186296, 3036, 49060, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -246038, 186578, 3038, 49151, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245481, 186569, 3038, 49041, false));
+ SPAWNS_BARRICADE.add(new SpawnHolder(BARRICADE, -245763, 186884, 3040, 48798, false));
+ }
+ private static final List SPAWNS_MINIONS = new ArrayList<>();
+ static
+ {
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(MARTYR_OF_GREED, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(LIBERATOR_OF_LUST, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(SEEKER_OF_DESPAIR, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ SPAWNS_MINIONS.add(new SpawnHolder(GUIDE_OF_PRIDE, KAIN_LOC, 0, false));
+ }
+ // Skills
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS = new SkillHolder(32317, 1);
+ private static final SkillHolder CALL_OF_SEVEN_SIGNS_SEAL_N = new SkillHolder(32004, 1);
+ private static final SkillHolder ETINA_REVELATION = new SkillHolder(32014, 2);
+ private static final SkillHolder STIGMA_OF_REVELATION = new SkillHolder(32015, 1);
+ private static final SkillHolder CRY_OF_HOLY_WAR = new SkillHolder(32017, 2);
+ private static final SkillHolder STIGMA_OF_MARTYR = new SkillHolder(32018, 1);
+ private static final SkillHolder UNDEAD_CREATURE = new SkillHolder(32020, 2);
+ private static final SkillHolder ETINA_DIVINE_PUNISHMENT = new SkillHolder(32023, 2);
+ private static final SkillHolder ETINA_OBSERVATION = new SkillHolder(32024, 2);
+ private static final SkillHolder RAGE_OF_THE_OPEN_EYE = new SkillHolder(32026, 2);
+ // Camille -> Horseshoe Trampling, Horizon Bash, Joust Lunge, Call of Etina (summon minions?)
+ // Vars
+ private static long _lastAction;
+ protected ScheduledFuture> _collapseTask;
+ protected ScheduledFuture> _gnosisCastTask;
+ protected ScheduledFuture> _strifeCastTask;
+ protected ScheduledFuture> _avariceCastTask;
+ protected ScheduledFuture> _punishmentCastTask;
+ protected ScheduledFuture> _awakeningCastTask;
+ // summon 5 black holes, that uses skill Explosion of Calamity(32029, 1)
+ protected ScheduledFuture> _calamityCastTask;
+ // summon 5 black holes, that uses skill Cyclone of Chaos(32028, 1)
+ protected ScheduledFuture> _destructionCastTask;
+ private static List _spawns = new ArrayList<>();
+ private static List _barricadeSpawns = new ArrayList<>();
+ private static List _minionSpawns = new ArrayList<>();
+ private Npc _sealOfGnosis;
+ private Npc _sealOfStrife;
+ private Npc _sealOfAvarice;
+ private Npc _sealOfPunishment;
+ private Npc _sealOfAwakening;
+ private Npc _sealOfCalamity;
+ private Npc _sealOfDestruction;
+ private static MonsterInstance _paragon;
+ private static GrandBossInstance _kain;
+ private static GrandBossInstance _etina;
+ private boolean _spawned = false;
+ private boolean _kain30 = false;
+ private boolean _kain60 = false;
+ private boolean _etina80 = false;
+ private boolean _etina15 = false;
+
+ public EtisVanEtina()
+ {
+ addEnterZoneId(ZONE_ID);
+ addExitZoneId(ZONE_ID);
+ addAttackId(CORRIDOR_MOBS);
+ addAttackId(KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+ addKillId(CORRIDOR_MOBS);
+ addKillId(PARAGON, KAIN_VAN_HALTER, ETIS_VAN_ETINA1, ETIS_VAN_ETINA2);
+
+ // Unlock
+ final StatSet info = GrandBossManager.getInstance().getStatSet(ETIS_VAN_ETINA1);
+ final int status = GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1);
+ if (status == DEAD)
+ {
+ final long time = info.getLong("respawn_time") - System.currentTimeMillis();
+ if (time > 0)
+ {
+ startQuestTimer("unlock_etina", time, null, null);
+ }
+ else
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+ else
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "unlock_etina":
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ break;
+ }
+ case "check_activity_task":
+ {
+ if ((_lastAction + 900000) < System.currentTimeMillis())
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ for (Creature creature : BOSS_ZONE.getCharactersInside())
+ {
+ if (creature != null)
+ {
+ if (creature.isNpc())
+ {
+ creature.deleteMe();
+ }
+ else if (creature.isPlayer())
+ {
+ creature.teleToLocation(MapRegionManager.getInstance().getTeleToLocation(creature, TeleportWhereType.TOWN));
+ }
+ }
+ }
+ startQuestTimer("end_etina", 2000, null, null);
+ }
+ else
+ {
+ startQuestTimer("check_activity_task", 60000, null, null);
+ }
+ break;
+ }
+ case "openInnerDoor":
+ {
+ openDoor(DOOR3, 0);
+ openDoor(DOOR4, 0);
+ startQuestTimer("show_intro_movie", 60000, null, null);
+ break;
+ }
+ case "show_intro_movie":
+ {
+ BOSS_ZONE.getPlayersInside().forEach(p ->
+ {
+ playMovie(p, Movie.SC_INZONE_KAIN_INTRO);
+ });
+ startQuestTimer("spawn_kain", 23000, null, null);
+ break;
+ }
+ case "spawn_kain":
+ {
+ closeDoor(DOOR1, 0);
+ closeDoor(DOOR2, 0);
+ closeDoor(DOOR3, 0);
+ closeDoor(DOOR4, 0);
+ _kain = (GrandBossInstance) addSpawn(KAIN_VAN_HALTER, KAIN_LOC, false, 0, true);
+ _etina = (GrandBossInstance) addSpawn(ETIS_VAN_ETINA1, ETINA_LOC, false, 0, true);
+ _etina.setInvul(true);
+ _etina.setTargetable(false);
+ _etina.setImmobilized(true);
+ BOSS_ZONE.getPlayersInside().forEach(p -> p.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_AND_HIS_APOSTLES_HAVE_APPEARED, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ break;
+ }
+ case "spawnTransformedEtina":
+ {
+ _etina = (GrandBossInstance) addSpawn(ETIS_VAN_ETINA2, KAIN_LOC, false, 0, true);
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ break;
+ }
+ case "cancel_timers":
+ {
+ QuestTimer activityTimer = getQuestTimer("check_activity_task", null, null);
+ if (activityTimer != null)
+ {
+ activityTimer.cancel();
+ }
+
+ QuestTimer forceEnd = getQuestTimer("end_etina", null, null);
+ if (forceEnd != null)
+ {
+ forceEnd.cancel();
+ }
+ break;
+ }
+ case "end_etina":
+ {
+ Clean();
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ protected void Clean()
+ {
+ BOSS_ZONE.getCharactersInside().forEach(mob ->
+ {
+ if (mob.isNpc())
+ {
+ mob.deleteMe();
+ }
+ });
+ if (_gnosisCastTask != null)
+ {
+ _gnosisCastTask.cancel(false);
+ _gnosisCastTask = null;
+ }
+ if (_strifeCastTask != null)
+ {
+ _strifeCastTask.cancel(false);
+ _strifeCastTask = null;
+ }
+ if (_avariceCastTask != null)
+ {
+ _avariceCastTask.cancel(false);
+ _avariceCastTask = null;
+ }
+ if (_punishmentCastTask != null)
+ {
+ _punishmentCastTask.cancel(false);
+ _punishmentCastTask = null;
+ }
+ if (_awakeningCastTask != null)
+ {
+ _awakeningCastTask.cancel(false);
+ _awakeningCastTask = null;
+ }
+ if (_calamityCastTask != null)
+ {
+ _calamityCastTask.cancel(false);
+ _calamityCastTask = null;
+ }
+ if (_destructionCastTask != null)
+ {
+ _destructionCastTask.cancel(false);
+ _destructionCastTask = null;
+ }
+ if (_collapseTask != null)
+ {
+ _collapseTask.cancel(false);
+ _collapseTask = null;
+ }
+ notifyEvent("cancel_timers", null, null);
+ BOSS_ZONE.oustAllPlayers();
+ closeDoor(DOOR1, 0);
+ closeDoor(DOOR2, 0);
+ closeDoor(DOOR3, 0);
+ closeDoor(DOOR4, 0);
+ if (GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1) != DEAD)
+ {
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, ALIVE);
+ }
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
+ {
+ _lastAction = System.currentTimeMillis();
+ // Anti BUGGERS
+ if (!BOSS_ZONE.isInsideZone(attacker))
+ {
+ attacker.doDie(null);
+ LOGGER.warning(getName() + ": Character: " + attacker.getName() + " attacked: " + npc.getName() + " out of the boss zone!");
+ }
+ if (!BOSS_ZONE.isInsideZone(npc))
+ {
+ Spawn spawn = npc.getSpawn();
+ if (spawn != null)
+ {
+ npc.teleToLocation(spawn.getX(), spawn.getY(), spawn.getZ());
+ }
+ LOGGER.warning(getName() + ": Character: " + attacker.getName() + " attacked: " + npc.getName() + " wich is out of the boss zone!");
+ }
+ if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.3)) && !_kain30)
+ {
+ _kain30 = true;
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.6)) && !_kain60)
+ {
+ _kain60 = true;
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_SUMMONS_HIS_APOSTLES_MINIONS, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ }
+ }
+ else if ((npc.getId() == ETIS_VAN_ETINA1))
+ {
+ if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.8)) && !_etina80)
+ {
+ _etina80 = true;
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ _etina.abortCast();
+ _etina.broadcastPacket(new MagicSkillUse(_etina, _etina, CALL_OF_SEVEN_SIGNS.getSkillId(), CALL_OF_SEVEN_SIGNS.getSkillLevel(), 3000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_USES_THE_POWER_OF_THE_SEVEN_SIGNS_TO_SUMMON_ALL_7_SEALS_INSIDE_THE_TEMPLE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ _sealOfGnosis = addSpawn(SEAL_OF_GNOSIS, SEAL_OF_GNOSIS_LOC);
+ _sealOfStrife = addSpawn(SEAL_OF_STRIFE, SEAL_OF_STRIFE_LOC);
+ _sealOfAvarice = addSpawn(SEAL_OF_AVARICE, SEAL_OF_AVARICE_LOC);
+ _sealOfPunishment = addSpawn(SEAL_OF_PUNISHMENT, SEAL_OF_PUNISHMENT_LOC);
+ _sealOfAwakening = addSpawn(SEAL_OF_AWAKENING, SEAL_OF_AWAKENING_LOC);
+ _sealOfCalamity = addSpawn(SEAL_OF_CALAMITY, SEAL_OF_CALAMITY_LOC);
+ _sealOfDestruction = addSpawn(SEAL_OF_DESTRUCTION, SEAL_OF_DESTRUCTION_LOC);
+ _gnosisCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfGnosis.setDisplayEffect(3);
+ _sealOfGnosis.broadcastPacket(new MagicSkillUse(_sealOfGnosis, _sealOfGnosis, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 1, 10000, 0));
+ int rnd = getRandom(BOSS_ZONE.getPlayersInside().size());
+ PlayerInstance member = BOSS_ZONE.getPlayersInside().get(rnd);
+ STIGMA_OF_REVELATION.getSkill().applyEffects(member, member);
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_REVELATION.getSkill().applyEffects(minion, minion);
+ ((Attackable) minion).addDamageHate(member, 0, 999999999);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_GNOSIS_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 10000, 120000);
+ _strifeCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfStrife.setDisplayEffect(3);
+ _sealOfStrife.broadcastPacket(new MagicSkillUse(_sealOfStrife, _sealOfStrife, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 2, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ CRY_OF_HOLY_WAR.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> STIGMA_OF_MARTYR.getSkill().applyEffects(player, player));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_STRIFE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 20000, 120000);
+ _avariceCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfAvarice.setDisplayEffect(3);
+ _sealOfAvarice.broadcastPacket(new MagicSkillUse(_sealOfAvarice, _sealOfAvarice, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 3, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ UNDEAD_CREATURE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_AVARICE_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 30000, 120000);
+ _punishmentCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfPunishment.setDisplayEffect(3);
+ _sealOfPunishment.broadcastPacket(new MagicSkillUse(_sealOfPunishment, _sealOfPunishment, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 4, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ ETINA_DIVINE_PUNISHMENT.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> ETINA_OBSERVATION.getSkill().applyEffects(player, player));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_PUNISHMENT_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 40000, 120000);
+ _awakeningCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfAwakening.setDisplayEffect(3);
+ _sealOfAwakening.broadcastPacket(new MagicSkillUse(_sealOfAwakening, _sealOfAwakening, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 5, 10000, 0));
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ RAGE_OF_THE_OPEN_EYE.getSkill().applyEffects(minion, minion);
+ }
+ });
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_AWAKENING_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 50000, 120000);
+ _calamityCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfCalamity.setDisplayEffect(3);
+ // TODO: Seal of Calamity skill cast.
+ _sealOfCalamity.broadcastPacket(new MagicSkillUse(_sealOfCalamity, _sealOfCalamity, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 6, 10000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_CALAMITY_ACTIVATES_AND_ENORMOUS_POWER_BEGINS_TO_FLOW_OUT, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 60000, 120000);
+ _destructionCastTask = ThreadPool.scheduleAtFixedRate(() ->
+ {
+ _sealOfDestruction.setDisplayEffect(3);
+ // TODO: Seal of Destruction skill cast.
+ _sealOfDestruction.broadcastPacket(new MagicSkillUse(_sealOfDestruction, _sealOfDestruction, CALL_OF_SEVEN_SIGNS_SEAL_N.getSkillId(), 7, 10000, 0));
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_SEAL_OF_DESTRUCTION_ACTIVATES_AND_THE_ENTIRE_ETINA_GREAT_TEMPLE_IS_NOW_UNDER_THE_INFLUENCE_OF_THE_SEAL, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }, 70000, 120000);
+ }
+ else if ((npc.getCurrentHp() <= (npc.getMaxHp() * 0.15)) && !_etina15)
+ {
+ _etina15 = true;
+ for (SpawnHolder spawn : SPAWNS_MINIONS)
+ {
+ _minionSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ // TODO: decrease etina and seals power
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_AND_THE_POWER_OF_SEVEN_SEALS_ARE_WEAKENING, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onEnterZone(Creature character, ZoneType zone)
+ {
+ if (zone.getId() == ZONE_ID)
+ {
+ if (_collapseTask != null)
+ {
+ _collapseTask.cancel(true);
+ _collapseTask = null;
+ }
+ if ((GrandBossManager.getInstance().getBossStatus(ETIS_VAN_ETINA1) == WAITING) && !_spawned)
+ {
+ _spawned = true;
+ _spawns.clear();
+ _barricadeSpawns.clear();
+ for (SpawnHolder spawn : SPAWNS_CORRIDOR)
+ {
+ _spawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ for (SpawnHolder spawn : SPAWNS_BARRICADE)
+ {
+ _barricadeSpawns.add(addSpawn(spawn.getNpcId(), spawn.getLocation()));
+ }
+ _paragon = (MonsterInstance) addSpawn(PARAGON, PARAGON_LOC);
+ _paragon.setInvul(true);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_T_DEFEAT_PARAGON_WHILE_PARAGON_S_MINIONS_ARE_ALIVE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, FIGHTING);
+ _lastAction = System.currentTimeMillis();
+ startQuestTimer("check_activity_task", 60000, null, null, true);
+ }
+ }
+ return super.onEnterZone(character, zone);
+ }
+
+ @Override
+ public String onExitZone(Creature character, ZoneType zone)
+ {
+ if (zone.getId() == ZONE_ID)
+ {
+ if (zone.getPlayersInside().isEmpty())
+ {
+ _collapseTask = ThreadPool.schedule(() -> Clean(), 900000);
+ }
+ }
+ return super.onExitZone(character, zone);
+ }
+
+ @Override
+ public String onKill(Npc npc, PlayerInstance killer, boolean isPet)
+ {
+ if (npc.getId() == ETIS_VAN_ETINA1)
+ {
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_ETIS_VAN_ETINA_TRANS);
+ });
+ startQuestTimer("spawnTransformedEtina", 15000, null, null);
+ }
+ else if (npc.getId() == ETIS_VAN_ETINA2)
+ {
+ notifyEvent("cancel_timers", null, null);
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_ETIS_VAN_ETINA_ENDING);
+ });
+ GrandBossManager.getInstance().setBossStatus(ETIS_VAN_ETINA1, DEAD);
+ final long respawnTime = (Config.ETINA_SPAWN_INTERVAL + getRandom(-Config.ETINA_SPAWN_RANDOM, Config.ETINA_SPAWN_RANDOM)) * 3600000;
+ final StatSet info = GrandBossManager.getInstance().getStatSet(ETIS_VAN_ETINA1);
+ info.set("respawn_time", System.currentTimeMillis() + respawnTime);
+ GrandBossManager.getInstance().setStatSet(ETIS_VAN_ETINA1, info);
+
+ startQuestTimer("unlock_etina", respawnTime, null, null);
+ startQuestTimer("end_etina", 900000, null, null);
+ }
+ else if (CommonUtil.contains(CORRIDOR_MOBS, npc.getId()))
+ {
+ _spawns.remove(npc);
+ if (_spawns.isEmpty())
+ {
+ _paragon.setInvul(false);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.PARAGON_IS_NO_LONGER_INVINCIBLE, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ }
+ }
+ else if (npc.getId() == PARAGON)
+ {
+ openDoor(DOOR1, 0);
+ openDoor(DOOR2, 0);
+ startQuestTimer("openInnerDoor", 30000, null, null);
+ }
+ else if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ _minionSpawns.forEach(minion ->
+ {
+ if (minion != null)
+ {
+ minion.doDie(null);
+ }
+ });
+ _etina.setInvul(false);
+ _etina.setImmobilized(false);
+ _etina.setTargetable(true);
+ BOSS_ZONE.getPlayersInside().forEach(player -> player.sendPacket(new ExShowScreenMessage(NpcStringId.ETIS_VAN_ETINA_APPROACHES, ExShowScreenMessage.TOP_CENTER, 7000, true)));
+ _kain.deleteMe();
+ BOSS_ZONE.getPlayersInside().forEach(player ->
+ {
+ playMovie(player, Movie.SC_KAIN_BOSS_ENDING);
+ });
+ }
+ return super.onKill(npc, killer, isPet);
+ }
+
+ public static void main(String[] args)
+ {
+ new EtisVanEtina();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
new file mode 100644
index 0000000000..b66a737f71
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleDarkJudge.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class GreatTempleDarkJudge extends AbstractNpcAI
+{
+ // Npc
+ private static final int GREAT_TEMPLE_DARK_JUDGE = 24095;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private GreatTempleDarkJudge()
+ {
+ registerMobs(GREAT_TEMPLE_DARK_JUDGE);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == GREAT_TEMPLE_DARK_JUDGE)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new GreatTempleDarkJudge();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
new file mode 100644
index 0000000000..ef143e1088
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/GreatTempleSoulGuide.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class GreatTempleSoulGuide extends AbstractNpcAI
+{
+ // Npc
+ private static final int GREAT_TEMPLE_SOUL_GUIDE = 24094;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private GreatTempleSoulGuide()
+ {
+ registerMobs(GREAT_TEMPLE_SOUL_GUIDE);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == GREAT_TEMPLE_SOUL_GUIDE)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new GreatTempleSoulGuide();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
new file mode 100644
index 0000000000..5ba7f93bff
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/JudgeOfHeresy.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class JudgeOfHeresy extends AbstractNpcAI
+{
+ // Npc
+ private static final int JUDGE_OF_HERESY = 24077;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private JudgeOfHeresy()
+ {
+ registerMobs(JUDGE_OF_HERESY);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == JUDGE_OF_HERESY)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new JudgeOfHeresy();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
new file mode 100644
index 0000000000..ec40bf98cf
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/Kain.java
@@ -0,0 +1,187 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class Kain extends AbstractNpcAI
+{
+ // Npc
+ private static final int KAIN_VAN_HALTER = 29320;
+ // Skills
+ private static final SkillHolder WALL_OF_VOID = new SkillHolder(32003, 1);
+ private static final SkillHolder FLASH_OF_DARKNESS = new SkillHolder(32007, 1);
+ private static final SkillHolder BANE_BLADE = new SkillHolder(32010, 1);
+ private static final SkillHolder SPINNING_SHADOW = new SkillHolder(32011, 1);
+
+ private Kain()
+ {
+ registerMobs(KAIN_VAN_HALTER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == KAIN_VAN_HALTER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = WALL_OF_VOID;
+ }
+ else if (getRandom(100) < 30)
+ {
+ skillToCast = SPINNING_SHADOW;
+ }
+ else if (getRandom(100) < 50)
+ {
+ skillToCast = FLASH_OF_DARKNESS;
+ }
+ else
+ {
+ skillToCast = BANE_BLADE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new Kain();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
new file mode 100644
index 0000000000..3ac3966287
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/LiberatorOfLust.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class LiberatorOfLust extends AbstractNpcAI
+{
+ // Npc
+ private static final int LIBERATOR_OF_LUST = 29324;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private LiberatorOfLust()
+ {
+ registerMobs(LIBERATOR_OF_LUST);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == LIBERATOR_OF_LUST)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new LiberatorOfLust();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
new file mode 100644
index 0000000000..c029102a64
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SeekerOfDespair.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class SeekerOfDespair extends AbstractNpcAI
+{
+ // Npc
+ private static final int SEEKER_OF_DESPAIR = 29323;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private SeekerOfDespair()
+ {
+ registerMobs(SEEKER_OF_DESPAIR);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == SEEKER_OF_DESPAIR)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new SeekerOfDespair();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
new file mode 100644
index 0000000000..3da99f7d62
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/SoulDestroyer.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class SoulDestroyer extends AbstractNpcAI
+{
+ // Npc
+ private static final int SOUL_DESTROYER = 24076;
+ // Skills
+ private static final SkillHolder ABYSS_BLAST = new SkillHolder(32300, 1);
+ private static final SkillHolder ABYSS_BUSTER = new SkillHolder(32301, 1);
+
+ private SoulDestroyer()
+ {
+ registerMobs(SOUL_DESTROYER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == SOUL_DESTROYER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = ABYSS_BUSTER;
+ }
+ else
+ {
+ skillToCast = ABYSS_BLAST;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new SoulDestroyer();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
new file mode 100644
index 0000000000..16ad7ae0e5
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleArchon.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleArchon extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_ARCHON = 24085;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private TempleArchon()
+ {
+ registerMobs(TEMPLE_ARCHON);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_ARCHON)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 10)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleArchon();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
new file mode 100644
index 0000000000..7a6eacccbc
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleDarkWizard.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleDarkWizard extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_DARK_WIZARD = 24083;
+ // Skills
+ private static final SkillHolder DARK_BREAKER = new SkillHolder(32289, 1);
+ private static final SkillHolder VAMPIRIC_FORCE = new SkillHolder(32294, 1);
+
+ private TempleDarkWizard()
+ {
+ registerMobs(TEMPLE_DARK_WIZARD);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_DARK_WIZARD)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = VAMPIRIC_FORCE;
+ }
+ else
+ {
+ skillToCast = DARK_BREAKER;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleDarkWizard();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
new file mode 100644
index 0000000000..509a7816b5
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleFlameMaster.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleFlameMaster extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_FLAME_MASTER = 24084;
+ // Skills
+ private static final SkillHolder DARK_BREAKER = new SkillHolder(32289, 1);
+ private static final SkillHolder BLOOD_TO_FLESH = new SkillHolder(32302, 1);
+
+ private TempleFlameMaster()
+ {
+ registerMobs(TEMPLE_FLAME_MASTER);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_FLAME_MASTER)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = BLOOD_TO_FLESH;
+ }
+ else
+ {
+ skillToCast = DARK_BREAKER;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleFlameMaster();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
new file mode 100644
index 0000000000..a7d200da1e
--- /dev/null
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/bosses/EtisVanEtina/TempleHighPriest.java
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.bosses.EtisVanEtina;
+
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.SkillHolder;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.skills.SkillCaster;
+import org.l2jmobius.gameserver.model.variables.NpcVariables;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author NviX
+ */
+public class TempleHighPriest extends AbstractNpcAI
+{
+ // Npc
+ private static final int TEMPLE_HIGH_PRIEST = 24086;
+ // Skills
+ private static final SkillHolder DARK_FIRE = new SkillHolder(32308, 1);
+ private static final SkillHolder CURSE_OF_BLAZE = new SkillHolder(32309, 1);
+
+ private TempleHighPriest()
+ {
+ registerMobs(TEMPLE_HIGH_PRIEST);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ switch (event)
+ {
+ case "MANAGE_SKILLS":
+ {
+ if (npc != null)
+ {
+ manageSkills(npc);
+ }
+ break;
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
+ {
+ if (npc.getId() == TEMPLE_HIGH_PRIEST)
+ {
+ if (skill == null)
+ {
+ refreshAiParams(attacker, npc, (damage * 1000));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 100));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
+ {
+ refreshAiParams(attacker, npc, (damage * 20));
+ }
+ else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
+ {
+ refreshAiParams(attacker, npc, (damage * 10));
+ }
+ else
+ {
+ refreshAiParams(attacker, npc, ((damage / 3) * 20));
+ }
+ manageSkills(npc);
+ }
+
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage)
+ {
+ refreshAiParams(attacker, npc, damage, damage);
+ }
+
+ private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
+ {
+ final int newAggroVal = damage + getRandom(3000);
+ final int aggroVal = aggro + 1000;
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ if (attacker == vars.getObject("c_quest" + i, Creature.class))
+ {
+ if (vars.getInt("i_quest" + i) < aggroVal)
+ {
+ vars.set("i_quest" + i, newAggroVal);
+ }
+ return;
+ }
+ }
+ final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ vars.set("i_quest" + index, newAggroVal);
+ vars.set("c_quest" + index, attacker);
+ }
+
+ @Override
+ public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
+ {
+ startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
+
+ return super.onSpellFinished(npc, player, skill);
+ }
+
+ private void manageSkills(Npc npc)
+ {
+ if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
+ {
+ return;
+ }
+
+ final NpcVariables vars = npc.getVariables();
+ for (int i = 0; i < 3; i++)
+ {
+ final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
+ if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
+ {
+ vars.set("i_quest" + i, 0);
+ }
+ }
+ final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
+ final Creature player = vars.getObject("c_quest" + index, Creature.class);
+ final int i2 = vars.getInt("i_quest" + index);
+ if ((i2 > 0) && (getRandom(100) < 70))
+ {
+ vars.set("i_quest" + index, 500);
+ }
+
+ SkillHolder skillToCast = null;
+ if ((player != null) && !player.isDead())
+ {
+ if (getRandom(100) < 20)
+ {
+ skillToCast = CURSE_OF_BLAZE;
+ }
+ else
+ {
+ skillToCast = DARK_FIRE;
+ }
+ }
+
+ if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
+
+ {
+ npc.setTarget(player);
+ npc.doCast(skillToCast.getSkill());
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new TempleHighPriest();
+ }
+}
diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
index a7f585c05a..c2e4514976 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
+++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/spawns/Gracia/KeucereusAllianceBase.xml
@@ -51,6 +51,7 @@
+
diff --git a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/Config.java b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/Config.java
index 04b483e65d..831e02ec6a 100644
--- a/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_7.0_PreludeOfWar/java/org/l2jmobius/Config.java
@@ -925,6 +925,13 @@ public class Config
public static int RAMONA_SPAWN_RANDOM;
public static int RAMONA_MIN_PLAYER;
+ // Etis van Etina
+ public static int ETINA_SPAWN_INTERVAL;
+ public static int ETINA_SPAWN_RANDOM;
+ public static int ETINA_MIN_PLAYERS;
+ public static int ETINA_MAX_PLAYERS;
+ public static int ETINA_MIN_PLAYER_LVL;
+
// Fafurion
public static int FAFURION_WAIT_TIME;
public static int FAFURION_SPAWN_INTERVAL;
@@ -2500,6 +2507,11 @@ public class Config
RAMONA_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfRamonaSpawn", 72);
RAMONA_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfRamonaSpawn", 48);
RAMONA_MIN_PLAYER = GrandBossSettings.getInt("RamonaMinPlayers", 7);
+ ETINA_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfEtinaSpawn", 264);
+ ETINA_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfEtinaSpawn", 72);
+ ETINA_MIN_PLAYERS = GrandBossSettings.getInt("EtinaMinPlayers", 49);
+ ETINA_MAX_PLAYERS = GrandBossSettings.getInt("EtinaMaxPlayers", 112);
+ ETINA_MIN_PLAYER_LVL = GrandBossSettings.getInt("EtinaMinPlayerLvl", 103);
FAFURION_WAIT_TIME = GrandBossSettings.getInt("FafurionWaitTime", 10);
FAFURION_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfFafurionSpawn", 264);
FAFURION_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfFafurionSpawn", 72);