From c666ea53f40e872f8dbcf217c0b9ce4322714c5c Mon Sep 17 00:00:00 2001
From: MobiusDev <8391001+MobiusDevelopment@users.noreply.github.com>
Date: Sun, 17 Feb 2019 11:09:48 +0000
Subject: [PATCH] Addition of Altar of Shilen. Contributed by gigilo1968.
---
.../dist/game/data/html/default/33515.htm | 7 +-
.../game/data/instances/AltarOfShilen.xml | 281 +++++++
.../instances/AltarOfShilen/19121.html | 4 +
.../instances/AltarOfShilen/19122.html | 4 +
.../instances/AltarOfShilen/34331-01.html | 5 +
.../instances/AltarOfShilen/34331-02.html | 7 +
.../instances/AltarOfShilen/34331.html | 5 +
.../instances/AltarOfShilen/34332.html | 6 +
.../AltarOfShilen/AltarOfShilen.java | 694 ++++++++++++++++++
.../instances/AltarOfShilen/condNoGroup.html | 5 +
.../instances/AltarOfShilen/condNoLevel.html | 3 +
.../AltarOfShilen/condNoPartyLeader.html | 3 +
.../AltarOfShilen/condSmallGroup.html | 3 +
.../dist/game/data/stats/npcs/19100-19199.xml | 6 +-
.../dist/game/data/stats/npcs/25800-25899.xml | 150 +++-
L2J_Mobius_1.0_Ertheia/readme.txt | 1 +
.../dist/game/data/html/default/33515.htm | 7 +-
.../game/data/instances/AltarOfShilen.xml | 281 +++++++
.../instances/AltarOfShilen/19121.html | 4 +
.../instances/AltarOfShilen/19122.html | 4 +
.../instances/AltarOfShilen/34331-01.html | 5 +
.../instances/AltarOfShilen/34331-02.html | 7 +
.../instances/AltarOfShilen/34331.html | 5 +
.../instances/AltarOfShilen/34332.html | 6 +
.../AltarOfShilen/AltarOfShilen.java | 694 ++++++++++++++++++
.../instances/AltarOfShilen/condNoGroup.html | 5 +
.../instances/AltarOfShilen/condNoLevel.html | 3 +
.../AltarOfShilen/condNoPartyLeader.html | 3 +
.../AltarOfShilen/condSmallGroup.html | 3 +
.../dist/game/data/stats/npcs/19100-19199.xml | 6 +-
.../dist/game/data/stats/npcs/25800-25899.xml | 150 +++-
L2J_Mobius_2.5_Underground/readme.txt | 1 +
.../dist/game/data/html/default/33515.htm | 7 +-
.../game/data/instances/AltarOfShilen.xml | 281 +++++++
.../instances/AltarOfShilen/19121.html | 4 +
.../instances/AltarOfShilen/19122.html | 4 +
.../instances/AltarOfShilen/34331-01.html | 5 +
.../instances/AltarOfShilen/34331-02.html | 7 +
.../instances/AltarOfShilen/34331.html | 5 +
.../instances/AltarOfShilen/34332.html | 6 +
.../AltarOfShilen/AltarOfShilen.java | 694 ++++++++++++++++++
.../instances/AltarOfShilen/condNoGroup.html | 5 +
.../instances/AltarOfShilen/condNoLevel.html | 3 +
.../AltarOfShilen/condNoPartyLeader.html | 3 +
.../AltarOfShilen/condSmallGroup.html | 3 +
.../dist/game/data/stats/npcs/19100-19199.xml | 6 +-
.../dist/game/data/stats/npcs/25800-25899.xml | 150 +++-
L2J_Mobius_3.0_Helios/readme.txt | 1 +
.../dist/game/data/html/default/33515.htm | 7 +-
.../game/data/instances/AltarOfShilen.xml | 281 +++++++
.../instances/AltarOfShilen/19121.html | 4 +
.../instances/AltarOfShilen/19122.html | 4 +
.../instances/AltarOfShilen/34331-01.html | 5 +
.../instances/AltarOfShilen/34331-02.html | 7 +
.../instances/AltarOfShilen/34331.html | 5 +
.../instances/AltarOfShilen/34332.html | 6 +
.../AltarOfShilen/AltarOfShilen.java | 694 ++++++++++++++++++
.../instances/AltarOfShilen/condNoGroup.html | 5 +
.../instances/AltarOfShilen/condNoLevel.html | 3 +
.../AltarOfShilen/condNoPartyLeader.html | 3 +
.../AltarOfShilen/condSmallGroup.html | 3 +
.../dist/game/data/stats/npcs/19100-19199.xml | 6 +-
.../dist/game/data/stats/npcs/25800-25899.xml | 32 +-
L2J_Mobius_4.0_GrandCrusade/readme.txt | 1 +
.../dist/game/data/html/default/33515.htm | 7 +-
.../game/data/instances/AltarOfShilen.xml | 281 +++++++
.../instances/AltarOfShilen/19121.html | 4 +
.../instances/AltarOfShilen/19122.html | 4 +
.../instances/AltarOfShilen/34331-01.html | 5 +
.../instances/AltarOfShilen/34331-02.html | 7 +
.../instances/AltarOfShilen/34331.html | 5 +
.../instances/AltarOfShilen/34332.html | 6 +
.../AltarOfShilen/AltarOfShilen.java | 694 ++++++++++++++++++
.../instances/AltarOfShilen/condNoGroup.html | 5 +
.../instances/AltarOfShilen/condNoLevel.html | 3 +
.../AltarOfShilen/condNoPartyLeader.html | 3 +
.../AltarOfShilen/condSmallGroup.html | 3 +
.../dist/game/data/stats/npcs/19100-19199.xml | 6 +-
.../dist/game/data/stats/npcs/25800-25899.xml | 32 +-
L2J_Mobius_5.0_Salvation/readme.txt | 1 +
.../dist/game/data/html/default/33515.htm | 7 +-
.../game/data/instances/AltarOfShilen.xml | 281 +++++++
.../instances/AltarOfShilen/19121.html | 4 +
.../instances/AltarOfShilen/19122.html | 4 +
.../instances/AltarOfShilen/34331-01.html | 5 +
.../instances/AltarOfShilen/34331-02.html | 7 +
.../instances/AltarOfShilen/34331.html | 5 +
.../instances/AltarOfShilen/34332.html | 6 +
.../AltarOfShilen/AltarOfShilen.java | 694 ++++++++++++++++++
.../instances/AltarOfShilen/condNoGroup.html | 5 +
.../instances/AltarOfShilen/condNoLevel.html | 3 +
.../AltarOfShilen/condNoPartyLeader.html | 3 +
.../AltarOfShilen/condSmallGroup.html | 3 +
.../dist/game/data/stats/npcs/19100-19199.xml | 6 +-
.../dist/game/data/stats/npcs/25800-25899.xml | 32 +-
L2J_Mobius_5.5_EtinasFate/readme.txt | 1 +
96 files changed, 6618 insertions(+), 132 deletions(-)
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/instances/AltarOfShilen.xml
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19121.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19122.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34332.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
create mode 100644 L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/instances/AltarOfShilen.xml
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19121.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19122.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34332.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
create mode 100644 L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/instances/AltarOfShilen.xml
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19121.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19122.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34332.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/instances/AltarOfShilen.xml
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19121.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19122.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34332.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/instances/AltarOfShilen.xml
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19121.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19122.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34332.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/instances/AltarOfShilen.xml
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19121.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19122.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34332.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/html/default/33515.htm b/L2J_Mobius_1.0_Ertheia/dist/game/data/html/default/33515.htm
index 24608a9b78..c4858bfe85 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/html/default/33515.htm
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/html/default/33515.htm
@@ -1,4 +1,7 @@
-
Agent Georgio:
-Sh... I'm currently on duty. If you don't have anything to say, please go away.
+Agent Georgio:
+Hush! I'm on a mission.
+The Kingdom's Royal Guards are investigating a report that a ritual is being held on the Altar of Shilen, which has been closed since Melisa and Isadora disappeared. I'd like to ask you to leave us, if you don't mind.
+Or, if you want to go to the Altar of Shilen to stop the ritual, I can send you there. Just tell me.
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/instances/AltarOfShilen.xml b/L2J_Mobius_1.0_Ertheia/dist/game/data/instances/AltarOfShilen.xml
new file mode 100644
index 0000000000..6457e49c6b
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/instances/AltarOfShilen.xml
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19121.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19121.html
new file mode 100644
index 0000000000..a29854329e
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19121.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19122.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19122.html
new file mode 100644
index 0000000000..b54e43083b
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/19122.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
new file mode 100644
index 0000000000..6b735ce5aa
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, you're the adventurer who volunteered to stop the ritual on the Altar of Shilen. You must be capable enough to stop it. Otherwise, you couldn't come this far. Okay, I'll open the door for you.
+Don't lower yourb guard once inside.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
new file mode 100644
index 0000000000..f45f7e769e
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
@@ -0,0 +1,7 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, it's you! You've come this far!
+The last altar is before you.
+After Embryos invaded the Keucereus Alliance Base, the existence of the Messiah Castle was revealed. Melisa and Isadora, the twin sisters who had long disappeared, returned and are threatening us. If we fail to stop the ritual, Embryos will invade Aden Continent in no time. We must stop them at all cost.
+My man Dinford will be waiting for you at the entrance to the last altar. Go to find him.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331.html
new file mode 100644
index 0000000000..cf6f3b0075
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34331.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+How did you get in here? The blockade was only recently lifted, and this area is still very dangerous. It is under the control of the Kingdom's Royal Guard.
+It is suspected that Embryos are preparing somewhere in this area to invade the Aden Continent. The Kingdom's Royal Guard is doing its best to stop them. are you here to stop the Embryo's ritual on the Altar of Shilen? if so. I'll gladly open open this door. Be careful. Only danger awaits you.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34332.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34332.html
new file mode 100644
index 0000000000..f194522b63
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/34332.html
@@ -0,0 +1,6 @@
+Quartermaster Dinford
+Who is it? Ah, you've come to stop the ritual the ritual on the Altar of Shilen!
+If so, I'll open the door to the altar.
+Please stop the threat of the Embrio.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
new file mode 100644
index 0000000000..c1d16e5517
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
@@ -0,0 +1,694 @@
+/*
+ * 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 instances.AltarOfShilen;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.gameserver.enums.ChatType;
+import com.l2jmobius.gameserver.instancemanager.InstanceManager;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.actor.L2Npc;
+import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.holders.SkillHolder;
+import com.l2jmobius.gameserver.model.instancezone.Instance;
+import com.l2jmobius.gameserver.network.NpcStringId;
+import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
+import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
+import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
+
+import instances.AbstractInstance;
+
+/**
+ * Instance Altar of Shilen
+ * @URL https://l2wiki.com/Altar_of_Shilen
+ * @author Gigi
+ * @date 2018-04-13 - [23:27:28]
+ */
+public class AltarOfShilen extends AbstractInstance
+{
+ // NPCs
+ private static final int LOGART_VAN_DYKE = 34331;
+ private static final int DINFORD = 34332;
+ private static final int ISADORA = 25856;
+ private static final int MELISSA0 = 25855;
+ private static final int MELISSA = 25876; // She dropping items
+ private static final int EXECUTOR_CAPTAIN = 23131;
+ private static final int ETINA_BLADESMAN = 23138;
+ private static final int CORRUPTED_CAPTAIN = 25857;
+ private static final int CORRUPTED_HIGH_PRIEST = 25858;
+ private static final int RITUAL_ALTAR0 = 19121;
+ private static final int RITUAL_ALTAR1 = 19122;
+ private static final int SHILLIEN_ALTAR = 19123;
+ private static final int INVISIBLE = 8561;
+ private static final int ETINA_GOSPEL = 23132;
+ private static final int ETINA_PRIEST = 23133;
+ private static final int ETINA_PROTECTORS = 23134;
+ private static final int ETINA_PUNISHERS = 23135;
+ private static final int ETINA_COMMINATION = 23136;
+ private static final int ETINA_DARKMONAGERS = 23137;
+ private static final int ELITE_ESCORT = 23126;
+ private static final int ELITE_CHASER = 23127;
+ private static final int ELITE_WARRIOR = 23128;
+ private static final int ELITE_ALCHEMIST = 23129;
+ private static final int ELITE_PRIEST = 23130;
+ private static final int EMBRYO_RESERCHER = 23139;
+ private static final int EMBRYO_WATCHMAN = 23140;
+ private static final int EMBRYO_FIGHTER = 23141;
+ private static final int EMBRYO_GUARD = 23142;
+ // Skills
+ static final SkillHolder PROTECTED_ALTAR = new SkillHolder(14496, 1);
+ // Misc
+ private static final int TEMPLATE_ID = 194;
+ private static final int ALTAR_TIME = 180;
+ //@formatter:off
+ private static final int[] DOORS = { 25180001, 25180002, 25180003, 25180004, 25180005, 25180006, 25180007 };
+ //@formatter:on
+ private static final NpcStringId[] SHOUT_MSG =
+ {
+ NpcStringId.I_NEED_HELP,
+ NpcStringId.FOCUS_FIRE_ACCORDING_TO_MY_ORCHESTRATION,
+ NpcStringId.I_NEED_HEAL,
+ NpcStringId.I_M_GOING_TO_BACK_OFF_FOR_A_BIT,
+ NpcStringId.I_WILL_ATTACK_THE_ENEMY_S_HEALER,
+ NpcStringId.STOP_ENEMIES_HEALING,
+ NpcStringId.ATTACK_WEAKENED_ENEMY,
+ NpcStringId.COME_AT_ME,
+ NpcStringId.SWITCH_TO_FAST_SHOOTING_MODE,
+ NpcStringId.SWITCH_TO_FAST_CASTING_MODE,
+ NpcStringId.BLINK_ATTACK,
+ NpcStringId.ONLY_DEATH_AWAITS_FOR_THE_WEAK,
+ };
+ static final Location MELISSA_SPAWN = new Location(178146, 14356, -13688);
+ private static final Location SECOND_FLOOR = new Location(179357, 13664, -9828);
+ private static final Location THIRD_FLOOR = new Location(179354, 12922, -12776);
+
+ final List playersInside = new ArrayList<>();
+ final Map killedMonsters = new ConcurrentHashMap<>();
+ static List firstFloorVictims = new ArrayList<>();
+ public static Future> timer;
+ public L2Npc altar;
+
+ public AltarOfShilen()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addFirstTalkId(LOGART_VAN_DYKE, RITUAL_ALTAR0, RITUAL_ALTAR1, DINFORD);
+ addSpawnId(CORRUPTED_CAPTAIN, CORRUPTED_HIGH_PRIEST, INVISIBLE, SHILLIEN_ALTAR);
+ addAttackId(ETINA_GOSPEL, ETINA_PRIEST, ETINA_PROTECTORS, ETINA_PUNISHERS, ETINA_COMMINATION, ETINA_DARKMONAGERS, ELITE_ESCORT, ELITE_CHASER, ELITE_WARRIOR, ELITE_ALCHEMIST, ELITE_PRIEST, EMBRYO_RESERCHER, EMBRYO_WATCHMAN, EMBRYO_FIGHTER, EMBRYO_GUARD);
+ addKillId(EXECUTOR_CAPTAIN, CORRUPTED_CAPTAIN, ETINA_BLADESMAN, CORRUPTED_HIGH_PRIEST, ETINA_GOSPEL, ETINA_PROTECTORS, ETINA_PUNISHERS, MELISSA0, MELISSA, ISADORA);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance instance, L2PcInstance player)
+ {
+ instance.spawnGroup("general");
+ instance.spawnGroup("first_floor");
+ instance.setStatus(1);
+ }
+
+ @Override
+ public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (event.equals("enterInstance"))
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ if (player.isGM())
+ {
+ playersInside.add(player);
+ }
+ if (player.getParty() != null)
+ {
+ for (L2PcInstance partyMember : player.getParty().getMembers())
+ {
+ playersInside.add(partyMember);
+ }
+ }
+ }
+ if (event.equals("check_player"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 400, p ->
+ {
+ if ((p != null) && p.isPlayer() && !p.isDead())
+ {
+ npc.setScriptValue(1);
+ final L2Npc gospel = addSpawn(ETINA_GOSPEL, npc, true, 0, false, world.getId());
+ final L2Npc priest = addSpawn(ETINA_PRIEST, npc, true, 0, false, world.getId());
+ final L2Npc protectors = addSpawn(ETINA_PROTECTORS, npc, true, 0, false, world.getId());
+ final L2Npc punishers = addSpawn(ETINA_PUNISHERS, npc, true, 0, false, world.getId());
+ final L2Npc commination = addSpawn(ETINA_COMMINATION, npc, true, 0, false, world.getId());
+ final L2Npc darkmonagers = addSpawn(ETINA_DARKMONAGERS, npc, true, 0, false, world.getId());
+ addAttackPlayerDesire(gospel, p);
+ addAttackPlayerDesire(priest, p);
+ addAttackPlayerDesire(protectors, p);
+ addAttackPlayerDesire(punishers, p);
+ addAttackPlayerDesire(commination, p);
+ addAttackPlayerDesire(darkmonagers, p);
+ }
+ });
+ }
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if (event.equals("open_door"))
+ {
+ if (world.getStatus() == 1)
+ {
+ if (world.getDoor(DOORS[0]) != null)
+ {
+ world.getDoor(DOORS[0]).openMe();
+ }
+ world.setStatus(2);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 3)
+ {
+ if (world.getDoor(DOORS[1]) != null)
+ {
+ world.getDoor(DOORS[1]).openMe();
+ }
+ world.setStatus(4);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 5)
+ {
+ if (world.getDoor(DOORS[2]) != null)
+ {
+ world.getDoor(DOORS[2]).openMe();
+ }
+ world.setStatus(6);
+ onStatusChanged(world);
+ break;
+ }
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if ((world.getStatus() == 3) && event.equals("teleport1"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(SECOND_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("second_floor");
+ });
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if ((world.getStatus() == 5) && event.equals("teleport2"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(THIRD_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("thrid_floor");
+ });
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if ((world.getStatus() == 6) && event.equals("final_door"))
+ {
+ if (!world.getDoor(DOORS[6]).isOpen())
+ {
+ world.getDoor(DOORS[6]).openMe();
+ }
+ world.setStatus(7);
+ onStatusChanged(world);
+ npc.deleteMe();
+ cancelQuestTimers("check_player");
+ }
+ break;
+ }
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ if (getRandom(30) < 3)
+ {
+ npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), SHOUT_MSG[getRandom(SHOUT_MSG.length)]));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (world != null)
+ {
+ int npcId = npc.getId();
+ if (!killedMonsters.containsKey(npcId))
+ {
+ killedMonsters.put(npcId, 1);
+ }
+ else
+ {
+ killedMonsters.put(npcId, killedMonsters.get(npcId) + 1);
+ }
+ // 1st Floor
+ if (world.getStatus() == 2)
+ {
+ if (killedMonsters.containsKey(EXECUTOR_CAPTAIN) && (killedMonsters.get(EXECUTOR_CAPTAIN) >= 3))
+ {
+ final int boos1 = world.getTemplateParameters().getInt("boss1");
+ final L2Npc captain = world.getNpc(boos1);
+ if (captain != null)
+ {
+ captain.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_CAPTAIN) && (killedMonsters.get(CORRUPTED_CAPTAIN) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("You can move to the next floor through the Altar of Sacrifice.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(3);
+ killedMonsters.clear();
+ onStatusChanged(world);
+ }
+ }
+ // 2st Floor
+ else if (world.getStatus() == 4)
+ {
+ if (killedMonsters.containsKey(ETINA_BLADESMAN) && (killedMonsters.get(ETINA_BLADESMAN) >= 3))
+ {
+ final int boos2 = world.getTemplateParameters().getInt("boss2");
+ final L2Npc priest = world.getNpc(boos2);
+ if (priest != null)
+ {
+ priest.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_HIGH_PRIEST) && (killedMonsters.get(CORRUPTED_HIGH_PRIEST) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("You can move to the next floor through the Altar of Sacrifice.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(5);
+ killedMonsters.clear();
+ onStatusChanged(world);
+
+ }
+ }
+ // 3st Floor
+ else if (world.getStatus() == 6)
+ {
+ switch (npc.getId())
+ {
+ case ETINA_GOSPEL:
+ {
+ world.getDoor(DOORS[3]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[3]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PROTECTORS:
+ {
+ world.getDoor(DOORS[4]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[4]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PUNISHERS:
+ {
+ world.getDoor(DOORS[5]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[5]).closeMe(), 5000);
+ break;
+ }
+ }
+ }
+ else if (world.getStatus() == 8)
+ {
+ if (killedMonsters.containsKey(MELISSA) && (killedMonsters.get(MELISSA) == 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_HAS_BEEN_DESTROYED_YOU_VE_WON, ExShowScreenMessage.TOP_CENTER, 5000, true));
+ }
+ playersInside.clear();
+ killedMonsters.clear();
+ world.finishInstance(1);
+ }
+ }
+ }
+ return super.onKill(npc, killer, isSummon);
+ }
+
+ @Override
+ public String onSpawn(L2Npc npc)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ switch (npc.getId())
+ {
+ case CORRUPTED_CAPTAIN:
+ case CORRUPTED_HIGH_PRIEST:
+ {
+ npc.setIsInvul(true);
+ break;
+ }
+ case INVISIBLE:
+ {
+ if (npc.isScriptValue(0))
+ {
+ startQuestTimer("check_player", 2000, npc, null, true);
+ }
+ break;
+ }
+ case SHILLIEN_ALTAR:
+ {
+ altar = npc;
+ break;
+ }
+ }
+ }
+ return super.onSpawn(npc);
+ }
+
+ @Override
+ public String onFirstTalk(L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if ((world.getStatus() > 0) && (world.getStatus() < 3))
+ {
+ return "34331.html";
+ }
+ else if ((world.getStatus() >= 3) && (world.getStatus() < 5))
+ {
+ return "34331-01.html";
+ }
+ else if (world.getStatus() >= 5)
+ {
+ return "34331-02.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if (world.getStatus() >= 3)
+ {
+ return "19121.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "19122.html";
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "34332.html";
+ }
+ break;
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static class VictimDefeatTask implements Runnable
+ {
+ private final Instance _world;
+ private int _victims;
+ private final int _initialTime;
+ private int _time;
+
+ VictimDefeatTask(int victims, int time, Instance world)
+ {
+ _world = world;
+ _victims = victims;
+ _initialTime = time;
+ _time = time;
+ }
+
+ @Override
+ public void run()
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_GP_TIMER, (_time--), 0, NpcStringId.SACRIFICE_LEFT_S1, new String[]
+ {
+ String.valueOf(_victims)
+ }));
+ }
+ if (_time <= 0)
+ {
+ _time = _initialTime;
+ --_victims;
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 20, 5));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.SACRIFICE_HAS_BEEN_KILLED_SACRIFICE_LEFT_S1, ExShowScreenMessage.MIDDLE_CENTER, 3000, String.valueOf(_victims)));
+ }
+ }
+ if ((_world.getStatus() == 2) && !firstFloorVictims.isEmpty())
+ {
+ firstFloorVictims.get(0).deleteMe();
+ firstFloorVictims.remove(0);
+ }
+ if ((_victims == 1) && (_world.getStatus() == 2))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("4 lives were sacrificed and the Blessing of Blood is bestowed upon the Corrupted Captain.", ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if ((_victims == 1) && (_world.getStatus() == 4))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("4 lives were sacrificed and the Blessing of Blood is bestowed upon the Corrupted High Priest.", ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if (_victims <= 0)
+ {
+ ThreadPool.schedule(() ->
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("All offerings were sacrificed and the Blessing of Blood is bestowed upon the Embryo Colony in that floor.", ExShowScreenMessage.MIDDLE_CENTER, 3000));
+ }
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ _world.finishInstance(1);
+ }, 3000);
+ }
+ }
+ }
+
+ private void onStatusChanged(final Instance world)
+ {
+ final Instance instance = InstanceManager.getInstance().getInstance(world.getId());
+ switch (instance.getStatus())
+ {
+ case 1:
+ {
+ break;
+ }
+ case 2:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 3:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 5:
+ case 6:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 7:
+ {
+ ThreadPool.schedule(() -> timer = ThreadPool.scheduleAtFixedRate(new Runnable()
+ {
+ private int _time = ALTAR_TIME;
+
+ @Override
+ public void run()
+ {
+ if (_time <= 0)
+ {
+ return;
+ }
+ boolean defeated = false;
+ if (killedMonsters.containsKey(MELISSA0) && (killedMonsters.get(MELISSA0) == 1) && killedMonsters.containsKey(ISADORA) && (killedMonsters.get(ISADORA) == 1))
+ {
+ defeated = true;
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExSendUIEvent(player, 0x01, 0, 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_HAS_STOPPED, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ addSpawn(MELISSA, MELISSA_SPAWN.getX(), MELISSA_SPAWN.getY(), MELISSA_SPAWN.getZ(), 0, false, 0, true, world.getId());
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ altar.deleteMe();
+ world.setStatus(8);
+ }
+ }
+ else
+ {
+ for (L2PcInstance player : world.getPlayers())
+ {
+ if (_time == ALTAR_TIME)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_IS_STARTING_MUST_FOCUS_FIRE_THE_ALTAR, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ }
+ }
+
+ if (!defeated && (_time == 9))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("The Altar of Shilen will become activated in 10 seconds.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time == 4))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("The Altar of Shilen will become activated in 5 seconds.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time <= 0))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOCUS_FIRE_THE_ALTAR_TO_STOP_BLESSING_OF_SHILEN, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+
+ if (isInInstance(world))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(altar, L2MonsterInstance.class, 8000, boss ->
+ {
+ if ((boss != null) && !boss.isDead())
+ {
+ altar.doCast(PROTECTED_ALTAR.getSkill());
+ boss.setCurrentHp(boss.getCurrentHp() + (boss.getMaxHp() / 2));
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 30, 5));
+ }
+ }
+ });
+ }
+ }
+
+ if ((_time <= 0) && world.isStatus(7))
+ {
+ ThreadPool.schedule(() ->
+ {
+ _time = ALTAR_TIME;
+ }, 15000);
+ }
+ }
+ }, 0, 1000), 5000);
+ break;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new AltarOfShilen();
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
new file mode 100644
index 0000000000..193aa80dde
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
@@ -0,0 +1,5 @@
+Agent Georgio:
+The Altar of Shilen is extremely dangerous.
+You're trying to go there alone. You may be either very confident or reckless.
+To let you go is to send you to your death. If you want to go to the Altar of Shilen and stop the ritual, please gather allies and return.
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
new file mode 100644
index 0000000000..5ceb23f4c5
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+(A party members level must be 101 - 105 Lvl to challenge Altar of Shilen.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
new file mode 100644
index 0000000000..538b8bed55
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+Only a party leader may enter the altar of Shilen
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
new file mode 100644
index 0000000000..361fbf1ca0
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+You are too weak. Gather more people.
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/19100-19199.xml b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/19100-19199.xml
index a48899e1b4..11cf48c241 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/19100-19199.xml
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/19100-19199.xml
@@ -812,7 +812,7 @@
-
+
CONSTRUCT
MALE
@@ -839,7 +839,7 @@
-
+
CONSTRUCT
MALE
@@ -866,7 +866,7 @@
-
+
CONSTRUCT
MALE
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/25800-25899.xml b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/25800-25899.xml
index 57b2d0fecb..ab8a7867d1 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/25800-25899.xml
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/stats/npcs/25800-25899.xml
@@ -2294,19 +2294,19 @@
-
+
-
-
+
+
HUMANOID
FEMALE
-
+
@@ -2329,9 +2329,9 @@
-
-
-
+
+
+
@@ -2340,7 +2340,7 @@
-
+
EMBRYO_BOSS
@@ -2349,21 +2349,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
HUMANOID
MALE
-
+
-
+
@@ -2380,10 +2482,12 @@
-
+
+
+
@@ -2400,20 +2504,21 @@
-
+
-
-
+
+
+
HUMANOID
FEMALE
-
+
-
+
@@ -2426,13 +2531,16 @@
-
+
+
+
+
@@ -2837,7 +2945,7 @@
-
+
diff --git a/L2J_Mobius_1.0_Ertheia/readme.txt b/L2J_Mobius_1.0_Ertheia/readme.txt
index 23f78f4eec..786ae3c7bf 100644
--- a/L2J_Mobius_1.0_Ertheia/readme.txt
+++ b/L2J_Mobius_1.0_Ertheia/readme.txt
@@ -31,6 +31,7 @@ Goddess of Destruction:
-Kartia
-Fortuna
-Nursery
+-Altar of Shilen
-Kimerian
-Istina
-Octavis
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/html/default/33515.htm b/L2J_Mobius_2.5_Underground/dist/game/data/html/default/33515.htm
index 24608a9b78..c4858bfe85 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/html/default/33515.htm
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/html/default/33515.htm
@@ -1,4 +1,7 @@
-Agent Georgio:
-Sh... I'm currently on duty. If you don't have anything to say, please go away.
+Agent Georgio:
+Hush! I'm on a mission.
+The Kingdom's Royal Guards are investigating a report that a ritual is being held on the Altar of Shilen, which has been closed since Melisa and Isadora disappeared. I'd like to ask you to leave us, if you don't mind.
+Or, if you want to go to the Altar of Shilen to stop the ritual, I can send you there. Just tell me.
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/instances/AltarOfShilen.xml b/L2J_Mobius_2.5_Underground/dist/game/data/instances/AltarOfShilen.xml
new file mode 100644
index 0000000000..6457e49c6b
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/instances/AltarOfShilen.xml
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19121.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19121.html
new file mode 100644
index 0000000000..a29854329e
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19121.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19122.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19122.html
new file mode 100644
index 0000000000..b54e43083b
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/19122.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
new file mode 100644
index 0000000000..6b735ce5aa
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, you're the adventurer who volunteered to stop the ritual on the Altar of Shilen. You must be capable enough to stop it. Otherwise, you couldn't come this far. Okay, I'll open the door for you.
+Don't lower yourb guard once inside.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
new file mode 100644
index 0000000000..f45f7e769e
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
@@ -0,0 +1,7 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, it's you! You've come this far!
+The last altar is before you.
+After Embryos invaded the Keucereus Alliance Base, the existence of the Messiah Castle was revealed. Melisa and Isadora, the twin sisters who had long disappeared, returned and are threatening us. If we fail to stop the ritual, Embryos will invade Aden Continent in no time. We must stop them at all cost.
+My man Dinford will be waiting for you at the entrance to the last altar. Go to find him.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331.html
new file mode 100644
index 0000000000..cf6f3b0075
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34331.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+How did you get in here? The blockade was only recently lifted, and this area is still very dangerous. It is under the control of the Kingdom's Royal Guard.
+It is suspected that Embryos are preparing somewhere in this area to invade the Aden Continent. The Kingdom's Royal Guard is doing its best to stop them. are you here to stop the Embryo's ritual on the Altar of Shilen? if so. I'll gladly open open this door. Be careful. Only danger awaits you.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34332.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34332.html
new file mode 100644
index 0000000000..f194522b63
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/34332.html
@@ -0,0 +1,6 @@
+Quartermaster Dinford
+Who is it? Ah, you've come to stop the ritual the ritual on the Altar of Shilen!
+If so, I'll open the door to the altar.
+Please stop the threat of the Embrio.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
new file mode 100644
index 0000000000..c1d16e5517
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
@@ -0,0 +1,694 @@
+/*
+ * 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 instances.AltarOfShilen;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.gameserver.enums.ChatType;
+import com.l2jmobius.gameserver.instancemanager.InstanceManager;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.actor.L2Npc;
+import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.holders.SkillHolder;
+import com.l2jmobius.gameserver.model.instancezone.Instance;
+import com.l2jmobius.gameserver.network.NpcStringId;
+import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
+import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
+import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
+
+import instances.AbstractInstance;
+
+/**
+ * Instance Altar of Shilen
+ * @URL https://l2wiki.com/Altar_of_Shilen
+ * @author Gigi
+ * @date 2018-04-13 - [23:27:28]
+ */
+public class AltarOfShilen extends AbstractInstance
+{
+ // NPCs
+ private static final int LOGART_VAN_DYKE = 34331;
+ private static final int DINFORD = 34332;
+ private static final int ISADORA = 25856;
+ private static final int MELISSA0 = 25855;
+ private static final int MELISSA = 25876; // She dropping items
+ private static final int EXECUTOR_CAPTAIN = 23131;
+ private static final int ETINA_BLADESMAN = 23138;
+ private static final int CORRUPTED_CAPTAIN = 25857;
+ private static final int CORRUPTED_HIGH_PRIEST = 25858;
+ private static final int RITUAL_ALTAR0 = 19121;
+ private static final int RITUAL_ALTAR1 = 19122;
+ private static final int SHILLIEN_ALTAR = 19123;
+ private static final int INVISIBLE = 8561;
+ private static final int ETINA_GOSPEL = 23132;
+ private static final int ETINA_PRIEST = 23133;
+ private static final int ETINA_PROTECTORS = 23134;
+ private static final int ETINA_PUNISHERS = 23135;
+ private static final int ETINA_COMMINATION = 23136;
+ private static final int ETINA_DARKMONAGERS = 23137;
+ private static final int ELITE_ESCORT = 23126;
+ private static final int ELITE_CHASER = 23127;
+ private static final int ELITE_WARRIOR = 23128;
+ private static final int ELITE_ALCHEMIST = 23129;
+ private static final int ELITE_PRIEST = 23130;
+ private static final int EMBRYO_RESERCHER = 23139;
+ private static final int EMBRYO_WATCHMAN = 23140;
+ private static final int EMBRYO_FIGHTER = 23141;
+ private static final int EMBRYO_GUARD = 23142;
+ // Skills
+ static final SkillHolder PROTECTED_ALTAR = new SkillHolder(14496, 1);
+ // Misc
+ private static final int TEMPLATE_ID = 194;
+ private static final int ALTAR_TIME = 180;
+ //@formatter:off
+ private static final int[] DOORS = { 25180001, 25180002, 25180003, 25180004, 25180005, 25180006, 25180007 };
+ //@formatter:on
+ private static final NpcStringId[] SHOUT_MSG =
+ {
+ NpcStringId.I_NEED_HELP,
+ NpcStringId.FOCUS_FIRE_ACCORDING_TO_MY_ORCHESTRATION,
+ NpcStringId.I_NEED_HEAL,
+ NpcStringId.I_M_GOING_TO_BACK_OFF_FOR_A_BIT,
+ NpcStringId.I_WILL_ATTACK_THE_ENEMY_S_HEALER,
+ NpcStringId.STOP_ENEMIES_HEALING,
+ NpcStringId.ATTACK_WEAKENED_ENEMY,
+ NpcStringId.COME_AT_ME,
+ NpcStringId.SWITCH_TO_FAST_SHOOTING_MODE,
+ NpcStringId.SWITCH_TO_FAST_CASTING_MODE,
+ NpcStringId.BLINK_ATTACK,
+ NpcStringId.ONLY_DEATH_AWAITS_FOR_THE_WEAK,
+ };
+ static final Location MELISSA_SPAWN = new Location(178146, 14356, -13688);
+ private static final Location SECOND_FLOOR = new Location(179357, 13664, -9828);
+ private static final Location THIRD_FLOOR = new Location(179354, 12922, -12776);
+
+ final List playersInside = new ArrayList<>();
+ final Map killedMonsters = new ConcurrentHashMap<>();
+ static List firstFloorVictims = new ArrayList<>();
+ public static Future> timer;
+ public L2Npc altar;
+
+ public AltarOfShilen()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addFirstTalkId(LOGART_VAN_DYKE, RITUAL_ALTAR0, RITUAL_ALTAR1, DINFORD);
+ addSpawnId(CORRUPTED_CAPTAIN, CORRUPTED_HIGH_PRIEST, INVISIBLE, SHILLIEN_ALTAR);
+ addAttackId(ETINA_GOSPEL, ETINA_PRIEST, ETINA_PROTECTORS, ETINA_PUNISHERS, ETINA_COMMINATION, ETINA_DARKMONAGERS, ELITE_ESCORT, ELITE_CHASER, ELITE_WARRIOR, ELITE_ALCHEMIST, ELITE_PRIEST, EMBRYO_RESERCHER, EMBRYO_WATCHMAN, EMBRYO_FIGHTER, EMBRYO_GUARD);
+ addKillId(EXECUTOR_CAPTAIN, CORRUPTED_CAPTAIN, ETINA_BLADESMAN, CORRUPTED_HIGH_PRIEST, ETINA_GOSPEL, ETINA_PROTECTORS, ETINA_PUNISHERS, MELISSA0, MELISSA, ISADORA);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance instance, L2PcInstance player)
+ {
+ instance.spawnGroup("general");
+ instance.spawnGroup("first_floor");
+ instance.setStatus(1);
+ }
+
+ @Override
+ public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (event.equals("enterInstance"))
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ if (player.isGM())
+ {
+ playersInside.add(player);
+ }
+ if (player.getParty() != null)
+ {
+ for (L2PcInstance partyMember : player.getParty().getMembers())
+ {
+ playersInside.add(partyMember);
+ }
+ }
+ }
+ if (event.equals("check_player"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 400, p ->
+ {
+ if ((p != null) && p.isPlayer() && !p.isDead())
+ {
+ npc.setScriptValue(1);
+ final L2Npc gospel = addSpawn(ETINA_GOSPEL, npc, true, 0, false, world.getId());
+ final L2Npc priest = addSpawn(ETINA_PRIEST, npc, true, 0, false, world.getId());
+ final L2Npc protectors = addSpawn(ETINA_PROTECTORS, npc, true, 0, false, world.getId());
+ final L2Npc punishers = addSpawn(ETINA_PUNISHERS, npc, true, 0, false, world.getId());
+ final L2Npc commination = addSpawn(ETINA_COMMINATION, npc, true, 0, false, world.getId());
+ final L2Npc darkmonagers = addSpawn(ETINA_DARKMONAGERS, npc, true, 0, false, world.getId());
+ addAttackPlayerDesire(gospel, p);
+ addAttackPlayerDesire(priest, p);
+ addAttackPlayerDesire(protectors, p);
+ addAttackPlayerDesire(punishers, p);
+ addAttackPlayerDesire(commination, p);
+ addAttackPlayerDesire(darkmonagers, p);
+ }
+ });
+ }
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if (event.equals("open_door"))
+ {
+ if (world.getStatus() == 1)
+ {
+ if (world.getDoor(DOORS[0]) != null)
+ {
+ world.getDoor(DOORS[0]).openMe();
+ }
+ world.setStatus(2);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 3)
+ {
+ if (world.getDoor(DOORS[1]) != null)
+ {
+ world.getDoor(DOORS[1]).openMe();
+ }
+ world.setStatus(4);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 5)
+ {
+ if (world.getDoor(DOORS[2]) != null)
+ {
+ world.getDoor(DOORS[2]).openMe();
+ }
+ world.setStatus(6);
+ onStatusChanged(world);
+ break;
+ }
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if ((world.getStatus() == 3) && event.equals("teleport1"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(SECOND_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("second_floor");
+ });
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if ((world.getStatus() == 5) && event.equals("teleport2"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(THIRD_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("thrid_floor");
+ });
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if ((world.getStatus() == 6) && event.equals("final_door"))
+ {
+ if (!world.getDoor(DOORS[6]).isOpen())
+ {
+ world.getDoor(DOORS[6]).openMe();
+ }
+ world.setStatus(7);
+ onStatusChanged(world);
+ npc.deleteMe();
+ cancelQuestTimers("check_player");
+ }
+ break;
+ }
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ if (getRandom(30) < 3)
+ {
+ npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), SHOUT_MSG[getRandom(SHOUT_MSG.length)]));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (world != null)
+ {
+ int npcId = npc.getId();
+ if (!killedMonsters.containsKey(npcId))
+ {
+ killedMonsters.put(npcId, 1);
+ }
+ else
+ {
+ killedMonsters.put(npcId, killedMonsters.get(npcId) + 1);
+ }
+ // 1st Floor
+ if (world.getStatus() == 2)
+ {
+ if (killedMonsters.containsKey(EXECUTOR_CAPTAIN) && (killedMonsters.get(EXECUTOR_CAPTAIN) >= 3))
+ {
+ final int boos1 = world.getTemplateParameters().getInt("boss1");
+ final L2Npc captain = world.getNpc(boos1);
+ if (captain != null)
+ {
+ captain.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_CAPTAIN) && (killedMonsters.get(CORRUPTED_CAPTAIN) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("You can move to the next floor through the Altar of Sacrifice.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(3);
+ killedMonsters.clear();
+ onStatusChanged(world);
+ }
+ }
+ // 2st Floor
+ else if (world.getStatus() == 4)
+ {
+ if (killedMonsters.containsKey(ETINA_BLADESMAN) && (killedMonsters.get(ETINA_BLADESMAN) >= 3))
+ {
+ final int boos2 = world.getTemplateParameters().getInt("boss2");
+ final L2Npc priest = world.getNpc(boos2);
+ if (priest != null)
+ {
+ priest.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_HIGH_PRIEST) && (killedMonsters.get(CORRUPTED_HIGH_PRIEST) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("You can move to the next floor through the Altar of Sacrifice.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(5);
+ killedMonsters.clear();
+ onStatusChanged(world);
+
+ }
+ }
+ // 3st Floor
+ else if (world.getStatus() == 6)
+ {
+ switch (npc.getId())
+ {
+ case ETINA_GOSPEL:
+ {
+ world.getDoor(DOORS[3]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[3]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PROTECTORS:
+ {
+ world.getDoor(DOORS[4]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[4]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PUNISHERS:
+ {
+ world.getDoor(DOORS[5]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[5]).closeMe(), 5000);
+ break;
+ }
+ }
+ }
+ else if (world.getStatus() == 8)
+ {
+ if (killedMonsters.containsKey(MELISSA) && (killedMonsters.get(MELISSA) == 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_HAS_BEEN_DESTROYED_YOU_VE_WON, ExShowScreenMessage.TOP_CENTER, 5000, true));
+ }
+ playersInside.clear();
+ killedMonsters.clear();
+ world.finishInstance(1);
+ }
+ }
+ }
+ return super.onKill(npc, killer, isSummon);
+ }
+
+ @Override
+ public String onSpawn(L2Npc npc)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ switch (npc.getId())
+ {
+ case CORRUPTED_CAPTAIN:
+ case CORRUPTED_HIGH_PRIEST:
+ {
+ npc.setIsInvul(true);
+ break;
+ }
+ case INVISIBLE:
+ {
+ if (npc.isScriptValue(0))
+ {
+ startQuestTimer("check_player", 2000, npc, null, true);
+ }
+ break;
+ }
+ case SHILLIEN_ALTAR:
+ {
+ altar = npc;
+ break;
+ }
+ }
+ }
+ return super.onSpawn(npc);
+ }
+
+ @Override
+ public String onFirstTalk(L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if ((world.getStatus() > 0) && (world.getStatus() < 3))
+ {
+ return "34331.html";
+ }
+ else if ((world.getStatus() >= 3) && (world.getStatus() < 5))
+ {
+ return "34331-01.html";
+ }
+ else if (world.getStatus() >= 5)
+ {
+ return "34331-02.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if (world.getStatus() >= 3)
+ {
+ return "19121.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "19122.html";
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "34332.html";
+ }
+ break;
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static class VictimDefeatTask implements Runnable
+ {
+ private final Instance _world;
+ private int _victims;
+ private final int _initialTime;
+ private int _time;
+
+ VictimDefeatTask(int victims, int time, Instance world)
+ {
+ _world = world;
+ _victims = victims;
+ _initialTime = time;
+ _time = time;
+ }
+
+ @Override
+ public void run()
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_GP_TIMER, (_time--), 0, NpcStringId.SACRIFICE_LEFT_S1, new String[]
+ {
+ String.valueOf(_victims)
+ }));
+ }
+ if (_time <= 0)
+ {
+ _time = _initialTime;
+ --_victims;
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 20, 5));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.SACRIFICE_HAS_BEEN_KILLED_SACRIFICE_LEFT_S1, ExShowScreenMessage.MIDDLE_CENTER, 3000, String.valueOf(_victims)));
+ }
+ }
+ if ((_world.getStatus() == 2) && !firstFloorVictims.isEmpty())
+ {
+ firstFloorVictims.get(0).deleteMe();
+ firstFloorVictims.remove(0);
+ }
+ if ((_victims == 1) && (_world.getStatus() == 2))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("4 lives were sacrificed and the Blessing of Blood is bestowed upon the Corrupted Captain.", ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if ((_victims == 1) && (_world.getStatus() == 4))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("4 lives were sacrificed and the Blessing of Blood is bestowed upon the Corrupted High Priest.", ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if (_victims <= 0)
+ {
+ ThreadPool.schedule(() ->
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("All offerings were sacrificed and the Blessing of Blood is bestowed upon the Embryo Colony in that floor.", ExShowScreenMessage.MIDDLE_CENTER, 3000));
+ }
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ _world.finishInstance(1);
+ }, 3000);
+ }
+ }
+ }
+
+ private void onStatusChanged(final Instance world)
+ {
+ final Instance instance = InstanceManager.getInstance().getInstance(world.getId());
+ switch (instance.getStatus())
+ {
+ case 1:
+ {
+ break;
+ }
+ case 2:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 3:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 5:
+ case 6:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 7:
+ {
+ ThreadPool.schedule(() -> timer = ThreadPool.scheduleAtFixedRate(new Runnable()
+ {
+ private int _time = ALTAR_TIME;
+
+ @Override
+ public void run()
+ {
+ if (_time <= 0)
+ {
+ return;
+ }
+ boolean defeated = false;
+ if (killedMonsters.containsKey(MELISSA0) && (killedMonsters.get(MELISSA0) == 1) && killedMonsters.containsKey(ISADORA) && (killedMonsters.get(ISADORA) == 1))
+ {
+ defeated = true;
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExSendUIEvent(player, 0x01, 0, 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_HAS_STOPPED, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ addSpawn(MELISSA, MELISSA_SPAWN.getX(), MELISSA_SPAWN.getY(), MELISSA_SPAWN.getZ(), 0, false, 0, true, world.getId());
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ altar.deleteMe();
+ world.setStatus(8);
+ }
+ }
+ else
+ {
+ for (L2PcInstance player : world.getPlayers())
+ {
+ if (_time == ALTAR_TIME)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_IS_STARTING_MUST_FOCUS_FIRE_THE_ALTAR, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ }
+ }
+
+ if (!defeated && (_time == 9))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("The Altar of Shilen will become activated in 10 seconds.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time == 4))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("The Altar of Shilen will become activated in 5 seconds.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time <= 0))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOCUS_FIRE_THE_ALTAR_TO_STOP_BLESSING_OF_SHILEN, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+
+ if (isInInstance(world))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(altar, L2MonsterInstance.class, 8000, boss ->
+ {
+ if ((boss != null) && !boss.isDead())
+ {
+ altar.doCast(PROTECTED_ALTAR.getSkill());
+ boss.setCurrentHp(boss.getCurrentHp() + (boss.getMaxHp() / 2));
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 30, 5));
+ }
+ }
+ });
+ }
+ }
+
+ if ((_time <= 0) && world.isStatus(7))
+ {
+ ThreadPool.schedule(() ->
+ {
+ _time = ALTAR_TIME;
+ }, 15000);
+ }
+ }
+ }, 0, 1000), 5000);
+ break;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new AltarOfShilen();
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
new file mode 100644
index 0000000000..193aa80dde
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
@@ -0,0 +1,5 @@
+Agent Georgio:
+The Altar of Shilen is extremely dangerous.
+You're trying to go there alone. You may be either very confident or reckless.
+To let you go is to send you to your death. If you want to go to the Altar of Shilen and stop the ritual, please gather allies and return.
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
new file mode 100644
index 0000000000..5ceb23f4c5
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+(A party members level must be 101 - 105 Lvl to challenge Altar of Shilen.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
new file mode 100644
index 0000000000..538b8bed55
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+Only a party leader may enter the altar of Shilen
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
new file mode 100644
index 0000000000..361fbf1ca0
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+You are too weak. Gather more people.
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/19100-19199.xml b/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/19100-19199.xml
index 634139d668..82b90b8845 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/19100-19199.xml
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/19100-19199.xml
@@ -812,7 +812,7 @@
-
+
CONSTRUCT
MALE
@@ -839,7 +839,7 @@
-
+
CONSTRUCT
MALE
@@ -866,7 +866,7 @@
-
+
CONSTRUCT
MALE
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/25800-25899.xml b/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/25800-25899.xml
index 3425f529ba..01c3be8776 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/25800-25899.xml
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/stats/npcs/25800-25899.xml
@@ -2349,19 +2349,19 @@
-
+
-
-
+
+
HUMANOID
FEMALE
-
+
@@ -2384,9 +2384,9 @@
-
-
-
+
+
+
@@ -2395,7 +2395,7 @@
-
+
EMBRYO_BOSS
@@ -2404,21 +2404,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
HUMANOID
MALE
-
+
-
+
@@ -2435,10 +2537,12 @@
-
+
+
+
@@ -2455,20 +2559,21 @@
-
+
-
-
+
+
+
HUMANOID
FEMALE
-
+
-
+
@@ -2481,13 +2586,16 @@
-
+
+
+
+
@@ -2892,7 +3000,7 @@
-
+
diff --git a/L2J_Mobius_2.5_Underground/readme.txt b/L2J_Mobius_2.5_Underground/readme.txt
index e8f800e260..0718d05a0e 100644
--- a/L2J_Mobius_2.5_Underground/readme.txt
+++ b/L2J_Mobius_2.5_Underground/readme.txt
@@ -31,6 +31,7 @@ Goddess of Destruction:
-Kartia
-Fortuna
-Nursery
+-Altar of Shilen
-Kimerian
-Istina
-Octavis
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/default/33515.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/default/33515.htm
index 24608a9b78..c4858bfe85 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/default/33515.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/default/33515.htm
@@ -1,4 +1,7 @@
-Agent Georgio:
-Sh... I'm currently on duty. If you don't have anything to say, please go away.
+Agent Georgio:
+Hush! I'm on a mission.
+The Kingdom's Royal Guards are investigating a report that a ritual is being held on the Altar of Shilen, which has been closed since Melisa and Isadora disappeared. I'd like to ask you to leave us, if you don't mind.
+Or, if you want to go to the Altar of Shilen to stop the ritual, I can send you there. Just tell me.
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/instances/AltarOfShilen.xml b/L2J_Mobius_3.0_Helios/dist/game/data/instances/AltarOfShilen.xml
new file mode 100644
index 0000000000..6457e49c6b
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/instances/AltarOfShilen.xml
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19121.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19121.html
new file mode 100644
index 0000000000..a29854329e
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19121.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19122.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19122.html
new file mode 100644
index 0000000000..b54e43083b
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/19122.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
new file mode 100644
index 0000000000..6b735ce5aa
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, you're the adventurer who volunteered to stop the ritual on the Altar of Shilen. You must be capable enough to stop it. Otherwise, you couldn't come this far. Okay, I'll open the door for you.
+Don't lower yourb guard once inside.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
new file mode 100644
index 0000000000..f45f7e769e
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
@@ -0,0 +1,7 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, it's you! You've come this far!
+The last altar is before you.
+After Embryos invaded the Keucereus Alliance Base, the existence of the Messiah Castle was revealed. Melisa and Isadora, the twin sisters who had long disappeared, returned and are threatening us. If we fail to stop the ritual, Embryos will invade Aden Continent in no time. We must stop them at all cost.
+My man Dinford will be waiting for you at the entrance to the last altar. Go to find him.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331.html
new file mode 100644
index 0000000000..cf6f3b0075
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34331.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+How did you get in here? The blockade was only recently lifted, and this area is still very dangerous. It is under the control of the Kingdom's Royal Guard.
+It is suspected that Embryos are preparing somewhere in this area to invade the Aden Continent. The Kingdom's Royal Guard is doing its best to stop them. are you here to stop the Embryo's ritual on the Altar of Shilen? if so. I'll gladly open open this door. Be careful. Only danger awaits you.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34332.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34332.html
new file mode 100644
index 0000000000..f194522b63
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/34332.html
@@ -0,0 +1,6 @@
+Quartermaster Dinford
+Who is it? Ah, you've come to stop the ritual the ritual on the Altar of Shilen!
+If so, I'll open the door to the altar.
+Please stop the threat of the Embrio.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
new file mode 100644
index 0000000000..c1d16e5517
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
@@ -0,0 +1,694 @@
+/*
+ * 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 instances.AltarOfShilen;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.gameserver.enums.ChatType;
+import com.l2jmobius.gameserver.instancemanager.InstanceManager;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.actor.L2Npc;
+import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.holders.SkillHolder;
+import com.l2jmobius.gameserver.model.instancezone.Instance;
+import com.l2jmobius.gameserver.network.NpcStringId;
+import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
+import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
+import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
+
+import instances.AbstractInstance;
+
+/**
+ * Instance Altar of Shilen
+ * @URL https://l2wiki.com/Altar_of_Shilen
+ * @author Gigi
+ * @date 2018-04-13 - [23:27:28]
+ */
+public class AltarOfShilen extends AbstractInstance
+{
+ // NPCs
+ private static final int LOGART_VAN_DYKE = 34331;
+ private static final int DINFORD = 34332;
+ private static final int ISADORA = 25856;
+ private static final int MELISSA0 = 25855;
+ private static final int MELISSA = 25876; // She dropping items
+ private static final int EXECUTOR_CAPTAIN = 23131;
+ private static final int ETINA_BLADESMAN = 23138;
+ private static final int CORRUPTED_CAPTAIN = 25857;
+ private static final int CORRUPTED_HIGH_PRIEST = 25858;
+ private static final int RITUAL_ALTAR0 = 19121;
+ private static final int RITUAL_ALTAR1 = 19122;
+ private static final int SHILLIEN_ALTAR = 19123;
+ private static final int INVISIBLE = 8561;
+ private static final int ETINA_GOSPEL = 23132;
+ private static final int ETINA_PRIEST = 23133;
+ private static final int ETINA_PROTECTORS = 23134;
+ private static final int ETINA_PUNISHERS = 23135;
+ private static final int ETINA_COMMINATION = 23136;
+ private static final int ETINA_DARKMONAGERS = 23137;
+ private static final int ELITE_ESCORT = 23126;
+ private static final int ELITE_CHASER = 23127;
+ private static final int ELITE_WARRIOR = 23128;
+ private static final int ELITE_ALCHEMIST = 23129;
+ private static final int ELITE_PRIEST = 23130;
+ private static final int EMBRYO_RESERCHER = 23139;
+ private static final int EMBRYO_WATCHMAN = 23140;
+ private static final int EMBRYO_FIGHTER = 23141;
+ private static final int EMBRYO_GUARD = 23142;
+ // Skills
+ static final SkillHolder PROTECTED_ALTAR = new SkillHolder(14496, 1);
+ // Misc
+ private static final int TEMPLATE_ID = 194;
+ private static final int ALTAR_TIME = 180;
+ //@formatter:off
+ private static final int[] DOORS = { 25180001, 25180002, 25180003, 25180004, 25180005, 25180006, 25180007 };
+ //@formatter:on
+ private static final NpcStringId[] SHOUT_MSG =
+ {
+ NpcStringId.I_NEED_HELP,
+ NpcStringId.FOCUS_FIRE_ACCORDING_TO_MY_ORCHESTRATION,
+ NpcStringId.I_NEED_HEAL,
+ NpcStringId.I_M_GOING_TO_BACK_OFF_FOR_A_BIT,
+ NpcStringId.I_WILL_ATTACK_THE_ENEMY_S_HEALER,
+ NpcStringId.STOP_ENEMIES_HEALING,
+ NpcStringId.ATTACK_WEAKENED_ENEMY,
+ NpcStringId.COME_AT_ME,
+ NpcStringId.SWITCH_TO_FAST_SHOOTING_MODE,
+ NpcStringId.SWITCH_TO_FAST_CASTING_MODE,
+ NpcStringId.BLINK_ATTACK,
+ NpcStringId.ONLY_DEATH_AWAITS_FOR_THE_WEAK,
+ };
+ static final Location MELISSA_SPAWN = new Location(178146, 14356, -13688);
+ private static final Location SECOND_FLOOR = new Location(179357, 13664, -9828);
+ private static final Location THIRD_FLOOR = new Location(179354, 12922, -12776);
+
+ final List playersInside = new ArrayList<>();
+ final Map killedMonsters = new ConcurrentHashMap<>();
+ static List firstFloorVictims = new ArrayList<>();
+ public static Future> timer;
+ public L2Npc altar;
+
+ public AltarOfShilen()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addFirstTalkId(LOGART_VAN_DYKE, RITUAL_ALTAR0, RITUAL_ALTAR1, DINFORD);
+ addSpawnId(CORRUPTED_CAPTAIN, CORRUPTED_HIGH_PRIEST, INVISIBLE, SHILLIEN_ALTAR);
+ addAttackId(ETINA_GOSPEL, ETINA_PRIEST, ETINA_PROTECTORS, ETINA_PUNISHERS, ETINA_COMMINATION, ETINA_DARKMONAGERS, ELITE_ESCORT, ELITE_CHASER, ELITE_WARRIOR, ELITE_ALCHEMIST, ELITE_PRIEST, EMBRYO_RESERCHER, EMBRYO_WATCHMAN, EMBRYO_FIGHTER, EMBRYO_GUARD);
+ addKillId(EXECUTOR_CAPTAIN, CORRUPTED_CAPTAIN, ETINA_BLADESMAN, CORRUPTED_HIGH_PRIEST, ETINA_GOSPEL, ETINA_PROTECTORS, ETINA_PUNISHERS, MELISSA0, MELISSA, ISADORA);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance instance, L2PcInstance player)
+ {
+ instance.spawnGroup("general");
+ instance.spawnGroup("first_floor");
+ instance.setStatus(1);
+ }
+
+ @Override
+ public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (event.equals("enterInstance"))
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ if (player.isGM())
+ {
+ playersInside.add(player);
+ }
+ if (player.getParty() != null)
+ {
+ for (L2PcInstance partyMember : player.getParty().getMembers())
+ {
+ playersInside.add(partyMember);
+ }
+ }
+ }
+ if (event.equals("check_player"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 400, p ->
+ {
+ if ((p != null) && p.isPlayer() && !p.isDead())
+ {
+ npc.setScriptValue(1);
+ final L2Npc gospel = addSpawn(ETINA_GOSPEL, npc, true, 0, false, world.getId());
+ final L2Npc priest = addSpawn(ETINA_PRIEST, npc, true, 0, false, world.getId());
+ final L2Npc protectors = addSpawn(ETINA_PROTECTORS, npc, true, 0, false, world.getId());
+ final L2Npc punishers = addSpawn(ETINA_PUNISHERS, npc, true, 0, false, world.getId());
+ final L2Npc commination = addSpawn(ETINA_COMMINATION, npc, true, 0, false, world.getId());
+ final L2Npc darkmonagers = addSpawn(ETINA_DARKMONAGERS, npc, true, 0, false, world.getId());
+ addAttackPlayerDesire(gospel, p);
+ addAttackPlayerDesire(priest, p);
+ addAttackPlayerDesire(protectors, p);
+ addAttackPlayerDesire(punishers, p);
+ addAttackPlayerDesire(commination, p);
+ addAttackPlayerDesire(darkmonagers, p);
+ }
+ });
+ }
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if (event.equals("open_door"))
+ {
+ if (world.getStatus() == 1)
+ {
+ if (world.getDoor(DOORS[0]) != null)
+ {
+ world.getDoor(DOORS[0]).openMe();
+ }
+ world.setStatus(2);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 3)
+ {
+ if (world.getDoor(DOORS[1]) != null)
+ {
+ world.getDoor(DOORS[1]).openMe();
+ }
+ world.setStatus(4);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 5)
+ {
+ if (world.getDoor(DOORS[2]) != null)
+ {
+ world.getDoor(DOORS[2]).openMe();
+ }
+ world.setStatus(6);
+ onStatusChanged(world);
+ break;
+ }
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if ((world.getStatus() == 3) && event.equals("teleport1"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(SECOND_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("second_floor");
+ });
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if ((world.getStatus() == 5) && event.equals("teleport2"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(THIRD_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("thrid_floor");
+ });
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if ((world.getStatus() == 6) && event.equals("final_door"))
+ {
+ if (!world.getDoor(DOORS[6]).isOpen())
+ {
+ world.getDoor(DOORS[6]).openMe();
+ }
+ world.setStatus(7);
+ onStatusChanged(world);
+ npc.deleteMe();
+ cancelQuestTimers("check_player");
+ }
+ break;
+ }
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ if (getRandom(30) < 3)
+ {
+ npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), SHOUT_MSG[getRandom(SHOUT_MSG.length)]));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (world != null)
+ {
+ int npcId = npc.getId();
+ if (!killedMonsters.containsKey(npcId))
+ {
+ killedMonsters.put(npcId, 1);
+ }
+ else
+ {
+ killedMonsters.put(npcId, killedMonsters.get(npcId) + 1);
+ }
+ // 1st Floor
+ if (world.getStatus() == 2)
+ {
+ if (killedMonsters.containsKey(EXECUTOR_CAPTAIN) && (killedMonsters.get(EXECUTOR_CAPTAIN) >= 3))
+ {
+ final int boos1 = world.getTemplateParameters().getInt("boss1");
+ final L2Npc captain = world.getNpc(boos1);
+ if (captain != null)
+ {
+ captain.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_CAPTAIN) && (killedMonsters.get(CORRUPTED_CAPTAIN) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("You can move to the next floor through the Altar of Sacrifice.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(3);
+ killedMonsters.clear();
+ onStatusChanged(world);
+ }
+ }
+ // 2st Floor
+ else if (world.getStatus() == 4)
+ {
+ if (killedMonsters.containsKey(ETINA_BLADESMAN) && (killedMonsters.get(ETINA_BLADESMAN) >= 3))
+ {
+ final int boos2 = world.getTemplateParameters().getInt("boss2");
+ final L2Npc priest = world.getNpc(boos2);
+ if (priest != null)
+ {
+ priest.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_HIGH_PRIEST) && (killedMonsters.get(CORRUPTED_HIGH_PRIEST) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("You can move to the next floor through the Altar of Sacrifice.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(5);
+ killedMonsters.clear();
+ onStatusChanged(world);
+
+ }
+ }
+ // 3st Floor
+ else if (world.getStatus() == 6)
+ {
+ switch (npc.getId())
+ {
+ case ETINA_GOSPEL:
+ {
+ world.getDoor(DOORS[3]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[3]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PROTECTORS:
+ {
+ world.getDoor(DOORS[4]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[4]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PUNISHERS:
+ {
+ world.getDoor(DOORS[5]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[5]).closeMe(), 5000);
+ break;
+ }
+ }
+ }
+ else if (world.getStatus() == 8)
+ {
+ if (killedMonsters.containsKey(MELISSA) && (killedMonsters.get(MELISSA) == 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_HAS_BEEN_DESTROYED_YOU_VE_WON, ExShowScreenMessage.TOP_CENTER, 5000, true));
+ }
+ playersInside.clear();
+ killedMonsters.clear();
+ world.finishInstance(1);
+ }
+ }
+ }
+ return super.onKill(npc, killer, isSummon);
+ }
+
+ @Override
+ public String onSpawn(L2Npc npc)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ switch (npc.getId())
+ {
+ case CORRUPTED_CAPTAIN:
+ case CORRUPTED_HIGH_PRIEST:
+ {
+ npc.setIsInvul(true);
+ break;
+ }
+ case INVISIBLE:
+ {
+ if (npc.isScriptValue(0))
+ {
+ startQuestTimer("check_player", 2000, npc, null, true);
+ }
+ break;
+ }
+ case SHILLIEN_ALTAR:
+ {
+ altar = npc;
+ break;
+ }
+ }
+ }
+ return super.onSpawn(npc);
+ }
+
+ @Override
+ public String onFirstTalk(L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if ((world.getStatus() > 0) && (world.getStatus() < 3))
+ {
+ return "34331.html";
+ }
+ else if ((world.getStatus() >= 3) && (world.getStatus() < 5))
+ {
+ return "34331-01.html";
+ }
+ else if (world.getStatus() >= 5)
+ {
+ return "34331-02.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if (world.getStatus() >= 3)
+ {
+ return "19121.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "19122.html";
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "34332.html";
+ }
+ break;
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static class VictimDefeatTask implements Runnable
+ {
+ private final Instance _world;
+ private int _victims;
+ private final int _initialTime;
+ private int _time;
+
+ VictimDefeatTask(int victims, int time, Instance world)
+ {
+ _world = world;
+ _victims = victims;
+ _initialTime = time;
+ _time = time;
+ }
+
+ @Override
+ public void run()
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_GP_TIMER, (_time--), 0, NpcStringId.SACRIFICE_LEFT_S1, new String[]
+ {
+ String.valueOf(_victims)
+ }));
+ }
+ if (_time <= 0)
+ {
+ _time = _initialTime;
+ --_victims;
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 20, 5));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.SACRIFICE_HAS_BEEN_KILLED_SACRIFICE_LEFT_S1, ExShowScreenMessage.MIDDLE_CENTER, 3000, String.valueOf(_victims)));
+ }
+ }
+ if ((_world.getStatus() == 2) && !firstFloorVictims.isEmpty())
+ {
+ firstFloorVictims.get(0).deleteMe();
+ firstFloorVictims.remove(0);
+ }
+ if ((_victims == 1) && (_world.getStatus() == 2))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("4 lives were sacrificed and the Blessing of Blood is bestowed upon the Corrupted Captain.", ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if ((_victims == 1) && (_world.getStatus() == 4))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("4 lives were sacrificed and the Blessing of Blood is bestowed upon the Corrupted High Priest.", ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if (_victims <= 0)
+ {
+ ThreadPool.schedule(() ->
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage("All offerings were sacrificed and the Blessing of Blood is bestowed upon the Embryo Colony in that floor.", ExShowScreenMessage.MIDDLE_CENTER, 3000));
+ }
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ _world.finishInstance(1);
+ }, 3000);
+ }
+ }
+ }
+
+ private void onStatusChanged(final Instance world)
+ {
+ final Instance instance = InstanceManager.getInstance().getInstance(world.getId());
+ switch (instance.getStatus())
+ {
+ case 1:
+ {
+ break;
+ }
+ case 2:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 3:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 5:
+ case 6:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 7:
+ {
+ ThreadPool.schedule(() -> timer = ThreadPool.scheduleAtFixedRate(new Runnable()
+ {
+ private int _time = ALTAR_TIME;
+
+ @Override
+ public void run()
+ {
+ if (_time <= 0)
+ {
+ return;
+ }
+ boolean defeated = false;
+ if (killedMonsters.containsKey(MELISSA0) && (killedMonsters.get(MELISSA0) == 1) && killedMonsters.containsKey(ISADORA) && (killedMonsters.get(ISADORA) == 1))
+ {
+ defeated = true;
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExSendUIEvent(player, 0x01, 0, 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_HAS_STOPPED, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ addSpawn(MELISSA, MELISSA_SPAWN.getX(), MELISSA_SPAWN.getY(), MELISSA_SPAWN.getZ(), 0, false, 0, true, world.getId());
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ altar.deleteMe();
+ world.setStatus(8);
+ }
+ }
+ else
+ {
+ for (L2PcInstance player : world.getPlayers())
+ {
+ if (_time == ALTAR_TIME)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_IS_STARTING_MUST_FOCUS_FIRE_THE_ALTAR, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ }
+ }
+
+ if (!defeated && (_time == 9))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("The Altar of Shilen will become activated in 10 seconds.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time == 4))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage("The Altar of Shilen will become activated in 5 seconds.", ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time <= 0))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOCUS_FIRE_THE_ALTAR_TO_STOP_BLESSING_OF_SHILEN, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+
+ if (isInInstance(world))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(altar, L2MonsterInstance.class, 8000, boss ->
+ {
+ if ((boss != null) && !boss.isDead())
+ {
+ altar.doCast(PROTECTED_ALTAR.getSkill());
+ boss.setCurrentHp(boss.getCurrentHp() + (boss.getMaxHp() / 2));
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 30, 5));
+ }
+ }
+ });
+ }
+ }
+
+ if ((_time <= 0) && world.isStatus(7))
+ {
+ ThreadPool.schedule(() ->
+ {
+ _time = ALTAR_TIME;
+ }, 15000);
+ }
+ }
+ }, 0, 1000), 5000);
+ break;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new AltarOfShilen();
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
new file mode 100644
index 0000000000..193aa80dde
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
@@ -0,0 +1,5 @@
+Agent Georgio:
+The Altar of Shilen is extremely dangerous.
+You're trying to go there alone. You may be either very confident or reckless.
+To let you go is to send you to your death. If you want to go to the Altar of Shilen and stop the ritual, please gather allies and return.
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
new file mode 100644
index 0000000000..5ceb23f4c5
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+(A party members level must be 101 - 105 Lvl to challenge Altar of Shilen.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
new file mode 100644
index 0000000000..538b8bed55
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+Only a party leader may enter the altar of Shilen
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
new file mode 100644
index 0000000000..361fbf1ca0
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+You are too weak. Gather more people.
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/19100-19199.xml b/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/19100-19199.xml
index 3f350a842c..23d3595e8b 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/19100-19199.xml
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/19100-19199.xml
@@ -683,7 +683,7 @@
-
+
CONSTRUCT
MALE
@@ -710,7 +710,7 @@
-
+
CONSTRUCT
MALE
@@ -737,7 +737,7 @@
-
+
CONSTRUCT
MALE
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/25800-25899.xml b/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/25800-25899.xml
index 3425f529ba..01c3be8776 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/25800-25899.xml
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/stats/npcs/25800-25899.xml
@@ -2349,19 +2349,19 @@
-
+
-
-
+
+
HUMANOID
FEMALE
-
+
@@ -2384,9 +2384,9 @@
-
-
-
+
+
+
@@ -2395,7 +2395,7 @@
-
+
EMBRYO_BOSS
@@ -2404,21 +2404,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
HUMANOID
MALE
-
+
-
+
@@ -2435,10 +2537,12 @@
-
+
+
+
@@ -2455,20 +2559,21 @@
-
+
-
-
+
+
+
HUMANOID
FEMALE
-
+
-
+
@@ -2481,13 +2586,16 @@
-
+
+
+
+
@@ -2892,7 +3000,7 @@
-
+
diff --git a/L2J_Mobius_3.0_Helios/readme.txt b/L2J_Mobius_3.0_Helios/readme.txt
index d29dbf1685..fb3392a340 100644
--- a/L2J_Mobius_3.0_Helios/readme.txt
+++ b/L2J_Mobius_3.0_Helios/readme.txt
@@ -31,6 +31,7 @@ Goddess of Destruction:
-Kartia
-Fortuna
-Nursery
+-Altar of Shilen
-Kimerian
-Istina
-Octavis
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/33515.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/33515.htm
index 24608a9b78..c4858bfe85 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/33515.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/33515.htm
@@ -1,4 +1,7 @@
-Agent Georgio:
-Sh... I'm currently on duty. If you don't have anything to say, please go away.
+Agent Georgio:
+Hush! I'm on a mission.
+The Kingdom's Royal Guards are investigating a report that a ritual is being held on the Altar of Shilen, which has been closed since Melisa and Isadora disappeared. I'd like to ask you to leave us, if you don't mind.
+Or, if you want to go to the Altar of Shilen to stop the ritual, I can send you there. Just tell me.
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/instances/AltarOfShilen.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/instances/AltarOfShilen.xml
new file mode 100644
index 0000000000..6457e49c6b
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/instances/AltarOfShilen.xml
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19121.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19121.html
new file mode 100644
index 0000000000..a29854329e
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19121.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19122.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19122.html
new file mode 100644
index 0000000000..b54e43083b
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/19122.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
new file mode 100644
index 0000000000..6b735ce5aa
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, you're the adventurer who volunteered to stop the ritual on the Altar of Shilen. You must be capable enough to stop it. Otherwise, you couldn't come this far. Okay, I'll open the door for you.
+Don't lower yourb guard once inside.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
new file mode 100644
index 0000000000..f45f7e769e
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
@@ -0,0 +1,7 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, it's you! You've come this far!
+The last altar is before you.
+After Embryos invaded the Keucereus Alliance Base, the existence of the Messiah Castle was revealed. Melisa and Isadora, the twin sisters who had long disappeared, returned and are threatening us. If we fail to stop the ritual, Embryos will invade Aden Continent in no time. We must stop them at all cost.
+My man Dinford will be waiting for you at the entrance to the last altar. Go to find him.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331.html
new file mode 100644
index 0000000000..cf6f3b0075
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34331.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+How did you get in here? The blockade was only recently lifted, and this area is still very dangerous. It is under the control of the Kingdom's Royal Guard.
+It is suspected that Embryos are preparing somewhere in this area to invade the Aden Continent. The Kingdom's Royal Guard is doing its best to stop them. are you here to stop the Embryo's ritual on the Altar of Shilen? if so. I'll gladly open open this door. Be careful. Only danger awaits you.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34332.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34332.html
new file mode 100644
index 0000000000..f194522b63
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/34332.html
@@ -0,0 +1,6 @@
+Quartermaster Dinford
+Who is it? Ah, you've come to stop the ritual the ritual on the Altar of Shilen!
+If so, I'll open the door to the altar.
+Please stop the threat of the Embrio.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
new file mode 100644
index 0000000000..5306b343b6
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
@@ -0,0 +1,694 @@
+/*
+ * 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 instances.AltarOfShilen;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.gameserver.enums.ChatType;
+import com.l2jmobius.gameserver.instancemanager.InstanceManager;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.actor.L2Npc;
+import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.holders.SkillHolder;
+import com.l2jmobius.gameserver.model.instancezone.Instance;
+import com.l2jmobius.gameserver.network.NpcStringId;
+import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
+import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
+import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
+
+import instances.AbstractInstance;
+
+/**
+ * Instance Altar of Shilen
+ * @URL https://l2wiki.com/Altar_of_Shilen
+ * @author Gigi
+ * @date 2018-04-13 - [23:27:28]
+ */
+public class AltarOfShilen extends AbstractInstance
+{
+ // NPCs
+ private static final int LOGART_VAN_DYKE = 34331;
+ private static final int DINFORD = 34332;
+ private static final int ISADORA = 25856;
+ private static final int MELISSA0 = 25855;
+ private static final int MELISSA = 25876; // She dropping items
+ private static final int EXECUTOR_CAPTAIN = 23131;
+ private static final int ETINA_BLADESMAN = 23138;
+ private static final int CORRUPTED_CAPTAIN = 25857;
+ private static final int CORRUPTED_HIGH_PRIEST = 25858;
+ private static final int RITUAL_ALTAR0 = 19121;
+ private static final int RITUAL_ALTAR1 = 19122;
+ private static final int SHILLIEN_ALTAR = 19123;
+ private static final int INVISIBLE = 8561;
+ private static final int ETINA_GOSPEL = 23132;
+ private static final int ETINA_PRIEST = 23133;
+ private static final int ETINA_PROTECTORS = 23134;
+ private static final int ETINA_PUNISHERS = 23135;
+ private static final int ETINA_COMMINATION = 23136;
+ private static final int ETINA_DARKMONAGERS = 23137;
+ private static final int ELITE_ESCORT = 23126;
+ private static final int ELITE_CHASER = 23127;
+ private static final int ELITE_WARRIOR = 23128;
+ private static final int ELITE_ALCHEMIST = 23129;
+ private static final int ELITE_PRIEST = 23130;
+ private static final int EMBRYO_RESERCHER = 23139;
+ private static final int EMBRYO_WATCHMAN = 23140;
+ private static final int EMBRYO_FIGHTER = 23141;
+ private static final int EMBRYO_GUARD = 23142;
+ // Skills
+ static final SkillHolder PROTECTED_ALTAR = new SkillHolder(14496, 1);
+ // Misc
+ private static final int TEMPLATE_ID = 194;
+ private static final int ALTAR_TIME = 180;
+ //@formatter:off
+ private static final int[] DOORS = { 25180001, 25180002, 25180003, 25180004, 25180005, 25180006, 25180007 };
+ //@formatter:on
+ private static final NpcStringId[] SHOUT_MSG =
+ {
+ NpcStringId.I_NEED_HELP,
+ NpcStringId.FOCUS_FIRE_ACCORDING_TO_MY_ORCHESTRATION,
+ NpcStringId.I_NEED_HEAL,
+ NpcStringId.I_M_GOING_TO_BACK_OFF_FOR_A_BIT,
+ NpcStringId.I_WILL_ATTACK_THE_ENEMY_S_HEALER,
+ NpcStringId.STOP_ENEMIES_HEALING,
+ NpcStringId.ATTACK_WEAKENED_ENEMY,
+ NpcStringId.COME_AT_ME,
+ NpcStringId.SWITCH_TO_FAST_SHOOTING_MODE,
+ NpcStringId.SWITCH_TO_FAST_CASTING_MODE,
+ NpcStringId.BLINK_ATTACK,
+ NpcStringId.ONLY_DEATH_AWAITS_FOR_THE_WEAK,
+ };
+ static final Location MELISSA_SPAWN = new Location(178146, 14356, -13688);
+ private static final Location SECOND_FLOOR = new Location(179357, 13664, -9828);
+ private static final Location THIRD_FLOOR = new Location(179354, 12922, -12776);
+
+ final List playersInside = new ArrayList<>();
+ final Map killedMonsters = new ConcurrentHashMap<>();
+ static List firstFloorVictims = new ArrayList<>();
+ public static Future> timer;
+ public L2Npc altar;
+
+ public AltarOfShilen()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addFirstTalkId(LOGART_VAN_DYKE, RITUAL_ALTAR0, RITUAL_ALTAR1, DINFORD);
+ addSpawnId(CORRUPTED_CAPTAIN, CORRUPTED_HIGH_PRIEST, INVISIBLE, SHILLIEN_ALTAR);
+ addAttackId(ETINA_GOSPEL, ETINA_PRIEST, ETINA_PROTECTORS, ETINA_PUNISHERS, ETINA_COMMINATION, ETINA_DARKMONAGERS, ELITE_ESCORT, ELITE_CHASER, ELITE_WARRIOR, ELITE_ALCHEMIST, ELITE_PRIEST, EMBRYO_RESERCHER, EMBRYO_WATCHMAN, EMBRYO_FIGHTER, EMBRYO_GUARD);
+ addKillId(EXECUTOR_CAPTAIN, CORRUPTED_CAPTAIN, ETINA_BLADESMAN, CORRUPTED_HIGH_PRIEST, ETINA_GOSPEL, ETINA_PROTECTORS, ETINA_PUNISHERS, MELISSA0, MELISSA, ISADORA);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance instance, L2PcInstance player)
+ {
+ instance.spawnGroup("general");
+ instance.spawnGroup("first_floor");
+ instance.setStatus(1);
+ }
+
+ @Override
+ public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (event.equals("enterInstance"))
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ if (player.isGM())
+ {
+ playersInside.add(player);
+ }
+ if (player.getParty() != null)
+ {
+ for (L2PcInstance partyMember : player.getParty().getMembers())
+ {
+ playersInside.add(partyMember);
+ }
+ }
+ }
+ if (event.equals("check_player"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 400, p ->
+ {
+ if ((p != null) && p.isPlayer() && !p.isDead())
+ {
+ npc.setScriptValue(1);
+ final L2Npc gospel = addSpawn(ETINA_GOSPEL, npc, true, 0, false, world.getId());
+ final L2Npc priest = addSpawn(ETINA_PRIEST, npc, true, 0, false, world.getId());
+ final L2Npc protectors = addSpawn(ETINA_PROTECTORS, npc, true, 0, false, world.getId());
+ final L2Npc punishers = addSpawn(ETINA_PUNISHERS, npc, true, 0, false, world.getId());
+ final L2Npc commination = addSpawn(ETINA_COMMINATION, npc, true, 0, false, world.getId());
+ final L2Npc darkmonagers = addSpawn(ETINA_DARKMONAGERS, npc, true, 0, false, world.getId());
+ addAttackPlayerDesire(gospel, p);
+ addAttackPlayerDesire(priest, p);
+ addAttackPlayerDesire(protectors, p);
+ addAttackPlayerDesire(punishers, p);
+ addAttackPlayerDesire(commination, p);
+ addAttackPlayerDesire(darkmonagers, p);
+ }
+ });
+ }
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if (event.equals("open_door"))
+ {
+ if (world.getStatus() == 1)
+ {
+ if (world.getDoor(DOORS[0]) != null)
+ {
+ world.getDoor(DOORS[0]).openMe();
+ }
+ world.setStatus(2);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 3)
+ {
+ if (world.getDoor(DOORS[1]) != null)
+ {
+ world.getDoor(DOORS[1]).openMe();
+ }
+ world.setStatus(4);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 5)
+ {
+ if (world.getDoor(DOORS[2]) != null)
+ {
+ world.getDoor(DOORS[2]).openMe();
+ }
+ world.setStatus(6);
+ onStatusChanged(world);
+ break;
+ }
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if ((world.getStatus() == 3) && event.equals("teleport1"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(SECOND_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("second_floor");
+ });
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if ((world.getStatus() == 5) && event.equals("teleport2"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(THIRD_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("thrid_floor");
+ });
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if ((world.getStatus() == 6) && event.equals("final_door"))
+ {
+ if (!world.getDoor(DOORS[6]).isOpen())
+ {
+ world.getDoor(DOORS[6]).openMe();
+ }
+ world.setStatus(7);
+ onStatusChanged(world);
+ npc.deleteMe();
+ cancelQuestTimers("check_player");
+ }
+ break;
+ }
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ if (getRandom(30) < 3)
+ {
+ npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), SHOUT_MSG[getRandom(SHOUT_MSG.length)]));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (world != null)
+ {
+ int npcId = npc.getId();
+ if (!killedMonsters.containsKey(npcId))
+ {
+ killedMonsters.put(npcId, 1);
+ }
+ else
+ {
+ killedMonsters.put(npcId, killedMonsters.get(npcId) + 1);
+ }
+ // 1st Floor
+ if (world.getStatus() == 2)
+ {
+ if (killedMonsters.containsKey(EXECUTOR_CAPTAIN) && (killedMonsters.get(EXECUTOR_CAPTAIN) >= 3))
+ {
+ final int boos1 = world.getTemplateParameters().getInt("boss1");
+ final L2Npc captain = world.getNpc(boos1);
+ if (captain != null)
+ {
+ captain.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_CAPTAIN) && (killedMonsters.get(CORRUPTED_CAPTAIN) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_MOVE_TO_THE_NEXT_FLOOR_THROUGH_THE_ALTAR_OF_SACRIFICE, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(3);
+ killedMonsters.clear();
+ onStatusChanged(world);
+ }
+ }
+ // 2st Floor
+ else if (world.getStatus() == 4)
+ {
+ if (killedMonsters.containsKey(ETINA_BLADESMAN) && (killedMonsters.get(ETINA_BLADESMAN) >= 3))
+ {
+ final int boos2 = world.getTemplateParameters().getInt("boss2");
+ final L2Npc priest = world.getNpc(boos2);
+ if (priest != null)
+ {
+ priest.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_HIGH_PRIEST) && (killedMonsters.get(CORRUPTED_HIGH_PRIEST) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_MOVE_TO_THE_NEXT_FLOOR_THROUGH_THE_ALTAR_OF_SACRIFICE, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(5);
+ killedMonsters.clear();
+ onStatusChanged(world);
+
+ }
+ }
+ // 3st Floor
+ else if (world.getStatus() == 6)
+ {
+ switch (npc.getId())
+ {
+ case ETINA_GOSPEL:
+ {
+ world.getDoor(DOORS[3]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[3]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PROTECTORS:
+ {
+ world.getDoor(DOORS[4]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[4]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PUNISHERS:
+ {
+ world.getDoor(DOORS[5]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[5]).closeMe(), 5000);
+ break;
+ }
+ }
+ }
+ else if (world.getStatus() == 8)
+ {
+ if (killedMonsters.containsKey(MELISSA) && (killedMonsters.get(MELISSA) == 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_HAS_BEEN_DESTROYED_YOU_VE_WON, ExShowScreenMessage.TOP_CENTER, 5000, true));
+ }
+ playersInside.clear();
+ killedMonsters.clear();
+ world.finishInstance(1);
+ }
+ }
+ }
+ return super.onKill(npc, killer, isSummon);
+ }
+
+ @Override
+ public String onSpawn(L2Npc npc)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ switch (npc.getId())
+ {
+ case CORRUPTED_CAPTAIN:
+ case CORRUPTED_HIGH_PRIEST:
+ {
+ npc.setIsInvul(true);
+ break;
+ }
+ case INVISIBLE:
+ {
+ if (npc.isScriptValue(0))
+ {
+ startQuestTimer("check_player", 2000, npc, null, true);
+ }
+ break;
+ }
+ case SHILLIEN_ALTAR:
+ {
+ altar = npc;
+ break;
+ }
+ }
+ }
+ return super.onSpawn(npc);
+ }
+
+ @Override
+ public String onFirstTalk(L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if ((world.getStatus() > 0) && (world.getStatus() < 3))
+ {
+ return "34331.html";
+ }
+ else if ((world.getStatus() >= 3) && (world.getStatus() < 5))
+ {
+ return "34331-01.html";
+ }
+ else if (world.getStatus() >= 5)
+ {
+ return "34331-02.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if (world.getStatus() >= 3)
+ {
+ return "19121.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "19122.html";
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "34332.html";
+ }
+ break;
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static class VictimDefeatTask implements Runnable
+ {
+ private final Instance _world;
+ private int _victims;
+ private final int _initialTime;
+ private int _time;
+
+ VictimDefeatTask(int victims, int time, Instance world)
+ {
+ _world = world;
+ _victims = victims;
+ _initialTime = time;
+ _time = time;
+ }
+
+ @Override
+ public void run()
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_GP_TIMER, (_time--), 0, NpcStringId.SACRIFICE_LEFT_S1, new String[]
+ {
+ String.valueOf(_victims)
+ }));
+ }
+ if (_time <= 0)
+ {
+ _time = _initialTime;
+ --_victims;
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 20, 5));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.SACRIFICE_HAS_BEEN_KILLED_SACRIFICE_LEFT_S1, ExShowScreenMessage.MIDDLE_CENTER, 3000, String.valueOf(_victims)));
+ }
+ }
+ if ((_world.getStatus() == 2) && !firstFloorVictims.isEmpty())
+ {
+ firstFloorVictims.get(0).deleteMe();
+ firstFloorVictims.remove(0);
+ }
+ if ((_victims == 1) && (_world.getStatus() == 2))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOUR_LIVES_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_CORRUPTED_CAPTAIN, ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if ((_victims == 1) && (_world.getStatus() == 4))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOUR_LIVES_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_CORRUPTED_HIGH_PRIEST, ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if (_victims <= 0)
+ {
+ ThreadPool.schedule(() ->
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALL_OFFERINGS_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_EMBRYO_COLONY_IN_THAT_FLOOR, ExShowScreenMessage.MIDDLE_CENTER, 3000));
+ }
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ _world.finishInstance(1);
+ }, 3000);
+ }
+ }
+ }
+
+ private void onStatusChanged(final Instance world)
+ {
+ final Instance instance = InstanceManager.getInstance().getInstance(world.getId());
+ switch (instance.getStatus())
+ {
+ case 1:
+ {
+ break;
+ }
+ case 2:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 3:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 5:
+ case 6:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 7:
+ {
+ ThreadPool.schedule(() -> timer = ThreadPool.scheduleAtFixedRate(new Runnable()
+ {
+ private int _time = ALTAR_TIME;
+
+ @Override
+ public void run()
+ {
+ if (_time <= 0)
+ {
+ return;
+ }
+ boolean defeated = false;
+ if (killedMonsters.containsKey(MELISSA0) && (killedMonsters.get(MELISSA0) == 1) && killedMonsters.containsKey(ISADORA) && (killedMonsters.get(ISADORA) == 1))
+ {
+ defeated = true;
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExSendUIEvent(player, 0x01, 0, 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_HAS_STOPPED, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ addSpawn(MELISSA, MELISSA_SPAWN.getX(), MELISSA_SPAWN.getY(), MELISSA_SPAWN.getZ(), 0, false, 0, true, world.getId());
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ altar.deleteMe();
+ world.setStatus(8);
+ }
+ }
+ else
+ {
+ for (L2PcInstance player : world.getPlayers())
+ {
+ if (_time == ALTAR_TIME)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_IS_STARTING_MUST_FOCUS_FIRE_THE_ALTAR, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ }
+ }
+
+ if (!defeated && (_time == 9))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_ALTAR_OF_SHILEN_WILL_BECOME_ACTIVATED_IN_10_SECONDS, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time == 4))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_ALTAR_OF_SHILEN_WILL_BECOME_ACTIVATED_IN_5_SECONDS, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time <= 0))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOCUS_FIRE_THE_ALTAR_TO_STOP_BLESSING_OF_SHILEN, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+
+ if (isInInstance(world))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(altar, L2MonsterInstance.class, 8000, boss ->
+ {
+ if ((boss != null) && !boss.isDead())
+ {
+ altar.doCast(PROTECTED_ALTAR.getSkill());
+ boss.setCurrentHp(boss.getCurrentHp() + (boss.getMaxHp() / 2));
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 30, 5));
+ }
+ }
+ });
+ }
+ }
+
+ if ((_time <= 0) && world.isStatus(7))
+ {
+ ThreadPool.schedule(() ->
+ {
+ _time = ALTAR_TIME;
+ }, 15000);
+ }
+ }
+ }, 0, 1000), 5000);
+ break;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new AltarOfShilen();
+ }
+}
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
new file mode 100644
index 0000000000..193aa80dde
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
@@ -0,0 +1,5 @@
+Agent Georgio:
+The Altar of Shilen is extremely dangerous.
+You're trying to go there alone. You may be either very confident or reckless.
+To let you go is to send you to your death. If you want to go to the Altar of Shilen and stop the ritual, please gather allies and return.
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
new file mode 100644
index 0000000000..5ceb23f4c5
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+(A party members level must be 101 - 105 Lvl to challenge Altar of Shilen.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
new file mode 100644
index 0000000000..538b8bed55
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+Only a party leader may enter the altar of Shilen
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
new file mode 100644
index 0000000000..361fbf1ca0
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+You are too weak. Gather more people.
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/19100-19199.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/19100-19199.xml
index 0a8bf574ad..ca1ed03e25 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/19100-19199.xml
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/19100-19199.xml
@@ -683,7 +683,7 @@
-
+
CONSTRUCT
MALE
@@ -710,7 +710,7 @@
-
+
CONSTRUCT
MALE
@@ -737,7 +737,7 @@
-
+
CONSTRUCT
MALE
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/25800-25899.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/25800-25899.xml
index abace73921..1c69307620 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/25800-25899.xml
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/stats/npcs/25800-25899.xml
@@ -3245,8 +3245,8 @@
-
-
+
+
HUMANOID
@@ -3276,9 +3276,9 @@
-
-
-
+
+
+
@@ -3287,7 +3287,7 @@
-
+
EMBRYO_BOSS
@@ -3403,8 +3403,8 @@
-
-
+
+
HUMANOID
@@ -3429,10 +3429,12 @@
-
+
+
+
@@ -3453,8 +3455,9 @@
-
-
+
+
+
HUMANOID
@@ -3475,13 +3478,16 @@
-
+
+
+
+
@@ -4128,7 +4134,7 @@
-
+
diff --git a/L2J_Mobius_4.0_GrandCrusade/readme.txt b/L2J_Mobius_4.0_GrandCrusade/readme.txt
index f5ebe7d710..2adab6efcb 100644
--- a/L2J_Mobius_4.0_GrandCrusade/readme.txt
+++ b/L2J_Mobius_4.0_GrandCrusade/readme.txt
@@ -31,6 +31,7 @@ Goddess of Destruction:
-Kartia
-Fortuna
-Nursery
+-Altar of Shilen
-Kimerian
-Istina
-Octavis
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/33515.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/33515.htm
index 24608a9b78..c4858bfe85 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/33515.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/33515.htm
@@ -1,4 +1,7 @@
-Agent Georgio:
-Sh... I'm currently on duty. If you don't have anything to say, please go away.
+Agent Georgio:
+Hush! I'm on a mission.
+The Kingdom's Royal Guards are investigating a report that a ritual is being held on the Altar of Shilen, which has been closed since Melisa and Isadora disappeared. I'd like to ask you to leave us, if you don't mind.
+Or, if you want to go to the Altar of Shilen to stop the ritual, I can send you there. Just tell me.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/instances/AltarOfShilen.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/instances/AltarOfShilen.xml
new file mode 100644
index 0000000000..6457e49c6b
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/instances/AltarOfShilen.xml
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19121.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19121.html
new file mode 100644
index 0000000000..a29854329e
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19121.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19122.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19122.html
new file mode 100644
index 0000000000..b54e43083b
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/19122.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
new file mode 100644
index 0000000000..6b735ce5aa
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, you're the adventurer who volunteered to stop the ritual on the Altar of Shilen. You must be capable enough to stop it. Otherwise, you couldn't come this far. Okay, I'll open the door for you.
+Don't lower yourb guard once inside.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
new file mode 100644
index 0000000000..f45f7e769e
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
@@ -0,0 +1,7 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, it's you! You've come this far!
+The last altar is before you.
+After Embryos invaded the Keucereus Alliance Base, the existence of the Messiah Castle was revealed. Melisa and Isadora, the twin sisters who had long disappeared, returned and are threatening us. If we fail to stop the ritual, Embryos will invade Aden Continent in no time. We must stop them at all cost.
+My man Dinford will be waiting for you at the entrance to the last altar. Go to find him.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331.html
new file mode 100644
index 0000000000..cf6f3b0075
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34331.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+How did you get in here? The blockade was only recently lifted, and this area is still very dangerous. It is under the control of the Kingdom's Royal Guard.
+It is suspected that Embryos are preparing somewhere in this area to invade the Aden Continent. The Kingdom's Royal Guard is doing its best to stop them. are you here to stop the Embryo's ritual on the Altar of Shilen? if so. I'll gladly open open this door. Be careful. Only danger awaits you.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34332.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34332.html
new file mode 100644
index 0000000000..f194522b63
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/34332.html
@@ -0,0 +1,6 @@
+Quartermaster Dinford
+Who is it? Ah, you've come to stop the ritual the ritual on the Altar of Shilen!
+If so, I'll open the door to the altar.
+Please stop the threat of the Embrio.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
new file mode 100644
index 0000000000..5306b343b6
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
@@ -0,0 +1,694 @@
+/*
+ * 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 instances.AltarOfShilen;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.gameserver.enums.ChatType;
+import com.l2jmobius.gameserver.instancemanager.InstanceManager;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.actor.L2Npc;
+import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.holders.SkillHolder;
+import com.l2jmobius.gameserver.model.instancezone.Instance;
+import com.l2jmobius.gameserver.network.NpcStringId;
+import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
+import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
+import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
+
+import instances.AbstractInstance;
+
+/**
+ * Instance Altar of Shilen
+ * @URL https://l2wiki.com/Altar_of_Shilen
+ * @author Gigi
+ * @date 2018-04-13 - [23:27:28]
+ */
+public class AltarOfShilen extends AbstractInstance
+{
+ // NPCs
+ private static final int LOGART_VAN_DYKE = 34331;
+ private static final int DINFORD = 34332;
+ private static final int ISADORA = 25856;
+ private static final int MELISSA0 = 25855;
+ private static final int MELISSA = 25876; // She dropping items
+ private static final int EXECUTOR_CAPTAIN = 23131;
+ private static final int ETINA_BLADESMAN = 23138;
+ private static final int CORRUPTED_CAPTAIN = 25857;
+ private static final int CORRUPTED_HIGH_PRIEST = 25858;
+ private static final int RITUAL_ALTAR0 = 19121;
+ private static final int RITUAL_ALTAR1 = 19122;
+ private static final int SHILLIEN_ALTAR = 19123;
+ private static final int INVISIBLE = 8561;
+ private static final int ETINA_GOSPEL = 23132;
+ private static final int ETINA_PRIEST = 23133;
+ private static final int ETINA_PROTECTORS = 23134;
+ private static final int ETINA_PUNISHERS = 23135;
+ private static final int ETINA_COMMINATION = 23136;
+ private static final int ETINA_DARKMONAGERS = 23137;
+ private static final int ELITE_ESCORT = 23126;
+ private static final int ELITE_CHASER = 23127;
+ private static final int ELITE_WARRIOR = 23128;
+ private static final int ELITE_ALCHEMIST = 23129;
+ private static final int ELITE_PRIEST = 23130;
+ private static final int EMBRYO_RESERCHER = 23139;
+ private static final int EMBRYO_WATCHMAN = 23140;
+ private static final int EMBRYO_FIGHTER = 23141;
+ private static final int EMBRYO_GUARD = 23142;
+ // Skills
+ static final SkillHolder PROTECTED_ALTAR = new SkillHolder(14496, 1);
+ // Misc
+ private static final int TEMPLATE_ID = 194;
+ private static final int ALTAR_TIME = 180;
+ //@formatter:off
+ private static final int[] DOORS = { 25180001, 25180002, 25180003, 25180004, 25180005, 25180006, 25180007 };
+ //@formatter:on
+ private static final NpcStringId[] SHOUT_MSG =
+ {
+ NpcStringId.I_NEED_HELP,
+ NpcStringId.FOCUS_FIRE_ACCORDING_TO_MY_ORCHESTRATION,
+ NpcStringId.I_NEED_HEAL,
+ NpcStringId.I_M_GOING_TO_BACK_OFF_FOR_A_BIT,
+ NpcStringId.I_WILL_ATTACK_THE_ENEMY_S_HEALER,
+ NpcStringId.STOP_ENEMIES_HEALING,
+ NpcStringId.ATTACK_WEAKENED_ENEMY,
+ NpcStringId.COME_AT_ME,
+ NpcStringId.SWITCH_TO_FAST_SHOOTING_MODE,
+ NpcStringId.SWITCH_TO_FAST_CASTING_MODE,
+ NpcStringId.BLINK_ATTACK,
+ NpcStringId.ONLY_DEATH_AWAITS_FOR_THE_WEAK,
+ };
+ static final Location MELISSA_SPAWN = new Location(178146, 14356, -13688);
+ private static final Location SECOND_FLOOR = new Location(179357, 13664, -9828);
+ private static final Location THIRD_FLOOR = new Location(179354, 12922, -12776);
+
+ final List playersInside = new ArrayList<>();
+ final Map killedMonsters = new ConcurrentHashMap<>();
+ static List firstFloorVictims = new ArrayList<>();
+ public static Future> timer;
+ public L2Npc altar;
+
+ public AltarOfShilen()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addFirstTalkId(LOGART_VAN_DYKE, RITUAL_ALTAR0, RITUAL_ALTAR1, DINFORD);
+ addSpawnId(CORRUPTED_CAPTAIN, CORRUPTED_HIGH_PRIEST, INVISIBLE, SHILLIEN_ALTAR);
+ addAttackId(ETINA_GOSPEL, ETINA_PRIEST, ETINA_PROTECTORS, ETINA_PUNISHERS, ETINA_COMMINATION, ETINA_DARKMONAGERS, ELITE_ESCORT, ELITE_CHASER, ELITE_WARRIOR, ELITE_ALCHEMIST, ELITE_PRIEST, EMBRYO_RESERCHER, EMBRYO_WATCHMAN, EMBRYO_FIGHTER, EMBRYO_GUARD);
+ addKillId(EXECUTOR_CAPTAIN, CORRUPTED_CAPTAIN, ETINA_BLADESMAN, CORRUPTED_HIGH_PRIEST, ETINA_GOSPEL, ETINA_PROTECTORS, ETINA_PUNISHERS, MELISSA0, MELISSA, ISADORA);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance instance, L2PcInstance player)
+ {
+ instance.spawnGroup("general");
+ instance.spawnGroup("first_floor");
+ instance.setStatus(1);
+ }
+
+ @Override
+ public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (event.equals("enterInstance"))
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ if (player.isGM())
+ {
+ playersInside.add(player);
+ }
+ if (player.getParty() != null)
+ {
+ for (L2PcInstance partyMember : player.getParty().getMembers())
+ {
+ playersInside.add(partyMember);
+ }
+ }
+ }
+ if (event.equals("check_player"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 400, p ->
+ {
+ if ((p != null) && p.isPlayer() && !p.isDead())
+ {
+ npc.setScriptValue(1);
+ final L2Npc gospel = addSpawn(ETINA_GOSPEL, npc, true, 0, false, world.getId());
+ final L2Npc priest = addSpawn(ETINA_PRIEST, npc, true, 0, false, world.getId());
+ final L2Npc protectors = addSpawn(ETINA_PROTECTORS, npc, true, 0, false, world.getId());
+ final L2Npc punishers = addSpawn(ETINA_PUNISHERS, npc, true, 0, false, world.getId());
+ final L2Npc commination = addSpawn(ETINA_COMMINATION, npc, true, 0, false, world.getId());
+ final L2Npc darkmonagers = addSpawn(ETINA_DARKMONAGERS, npc, true, 0, false, world.getId());
+ addAttackPlayerDesire(gospel, p);
+ addAttackPlayerDesire(priest, p);
+ addAttackPlayerDesire(protectors, p);
+ addAttackPlayerDesire(punishers, p);
+ addAttackPlayerDesire(commination, p);
+ addAttackPlayerDesire(darkmonagers, p);
+ }
+ });
+ }
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if (event.equals("open_door"))
+ {
+ if (world.getStatus() == 1)
+ {
+ if (world.getDoor(DOORS[0]) != null)
+ {
+ world.getDoor(DOORS[0]).openMe();
+ }
+ world.setStatus(2);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 3)
+ {
+ if (world.getDoor(DOORS[1]) != null)
+ {
+ world.getDoor(DOORS[1]).openMe();
+ }
+ world.setStatus(4);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 5)
+ {
+ if (world.getDoor(DOORS[2]) != null)
+ {
+ world.getDoor(DOORS[2]).openMe();
+ }
+ world.setStatus(6);
+ onStatusChanged(world);
+ break;
+ }
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if ((world.getStatus() == 3) && event.equals("teleport1"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(SECOND_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("second_floor");
+ });
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if ((world.getStatus() == 5) && event.equals("teleport2"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(THIRD_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("thrid_floor");
+ });
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if ((world.getStatus() == 6) && event.equals("final_door"))
+ {
+ if (!world.getDoor(DOORS[6]).isOpen())
+ {
+ world.getDoor(DOORS[6]).openMe();
+ }
+ world.setStatus(7);
+ onStatusChanged(world);
+ npc.deleteMe();
+ cancelQuestTimers("check_player");
+ }
+ break;
+ }
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ if (getRandom(30) < 3)
+ {
+ npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), SHOUT_MSG[getRandom(SHOUT_MSG.length)]));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (world != null)
+ {
+ int npcId = npc.getId();
+ if (!killedMonsters.containsKey(npcId))
+ {
+ killedMonsters.put(npcId, 1);
+ }
+ else
+ {
+ killedMonsters.put(npcId, killedMonsters.get(npcId) + 1);
+ }
+ // 1st Floor
+ if (world.getStatus() == 2)
+ {
+ if (killedMonsters.containsKey(EXECUTOR_CAPTAIN) && (killedMonsters.get(EXECUTOR_CAPTAIN) >= 3))
+ {
+ final int boos1 = world.getTemplateParameters().getInt("boss1");
+ final L2Npc captain = world.getNpc(boos1);
+ if (captain != null)
+ {
+ captain.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_CAPTAIN) && (killedMonsters.get(CORRUPTED_CAPTAIN) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_MOVE_TO_THE_NEXT_FLOOR_THROUGH_THE_ALTAR_OF_SACRIFICE, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(3);
+ killedMonsters.clear();
+ onStatusChanged(world);
+ }
+ }
+ // 2st Floor
+ else if (world.getStatus() == 4)
+ {
+ if (killedMonsters.containsKey(ETINA_BLADESMAN) && (killedMonsters.get(ETINA_BLADESMAN) >= 3))
+ {
+ final int boos2 = world.getTemplateParameters().getInt("boss2");
+ final L2Npc priest = world.getNpc(boos2);
+ if (priest != null)
+ {
+ priest.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_HIGH_PRIEST) && (killedMonsters.get(CORRUPTED_HIGH_PRIEST) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_MOVE_TO_THE_NEXT_FLOOR_THROUGH_THE_ALTAR_OF_SACRIFICE, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(5);
+ killedMonsters.clear();
+ onStatusChanged(world);
+
+ }
+ }
+ // 3st Floor
+ else if (world.getStatus() == 6)
+ {
+ switch (npc.getId())
+ {
+ case ETINA_GOSPEL:
+ {
+ world.getDoor(DOORS[3]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[3]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PROTECTORS:
+ {
+ world.getDoor(DOORS[4]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[4]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PUNISHERS:
+ {
+ world.getDoor(DOORS[5]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[5]).closeMe(), 5000);
+ break;
+ }
+ }
+ }
+ else if (world.getStatus() == 8)
+ {
+ if (killedMonsters.containsKey(MELISSA) && (killedMonsters.get(MELISSA) == 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_HAS_BEEN_DESTROYED_YOU_VE_WON, ExShowScreenMessage.TOP_CENTER, 5000, true));
+ }
+ playersInside.clear();
+ killedMonsters.clear();
+ world.finishInstance(1);
+ }
+ }
+ }
+ return super.onKill(npc, killer, isSummon);
+ }
+
+ @Override
+ public String onSpawn(L2Npc npc)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ switch (npc.getId())
+ {
+ case CORRUPTED_CAPTAIN:
+ case CORRUPTED_HIGH_PRIEST:
+ {
+ npc.setIsInvul(true);
+ break;
+ }
+ case INVISIBLE:
+ {
+ if (npc.isScriptValue(0))
+ {
+ startQuestTimer("check_player", 2000, npc, null, true);
+ }
+ break;
+ }
+ case SHILLIEN_ALTAR:
+ {
+ altar = npc;
+ break;
+ }
+ }
+ }
+ return super.onSpawn(npc);
+ }
+
+ @Override
+ public String onFirstTalk(L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if ((world.getStatus() > 0) && (world.getStatus() < 3))
+ {
+ return "34331.html";
+ }
+ else if ((world.getStatus() >= 3) && (world.getStatus() < 5))
+ {
+ return "34331-01.html";
+ }
+ else if (world.getStatus() >= 5)
+ {
+ return "34331-02.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if (world.getStatus() >= 3)
+ {
+ return "19121.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "19122.html";
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "34332.html";
+ }
+ break;
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static class VictimDefeatTask implements Runnable
+ {
+ private final Instance _world;
+ private int _victims;
+ private final int _initialTime;
+ private int _time;
+
+ VictimDefeatTask(int victims, int time, Instance world)
+ {
+ _world = world;
+ _victims = victims;
+ _initialTime = time;
+ _time = time;
+ }
+
+ @Override
+ public void run()
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_GP_TIMER, (_time--), 0, NpcStringId.SACRIFICE_LEFT_S1, new String[]
+ {
+ String.valueOf(_victims)
+ }));
+ }
+ if (_time <= 0)
+ {
+ _time = _initialTime;
+ --_victims;
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 20, 5));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.SACRIFICE_HAS_BEEN_KILLED_SACRIFICE_LEFT_S1, ExShowScreenMessage.MIDDLE_CENTER, 3000, String.valueOf(_victims)));
+ }
+ }
+ if ((_world.getStatus() == 2) && !firstFloorVictims.isEmpty())
+ {
+ firstFloorVictims.get(0).deleteMe();
+ firstFloorVictims.remove(0);
+ }
+ if ((_victims == 1) && (_world.getStatus() == 2))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOUR_LIVES_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_CORRUPTED_CAPTAIN, ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if ((_victims == 1) && (_world.getStatus() == 4))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOUR_LIVES_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_CORRUPTED_HIGH_PRIEST, ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if (_victims <= 0)
+ {
+ ThreadPool.schedule(() ->
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALL_OFFERINGS_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_EMBRYO_COLONY_IN_THAT_FLOOR, ExShowScreenMessage.MIDDLE_CENTER, 3000));
+ }
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ _world.finishInstance(1);
+ }, 3000);
+ }
+ }
+ }
+
+ private void onStatusChanged(final Instance world)
+ {
+ final Instance instance = InstanceManager.getInstance().getInstance(world.getId());
+ switch (instance.getStatus())
+ {
+ case 1:
+ {
+ break;
+ }
+ case 2:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 3:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 5:
+ case 6:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 7:
+ {
+ ThreadPool.schedule(() -> timer = ThreadPool.scheduleAtFixedRate(new Runnable()
+ {
+ private int _time = ALTAR_TIME;
+
+ @Override
+ public void run()
+ {
+ if (_time <= 0)
+ {
+ return;
+ }
+ boolean defeated = false;
+ if (killedMonsters.containsKey(MELISSA0) && (killedMonsters.get(MELISSA0) == 1) && killedMonsters.containsKey(ISADORA) && (killedMonsters.get(ISADORA) == 1))
+ {
+ defeated = true;
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExSendUIEvent(player, 0x01, 0, 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_HAS_STOPPED, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ addSpawn(MELISSA, MELISSA_SPAWN.getX(), MELISSA_SPAWN.getY(), MELISSA_SPAWN.getZ(), 0, false, 0, true, world.getId());
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ altar.deleteMe();
+ world.setStatus(8);
+ }
+ }
+ else
+ {
+ for (L2PcInstance player : world.getPlayers())
+ {
+ if (_time == ALTAR_TIME)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_IS_STARTING_MUST_FOCUS_FIRE_THE_ALTAR, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ }
+ }
+
+ if (!defeated && (_time == 9))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_ALTAR_OF_SHILEN_WILL_BECOME_ACTIVATED_IN_10_SECONDS, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time == 4))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_ALTAR_OF_SHILEN_WILL_BECOME_ACTIVATED_IN_5_SECONDS, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time <= 0))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOCUS_FIRE_THE_ALTAR_TO_STOP_BLESSING_OF_SHILEN, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+
+ if (isInInstance(world))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(altar, L2MonsterInstance.class, 8000, boss ->
+ {
+ if ((boss != null) && !boss.isDead())
+ {
+ altar.doCast(PROTECTED_ALTAR.getSkill());
+ boss.setCurrentHp(boss.getCurrentHp() + (boss.getMaxHp() / 2));
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 30, 5));
+ }
+ }
+ });
+ }
+ }
+
+ if ((_time <= 0) && world.isStatus(7))
+ {
+ ThreadPool.schedule(() ->
+ {
+ _time = ALTAR_TIME;
+ }, 15000);
+ }
+ }
+ }, 0, 1000), 5000);
+ break;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new AltarOfShilen();
+ }
+}
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
new file mode 100644
index 0000000000..193aa80dde
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
@@ -0,0 +1,5 @@
+Agent Georgio:
+The Altar of Shilen is extremely dangerous.
+You're trying to go there alone. You may be either very confident or reckless.
+To let you go is to send you to your death. If you want to go to the Altar of Shilen and stop the ritual, please gather allies and return.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
new file mode 100644
index 0000000000..5ceb23f4c5
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+(A party members level must be 101 - 105 Lvl to challenge Altar of Shilen.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
new file mode 100644
index 0000000000..538b8bed55
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+Only a party leader may enter the altar of Shilen
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
new file mode 100644
index 0000000000..361fbf1ca0
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+You are too weak. Gather more people.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/19100-19199.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/19100-19199.xml
index 8bb55b2e76..385604a193 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/19100-19199.xml
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/19100-19199.xml
@@ -683,7 +683,7 @@
-
+
CONSTRUCT
MALE
@@ -710,7 +710,7 @@
-
+
CONSTRUCT
MALE
@@ -737,7 +737,7 @@
-
+
CONSTRUCT
MALE
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/25800-25899.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/25800-25899.xml
index 6c4644e93c..f6f16be60c 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/25800-25899.xml
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/stats/npcs/25800-25899.xml
@@ -3245,8 +3245,8 @@
-
-
+
+
HUMANOID
@@ -3276,9 +3276,9 @@
-
-
-
+
+
+
@@ -3287,7 +3287,7 @@
-
+
EMBRYO_BOSS
@@ -3403,8 +3403,8 @@
-
-
+
+
HUMANOID
@@ -3429,10 +3429,12 @@
-
+
+
+
@@ -3453,8 +3455,9 @@
-
-
+
+
+
HUMANOID
@@ -3475,13 +3478,16 @@
-
+
+
+
+
@@ -4128,7 +4134,7 @@
-
+
diff --git a/L2J_Mobius_5.0_Salvation/readme.txt b/L2J_Mobius_5.0_Salvation/readme.txt
index 847386c4fb..dd3d5bf26a 100644
--- a/L2J_Mobius_5.0_Salvation/readme.txt
+++ b/L2J_Mobius_5.0_Salvation/readme.txt
@@ -29,6 +29,7 @@ Goddess of Destruction:
-Kartia
-Fortuna
-Nursery
+-Altar of Shilen
-Kimerian
-Istina
-Octavis
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/33515.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/33515.htm
index 24608a9b78..c4858bfe85 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/33515.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/33515.htm
@@ -1,4 +1,7 @@
-Agent Georgio:
-Sh... I'm currently on duty. If you don't have anything to say, please go away.
+Agent Georgio:
+Hush! I'm on a mission.
+The Kingdom's Royal Guards are investigating a report that a ritual is being held on the Altar of Shilen, which has been closed since Melisa and Isadora disappeared. I'd like to ask you to leave us, if you don't mind.
+Or, if you want to go to the Altar of Shilen to stop the ritual, I can send you there. Just tell me.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/instances/AltarOfShilen.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/instances/AltarOfShilen.xml
new file mode 100644
index 0000000000..6457e49c6b
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/instances/AltarOfShilen.xml
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19121.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19121.html
new file mode 100644
index 0000000000..a29854329e
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19121.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19122.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19122.html
new file mode 100644
index 0000000000..b54e43083b
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/19122.html
@@ -0,0 +1,4 @@
+
+The altar stops humming, and you feel the reverberating power of dimensional.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
new file mode 100644
index 0000000000..6b735ce5aa
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-01.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, you're the adventurer who volunteered to stop the ritual on the Altar of Shilen. You must be capable enough to stop it. Otherwise, you couldn't come this far. Okay, I'll open the door for you.
+Don't lower yourb guard once inside.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
new file mode 100644
index 0000000000..f45f7e769e
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331-02.html
@@ -0,0 +1,7 @@
+Royal Guard Captain Logart Van Dyke:
+Who is it? Ah, it's you! You've come this far!
+The last altar is before you.
+After Embryos invaded the Keucereus Alliance Base, the existence of the Messiah Castle was revealed. Melisa and Isadora, the twin sisters who had long disappeared, returned and are threatening us. If we fail to stop the ritual, Embryos will invade Aden Continent in no time. We must stop them at all cost.
+My man Dinford will be waiting for you at the entrance to the last altar. Go to find him.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331.html
new file mode 100644
index 0000000000..cf6f3b0075
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34331.html
@@ -0,0 +1,5 @@
+Royal Guard Captain Logart Van Dyke:
+How did you get in here? The blockade was only recently lifted, and this area is still very dangerous. It is under the control of the Kingdom's Royal Guard.
+It is suspected that Embryos are preparing somewhere in this area to invade the Aden Continent. The Kingdom's Royal Guard is doing its best to stop them. are you here to stop the Embryo's ritual on the Altar of Shilen? if so. I'll gladly open open this door. Be careful. Only danger awaits you.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34332.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34332.html
new file mode 100644
index 0000000000..f194522b63
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/34332.html
@@ -0,0 +1,6 @@
+Quartermaster Dinford
+Who is it? Ah, you've come to stop the ritual the ritual on the Altar of Shilen!
+If so, I'll open the door to the altar.
+Please stop the threat of the Embrio.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
new file mode 100644
index 0000000000..5306b343b6
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/AltarOfShilen.java
@@ -0,0 +1,694 @@
+/*
+ * 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 instances.AltarOfShilen;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.gameserver.enums.ChatType;
+import com.l2jmobius.gameserver.instancemanager.InstanceManager;
+import com.l2jmobius.gameserver.model.L2World;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.actor.L2Npc;
+import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.holders.SkillHolder;
+import com.l2jmobius.gameserver.model.instancezone.Instance;
+import com.l2jmobius.gameserver.network.NpcStringId;
+import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
+import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
+import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
+
+import instances.AbstractInstance;
+
+/**
+ * Instance Altar of Shilen
+ * @URL https://l2wiki.com/Altar_of_Shilen
+ * @author Gigi
+ * @date 2018-04-13 - [23:27:28]
+ */
+public class AltarOfShilen extends AbstractInstance
+{
+ // NPCs
+ private static final int LOGART_VAN_DYKE = 34331;
+ private static final int DINFORD = 34332;
+ private static final int ISADORA = 25856;
+ private static final int MELISSA0 = 25855;
+ private static final int MELISSA = 25876; // She dropping items
+ private static final int EXECUTOR_CAPTAIN = 23131;
+ private static final int ETINA_BLADESMAN = 23138;
+ private static final int CORRUPTED_CAPTAIN = 25857;
+ private static final int CORRUPTED_HIGH_PRIEST = 25858;
+ private static final int RITUAL_ALTAR0 = 19121;
+ private static final int RITUAL_ALTAR1 = 19122;
+ private static final int SHILLIEN_ALTAR = 19123;
+ private static final int INVISIBLE = 8561;
+ private static final int ETINA_GOSPEL = 23132;
+ private static final int ETINA_PRIEST = 23133;
+ private static final int ETINA_PROTECTORS = 23134;
+ private static final int ETINA_PUNISHERS = 23135;
+ private static final int ETINA_COMMINATION = 23136;
+ private static final int ETINA_DARKMONAGERS = 23137;
+ private static final int ELITE_ESCORT = 23126;
+ private static final int ELITE_CHASER = 23127;
+ private static final int ELITE_WARRIOR = 23128;
+ private static final int ELITE_ALCHEMIST = 23129;
+ private static final int ELITE_PRIEST = 23130;
+ private static final int EMBRYO_RESERCHER = 23139;
+ private static final int EMBRYO_WATCHMAN = 23140;
+ private static final int EMBRYO_FIGHTER = 23141;
+ private static final int EMBRYO_GUARD = 23142;
+ // Skills
+ static final SkillHolder PROTECTED_ALTAR = new SkillHolder(14496, 1);
+ // Misc
+ private static final int TEMPLATE_ID = 194;
+ private static final int ALTAR_TIME = 180;
+ //@formatter:off
+ private static final int[] DOORS = { 25180001, 25180002, 25180003, 25180004, 25180005, 25180006, 25180007 };
+ //@formatter:on
+ private static final NpcStringId[] SHOUT_MSG =
+ {
+ NpcStringId.I_NEED_HELP,
+ NpcStringId.FOCUS_FIRE_ACCORDING_TO_MY_ORCHESTRATION,
+ NpcStringId.I_NEED_HEAL,
+ NpcStringId.I_M_GOING_TO_BACK_OFF_FOR_A_BIT,
+ NpcStringId.I_WILL_ATTACK_THE_ENEMY_S_HEALER,
+ NpcStringId.STOP_ENEMIES_HEALING,
+ NpcStringId.ATTACK_WEAKENED_ENEMY,
+ NpcStringId.COME_AT_ME,
+ NpcStringId.SWITCH_TO_FAST_SHOOTING_MODE,
+ NpcStringId.SWITCH_TO_FAST_CASTING_MODE,
+ NpcStringId.BLINK_ATTACK,
+ NpcStringId.ONLY_DEATH_AWAITS_FOR_THE_WEAK,
+ };
+ static final Location MELISSA_SPAWN = new Location(178146, 14356, -13688);
+ private static final Location SECOND_FLOOR = new Location(179357, 13664, -9828);
+ private static final Location THIRD_FLOOR = new Location(179354, 12922, -12776);
+
+ final List playersInside = new ArrayList<>();
+ final Map killedMonsters = new ConcurrentHashMap<>();
+ static List firstFloorVictims = new ArrayList<>();
+ public static Future> timer;
+ public L2Npc altar;
+
+ public AltarOfShilen()
+ {
+ super(TEMPLATE_ID);
+ addInstanceCreatedId(TEMPLATE_ID);
+ addFirstTalkId(LOGART_VAN_DYKE, RITUAL_ALTAR0, RITUAL_ALTAR1, DINFORD);
+ addSpawnId(CORRUPTED_CAPTAIN, CORRUPTED_HIGH_PRIEST, INVISIBLE, SHILLIEN_ALTAR);
+ addAttackId(ETINA_GOSPEL, ETINA_PRIEST, ETINA_PROTECTORS, ETINA_PUNISHERS, ETINA_COMMINATION, ETINA_DARKMONAGERS, ELITE_ESCORT, ELITE_CHASER, ELITE_WARRIOR, ELITE_ALCHEMIST, ELITE_PRIEST, EMBRYO_RESERCHER, EMBRYO_WATCHMAN, EMBRYO_FIGHTER, EMBRYO_GUARD);
+ addKillId(EXECUTOR_CAPTAIN, CORRUPTED_CAPTAIN, ETINA_BLADESMAN, CORRUPTED_HIGH_PRIEST, ETINA_GOSPEL, ETINA_PROTECTORS, ETINA_PUNISHERS, MELISSA0, MELISSA, ISADORA);
+ }
+
+ @Override
+ public void onInstanceCreated(Instance instance, L2PcInstance player)
+ {
+ instance.spawnGroup("general");
+ instance.spawnGroup("first_floor");
+ instance.setStatus(1);
+ }
+
+ @Override
+ public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (event.equals("enterInstance"))
+ {
+ enterInstance(player, npc, TEMPLATE_ID);
+ if (player.isGM())
+ {
+ playersInside.add(player);
+ }
+ if (player.getParty() != null)
+ {
+ for (L2PcInstance partyMember : player.getParty().getMembers())
+ {
+ playersInside.add(partyMember);
+ }
+ }
+ }
+ if (event.equals("check_player"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 400, p ->
+ {
+ if ((p != null) && p.isPlayer() && !p.isDead())
+ {
+ npc.setScriptValue(1);
+ final L2Npc gospel = addSpawn(ETINA_GOSPEL, npc, true, 0, false, world.getId());
+ final L2Npc priest = addSpawn(ETINA_PRIEST, npc, true, 0, false, world.getId());
+ final L2Npc protectors = addSpawn(ETINA_PROTECTORS, npc, true, 0, false, world.getId());
+ final L2Npc punishers = addSpawn(ETINA_PUNISHERS, npc, true, 0, false, world.getId());
+ final L2Npc commination = addSpawn(ETINA_COMMINATION, npc, true, 0, false, world.getId());
+ final L2Npc darkmonagers = addSpawn(ETINA_DARKMONAGERS, npc, true, 0, false, world.getId());
+ addAttackPlayerDesire(gospel, p);
+ addAttackPlayerDesire(priest, p);
+ addAttackPlayerDesire(protectors, p);
+ addAttackPlayerDesire(punishers, p);
+ addAttackPlayerDesire(commination, p);
+ addAttackPlayerDesire(darkmonagers, p);
+ }
+ });
+ }
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if (event.equals("open_door"))
+ {
+ if (world.getStatus() == 1)
+ {
+ if (world.getDoor(DOORS[0]) != null)
+ {
+ world.getDoor(DOORS[0]).openMe();
+ }
+ world.setStatus(2);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 3)
+ {
+ if (world.getDoor(DOORS[1]) != null)
+ {
+ world.getDoor(DOORS[1]).openMe();
+ }
+ world.setStatus(4);
+ onStatusChanged(world);
+ break;
+ }
+ else if (world.getStatus() == 5)
+ {
+ if (world.getDoor(DOORS[2]) != null)
+ {
+ world.getDoor(DOORS[2]).openMe();
+ }
+ world.setStatus(6);
+ onStatusChanged(world);
+ break;
+ }
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if ((world.getStatus() == 3) && event.equals("teleport1"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(SECOND_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("second_floor");
+ });
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if ((world.getStatus() == 5) && event.equals("teleport2"))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(npc, L2PcInstance.class, 1000, p ->
+ {
+ if ((p != null) && p.isPlayable() && !p.isDead())
+ {
+ p.teleToLocation(THIRD_FLOOR, world.getTemplateId());
+ }
+ world.spawnGroup("thrid_floor");
+ });
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if ((world.getStatus() == 6) && event.equals("final_door"))
+ {
+ if (!world.getDoor(DOORS[6]).isOpen())
+ {
+ world.getDoor(DOORS[6]).openMe();
+ }
+ world.setStatus(7);
+ onStatusChanged(world);
+ npc.deleteMe();
+ cancelQuestTimers("check_player");
+ }
+ break;
+ }
+ }
+ }
+ return super.onAdvEvent(event, npc, player);
+ }
+
+ @Override
+ public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ if (getRandom(30) < 3)
+ {
+ npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), SHOUT_MSG[getRandom(SHOUT_MSG.length)]));
+ }
+ }
+ return super.onAttack(npc, attacker, damage, isSummon);
+ }
+
+ @Override
+ public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
+ {
+ final Instance world = npc.getInstanceWorld();
+ if (world != null)
+ {
+ int npcId = npc.getId();
+ if (!killedMonsters.containsKey(npcId))
+ {
+ killedMonsters.put(npcId, 1);
+ }
+ else
+ {
+ killedMonsters.put(npcId, killedMonsters.get(npcId) + 1);
+ }
+ // 1st Floor
+ if (world.getStatus() == 2)
+ {
+ if (killedMonsters.containsKey(EXECUTOR_CAPTAIN) && (killedMonsters.get(EXECUTOR_CAPTAIN) >= 3))
+ {
+ final int boos1 = world.getTemplateParameters().getInt("boss1");
+ final L2Npc captain = world.getNpc(boos1);
+ if (captain != null)
+ {
+ captain.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_CAPTAIN) && (killedMonsters.get(CORRUPTED_CAPTAIN) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_MOVE_TO_THE_NEXT_FLOOR_THROUGH_THE_ALTAR_OF_SACRIFICE, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(3);
+ killedMonsters.clear();
+ onStatusChanged(world);
+ }
+ }
+ // 2st Floor
+ else if (world.getStatus() == 4)
+ {
+ if (killedMonsters.containsKey(ETINA_BLADESMAN) && (killedMonsters.get(ETINA_BLADESMAN) >= 3))
+ {
+ final int boos2 = world.getTemplateParameters().getInt("boss2");
+ final L2Npc priest = world.getNpc(boos2);
+ if (priest != null)
+ {
+ priest.setIsInvul(false);
+ }
+ }
+ if (killedMonsters.containsKey(CORRUPTED_HIGH_PRIEST) && (killedMonsters.get(CORRUPTED_HIGH_PRIEST) >= 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_CAN_MOVE_TO_THE_NEXT_FLOOR_THROUGH_THE_ALTAR_OF_SACRIFICE, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ world.setStatus(5);
+ killedMonsters.clear();
+ onStatusChanged(world);
+
+ }
+ }
+ // 3st Floor
+ else if (world.getStatus() == 6)
+ {
+ switch (npc.getId())
+ {
+ case ETINA_GOSPEL:
+ {
+ world.getDoor(DOORS[3]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[3]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PROTECTORS:
+ {
+ world.getDoor(DOORS[4]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[4]).closeMe(), 5000);
+ break;
+ }
+ case ETINA_PUNISHERS:
+ {
+ world.getDoor(DOORS[5]).openMe();
+ ThreadPool.schedule(() -> world.getDoor(DOORS[5]).closeMe(), 5000);
+ break;
+ }
+ }
+ }
+ else if (world.getStatus() == 8)
+ {
+ if (killedMonsters.containsKey(MELISSA) && (killedMonsters.get(MELISSA) == 1))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_HAS_BEEN_DESTROYED_YOU_VE_WON, ExShowScreenMessage.TOP_CENTER, 5000, true));
+ }
+ playersInside.clear();
+ killedMonsters.clear();
+ world.finishInstance(1);
+ }
+ }
+ }
+ return super.onKill(npc, killer, isSummon);
+ }
+
+ @Override
+ public String onSpawn(L2Npc npc)
+ {
+ if (npc.getInstanceWorld() != null)
+ {
+ switch (npc.getId())
+ {
+ case CORRUPTED_CAPTAIN:
+ case CORRUPTED_HIGH_PRIEST:
+ {
+ npc.setIsInvul(true);
+ break;
+ }
+ case INVISIBLE:
+ {
+ if (npc.isScriptValue(0))
+ {
+ startQuestTimer("check_player", 2000, npc, null, true);
+ }
+ break;
+ }
+ case SHILLIEN_ALTAR:
+ {
+ altar = npc;
+ break;
+ }
+ }
+ }
+ return super.onSpawn(npc);
+ }
+
+ @Override
+ public String onFirstTalk(L2Npc npc, L2PcInstance player)
+ {
+ final Instance world = npc.getInstanceWorld();
+ String htmltext = null;
+ if (isInInstance(world))
+ {
+ switch (npc.getId())
+ {
+ case LOGART_VAN_DYKE:
+ {
+ if ((world.getStatus() > 0) && (world.getStatus() < 3))
+ {
+ return "34331.html";
+ }
+ else if ((world.getStatus() >= 3) && (world.getStatus() < 5))
+ {
+ return "34331-01.html";
+ }
+ else if (world.getStatus() >= 5)
+ {
+ return "34331-02.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR0:
+ {
+ if (world.getStatus() >= 3)
+ {
+ return "19121.html";
+ }
+ break;
+ }
+ case RITUAL_ALTAR1:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "19122.html";
+ }
+ break;
+ }
+ case DINFORD:
+ {
+ if (world.getStatus() >= 5)
+ {
+ return "34332.html";
+ }
+ break;
+ }
+ }
+ }
+ return htmltext;
+ }
+
+ public static class VictimDefeatTask implements Runnable
+ {
+ private final Instance _world;
+ private int _victims;
+ private final int _initialTime;
+ private int _time;
+
+ VictimDefeatTask(int victims, int time, Instance world)
+ {
+ _world = world;
+ _victims = victims;
+ _initialTime = time;
+ _time = time;
+ }
+
+ @Override
+ public void run()
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_GP_TIMER, (_time--), 0, NpcStringId.SACRIFICE_LEFT_S1, new String[]
+ {
+ String.valueOf(_victims)
+ }));
+ }
+ if (_time <= 0)
+ {
+ _time = _initialTime;
+ --_victims;
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 20, 5));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.SACRIFICE_HAS_BEEN_KILLED_SACRIFICE_LEFT_S1, ExShowScreenMessage.MIDDLE_CENTER, 3000, String.valueOf(_victims)));
+ }
+ }
+ if ((_world.getStatus() == 2) && !firstFloorVictims.isEmpty())
+ {
+ firstFloorVictims.get(0).deleteMe();
+ firstFloorVictims.remove(0);
+ }
+ if ((_victims == 1) && (_world.getStatus() == 2))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOUR_LIVES_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_CORRUPTED_CAPTAIN, ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if ((_victims == 1) && (_world.getStatus() == 4))
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOUR_LIVES_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_CORRUPTED_HIGH_PRIEST, ExShowScreenMessage.MIDDLE_CENTER, 10000));
+ }
+ }
+ if (_victims <= 0)
+ {
+ ThreadPool.schedule(() ->
+ {
+ for (L2PcInstance player : _world.getPlayers())
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALL_OFFERINGS_WERE_SACRIFICED_AND_THE_BLESSING_OF_BLOOD_IS_BESTOWED_UPON_THE_EMBRYO_COLONY_IN_THAT_FLOOR, ExShowScreenMessage.MIDDLE_CENTER, 3000));
+ }
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ _world.finishInstance(1);
+ }, 3000);
+ }
+ }
+ }
+
+ private void onStatusChanged(final Instance world)
+ {
+ final Instance instance = InstanceManager.getInstance().getInstance(world.getId());
+ switch (instance.getStatus())
+ {
+ case 1:
+ {
+ break;
+ }
+ case 2:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 3:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ }
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.YOU_MUST_STOP_THE_ALTAR_BEFORE_EVERYTHING_IS_SACRIFICED, ExShowScreenMessage.MIDDLE_CENTER, 6000));
+ }
+ timer = ThreadPool.scheduleAtFixedRate(new VictimDefeatTask(5, ALTAR_TIME, world), 0, 1000);
+ break;
+ }
+ case 5:
+ case 6:
+ {
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ break;
+ }
+ case 7:
+ {
+ ThreadPool.schedule(() -> timer = ThreadPool.scheduleAtFixedRate(new Runnable()
+ {
+ private int _time = ALTAR_TIME;
+
+ @Override
+ public void run()
+ {
+ if (_time <= 0)
+ {
+ return;
+ }
+ boolean defeated = false;
+ if (killedMonsters.containsKey(MELISSA0) && (killedMonsters.get(MELISSA0) == 1) && killedMonsters.containsKey(ISADORA) && (killedMonsters.get(ISADORA) == 1))
+ {
+ defeated = true;
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExSendUIEvent(player, 0x01, 0, 0, 0, 0, 0, 2518008));
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_HAS_STOPPED, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ addSpawn(MELISSA, MELISSA_SPAWN.getX(), MELISSA_SPAWN.getY(), MELISSA_SPAWN.getZ(), 0, false, 0, true, world.getId());
+ if (timer != null)
+ {
+ timer.cancel(true);
+ timer = null;
+ }
+ altar.deleteMe();
+ world.setStatus(8);
+ }
+ }
+ else
+ {
+ for (L2PcInstance player : world.getPlayers())
+ {
+ if (_time == ALTAR_TIME)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.ALTAR_OF_SHILEN_IS_STARTING_MUST_FOCUS_FIRE_THE_ALTAR, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ player.sendPacket(new ExSendUIEvent(player, ExSendUIEvent.TYPE_NORNIL, (_time--), 0, 0, 0, 0, 2518008));
+ }
+ }
+
+ if (!defeated && (_time == 9))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_ALTAR_OF_SHILEN_WILL_BECOME_ACTIVATED_IN_10_SECONDS, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time == 4))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.THE_ALTAR_OF_SHILEN_WILL_BECOME_ACTIVATED_IN_5_SECONDS, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+ }
+
+ if (!defeated && (_time <= 0))
+ {
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new ExShowScreenMessage(NpcStringId.FOCUS_FIRE_THE_ALTAR_TO_STOP_BLESSING_OF_SHILEN, ExShowScreenMessage.MIDDLE_CENTER, 5000));
+ }
+
+ if (isInInstance(world))
+ {
+ L2World.getInstance().forEachVisibleObjectInRange(altar, L2MonsterInstance.class, 8000, boss ->
+ {
+ if ((boss != null) && !boss.isDead())
+ {
+ altar.doCast(PROTECTED_ALTAR.getSkill());
+ boss.setCurrentHp(boss.getCurrentHp() + (boss.getMaxHp() / 2));
+ for (L2PcInstance player : playersInside)
+ {
+ player.sendPacket(new Earthquake(player.getX(), player.getY(), player.getZ(), 30, 5));
+ }
+ }
+ });
+ }
+ }
+
+ if ((_time <= 0) && world.isStatus(7))
+ {
+ ThreadPool.schedule(() ->
+ {
+ _time = ALTAR_TIME;
+ }, 15000);
+ }
+ }
+ }, 0, 1000), 5000);
+ break;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new AltarOfShilen();
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
new file mode 100644
index 0000000000..193aa80dde
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoGroup.html
@@ -0,0 +1,5 @@
+Agent Georgio:
+The Altar of Shilen is extremely dangerous.
+You're trying to go there alone. You may be either very confident or reckless.
+To let you go is to send you to your death. If you want to go to the Altar of Shilen and stop the ritual, please gather allies and return.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
new file mode 100644
index 0000000000..5ceb23f4c5
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoLevel.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+(A party members level must be 101 - 105 Lvl to challenge Altar of Shilen.)
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
new file mode 100644
index 0000000000..538b8bed55
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condNoPartyLeader.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+Only a party leader may enter the altar of Shilen
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
new file mode 100644
index 0000000000..361fbf1ca0
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/instances/AltarOfShilen/condSmallGroup.html
@@ -0,0 +1,3 @@
+Agent Georgio:
+You are too weak. Gather more people.
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/19100-19199.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/19100-19199.xml
index 747f9aa1b0..31bd5d886e 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/19100-19199.xml
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/19100-19199.xml
@@ -683,7 +683,7 @@
-
+
CONSTRUCT
MALE
@@ -710,7 +710,7 @@
-
+
CONSTRUCT
MALE
@@ -737,7 +737,7 @@
-
+
CONSTRUCT
MALE
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/25800-25899.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/25800-25899.xml
index df8ddd66c9..4c44fba367 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/25800-25899.xml
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/stats/npcs/25800-25899.xml
@@ -3245,8 +3245,8 @@
-
-
+
+
HUMANOID
@@ -3276,9 +3276,9 @@
-
-
-
+
+
+
@@ -3287,7 +3287,7 @@
-
+
EMBRYO_BOSS
@@ -3403,8 +3403,8 @@
-
-
+
+
HUMANOID
@@ -3429,10 +3429,12 @@
-
+
+
+
@@ -3453,8 +3455,9 @@
-
-
+
+
+
HUMANOID
@@ -3475,13 +3478,16 @@
-
+
+
+
+
@@ -4128,7 +4134,7 @@
-
+
diff --git a/L2J_Mobius_5.5_EtinasFate/readme.txt b/L2J_Mobius_5.5_EtinasFate/readme.txt
index cb80c57192..891ba3330f 100644
--- a/L2J_Mobius_5.5_EtinasFate/readme.txt
+++ b/L2J_Mobius_5.5_EtinasFate/readme.txt
@@ -29,6 +29,7 @@ Goddess of Destruction:
-Kartia
-Fortuna
-Nursery
+-Altar of Shilen
-Kimerian
-Istina
-Octavis