diff --git a/L2J_Mobius_Underground/dist/db_installer/sql/game/grandboss_data.sql b/L2J_Mobius_Underground/dist/db_installer/sql/game/grandboss_data.sql index 9fac096f8e..6bada0f6c6 100644 --- a/L2J_Mobius_Underground/dist/db_installer/sql/game/grandboss_data.sql +++ b/L2J_Mobius_Underground/dist/db_installer/sql/game/grandboss_data.sql @@ -24,7 +24,7 @@ INSERT IGNORE INTO `grandboss_data` (`boss_id`,`loc_x`,`loc_y`,`loc_z`,`heading` -- (29066, 185708, 114298, -8221,32768, 14518000, 3996000), -- Antharas Weak (79) -- (29067, 185708, 114298, -8221,32768, 16184000, 3996000), -- Antharas Normal (79) (29068, 185708, 114298, -8221,32768, 62802301, 1998000), -- Antharas Strong (85) -(29118, 0, 0, 0, 0, 4109288, 1220547); -- Beleth (83); +(29118, 0, 0, 0, 0, 4109288, 1220547), -- Beleth (83); -- (29045, -87780, -155086, -9080, 16384, 1018821.42723286, 52001.06567747795), -- Frintezza (85) -- (29046, -87789, -153295, -9176, 16384, 1824900, 23310), -- Scarlet Van Halisha (85) -- (29047, -87789, -153295, -9176, 16384, 898044, 4519), -- Scarlet Van Halisha (85) @@ -37,4 +37,5 @@ INSERT IGNORE INTO `grandboss_data` (`boss_id`,`loc_x`,`loc_y`,`loc_z`,`heading` -- (29178, 0, 0, 0, 0, 0, 0), -- Freya (Spelling) (85) -- (29178, 0, 0, 0, 0, 0, 0), -- Freya (Stand) (85) -- (29178, 0, 0, 0, 0, 0, 0), -- Freya (Stand Hard) (85) --- (29179, 0, 0, 0, 0, 0, 0), -- Zaken Day (83) \ No newline at end of file +-- (29179, 0, 0, 0, 0, 0, 0), -- Zaken Day (83) +(26124, 0, 0, 0, 0, 13945521, 50920); -- Kelbim; \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/config/GrandBoss.ini b/L2J_Mobius_Underground/dist/game/config/GrandBoss.ini index 83a15541ae..6a8f065de6 100644 --- a/L2J_Mobius_Underground/dist/game/config/GrandBoss.ini +++ b/L2J_Mobius_Underground/dist/game/config/GrandBoss.ini @@ -84,4 +84,23 @@ BelethFightDuration = 90 BelethMinPlayers = 49 #Maximum count of players for enter to Beleth. Retail: 350 -BelethMaxPlayers = 350 \ No newline at end of file +BelethMaxPlayers = 350 + +# --------------------------------------------------------------------------- +# Kelbim +# --------------------------------------------------------------------------- + +# Delay of appearance time of Kelbim. Value is minute. Range 3-60 +KelbimWaitTime = 5 + +# Interval time of Kelbim. Value is hour. Range 1-480. Retail: 48 +IntervalOfKelbimSpawn = 48 + +# Random interval. Range 1-192. Retail: 24 +RandomOfKelbimSpawn = 24 + +#Minimal count of players for enter to Kelbim. Retail: 21 +KelbimMinPlayers = 21 + +#Maximum count of players for enter to Kelbim. Retail: 35 +KelbimMaxPlayers = 35 \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/html/default/34052.htm b/L2J_Mobius_Underground/dist/game/data/html/default/34052.htm deleted file mode 100644 index 7d4aeac1c4..0000000000 --- a/L2J_Mobius_Underground/dist/game/data/html/default/34052.htm +++ /dev/null @@ -1,5 +0,0 @@ -Teleport Device:
-I'll help you enter the Atelia Castle. -Would you like to enter? - - \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-1.html b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-1.html new file mode 100644 index 0000000000..bb8512165e --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-1.html @@ -0,0 +1,4 @@ +Teleport Device:
+Cannot enter the Atelia Castle.
+(Kelbim has not appeared in the Atelia Fortress so you cannot enter.) + \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-2.html b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-2.html new file mode 100644 index 0000000000..715cb56d7d --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-2.html @@ -0,0 +1,3 @@ +Teleport Device:
+(A command channel needs at least %min% members to challenge Kelbim.) + \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-3.html b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-3.html new file mode 100644 index 0000000000..9fe2bf7f51 --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052-3.html @@ -0,0 +1,4 @@ +Teleport Device:
+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_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052.html b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052.html new file mode 100644 index 0000000000..fb2e54a0f8 --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/34052.html @@ -0,0 +1,5 @@ +Teleport Device:
+I'll help you enter the Atelia Castle. +Would you like to enter?
+ + \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/Kelbim.java b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/Kelbim.java new file mode 100644 index 0000000000..e01fd96224 --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/ai/bosses/Kelbim/Kelbim.java @@ -0,0 +1,437 @@ +/* + * 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.Kelbim; + +import java.util.ArrayList; +import java.util.List; + +import com.l2jmobius.Config; +import com.l2jmobius.commons.util.Rnd; +import com.l2jmobius.gameserver.data.xml.impl.SkillData; +import com.l2jmobius.gameserver.enums.Movie; +import com.l2jmobius.gameserver.instancemanager.GrandBossManager; +import com.l2jmobius.gameserver.instancemanager.MapRegionManager; +import com.l2jmobius.gameserver.instancemanager.ZoneManager; +import com.l2jmobius.gameserver.model.L2Party; +import com.l2jmobius.gameserver.model.Location; +import com.l2jmobius.gameserver.model.StatsSet; +import com.l2jmobius.gameserver.model.TeleportWhereType; +import com.l2jmobius.gameserver.model.actor.L2Attackable; +import com.l2jmobius.gameserver.model.actor.L2Character; +import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.quest.QuestTimer; +import com.l2jmobius.gameserver.model.skills.Skill; +import com.l2jmobius.gameserver.model.zone.L2ZoneType; +import com.l2jmobius.gameserver.network.serverpackets.Earthquake; +import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; +import com.l2jmobius.gameserver.util.Broadcast; + +import ai.AbstractNpcAI; + +/** + * Kelbim AI
+ * @author LasTravel
+ * @video https://www.youtube.com/watch?v=qVkk2BJoGoU + */ +public class Kelbim 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 ENTER_DEVICE = 34052; + private static final int TELEPORT_DEVICE = 34053; + private static final int KELBIM_SHOUT = 19597; + private static final int KELBIM = 26124; + private static final int GUARDIAN_SINISTRA = 26126; + private static final int GUARDIAN_DESTRA = 26127; + private static final int[] KELBIM_GUARDIANS = + { + GUARDIAN_SINISTRA, + GUARDIAN_DESTRA + }; + private static final int KELBIM_GUARD = 26129; + private static final int KELBIM_ALTAR = 26130; + private static final int[] KELBIM_MINIONS = + { + GUARDIAN_SINISTRA, + GUARDIAN_DESTRA, + KELBIM_GUARD + }; + private static final int[] ALL_MONSTERS = + { + KELBIM, + KELBIM_MINIONS[0], + KELBIM_MINIONS[1], + KELBIM_MINIONS[2], + KELBIM_ALTAR + }; + // Doors + private static final int DOOR1 = 18190002; + private static final int DOOR2 = 18190004; + // Skills + private static final Skill METEOR_CRASH = SkillData.getInstance().getSkill(23692, 1); + private static final Skill WATER_DROP = SkillData.getInstance().getSkill(23693, 1); + private static final Skill TORNADO_SACKLE = SkillData.getInstance().getSkill(23694, 1); + private static final Skill FLAME_THROWER = SkillData.getInstance().getSkill(23699, 1); + private static final Skill[] AREA_SKILLS = + { + METEOR_CRASH, + WATER_DROP, + TORNADO_SACKLE, + FLAME_THROWER + }; + // Misc + private static final L2ZoneType ZONE = ZoneManager.getInstance().getZoneById(60023); + private static final Location KELBIM_LOCATION = new Location(-55386, 58939, -274); + // Vars + private static L2Npc _kelbimBoss; + private static long _lastAction; + private static int _bossStage; + private static ArrayList _minions = new ArrayList<>(); + + public Kelbim() + { + addTalkId(ENTER_DEVICE, TELEPORT_DEVICE); + addStartNpc(ENTER_DEVICE, TELEPORT_DEVICE); + addFirstTalkId(ENTER_DEVICE, TELEPORT_DEVICE); + addAttackId(ALL_MONSTERS); + addKillId(ALL_MONSTERS); + + // Unlock + final StatsSet info = GrandBossManager.getInstance().getStatsSet(KELBIM); + final long time = info.getLong("respawn_time") - System.currentTimeMillis(); + if (time > 0) + { + startQuestTimer("unlock_kelbim", time, null, null); + } + else + { + openDoor(DOOR1, 0); + openDoor(DOOR2, 0); + } + } + + @Override + public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) + { + switch (event) + { + case "unlock_kelbim": + { + GrandBossManager.getInstance().setBossStatus(KELBIM, ALIVE); + Broadcast.toAllOnlinePlayers(new Earthquake(-55754, 59903, -269, 20, 10)); + openDoor(DOOR1, 0); + openDoor(DOOR2, 0); + break; + } + case "check_activity_task": + { + if ((_lastAction + 900000) < System.currentTimeMillis()) + { + GrandBossManager.getInstance().setBossStatus(KELBIM, ALIVE); + for (L2Character charInside : ZONE.getCharactersInside()) + { + if (charInside != null) + { + if (charInside.isNpc()) + { + charInside.deleteMe(); + } + else if (charInside.isPlayer()) + { + charInside.teleToLocation(MapRegionManager.getInstance().getTeleToLocation(charInside, TeleportWhereType.TOWN)); + } + } + } + startQuestTimer("end_kelbim", 2000, null, null); + } + else + { + startQuestTimer("check_activity_task", 60000, null, null); + } + break; + } + case "stage_1_start": + { + _bossStage = 1; + GrandBossManager.getInstance().setBossStatus(KELBIM, FIGHTING); + playMovie(ZONE.getPlayersInside(), Movie.SC_KELBIM_OPENING); + startQuestTimer("stage_1_kelbim_spawn", 25000, null, null); + break; + } + case "stage_1_kelbim_spawn": + { + _kelbimBoss = addSpawn(KELBIM, -56340, 60801, -269, 54262, false, 0); + _lastAction = System.currentTimeMillis(); + startQuestTimer("check_activity_task", 60000, null, null, true); + startQuestTimer("stage_all_random_area_attack", Rnd.get(2, 3) * 60000, null, null); + break; + } + case "stage_all_spawn_minions": + { + for (int i = 0; i < Rnd.get((_bossStage * 5) / 2, _bossStage * 5); i++) + { + L2Npc minion = addSpawn(KELBIM_GUARD, _kelbimBoss.getX(), _kelbimBoss.getY(), _kelbimBoss.getZ(), 0, true, 0, true, 0); + minion.setIsRunning(true); + ((L2Attackable) minion).setIsRaidMinion(true); + _minions.add(minion); + } + for (int i = 0; i < Rnd.get((_bossStage * 2) / 2, _bossStage * 2); i++) + { + L2Npc minion = addSpawn(KELBIM_GUARDIANS[Rnd.get(KELBIM_GUARDIANS.length)], _kelbimBoss.getX(), _kelbimBoss.getY(), _kelbimBoss.getZ(), 0, true, 0, true, 0); + minion.setIsRunning(true); + ((L2Attackable) minion).setIsRaidMinion(true); + _minions.add(minion); + } + break; + } + case "stage_all_random_area_attack": + { + if ((_bossStage > 0) && (_bossStage < 7)) + { + if (_kelbimBoss.isInCombat()) + { + Skill randomAttackSkill = AREA_SKILLS[Rnd.get(AREA_SKILLS.length)]; + ArrayList _skillNpcs = new ArrayList<>(); + for (L2PcInstance pl : ZONE.getPlayersInside()) + { + if (pl == null) + { + continue; + } + if (Rnd.get(100) > 40) + { + L2Npc skillMob = addSpawn(KELBIM_SHOUT, pl.getX(), pl.getY(), pl.getZ() + 10, 0, true, 60000, false, 0); + _skillNpcs.add(skillMob); + _minions.add(skillMob); + } + } + for (L2Npc skillNpc : _skillNpcs) + { + if (skillNpc == null) + { + continue; + } + skillNpc.doCast(randomAttackSkill); + } + } + startQuestTimer("stage_all_random_area_attack", Rnd.get(1, 2) * 60000, null, null); + } + break; + } + case "cancel_timers": + { + QuestTimer activityTimer = getQuestTimer("check_activity_task", null, null); + if (activityTimer != null) + { + activityTimer.cancel(); + } + break; + } + case "end_kelbim": + { + _bossStage = 0; + ZONE.oustAllPlayers(); + if (_kelbimBoss != null) + { + _kelbimBoss.deleteMe(); + } + if (!_minions.isEmpty()) + { + for (L2Npc minion : _minions) + { + if (minion == null) + { + continue; + } + minion.deleteMe(); + } + } + _minions.clear(); + break; + } + } + return super.onAdvEvent(event, npc, player); + } + + @Override + public String onFirstTalk(L2Npc npc, L2PcInstance player) + { + switch (npc.getId()) + { + case TELEPORT_DEVICE: + { + player.teleToLocation(-55730, 55643, -1954); + break; + } + case ENTER_DEVICE: + { + return "34052.html"; + } + } + return super.onFirstTalk(npc, player); + } + + @Override + public String onTalk(L2Npc npc, L2PcInstance player) + { + if (npc.getId() == ENTER_DEVICE) + { + int status = GrandBossManager.getInstance().getBossStatus(KELBIM); + if (status > ALIVE) + { + return "34052-1.html"; + } + + if (!player.isInParty()) + { + final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId()); + packet.setHtml(getHtm(player.getHtmlPrefix(), "34052-2.html")); + packet.replace("%min%", Integer.toString(Config.KELBIM_MIN_PLAYERS)); + player.sendPacket(packet); + return null; + } + + final L2Party 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 "34052-3.html"; + } + else if ((members.size() < Config.KELBIM_MIN_PLAYERS) || (members.size() > Config.KELBIM_MAX_PLAYERS)) + { + final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId()); + packet.setHtml(getHtm(player.getHtmlPrefix(), "34052-2.html")); + packet.replace("%min%", Integer.toString(Config.KELBIM_MIN_PLAYERS)); + player.sendPacket(packet); + } + else + { + for (L2PcInstance member : members) + { + if (member.isInsideRadius(npc, 1000, true, false)) + { + member.teleToLocation(KELBIM_LOCATION, true); + } + } + } + + if (status == ALIVE) + { + GrandBossManager.getInstance().setBossStatus(KELBIM, WAITING); + startQuestTimer("stage_1_start", Config.KELBIM_WAIT_TIME * 60 * 1000, null, null); + } + } + return super.onTalk(npc, player); + } + + @Override + public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet) + { + if (npc.getId() == KELBIM) + { + _lastAction = System.currentTimeMillis(); + + switch (_bossStage) + { + case 1: + { + if (npc.getCurrentHp() < (npc.getMaxHp() * 0.80)) + { + _bossStage = 2; + notifyEvent("stage_all_spawn_minions", null, null); + } + break; + } + case 2: + { + if (npc.getCurrentHp() < (npc.getMaxHp() * 0.60)) + { + _bossStage = 3; + notifyEvent("stage_all_spawn_minions", null, null); + } + break; + } + case 3: + { + if (npc.getCurrentHp() < (npc.getMaxHp() * 0.40)) + { + _bossStage = 4; + notifyEvent("stage_all_spawn_minions", null, null); + } + break; + } + case 4: + { + if (npc.getCurrentHp() < (npc.getMaxHp() * 0.20)) + { + _bossStage = 5; + notifyEvent("stage_all_spawn_minions", null, null); + } + break; + } + case 5: + { + if (npc.getCurrentHp() < (npc.getMaxHp() * 0.05)) + { + _bossStage = 6; + notifyEvent("stage_all_spawn_minions", null, null); + } + break; + } + } + } + return super.onAttack(npc, attacker, damage, isPet); + } + + @Override + public String onKill(L2Npc npc, L2PcInstance killer, boolean isPet) + { + if (npc.getId() == KELBIM) + { + _bossStage = 7; + + addSpawn(TELEPORT_DEVICE, -54331, 58331, -264, 16292, false, 1800000); + + notifyEvent("cancel_timers", null, null); + + closeDoor(DOOR1, 0); + closeDoor(DOOR2, 0); + + GrandBossManager.getInstance().setBossStatus(KELBIM, DEAD); + final long respawnTime = (Config.KELBIM_SPAWN_INTERVAL + getRandom(-Config.KELBIM_SPAWN_RANDOM, Config.KELBIM_SPAWN_RANDOM)) * 3600000; + final StatsSet info = GrandBossManager.getInstance().getStatsSet(KELBIM); + info.set("respawn_time", System.currentTimeMillis() + respawnTime); + GrandBossManager.getInstance().setStatsSet(KELBIM, info); + + startQuestTimer("unlock_kelbim", respawnTime, null, null); + startQuestTimer("end_kelbim", 1800000, null, null); + } + return super.onKill(npc, killer, isPet); + } + + public static void main(String[] args) + { + new Kelbim(); + } +} diff --git a/L2J_Mobius_Underground/dist/game/data/zones/custom_script.xml b/L2J_Mobius_Underground/dist/game/data/zones/custom_script.xml index 8387ea0d6e..594c44d564 100644 --- a/L2J_Mobius_Underground/dist/game/data/zones/custom_script.xml +++ b/L2J_Mobius_Underground/dist/game/data/zones/custom_script.xml @@ -290,16 +290,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -458,23 +458,23 @@ - + - - - + + + - - - - - - - - - + + + + + + + + + @@ -758,6 +758,19 @@ + + + + + + + + + + + + + diff --git a/L2J_Mobius_Underground/java/com/l2jmobius/Config.java b/L2J_Mobius_Underground/java/com/l2jmobius/Config.java index ef8b8a838b..a1458a6fcb 100644 --- a/L2J_Mobius_Underground/java/com/l2jmobius/Config.java +++ b/L2J_Mobius_Underground/java/com/l2jmobius/Config.java @@ -991,6 +991,13 @@ public final class Config public static int BELETH_SPAWN_INTERVAL; public static int BELETH_SPAWN_RANDOM; + // Kelbim + public static int KELBIM_WAIT_TIME; + public static int KELBIM_MIN_PLAYERS; + public static int KELBIM_MAX_PLAYERS; + public static int KELBIM_SPAWN_INTERVAL; + public static int KELBIM_SPAWN_RANDOM; + // Gracia Seeds Settings public static int SOD_TIAT_KILL_COUNT; public static long SOD_STAGE_2_LENGTH; @@ -2384,6 +2391,12 @@ public final class Config BELETH_MAX_PLAYERS = GrandBossSettings.getInt("BelethMaxPlayers", 350); BELETH_FIGHT_DURATION = GrandBossSettings.getInt("BelethFightDuration", 90); + KELBIM_WAIT_TIME = GrandBossSettings.getInt("KelbimWaitTime", 5); + KELBIM_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfKelbimSpawn", 192); + KELBIM_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfKelbimSpawn", 148); + KELBIM_MIN_PLAYERS = GrandBossSettings.getInt("KelbimMinPlayers", 49); + KELBIM_MAX_PLAYERS = GrandBossSettings.getInt("KelbimMaxPlayers", 350); + // Gracia Seeds final PropertiesParser GraciaSeedsSettings = new PropertiesParser(GRACIASEEDS_CONFIG_FILE);