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