From 81d27511f929996fee35a4fe885b1c90ed2d3dc0 Mon Sep 17 00:00:00 2001
From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com>
Date: Fri, 6 Jan 2023 22:06:12 +0000
Subject: [PATCH] Battle with Balok. Contributed by Serenitty.
---
.../dist/game/config/GrandBoss.ini | 10 +
.../data/scripts/ai/bosses/Balok/Balok.java | 654 ++++++++++++++++++
.../data/spawns/Gludio/BalokBattleground.xml | 277 ++++++++
.../dist/game/data/zones/no_bookmark.xml | 7 +
.../java/org/l2jmobius/Config.java | 9 +
.../l2jmobius/gameserver/enums/MailType.java | 1 +
.../BattleWithBalokManager.java | 133 ++++
.../GlobalVariablesManager.java | 1 +
.../model/variables/PlayerVariables.java | 1 +
.../gameserver/network/ExClientPackets.java | 12 +-
.../balok/ExBalrogWarGetReward.java | 58 ++
.../balok/ExBalrogWarShowRanking.java | 46 ++
.../balok/ExBalrogWarShowUI.java | 40 ++
.../balok/ExBalrogWarTeleport.java | 88 +++
.../balok/BalrogWarBossInfo.java | 93 +++
.../balok/BalrogWarGetReward.java | 40 ++
.../serverpackets/balok/BalrogWarHud.java | 49 ++
.../balok/BalrogWarShowRanking.java | 53 ++
.../serverpackets/balok/BalrogWarShowUI.java | 49 ++
.../dist/game/config/GrandBoss.ini | 10 +
.../data/scripts/ai/bosses/Balok/Balok.java | 654 ++++++++++++++++++
.../data/spawns/Gludio/BalokBattleground.xml | 277 ++++++++
.../dist/game/data/zones/no_bookmark.xml | 7 +
.../java/org/l2jmobius/Config.java | 9 +
.../l2jmobius/gameserver/enums/MailType.java | 1 +
.../BattleWithBalokManager.java | 133 ++++
.../GlobalVariablesManager.java | 1 +
.../model/variables/PlayerVariables.java | 1 +
.../gameserver/network/ExClientPackets.java | 12 +-
.../balok/ExBalrogWarGetReward.java | 58 ++
.../balok/ExBalrogWarShowRanking.java | 46 ++
.../balok/ExBalrogWarShowUI.java | 40 ++
.../balok/ExBalrogWarTeleport.java | 88 +++
.../balok/BalrogWarBossInfo.java | 93 +++
.../balok/BalrogWarGetReward.java | 40 ++
.../serverpackets/balok/BalrogWarHud.java | 49 ++
.../balok/BalrogWarShowRanking.java | 53 ++
.../serverpackets/balok/BalrogWarShowUI.java | 49 ++
38 files changed, 3234 insertions(+), 8 deletions(-)
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/bosses/Balok/Balok.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/spawns/Gludio/BalokBattleground.xml
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/dist/game/data/scripts/ai/bosses/Balok/Balok.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/dist/game/data/spawns/Gludio/BalokBattleground.xml
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/GrandBoss.ini b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/GrandBoss.ini
index 9c2dd78e5b..eb9ee61a28 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/GrandBoss.ini
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/GrandBoss.ini
@@ -57,3 +57,13 @@ IntervalOfZakenSpawn = 168
# Random interval. Range 1-192
RandomOfZakenSpawn = 48
+
+# ---------------------------------------------------------------------------
+# Battle for Balok
+# ---------------------------------------------------------------------------
+
+# Time Battle for Balok starts.
+BalokTime = 20:30
+
+# Number of points that a player earns for defeating a monster.
+BalokPointsPerMonster = 10
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/bosses/Balok/Balok.java b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/bosses/Balok/Balok.java
new file mode 100644
index 0000000000..49446b9d5d
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/ai/bosses/Balok/Balok.java
@@ -0,0 +1,654 @@
+/*
+ * 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.Balok;
+
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.threads.ThreadPool;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.SpawnData;
+import org.l2jmobius.gameserver.enums.MailType;
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
+import org.l2jmobius.gameserver.instancemanager.MailManager;
+import org.l2jmobius.gameserver.instancemanager.ZoneManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Message;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.ListenerRegisterType;
+import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent;
+import org.l2jmobius.gameserver.model.events.annotations.RegisterType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.itemcontainer.Mail;
+import org.l2jmobius.gameserver.model.spawns.SpawnGroup;
+import org.l2jmobius.gameserver.model.spawns.SpawnTemplate;
+import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.zone.ZoneType;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarBossInfo;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarHud;
+import org.l2jmobius.gameserver.util.Broadcast;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author Serenitty
+ */
+public class Balok extends AbstractNpcAI
+{
+ // Monsters
+ private static final int SCORPION = 22416;
+ private static final Set NORMAL_MOBS = new HashSet<>();
+ static
+ {
+ NORMAL_MOBS.add(22413);
+ NORMAL_MOBS.add(22415);
+ NORMAL_MOBS.add(22414);
+ NORMAL_MOBS.add(22416);
+ }
+ // Intermid bosses
+ private static final int KESMA = 25956;
+ private static final int PRAIS = 25957;
+ private static final int VIRA = 25958;
+ private static final int HEEDER = 25959;
+ private static final int HEARAK = 25960;
+ private static final Set INTERMID_BOSSES = new HashSet<>();
+ static
+ {
+ INTERMID_BOSSES.add(KESMA);
+ INTERMID_BOSSES.add(PRAIS);
+ INTERMID_BOSSES.add(VIRA);
+ INTERMID_BOSSES.add(HEEDER);
+ INTERMID_BOSSES.add(HEARAK);
+ }
+ // Final boss
+ private static final int BALOK1 = 29157; // Balok red normal
+ private static final int BALOK2 = 29161; // Balok aqua
+ private static final int BALOK3 = 29165; // Balok yellow
+ private static final int LORD_BALOK = 29169;
+ private static final Set FINAL_BOSSES = new HashSet<>();
+ static
+ {
+ FINAL_BOSSES.add(BALOK1);
+ FINAL_BOSSES.add(BALOK2);
+ FINAL_BOSSES.add(BALOK3);
+ FINAL_BOSSES.add(LORD_BALOK);
+ }
+ // Locations
+ private static final Location KESMA_LOC = new Location(-17370, 184479, -3991, 49942);
+ private static final Location PRAIS_LOC = new Location(-21765, 178790, -4077, 7662);
+ private static final Location VIRA_LOC = new Location(-21375, 182516, -3969, 58095);
+ private static final Location HEEDER_LOC = new Location(-15210, 178553, -4277, 25134);
+ private static final Location HEARAK_LOC = new Location(-13947, 181909, -4348, 32883);
+ private static final Location BALOK_LOC = new Location(-18392, 181079, -3845, 48678);
+ // Zone
+ private static final ZoneType BALOK_BATTLE_ZONE = ZoneManager.getInstance().getZoneByName("balok_area");
+ // Misc
+ private static final AtomicReference NORMAL_BATTLE_MOBS = new AtomicReference<>();
+ private static final Set BOSS_SPAWNED = ConcurrentHashMap.newKeySet();
+ private static final int BATTLE_TIME = 1800000; // 30 min
+ private static final int PREPARATION_TIME = 1200000; // 20 min
+ private static final int REWARD_TIME = 2400000; // 40 min
+
+ private int _status = 0;
+ private int _stage = 0;
+ private int _globalPoints = 0;
+ private int _midbossDefeatCount = 0;
+ private int _kesmaStatus = 1;
+ private int _praisStatus = 1;
+ private int _viraStatus = 1;
+ private int _heederStatus = 0;
+ private int _hearakStatus = 0;
+ private int _finalBalokType = 1;
+ private int _finalBalokStatus = 1;
+ private boolean _inProgress = false;
+ private boolean _balokKilled = false;
+ private boolean _firstWaveKilled = false;
+ private boolean _secondWaveKilled = false;
+ private boolean _midBossFirstSpawn = false;
+ private boolean _midBossSecondSpawn = false;
+ private int _firstKillBalokId = 0;
+ ScheduledFuture> _rewardTask;
+
+ private Balok()
+ {
+ addKillId(VIRA, KESMA, PRAIS, HEEDER, HEARAK);
+ addKillId(FINAL_BOSSES);
+ addKillId(NORMAL_MOBS);
+ addExitZoneId(BALOK_BATTLE_ZONE.getId());
+ addEnterZoneId(BALOK_BATTLE_ZONE.getId());
+
+ final long currentTime = System.currentTimeMillis();
+ final Calendar startTime = Calendar.getInstance();
+ startTime.set(Calendar.HOUR_OF_DAY, Config.BALOK_HOUR);
+ startTime.set(Calendar.MINUTE, Config.BALOK_MINUTE);
+ startTime.set(Calendar.SECOND, 0);
+ if (startTime.getTimeInMillis() < currentTime)
+ {
+ startTime.add(Calendar.DAY_OF_YEAR, 1);
+ }
+ ThreadPool.scheduleAtFixedRate(this::startEvent, startTime.getTimeInMillis() - currentTime, 86400000); // 86400000 = 1 day
+ }
+
+ private void startEvent()
+ {
+ GlobalVariablesManager.getInstance().set(GlobalVariablesManager.BALOK_REMAIN_TIME, System.currentTimeMillis() + PREPARATION_TIME);
+ BattleWithBalokManager.getInstance().setGlobalStatus(_globalPoints);
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ setInProgress(true);
+ inPreparation();
+ }
+
+ private void inPreparation()
+ {
+ setStatus(1);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, 0));
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BATTLE_WITH_BALOK_STARTS_IN_20_MIN));
+ ThreadPool.schedule(this::inPreparation10, 600000); // 10 minutes
+ }
+
+ private void inPreparation10()
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BATTLE_WITH_BALOK_STARTS_IN_10_MIN));
+ NORMAL_BATTLE_MOBS.set(SpawnData.getInstance().getSpawns().stream().filter(t -> t.getName() != null).filter(t -> t.getName().contains("NormalMobsBattle")).findAny().orElse(null));
+ ThreadPool.schedule(this::inPreparationSoon, 540000); // 9 minutes
+ }
+
+ private void inPreparationSoon()
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BATTLE_WITH_BALOK_IS_STARTING_SOON));
+ ThreadPool.schedule(this::startSpawnMobs, 60000); // 1 minute
+ }
+
+ private void startSpawnMobs()
+ {
+ GlobalVariablesManager.getInstance().remove(GlobalVariablesManager.BALOK_REMAIN_TIME);
+ _stage = 1;
+ setStatus(2);
+ BattleWithBalokManager.getInstance().setInBattle(true);
+ GlobalVariablesManager.getInstance().set(GlobalVariablesManager.BALOK_REMAIN_TIME, System.currentTimeMillis() + BATTLE_TIME);
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.MONSTERS_ARE_SPAWNING_ON_THE_BALOK_BATTLEGROUND));
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ NORMAL_BATTLE_MOBS.get().getGroups().forEach(SpawnGroup::spawnAll);
+ _rewardTask = ThreadPool.schedule(this::finishAndReward, BATTLE_TIME); // 30 minutes
+ }
+
+ private void spawnInterBossesFirstWave()
+ {
+ if (!_midBossFirstSpawn && !_firstWaveKilled)
+ {
+ BOSS_SPAWNED.add(addSpawn(KESMA, KESMA_LOC));
+ BOSS_SPAWNED.add(addSpawn(PRAIS, PRAIS_LOC));
+ BOSS_SPAWNED.add(addSpawn(VIRA, VIRA_LOC));
+ setMidBossFirstSpawn(true);
+ BALOK_BATTLE_ZONE.broadcastPacket(new SystemMessage(SystemMessageId.THREE_BOSSES_HAVE_SPAWNED));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ }
+
+ private void spawnInterBossesSecondWave()
+ {
+ if (!_midBossSecondSpawn && !_secondWaveKilled)
+ {
+ BOSS_SPAWNED.add(addSpawn(HEARAK, HEARAK_LOC));
+ BOSS_SPAWNED.add(addSpawn(HEEDER, HEEDER_LOC));
+ setMidBossSecondSpawn(true);
+ _heederStatus = 1;
+ _hearakStatus = 1;
+ BALOK_BATTLE_ZONE.broadcastPacket(new SystemMessage(SystemMessageId.TWO_BOSSES_HAVE_SPAWNED));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ }
+
+ private void bypassRandomStage()
+ {
+ if (!_midBossSecondSpawn && (getRandom(100) < 3))
+ {
+ finalBossPlus();
+ _stage = 5;
+ }
+ else
+ {
+ finalBoss();
+ _stage = 4;
+ }
+ BOSS_SPAWNED.clear();
+ setSecondWaveKilled(true);
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void interBossesStatus()
+ {
+ if (_midbossDefeatCount == 3)
+ {
+ setFirstWaveKilled(true);
+ }
+ if (_midbossDefeatCount == 5)
+ {
+ setFirstWaveKilled(true);
+ }
+ if (_stage < 4)
+ {
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ }
+
+ private void spawnBalok()
+ {
+ final int random = getRandom(100);
+ int balokType = -1;
+ if (random < 50)
+ {
+ balokType = BALOK3;
+ setFinalBaloktype(BALOK3); // Yellow Balok
+ }
+ else if (random < 75)
+ {
+ balokType = BALOK2;
+ setFinalBaloktype(BALOK2); // Aqua Balok
+ }
+ else
+ {
+ balokType = BALOK1;
+ setFinalBaloktype(BALOK1);
+ }
+
+ BOSS_SPAWNED.add(addSpawn(balokType, BALOK_LOC));
+ setFinalBalokStatus(1);
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BALOK_IS_HERE));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void finalBoss()
+ {
+ if (((_stage == 4) && (getMidbossDefeatCount() == 5) && (_firstKillBalokId == KESMA)) || (_globalPoints > 1500000))
+ {
+ finalBossPlus();
+ }
+ else
+ {
+ spawnBalok();
+ }
+ }
+
+ private void finalBossPlus()
+ {
+ _stage = 5;
+ setFinalBaloktype(LORD_BALOK);
+ setFinalBalokStatus(1);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.LORD_BALOK_IS_HERE));
+ addSpawn(LORD_BALOK, BALOK_LOC, false);
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void rewardType()
+ {
+ int rewardId = -1;
+ if (_stage < 4)
+ {
+ rewardId = 91641; // Sayha's Blessing, consolation item reward.
+ }
+ if ((_stage <= 5) && !_balokKilled)
+ {
+ rewardId = 91641; // Sayha's Blessing, consolation item reward
+ }
+ if ((_stage == 5) && _balokKilled)
+ {
+ rewardId = 97087; // Lord Balok's Treasure Chest
+ }
+ if ((_stage == 4) && _balokKilled)
+ {
+ rewardId = (Rnd.get(97075, 97086)); // Balok's Treasure Chest
+ }
+ BattleWithBalokManager.getInstance().setReward(rewardId);
+ }
+
+ private void lastHitRewardMonsters(Player player)
+ {
+ final int rnd = Rnd.get(100);
+ int reward = 0;
+ if (rnd < 5)
+ {
+ reward = 33809; // Improved Scroll: Enchant A-grade Weapon
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_WEAPON, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+ else if (rnd < 15)
+ {
+ reward = 729; // Scroll: Enchant A-grade Weapon
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_WEAPON, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+ else
+ {
+ reward = 730; // Scroll: Enchant A-grade Armor
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_ARMOR, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+ player.addItem("Balok Last Hit Reward", reward, 1, player, true);
+ }
+
+ private void lastHitRewardBalok(Npc npc, Player player)
+ {
+ int reward = 0;
+ if (FINAL_BOSSES.contains(npc.getId()))
+ {
+ reward = 33809; // Improved Scroll: Enchant A-grade Weapon
+ }
+ if (reward > 0)
+ {
+ player.addItem("Balok Last Hit Reward", reward, 1, player, true);
+ }
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_WEAPON, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+
+ private void setInProgress(boolean value)
+ {
+ _inProgress = value;
+ }
+
+ private void setBalokKilled(boolean value)
+ {
+ _balokKilled = value;
+ }
+
+ private void setFirstWaveKilled(boolean value)
+ {
+ _firstWaveKilled = value;
+ }
+
+ private void setSecondWaveKilled(boolean value)
+ {
+ _secondWaveKilled = value;
+ }
+
+ private void setMidBossFirstSpawn(boolean value)
+ {
+ _midBossFirstSpawn = value;
+ }
+
+ public boolean midBossSpawn()
+ {
+ return _midBossFirstSpawn;
+ }
+
+ private void setMidBossSecondSpawn(boolean value)
+ {
+ _midBossSecondSpawn = value;
+ }
+
+ public boolean midBossSecondSpawn()
+ {
+ return _midBossSecondSpawn;
+ }
+
+ private void setStatus(int value)
+ {
+ _status = value;
+ }
+
+ private void addGlobalPoints(int value)
+ {
+ _globalPoints += value;
+ }
+
+ private int getMidbossDefeatCount()
+ {
+ return _midbossDefeatCount;
+ }
+
+ private void addMidbossDefeatCount(int value)
+ {
+ _midbossDefeatCount += value;
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void setFinalBaloktype(int value)
+ {
+ _finalBalokType = value;
+ }
+
+ private void setFinalBalokStatus(int value)
+ {
+ _finalBalokStatus = value;
+ }
+
+ @Override
+ public String onKill(Npc npc, Player player, boolean isSummon)
+ {
+ if (NORMAL_MOBS.contains(npc.getId()))
+ {
+ BattleWithBalokManager.getInstance().addPointsForPlayer(player, npc.getId() == SCORPION);
+ addGlobalPoints(npc.getId() == SCORPION ? Config.BALOK_POINTS_PER_MONSTER * 10 : Config.BALOK_POINTS_PER_MONSTER);
+ BattleWithBalokManager.getInstance().setGlobalPoints(_globalPoints);
+ }
+ if (INTERMID_BOSSES.contains(npc.getId()) && (_firstKillBalokId == 0)) // to lord balok plus
+ {
+ _firstKillBalokId = npc.getId();
+ }
+ if (FINAL_BOSSES.contains(npc.getId()))
+ {
+ if (_stage == 5)
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_WON_THE_BATTLE_WITH_LORD_BALOK));
+ }
+ else
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_WON_THE_BATTLE_WITH_BALOK));
+ }
+ setFinalBalokStatus(2);
+ setBalokKilled(true);
+ lastHitRewardBalok(npc, player);
+ finishAndReward();
+ }
+ if (npc.getId() == KESMA)
+ {
+ addMidbossDefeatCount(1);
+ _kesmaStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == PRAIS)
+ {
+ addMidbossDefeatCount(1);
+ _praisStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == VIRA)
+ {
+ addMidbossDefeatCount(1);
+ _viraStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == HEARAK)
+ {
+ addMidbossDefeatCount(1);
+ _hearakStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == HEEDER)
+ {
+ addMidbossDefeatCount(1);
+ _heederStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if ((_stage == 1) && (_globalPoints >= 250000))
+ {
+ _stage = 2;
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 2) && (_globalPoints >= 320000) && !_firstWaveKilled && !_midBossFirstSpawn)
+ {
+ spawnInterBossesFirstWave();
+ }
+ if ((_stage == 2) && (_midbossDefeatCount == 3) && _firstWaveKilled)
+ {
+ _stage = 3;
+ BOSS_SPAWNED.clear();
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 3) && (_globalPoints >= 800000) && !_secondWaveKilled && !_midBossSecondSpawn)
+ {
+ spawnInterBossesSecondWave();
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 3) && (_midbossDefeatCount == 5))
+ {
+ _stage = 4;
+ BOSS_SPAWNED.clear();
+ setSecondWaveKilled(true);
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ finalBoss();
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 1) && (_globalPoints < 3000) && (getRandom(5000) < 10))
+ {
+ bypassRandomStage();
+ }
+
+ return super.onKill(npc, player, isSummon);
+ }
+
+ public void finishAndReward()
+ {
+ _status = 3;
+ rewardType();
+ GlobalVariablesManager.getInstance().set(GlobalVariablesManager.BALOK_REMAIN_TIME, System.currentTimeMillis() + REWARD_TIME);
+ NORMAL_BATTLE_MOBS.get().getGroups().forEach(SpawnGroup::despawnAll);
+ BOSS_SPAWNED.stream().forEach(Npc::deleteMe);
+ BOSS_SPAWNED.clear();
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ if (!_balokKilled && (_stage == 4))
+ {
+ _finalBalokStatus = 3;
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_LOST_THE_BATTLE_WITH_BALOK));
+ }
+ if (!_balokKilled && (_stage == 5))
+ {
+ _finalBalokStatus = 3;
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_LOST_THE_BATTLE_WITH_LORD_BALOK));
+ }
+ if (_kesmaStatus != 2)
+ {
+ _kesmaStatus = 3;
+ }
+ if (_praisStatus != 2)
+ {
+ _praisStatus = 3;
+ }
+ if (_viraStatus != 2)
+ {
+ _viraStatus = 3;
+ }
+ if ((_heederStatus != 2) && (_stage >= 3) && (_globalPoints >= 800000))
+ {
+ _heederStatus = 3;
+ }
+ if ((_hearakStatus != 2) && (_stage >= 3) && (_globalPoints >= 800000))
+ {
+ _hearakStatus = 3;
+ }
+
+ interBossesStatus();
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ for (Player player : World.getInstance().getPlayers())
+ {
+ if (BattleWithBalokManager.getInstance().getMonsterPoints(player) < 1000)
+ {
+ return;
+ }
+
+ player.getVariables().set(PlayerVariables.BALOK_AVAILABLE_REWARD, 1);
+ }
+ if (_rewardTask != null)
+ {
+ _rewardTask.cancel(true);
+ }
+ ThreadPool.schedule(this::topRankingRewardFinish, 2400000); // 40 minutes
+ }
+
+ public void sendRankingReward()
+ {
+ for (Entry ranker : BattleWithBalokManager.getInstance().getTopPlayers(30).entrySet())
+ {
+ if (ranker == null)
+ {
+ return;
+ }
+
+ final int charId = ranker.getKey();
+ final Message mail = new Message(charId, "Battle with Balok Ranker Special Reward", "A special Reward given to rankers who contributed greatly in the balok Battle.", MailType.BALOK_RANKING_REWARD);
+ final Mail attachement = mail.createAttachments();
+ attachement.addItem("Battle with Balok", 91690, 100, null, null); // Special HP Recovery Potion
+ MailManager.getInstance().sendMessage(mail);
+ }
+ }
+
+ private void topRankingRewardFinish()
+ {
+ sendRankingReward();
+ GlobalVariablesManager.getInstance().remove(GlobalVariablesManager.BALOK_REMAIN_TIME);
+ }
+
+ @RegisterEvent(EventType.ON_PLAYER_LOGIN)
+ @RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
+ public void onPlayerLogin(OnPlayerLogin event)
+ {
+ final Player player = event.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (!_inProgress)
+ {
+ return;
+ }
+
+ player.sendPacket(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ public static void main(String[] args)
+ {
+ new Balok();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/spawns/Gludio/BalokBattleground.xml b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/spawns/Gludio/BalokBattleground.xml
new file mode 100644
index 0000000000..88cfd40530
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/spawns/Gludio/BalokBattleground.xml
@@ -0,0 +1,277 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/zones/no_bookmark.xml b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/zones/no_bookmark.xml
index bb754f418f..a1c8628ee9 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/zones/no_bookmark.xml
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/zones/no_bookmark.xml
@@ -8222,4 +8222,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java
index 2acaf11a12..33004c8362 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java
@@ -986,6 +986,11 @@ public class Config
public static int ZAKEN_SPAWN_INTERVAL;
public static int ZAKEN_SPAWN_RANDOM;
+ // Balok
+ public static int BALOK_HOUR;
+ public static int BALOK_MINUTE;
+ public static int BALOK_POINTS_PER_MONSTER;
+
// Gracia Seeds Settings
public static int SOD_TIAT_KILL_COUNT;
public static long SOD_STAGE_2_LENGTH;
@@ -2681,6 +2686,10 @@ public class Config
QUEEN_ANT_SPAWN_RANDOM = grandBossConfig.getInt("RandomOfQueenAntSpawn", 17);
ZAKEN_SPAWN_INTERVAL = grandBossConfig.getInt("IntervalOfZakenSpawn", 168);
ZAKEN_SPAWN_RANDOM = grandBossConfig.getInt("RandomOfZakenSpawn", 48);
+ final String[] balokTime = grandBossConfig.getString("BalokTime", "20:30").trim().split(":");
+ BALOK_HOUR = Integer.parseInt(balokTime[0]);
+ BALOK_MINUTE = Integer.parseInt(balokTime[1]);
+ BALOK_POINTS_PER_MONSTER = grandBossConfig.getInt("BalokPointsPerMonster", 10);
// Load HuntPass (if exists)
final PropertiesParser huntPassConfig = new PropertiesParser(HUNT_PASS_CONFIG_FILE);
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/MailType.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/MailType.java
index 86699332eb..23cc07c071 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/MailType.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/MailType.java
@@ -30,5 +30,6 @@ public enum MailType
MENTOR_NPC,
PRIME_SHOP_GIFT,
PURGE_REWARD,
+ BALOK_RANKING_REWARD,
PLEDGE_DONATION_CRITICAL_SUCCESS
}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java
new file mode 100644
index 0000000000..930d3b4f4b
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java
@@ -0,0 +1,133 @@
+/*
+ * 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 org.l2jmobius.gameserver.instancemanager;
+
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.model.actor.Player;
+
+/**
+ * @author Serenitty, Index
+ */
+public class BattleWithBalokManager
+{
+ private final Map _playerPoints = new ConcurrentHashMap<>();
+ private boolean _inBattle = false;
+ private int _reward = 0;
+ private int _globalPoints = 0;
+ private int _globalStage = 0;
+ private int _globalStatus = 0;
+
+ public BattleWithBalokManager()
+ {
+ }
+
+ public void addPointsForPlayer(Player player, boolean isScorpion)
+ {
+ final int pointsToAdd = isScorpion ? Config.BALOK_POINTS_PER_MONSTER * 10 : Config.BALOK_POINTS_PER_MONSTER;
+ final int currentPoints = _playerPoints.computeIfAbsent(player.getObjectId(), pts -> 0);
+ int sum = pointsToAdd + currentPoints;
+ _playerPoints.put(player.getObjectId(), sum);
+ }
+
+ public Map getTopPlayers(int count)
+ {
+ return _playerPoints.entrySet().stream().sorted(Entry.comparingByValue(Comparator.reverseOrder())).limit(count).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
+ }
+
+ public int getPlayerRank(Player player)
+ {
+ if (!_playerPoints.containsKey(player.getObjectId()))
+ {
+ return 0;
+ }
+
+ final Map sorted = _playerPoints.entrySet().stream().sorted(Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
+ return sorted.keySet().stream().toList().indexOf(player.getObjectId()) + 1;
+ }
+
+ public int getMonsterPoints(Player player)
+ {
+ return _playerPoints.computeIfAbsent(player.getObjectId(), pts -> 0);
+ }
+
+ public int getReward()
+ {
+ return _reward;
+ }
+
+ public void setReward(int value)
+ {
+ _reward = value;
+ }
+
+ public boolean getInBattle()
+ {
+ return _inBattle;
+ }
+
+ public void setInBattle(boolean value)
+ {
+ _inBattle = value;
+ }
+
+ public int getGlobalPoints()
+ {
+ return _globalPoints;
+ }
+
+ public void setGlobalPoints(int value)
+ {
+ _globalPoints = value;
+ }
+
+ public int getGlobalStage()
+ {
+ return _globalStage;
+ }
+
+ public void setGlobalStage(int value)
+ {
+ _globalStage = value;
+ }
+
+ public int getGlobalStatus()
+ {
+ return _globalStatus;
+ }
+
+ public void setGlobalStatus(int value)
+ {
+ _globalStatus = value;
+ }
+
+ public static BattleWithBalokManager getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final BattleWithBalokManager INSTANCE = new BattleWithBalokManager();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java
index 895c315971..287579ea6a 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java
@@ -47,6 +47,7 @@ public class GlobalVariablesManager extends AbstractVariables
public static final String RANKING_POWER_COOLDOWN = "RANKING_POWER_COOLDOWN";
public static final String RANKING_POWER_LOCATION = "RANKING_POWER_LOCATION";
public static final String PURGE_REWARD_TIME = "PURGE_REWARD_TIME";
+ public static final String BALOK_REMAIN_TIME = "BALOK_REMAIN_TIME";
protected GlobalVariablesManager()
{
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java
index 1bbb925636..93fe618eef 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java
@@ -92,6 +92,7 @@ public class PlayerVariables extends AbstractVariables
public static final String DYE_POTENTIAL_DAILY_STEP = "DYE_POTENTIAL_DAILY_STEP";
public static final String DYE_POTENTIAL_DAILY_COUNT = "DYE_POTENTIAL_DAILY_COUNT";
public static final String MISSION_LEVEL_PROGRESS = "MISSION_LEVEL_PROGRESS_";
+ public static final String BALOK_AVAILABLE_REWARD = "BALOK_AVAILABLE_REWARD";
private final int _objectId;
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java
index 8363331dd9..f390244b2b 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java
@@ -40,6 +40,10 @@ import org.l2jmobius.gameserver.network.clientpackets.autopeel.ExRequestReadyIte
import org.l2jmobius.gameserver.network.clientpackets.autopeel.ExRequestStopItemAutoPeel;
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExAutoPlaySetting;
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExRequestActivateAutoShortcut;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarGetReward;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarShowRanking;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarShowUI;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarTeleport;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionCancel;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionEnchant;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionPutItem;
@@ -796,10 +800,10 @@ public enum ExClientPackets
EX_WORLDCASTLEWAR_CASTLE_SIEGE_ALL_RANKING_INFO(0x235, null, ConnectionState.IN_GAME),
EX_MISSION_LEVEL_REWARD_LIST(0x236, RequestMissionRewardList::new, ConnectionState.IN_GAME),
EX_MISSION_LEVEL_RECEIVE_REWARD(0x237, RequestMissionLevelReceiveReward::new, ConnectionState.IN_GAME),
- EX_BALROGWAR_TELEPORT(0x238, null, ConnectionState.IN_GAME),
- EX_BALROGWAR_SHOW_UI(0x239, null, ConnectionState.IN_GAME),
- EX_BALROGWAR_SHOW_RANKING(0x23A, null, ConnectionState.IN_GAME),
- EX_BALROGWAR_GET_REWARD(0x23B, null, ConnectionState.IN_GAME),
+ EX_BALROGWAR_TELEPORT(0x238, ExBalrogWarTeleport::new, ConnectionState.IN_GAME),
+ EX_BALROGWAR_SHOW_UI(0x239, ExBalrogWarShowUI::new, ConnectionState.IN_GAME),
+ EX_BALROGWAR_SHOW_RANKING(0x23A, ExBalrogWarShowRanking::new, ConnectionState.IN_GAME),
+ EX_BALROGWAR_GET_REWARD(0x23B, ExBalrogWarGetReward::new, ConnectionState.IN_GAME),
EX_USER_RESTART_LOCKER_UPDATE(0x23C, null, ConnectionState.IN_GAME),
EX_WORLD_EXCHANGE_ITEM_LIST(0x23D, ExWorldExchangeItemList::new, ConnectionState.IN_GAME),
EX_WORLD_EXCHANGE_REGI_ITEM(0x23E, ExWorldExchangeRegisterItem::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java
new file mode 100644
index 0000000000..e6340aeb9b
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarGetReward;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarGetReward implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final int availableReward = player.getVariables().getInt(PlayerVariables.BALOK_AVAILABLE_REWARD, 0);
+ if (availableReward != 1)
+ {
+ return;
+ }
+
+ int count = 1;
+ final int globalStage = BattleWithBalokManager.getInstance().getGlobalStage();
+ if (globalStage < 4)
+ {
+ count = 30; // sayha potion sealed
+ }
+
+ final int reward = BattleWithBalokManager.getInstance().getReward();
+ player.addItem("Battle with Balok", reward, count, player, true);
+ player.getVariables().set(PlayerVariables.BALOK_AVAILABLE_REWARD, -1);
+ player.sendPacket(new BalrogWarGetReward(true));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java
new file mode 100644
index 0000000000..8375096414
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarShowRanking;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarShowRanking implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (!BattleWithBalokManager.getInstance().getInBattle())
+ {
+ return;
+ }
+
+ player.sendPacket(new BalrogWarShowRanking());
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java
new file mode 100644
index 0000000000..7f98be49fe
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarShowUI;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarShowUI implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new BalrogWarShowUI(player));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java
new file mode 100644
index 0000000000..af480a795c
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java
@@ -0,0 +1,88 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.effects.EffectFlag;
+import org.l2jmobius.gameserver.model.skill.CommonSkill;
+import org.l2jmobius.gameserver.model.zone.ZoneId;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarTeleport implements ClientPacket
+{
+ private static final Location BALOK_LOCATION = new Location(-18414, 180442, -3862);
+ private static final int TELEPORT_COST = 50000;
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ // Dead characters cannot use teleports.
+ if (player.isDead())
+ {
+ player.sendPacket(SystemMessageId.DEAD_CHARACTERS_CANNOT_USE_TELEPORTS);
+ return;
+ }
+
+ // Players should not be able to teleport if in a special location.
+ if ((player.getMovieHolder() != null) || player.isFishing() || player.isInInstance() || player.isOnEvent() || player.isInOlympiadMode() || player.inObserverMode() || player.isInTraingCamp() || player.isInsideZone(ZoneId.TIMED_HUNTING))
+ {
+ player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_RIGHT_NOW);
+ return;
+ }
+
+ // Cannot teleport in combat.
+ if ((player.isInCombat() || player.isCastingNow()))
+ {
+ player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_WHILE_IN_COMBAT_MODE);
+ return;
+ }
+
+ // Cannot escape effect.
+ if (player.isAffected(EffectFlag.CANNOT_ESCAPE))
+ {
+ player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_RIGHT_NOW);
+ return;
+ }
+
+ // Take teleport fee.
+ if (!player.destroyItemByItemId("Battle with Balok Teleport", 57, TELEPORT_COST, player, true))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_MONEY_TO_USE_THE_FUNCTION);
+ return;
+ }
+
+ // Stop moving.
+ player.abortCast();
+ player.stopMove(null);
+
+ // Teleport to Balok location.
+ player.setTeleportLocation(BALOK_LOCATION);
+ player.doCast(CommonSkill.TELEPORT.getSkill());
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java
new file mode 100644
index 0000000000..da92d36bf5
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java
@@ -0,0 +1,93 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty, NasSeKa
+ */
+public class BalrogWarBossInfo extends ServerPacket
+{
+ private final int _bossState1;
+ private final int _bossState2;
+ private final int _bossState3;
+ private final int _bossState4;
+ private final int _bossState5;
+ private final int _finalBossId;
+ private final int _finalState;
+
+ public BalrogWarBossInfo(int balokid, int balokstatus, int boss1, int boss2, int boss3, int boss4, int boss5)
+ {
+ _finalBossId = balokid + 1000000;
+ _finalState = balokstatus;
+ _bossState1 = boss1;
+ _bossState2 = boss2;
+ _bossState3 = boss3;
+ _bossState4 = boss4;
+ _bossState5 = boss5;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_BOSSINFO.writeId(this);
+ final long globalpoints = BattleWithBalokManager.getInstance().getGlobalPoints();
+ final int globalstage = BattleWithBalokManager.getInstance().getGlobalStage();
+ if ((globalpoints < 320000) && (globalstage <= 2))
+ {
+ writeInt(1);
+ writeInt(1);
+ writeInt(1);
+ writeInt(1);
+ writeInt(1);
+ writeInt(0);
+ writeInt(0);
+ writeInt(0);
+ writeInt(0);
+ writeInt(0);
+ }
+ else
+ {
+ final int bossId1 = 25956 + 1000000;
+ final int bossId2 = 25957 + 1000000;
+ final int bossId3 = 25958 + 1000000;
+ int bossId4 = 0;
+ int bossId5 = 0;
+ if ((globalpoints >= 800000) && (globalstage >= 3))
+ {
+ bossId4 = 25959 + 1000000;
+ bossId5 = 25960 + 1000000;
+ }
+
+ writeInt(bossId1);
+ writeInt(bossId2);
+ writeInt(bossId3);
+ writeInt(bossId4);
+ writeInt(bossId5);
+ writeInt(_bossState1);
+ writeInt(_bossState2);
+ writeInt(_bossState3);
+ writeInt(_bossState4);
+ writeInt(_bossState5);
+ writeInt(_finalBossId);
+ writeInt(_finalState);
+ }
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java
new file mode 100644
index 0000000000..4d1f08c366
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class BalrogWarGetReward extends ServerPacket
+{
+ private final boolean _available;
+
+ public BalrogWarGetReward(boolean available)
+ {
+ _available = available;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_GET_REWARD.writeId(this);
+ writeByte(_available);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java
new file mode 100644
index 0000000000..6e9e851ac4
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java
@@ -0,0 +1,49 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import java.util.concurrent.TimeUnit;
+
+import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Mobius, Serenitty
+ */
+public class BalrogWarHud extends ServerPacket
+{
+ private final int _state;
+ private final int _stage;
+
+ public BalrogWarHud(int state, int stage)
+ {
+ _state = state;
+ _stage = stage;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_HUD.writeId(this);
+ final long remainTime = GlobalVariablesManager.getInstance().getLong(GlobalVariablesManager.BALOK_REMAIN_TIME, 0);
+ final long currentTime = System.currentTimeMillis();
+ writeInt(_state); // State
+ writeInt(_stage); // Progress Step
+ writeInt((int) TimeUnit.MILLISECONDS.toSeconds(remainTime - currentTime)); // Time (in seconds)
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java
new file mode 100644
index 0000000000..7f64a3c7db
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java
@@ -0,0 +1,53 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.l2jmobius.gameserver.data.sql.CharNameTable;
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty, Index
+ */
+public class BalrogWarShowRanking extends ServerPacket
+{
+ private final Map _rankingData;
+
+ public BalrogWarShowRanking()
+ {
+ _rankingData = BattleWithBalokManager.getInstance().getTopPlayers(150);
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_SHOW_RANKING.writeId(this);
+ writeInt(_rankingData.size());
+ int rank = 0;
+ for (Entry entry : _rankingData.entrySet())
+ {
+ rank++;
+ writeInt(rank); // Rank
+ writeSizedString(CharNameTable.getInstance().getNameById(entry.getKey())); // Name
+ writeInt(entry.getValue()); // Score
+ }
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java
new file mode 100644
index 0000000000..8b34a18baf
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java
@@ -0,0 +1,49 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class BalrogWarShowUI extends ServerPacket
+{
+ private final Player _player;
+
+ public BalrogWarShowUI(Player player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_SHOW_UI.writeId(this);
+ final int personalPoints = BattleWithBalokManager.getInstance().getMonsterPoints(_player);
+ writeInt(personalPoints < 1 ? 0 : BattleWithBalokManager.getInstance().getPlayerRank(_player)); // personal rank
+ writeInt(personalPoints); // personal points
+ writeLong(BattleWithBalokManager.getInstance().getGlobalPoints()); // total points of players
+ writeInt(_player.getVariables().getInt(PlayerVariables.BALOK_AVAILABLE_REWARD, 0)); // reward activated or not
+ writeInt(BattleWithBalokManager.getInstance().getReward()); // RewardItemID
+ writeLong(1); // unknown
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/dist/game/config/GrandBoss.ini b/L2J_Mobius_Essence_6.3_Crusader/dist/game/config/GrandBoss.ini
index 9c2dd78e5b..eb9ee61a28 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/dist/game/config/GrandBoss.ini
+++ b/L2J_Mobius_Essence_6.3_Crusader/dist/game/config/GrandBoss.ini
@@ -57,3 +57,13 @@ IntervalOfZakenSpawn = 168
# Random interval. Range 1-192
RandomOfZakenSpawn = 48
+
+# ---------------------------------------------------------------------------
+# Battle for Balok
+# ---------------------------------------------------------------------------
+
+# Time Battle for Balok starts.
+BalokTime = 20:30
+
+# Number of points that a player earns for defeating a monster.
+BalokPointsPerMonster = 10
diff --git a/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/scripts/ai/bosses/Balok/Balok.java b/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/scripts/ai/bosses/Balok/Balok.java
new file mode 100644
index 0000000000..49446b9d5d
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/scripts/ai/bosses/Balok/Balok.java
@@ -0,0 +1,654 @@
+/*
+ * 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.Balok;
+
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.threads.ThreadPool;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.data.xml.SpawnData;
+import org.l2jmobius.gameserver.enums.MailType;
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
+import org.l2jmobius.gameserver.instancemanager.MailManager;
+import org.l2jmobius.gameserver.instancemanager.ZoneManager;
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.Message;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.ListenerRegisterType;
+import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent;
+import org.l2jmobius.gameserver.model.events.annotations.RegisterType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.itemcontainer.Mail;
+import org.l2jmobius.gameserver.model.spawns.SpawnGroup;
+import org.l2jmobius.gameserver.model.spawns.SpawnTemplate;
+import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.zone.ZoneType;
+import org.l2jmobius.gameserver.network.NpcStringId;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarBossInfo;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarHud;
+import org.l2jmobius.gameserver.util.Broadcast;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author Serenitty
+ */
+public class Balok extends AbstractNpcAI
+{
+ // Monsters
+ private static final int SCORPION = 22416;
+ private static final Set NORMAL_MOBS = new HashSet<>();
+ static
+ {
+ NORMAL_MOBS.add(22413);
+ NORMAL_MOBS.add(22415);
+ NORMAL_MOBS.add(22414);
+ NORMAL_MOBS.add(22416);
+ }
+ // Intermid bosses
+ private static final int KESMA = 25956;
+ private static final int PRAIS = 25957;
+ private static final int VIRA = 25958;
+ private static final int HEEDER = 25959;
+ private static final int HEARAK = 25960;
+ private static final Set INTERMID_BOSSES = new HashSet<>();
+ static
+ {
+ INTERMID_BOSSES.add(KESMA);
+ INTERMID_BOSSES.add(PRAIS);
+ INTERMID_BOSSES.add(VIRA);
+ INTERMID_BOSSES.add(HEEDER);
+ INTERMID_BOSSES.add(HEARAK);
+ }
+ // Final boss
+ private static final int BALOK1 = 29157; // Balok red normal
+ private static final int BALOK2 = 29161; // Balok aqua
+ private static final int BALOK3 = 29165; // Balok yellow
+ private static final int LORD_BALOK = 29169;
+ private static final Set FINAL_BOSSES = new HashSet<>();
+ static
+ {
+ FINAL_BOSSES.add(BALOK1);
+ FINAL_BOSSES.add(BALOK2);
+ FINAL_BOSSES.add(BALOK3);
+ FINAL_BOSSES.add(LORD_BALOK);
+ }
+ // Locations
+ private static final Location KESMA_LOC = new Location(-17370, 184479, -3991, 49942);
+ private static final Location PRAIS_LOC = new Location(-21765, 178790, -4077, 7662);
+ private static final Location VIRA_LOC = new Location(-21375, 182516, -3969, 58095);
+ private static final Location HEEDER_LOC = new Location(-15210, 178553, -4277, 25134);
+ private static final Location HEARAK_LOC = new Location(-13947, 181909, -4348, 32883);
+ private static final Location BALOK_LOC = new Location(-18392, 181079, -3845, 48678);
+ // Zone
+ private static final ZoneType BALOK_BATTLE_ZONE = ZoneManager.getInstance().getZoneByName("balok_area");
+ // Misc
+ private static final AtomicReference NORMAL_BATTLE_MOBS = new AtomicReference<>();
+ private static final Set BOSS_SPAWNED = ConcurrentHashMap.newKeySet();
+ private static final int BATTLE_TIME = 1800000; // 30 min
+ private static final int PREPARATION_TIME = 1200000; // 20 min
+ private static final int REWARD_TIME = 2400000; // 40 min
+
+ private int _status = 0;
+ private int _stage = 0;
+ private int _globalPoints = 0;
+ private int _midbossDefeatCount = 0;
+ private int _kesmaStatus = 1;
+ private int _praisStatus = 1;
+ private int _viraStatus = 1;
+ private int _heederStatus = 0;
+ private int _hearakStatus = 0;
+ private int _finalBalokType = 1;
+ private int _finalBalokStatus = 1;
+ private boolean _inProgress = false;
+ private boolean _balokKilled = false;
+ private boolean _firstWaveKilled = false;
+ private boolean _secondWaveKilled = false;
+ private boolean _midBossFirstSpawn = false;
+ private boolean _midBossSecondSpawn = false;
+ private int _firstKillBalokId = 0;
+ ScheduledFuture> _rewardTask;
+
+ private Balok()
+ {
+ addKillId(VIRA, KESMA, PRAIS, HEEDER, HEARAK);
+ addKillId(FINAL_BOSSES);
+ addKillId(NORMAL_MOBS);
+ addExitZoneId(BALOK_BATTLE_ZONE.getId());
+ addEnterZoneId(BALOK_BATTLE_ZONE.getId());
+
+ final long currentTime = System.currentTimeMillis();
+ final Calendar startTime = Calendar.getInstance();
+ startTime.set(Calendar.HOUR_OF_DAY, Config.BALOK_HOUR);
+ startTime.set(Calendar.MINUTE, Config.BALOK_MINUTE);
+ startTime.set(Calendar.SECOND, 0);
+ if (startTime.getTimeInMillis() < currentTime)
+ {
+ startTime.add(Calendar.DAY_OF_YEAR, 1);
+ }
+ ThreadPool.scheduleAtFixedRate(this::startEvent, startTime.getTimeInMillis() - currentTime, 86400000); // 86400000 = 1 day
+ }
+
+ private void startEvent()
+ {
+ GlobalVariablesManager.getInstance().set(GlobalVariablesManager.BALOK_REMAIN_TIME, System.currentTimeMillis() + PREPARATION_TIME);
+ BattleWithBalokManager.getInstance().setGlobalStatus(_globalPoints);
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ setInProgress(true);
+ inPreparation();
+ }
+
+ private void inPreparation()
+ {
+ setStatus(1);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, 0));
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BATTLE_WITH_BALOK_STARTS_IN_20_MIN));
+ ThreadPool.schedule(this::inPreparation10, 600000); // 10 minutes
+ }
+
+ private void inPreparation10()
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BATTLE_WITH_BALOK_STARTS_IN_10_MIN));
+ NORMAL_BATTLE_MOBS.set(SpawnData.getInstance().getSpawns().stream().filter(t -> t.getName() != null).filter(t -> t.getName().contains("NormalMobsBattle")).findAny().orElse(null));
+ ThreadPool.schedule(this::inPreparationSoon, 540000); // 9 minutes
+ }
+
+ private void inPreparationSoon()
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BATTLE_WITH_BALOK_IS_STARTING_SOON));
+ ThreadPool.schedule(this::startSpawnMobs, 60000); // 1 minute
+ }
+
+ private void startSpawnMobs()
+ {
+ GlobalVariablesManager.getInstance().remove(GlobalVariablesManager.BALOK_REMAIN_TIME);
+ _stage = 1;
+ setStatus(2);
+ BattleWithBalokManager.getInstance().setInBattle(true);
+ GlobalVariablesManager.getInstance().set(GlobalVariablesManager.BALOK_REMAIN_TIME, System.currentTimeMillis() + BATTLE_TIME);
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.MONSTERS_ARE_SPAWNING_ON_THE_BALOK_BATTLEGROUND));
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ NORMAL_BATTLE_MOBS.get().getGroups().forEach(SpawnGroup::spawnAll);
+ _rewardTask = ThreadPool.schedule(this::finishAndReward, BATTLE_TIME); // 30 minutes
+ }
+
+ private void spawnInterBossesFirstWave()
+ {
+ if (!_midBossFirstSpawn && !_firstWaveKilled)
+ {
+ BOSS_SPAWNED.add(addSpawn(KESMA, KESMA_LOC));
+ BOSS_SPAWNED.add(addSpawn(PRAIS, PRAIS_LOC));
+ BOSS_SPAWNED.add(addSpawn(VIRA, VIRA_LOC));
+ setMidBossFirstSpawn(true);
+ BALOK_BATTLE_ZONE.broadcastPacket(new SystemMessage(SystemMessageId.THREE_BOSSES_HAVE_SPAWNED));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ }
+
+ private void spawnInterBossesSecondWave()
+ {
+ if (!_midBossSecondSpawn && !_secondWaveKilled)
+ {
+ BOSS_SPAWNED.add(addSpawn(HEARAK, HEARAK_LOC));
+ BOSS_SPAWNED.add(addSpawn(HEEDER, HEEDER_LOC));
+ setMidBossSecondSpawn(true);
+ _heederStatus = 1;
+ _hearakStatus = 1;
+ BALOK_BATTLE_ZONE.broadcastPacket(new SystemMessage(SystemMessageId.TWO_BOSSES_HAVE_SPAWNED));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ }
+
+ private void bypassRandomStage()
+ {
+ if (!_midBossSecondSpawn && (getRandom(100) < 3))
+ {
+ finalBossPlus();
+ _stage = 5;
+ }
+ else
+ {
+ finalBoss();
+ _stage = 4;
+ }
+ BOSS_SPAWNED.clear();
+ setSecondWaveKilled(true);
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void interBossesStatus()
+ {
+ if (_midbossDefeatCount == 3)
+ {
+ setFirstWaveKilled(true);
+ }
+ if (_midbossDefeatCount == 5)
+ {
+ setFirstWaveKilled(true);
+ }
+ if (_stage < 4)
+ {
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ }
+
+ private void spawnBalok()
+ {
+ final int random = getRandom(100);
+ int balokType = -1;
+ if (random < 50)
+ {
+ balokType = BALOK3;
+ setFinalBaloktype(BALOK3); // Yellow Balok
+ }
+ else if (random < 75)
+ {
+ balokType = BALOK2;
+ setFinalBaloktype(BALOK2); // Aqua Balok
+ }
+ else
+ {
+ balokType = BALOK1;
+ setFinalBaloktype(BALOK1);
+ }
+
+ BOSS_SPAWNED.add(addSpawn(balokType, BALOK_LOC));
+ setFinalBalokStatus(1);
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.BALOK_IS_HERE));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void finalBoss()
+ {
+ if (((_stage == 4) && (getMidbossDefeatCount() == 5) && (_firstKillBalokId == KESMA)) || (_globalPoints > 1500000))
+ {
+ finalBossPlus();
+ }
+ else
+ {
+ spawnBalok();
+ }
+ }
+
+ private void finalBossPlus()
+ {
+ _stage = 5;
+ setFinalBaloktype(LORD_BALOK);
+ setFinalBalokStatus(1);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.LORD_BALOK_IS_HERE));
+ addSpawn(LORD_BALOK, BALOK_LOC, false);
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void rewardType()
+ {
+ int rewardId = -1;
+ if (_stage < 4)
+ {
+ rewardId = 91641; // Sayha's Blessing, consolation item reward.
+ }
+ if ((_stage <= 5) && !_balokKilled)
+ {
+ rewardId = 91641; // Sayha's Blessing, consolation item reward
+ }
+ if ((_stage == 5) && _balokKilled)
+ {
+ rewardId = 97087; // Lord Balok's Treasure Chest
+ }
+ if ((_stage == 4) && _balokKilled)
+ {
+ rewardId = (Rnd.get(97075, 97086)); // Balok's Treasure Chest
+ }
+ BattleWithBalokManager.getInstance().setReward(rewardId);
+ }
+
+ private void lastHitRewardMonsters(Player player)
+ {
+ final int rnd = Rnd.get(100);
+ int reward = 0;
+ if (rnd < 5)
+ {
+ reward = 33809; // Improved Scroll: Enchant A-grade Weapon
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_WEAPON, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+ else if (rnd < 15)
+ {
+ reward = 729; // Scroll: Enchant A-grade Weapon
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_WEAPON, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+ else
+ {
+ reward = 730; // Scroll: Enchant A-grade Armor
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_ARMOR, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+ player.addItem("Balok Last Hit Reward", reward, 1, player, true);
+ }
+
+ private void lastHitRewardBalok(Npc npc, Player player)
+ {
+ int reward = 0;
+ if (FINAL_BOSSES.contains(npc.getId()))
+ {
+ reward = 33809; // Improved Scroll: Enchant A-grade Weapon
+ }
+ if (reward > 0)
+ {
+ player.addItem("Balok Last Hit Reward", reward, 1, player, true);
+ }
+ BALOK_BATTLE_ZONE.broadcastPacket(new ExShowScreenMessage(NpcStringId.S1_RECEIVES_SCROLL_ENCHANT_WEAPON, ExShowScreenMessage.BOTTOM_RIGHT, 10000, false, player.getName()));
+ }
+
+ private void setInProgress(boolean value)
+ {
+ _inProgress = value;
+ }
+
+ private void setBalokKilled(boolean value)
+ {
+ _balokKilled = value;
+ }
+
+ private void setFirstWaveKilled(boolean value)
+ {
+ _firstWaveKilled = value;
+ }
+
+ private void setSecondWaveKilled(boolean value)
+ {
+ _secondWaveKilled = value;
+ }
+
+ private void setMidBossFirstSpawn(boolean value)
+ {
+ _midBossFirstSpawn = value;
+ }
+
+ public boolean midBossSpawn()
+ {
+ return _midBossFirstSpawn;
+ }
+
+ private void setMidBossSecondSpawn(boolean value)
+ {
+ _midBossSecondSpawn = value;
+ }
+
+ public boolean midBossSecondSpawn()
+ {
+ return _midBossSecondSpawn;
+ }
+
+ private void setStatus(int value)
+ {
+ _status = value;
+ }
+
+ private void addGlobalPoints(int value)
+ {
+ _globalPoints += value;
+ }
+
+ private int getMidbossDefeatCount()
+ {
+ return _midbossDefeatCount;
+ }
+
+ private void addMidbossDefeatCount(int value)
+ {
+ _midbossDefeatCount += value;
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ private void setFinalBaloktype(int value)
+ {
+ _finalBalokType = value;
+ }
+
+ private void setFinalBalokStatus(int value)
+ {
+ _finalBalokStatus = value;
+ }
+
+ @Override
+ public String onKill(Npc npc, Player player, boolean isSummon)
+ {
+ if (NORMAL_MOBS.contains(npc.getId()))
+ {
+ BattleWithBalokManager.getInstance().addPointsForPlayer(player, npc.getId() == SCORPION);
+ addGlobalPoints(npc.getId() == SCORPION ? Config.BALOK_POINTS_PER_MONSTER * 10 : Config.BALOK_POINTS_PER_MONSTER);
+ BattleWithBalokManager.getInstance().setGlobalPoints(_globalPoints);
+ }
+ if (INTERMID_BOSSES.contains(npc.getId()) && (_firstKillBalokId == 0)) // to lord balok plus
+ {
+ _firstKillBalokId = npc.getId();
+ }
+ if (FINAL_BOSSES.contains(npc.getId()))
+ {
+ if (_stage == 5)
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_WON_THE_BATTLE_WITH_LORD_BALOK));
+ }
+ else
+ {
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_WON_THE_BATTLE_WITH_BALOK));
+ }
+ setFinalBalokStatus(2);
+ setBalokKilled(true);
+ lastHitRewardBalok(npc, player);
+ finishAndReward();
+ }
+ if (npc.getId() == KESMA)
+ {
+ addMidbossDefeatCount(1);
+ _kesmaStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == PRAIS)
+ {
+ addMidbossDefeatCount(1);
+ _praisStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == VIRA)
+ {
+ addMidbossDefeatCount(1);
+ _viraStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == HEARAK)
+ {
+ addMidbossDefeatCount(1);
+ _hearakStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if (npc.getId() == HEEDER)
+ {
+ addMidbossDefeatCount(1);
+ _heederStatus = 2;
+ interBossesStatus();
+ lastHitRewardMonsters(player);
+ }
+ if ((_stage == 1) && (_globalPoints >= 250000))
+ {
+ _stage = 2;
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 2) && (_globalPoints >= 320000) && !_firstWaveKilled && !_midBossFirstSpawn)
+ {
+ spawnInterBossesFirstWave();
+ }
+ if ((_stage == 2) && (_midbossDefeatCount == 3) && _firstWaveKilled)
+ {
+ _stage = 3;
+ BOSS_SPAWNED.clear();
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 3) && (_globalPoints >= 800000) && !_secondWaveKilled && !_midBossSecondSpawn)
+ {
+ spawnInterBossesSecondWave();
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 3) && (_midbossDefeatCount == 5))
+ {
+ _stage = 4;
+ BOSS_SPAWNED.clear();
+ setSecondWaveKilled(true);
+ BattleWithBalokManager.getInstance().setGlobalStage(_stage);
+ finalBoss();
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+ if ((_stage == 1) && (_globalPoints < 3000) && (getRandom(5000) < 10))
+ {
+ bypassRandomStage();
+ }
+
+ return super.onKill(npc, player, isSummon);
+ }
+
+ public void finishAndReward()
+ {
+ _status = 3;
+ rewardType();
+ GlobalVariablesManager.getInstance().set(GlobalVariablesManager.BALOK_REMAIN_TIME, System.currentTimeMillis() + REWARD_TIME);
+ NORMAL_BATTLE_MOBS.get().getGroups().forEach(SpawnGroup::despawnAll);
+ BOSS_SPAWNED.stream().forEach(Npc::deleteMe);
+ BOSS_SPAWNED.clear();
+ Broadcast.toAllOnlinePlayers(new BalrogWarHud(_status, _stage));
+ if (!_balokKilled && (_stage == 4))
+ {
+ _finalBalokStatus = 3;
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_LOST_THE_BATTLE_WITH_BALOK));
+ }
+ if (!_balokKilled && (_stage == 5))
+ {
+ _finalBalokStatus = 3;
+ Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.YOU_VE_LOST_THE_BATTLE_WITH_LORD_BALOK));
+ }
+ if (_kesmaStatus != 2)
+ {
+ _kesmaStatus = 3;
+ }
+ if (_praisStatus != 2)
+ {
+ _praisStatus = 3;
+ }
+ if (_viraStatus != 2)
+ {
+ _viraStatus = 3;
+ }
+ if ((_heederStatus != 2) && (_stage >= 3) && (_globalPoints >= 800000))
+ {
+ _heederStatus = 3;
+ }
+ if ((_hearakStatus != 2) && (_stage >= 3) && (_globalPoints >= 800000))
+ {
+ _hearakStatus = 3;
+ }
+
+ interBossesStatus();
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ for (Player player : World.getInstance().getPlayers())
+ {
+ if (BattleWithBalokManager.getInstance().getMonsterPoints(player) < 1000)
+ {
+ return;
+ }
+
+ player.getVariables().set(PlayerVariables.BALOK_AVAILABLE_REWARD, 1);
+ }
+ if (_rewardTask != null)
+ {
+ _rewardTask.cancel(true);
+ }
+ ThreadPool.schedule(this::topRankingRewardFinish, 2400000); // 40 minutes
+ }
+
+ public void sendRankingReward()
+ {
+ for (Entry ranker : BattleWithBalokManager.getInstance().getTopPlayers(30).entrySet())
+ {
+ if (ranker == null)
+ {
+ return;
+ }
+
+ final int charId = ranker.getKey();
+ final Message mail = new Message(charId, "Battle with Balok Ranker Special Reward", "A special Reward given to rankers who contributed greatly in the balok Battle.", MailType.BALOK_RANKING_REWARD);
+ final Mail attachement = mail.createAttachments();
+ attachement.addItem("Battle with Balok", 91690, 100, null, null); // Special HP Recovery Potion
+ MailManager.getInstance().sendMessage(mail);
+ }
+ }
+
+ private void topRankingRewardFinish()
+ {
+ sendRankingReward();
+ GlobalVariablesManager.getInstance().remove(GlobalVariablesManager.BALOK_REMAIN_TIME);
+ }
+
+ @RegisterEvent(EventType.ON_PLAYER_LOGIN)
+ @RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
+ public void onPlayerLogin(OnPlayerLogin event)
+ {
+ final Player player = event.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (!_inProgress)
+ {
+ return;
+ }
+
+ player.sendPacket(new BalrogWarHud(_status, _stage));
+ Broadcast.toAllOnlinePlayers(new BalrogWarBossInfo(_finalBalokType, _finalBalokStatus, _kesmaStatus, _praisStatus, _viraStatus, _hearakStatus, _heederStatus));
+ }
+
+ public static void main(String[] args)
+ {
+ new Balok();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/spawns/Gludio/BalokBattleground.xml b/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/spawns/Gludio/BalokBattleground.xml
new file mode 100644
index 0000000000..88cfd40530
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/spawns/Gludio/BalokBattleground.xml
@@ -0,0 +1,277 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/zones/no_bookmark.xml b/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/zones/no_bookmark.xml
index bb754f418f..a1c8628ee9 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/zones/no_bookmark.xml
+++ b/L2J_Mobius_Essence_6.3_Crusader/dist/game/data/zones/no_bookmark.xml
@@ -8222,4 +8222,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java
index 2acaf11a12..33004c8362 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java
@@ -986,6 +986,11 @@ public class Config
public static int ZAKEN_SPAWN_INTERVAL;
public static int ZAKEN_SPAWN_RANDOM;
+ // Balok
+ public static int BALOK_HOUR;
+ public static int BALOK_MINUTE;
+ public static int BALOK_POINTS_PER_MONSTER;
+
// Gracia Seeds Settings
public static int SOD_TIAT_KILL_COUNT;
public static long SOD_STAGE_2_LENGTH;
@@ -2681,6 +2686,10 @@ public class Config
QUEEN_ANT_SPAWN_RANDOM = grandBossConfig.getInt("RandomOfQueenAntSpawn", 17);
ZAKEN_SPAWN_INTERVAL = grandBossConfig.getInt("IntervalOfZakenSpawn", 168);
ZAKEN_SPAWN_RANDOM = grandBossConfig.getInt("RandomOfZakenSpawn", 48);
+ final String[] balokTime = grandBossConfig.getString("BalokTime", "20:30").trim().split(":");
+ BALOK_HOUR = Integer.parseInt(balokTime[0]);
+ BALOK_MINUTE = Integer.parseInt(balokTime[1]);
+ BALOK_POINTS_PER_MONSTER = grandBossConfig.getInt("BalokPointsPerMonster", 10);
// Load HuntPass (if exists)
final PropertiesParser huntPassConfig = new PropertiesParser(HUNT_PASS_CONFIG_FILE);
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/MailType.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/MailType.java
index 86699332eb..23cc07c071 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/MailType.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/MailType.java
@@ -30,5 +30,6 @@ public enum MailType
MENTOR_NPC,
PRIME_SHOP_GIFT,
PURGE_REWARD,
+ BALOK_RANKING_REWARD,
PLEDGE_DONATION_CRITICAL_SUCCESS
}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java
new file mode 100644
index 0000000000..930d3b4f4b
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/BattleWithBalokManager.java
@@ -0,0 +1,133 @@
+/*
+ * 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 org.l2jmobius.gameserver.instancemanager;
+
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.model.actor.Player;
+
+/**
+ * @author Serenitty, Index
+ */
+public class BattleWithBalokManager
+{
+ private final Map _playerPoints = new ConcurrentHashMap<>();
+ private boolean _inBattle = false;
+ private int _reward = 0;
+ private int _globalPoints = 0;
+ private int _globalStage = 0;
+ private int _globalStatus = 0;
+
+ public BattleWithBalokManager()
+ {
+ }
+
+ public void addPointsForPlayer(Player player, boolean isScorpion)
+ {
+ final int pointsToAdd = isScorpion ? Config.BALOK_POINTS_PER_MONSTER * 10 : Config.BALOK_POINTS_PER_MONSTER;
+ final int currentPoints = _playerPoints.computeIfAbsent(player.getObjectId(), pts -> 0);
+ int sum = pointsToAdd + currentPoints;
+ _playerPoints.put(player.getObjectId(), sum);
+ }
+
+ public Map getTopPlayers(int count)
+ {
+ return _playerPoints.entrySet().stream().sorted(Entry.comparingByValue(Comparator.reverseOrder())).limit(count).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
+ }
+
+ public int getPlayerRank(Player player)
+ {
+ if (!_playerPoints.containsKey(player.getObjectId()))
+ {
+ return 0;
+ }
+
+ final Map sorted = _playerPoints.entrySet().stream().sorted(Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
+ return sorted.keySet().stream().toList().indexOf(player.getObjectId()) + 1;
+ }
+
+ public int getMonsterPoints(Player player)
+ {
+ return _playerPoints.computeIfAbsent(player.getObjectId(), pts -> 0);
+ }
+
+ public int getReward()
+ {
+ return _reward;
+ }
+
+ public void setReward(int value)
+ {
+ _reward = value;
+ }
+
+ public boolean getInBattle()
+ {
+ return _inBattle;
+ }
+
+ public void setInBattle(boolean value)
+ {
+ _inBattle = value;
+ }
+
+ public int getGlobalPoints()
+ {
+ return _globalPoints;
+ }
+
+ public void setGlobalPoints(int value)
+ {
+ _globalPoints = value;
+ }
+
+ public int getGlobalStage()
+ {
+ return _globalStage;
+ }
+
+ public void setGlobalStage(int value)
+ {
+ _globalStage = value;
+ }
+
+ public int getGlobalStatus()
+ {
+ return _globalStatus;
+ }
+
+ public void setGlobalStatus(int value)
+ {
+ _globalStatus = value;
+ }
+
+ public static BattleWithBalokManager getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final BattleWithBalokManager INSTANCE = new BattleWithBalokManager();
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java
index 895c315971..287579ea6a 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/instancemanager/GlobalVariablesManager.java
@@ -47,6 +47,7 @@ public class GlobalVariablesManager extends AbstractVariables
public static final String RANKING_POWER_COOLDOWN = "RANKING_POWER_COOLDOWN";
public static final String RANKING_POWER_LOCATION = "RANKING_POWER_LOCATION";
public static final String PURGE_REWARD_TIME = "PURGE_REWARD_TIME";
+ public static final String BALOK_REMAIN_TIME = "BALOK_REMAIN_TIME";
protected GlobalVariablesManager()
{
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java
index 1bbb925636..93fe618eef 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/variables/PlayerVariables.java
@@ -92,6 +92,7 @@ public class PlayerVariables extends AbstractVariables
public static final String DYE_POTENTIAL_DAILY_STEP = "DYE_POTENTIAL_DAILY_STEP";
public static final String DYE_POTENTIAL_DAILY_COUNT = "DYE_POTENTIAL_DAILY_COUNT";
public static final String MISSION_LEVEL_PROGRESS = "MISSION_LEVEL_PROGRESS_";
+ public static final String BALOK_AVAILABLE_REWARD = "BALOK_AVAILABLE_REWARD";
private final int _objectId;
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java
index f52175af60..76ca25af42 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java
@@ -40,6 +40,10 @@ import org.l2jmobius.gameserver.network.clientpackets.autopeel.ExRequestReadyIte
import org.l2jmobius.gameserver.network.clientpackets.autopeel.ExRequestStopItemAutoPeel;
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExAutoPlaySetting;
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExRequestActivateAutoShortcut;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarGetReward;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarShowRanking;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarShowUI;
+import org.l2jmobius.gameserver.network.clientpackets.balok.ExBalrogWarTeleport;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionCancel;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionEnchant;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionPutItem;
@@ -800,10 +804,10 @@ public enum ExClientPackets
EX_WORLDCASTLEWAR_CASTLE_SIEGE_ALL_RANKING_INFO(0x236, null, ConnectionState.IN_GAME),
EX_MISSION_LEVEL_REWARD_LIST(0x237, RequestMissionRewardList::new, ConnectionState.IN_GAME),
EX_MISSION_LEVEL_RECEIVE_REWARD(0x238, RequestMissionLevelReceiveReward::new, ConnectionState.IN_GAME),
- EX_BALROGWAR_TELEPORT(0x239, null, ConnectionState.IN_GAME),
- EX_BALROGWAR_SHOW_UI(0x23A, null, ConnectionState.IN_GAME),
- EX_BALROGWAR_SHOW_RANKING(0x23B, null, ConnectionState.IN_GAME),
- EX_BALROGWAR_GET_REWARD(0x23C, null, ConnectionState.IN_GAME),
+ EX_BALROGWAR_TELEPORT(0x239, ExBalrogWarTeleport::new, ConnectionState.IN_GAME),
+ EX_BALROGWAR_SHOW_UI(0x23A, ExBalrogWarShowUI::new, ConnectionState.IN_GAME),
+ EX_BALROGWAR_SHOW_RANKING(0x23B, ExBalrogWarShowRanking::new, ConnectionState.IN_GAME),
+ EX_BALROGWAR_GET_REWARD(0x23C, ExBalrogWarGetReward::new, ConnectionState.IN_GAME),
EX_USER_RESTART_LOCKER_UPDATE(0x23D, null, ConnectionState.IN_GAME),
EX_WORLD_EXCHANGE_ITEM_LIST(0x23E, ExWorldExchangeItemList::new, ConnectionState.IN_GAME),
EX_WORLD_EXCHANGE_REGI_ITEM(0x23F, ExWorldExchangeRegisterItem::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java
new file mode 100644
index 0000000000..e6340aeb9b
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarGetReward.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarGetReward;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarGetReward implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final int availableReward = player.getVariables().getInt(PlayerVariables.BALOK_AVAILABLE_REWARD, 0);
+ if (availableReward != 1)
+ {
+ return;
+ }
+
+ int count = 1;
+ final int globalStage = BattleWithBalokManager.getInstance().getGlobalStage();
+ if (globalStage < 4)
+ {
+ count = 30; // sayha potion sealed
+ }
+
+ final int reward = BattleWithBalokManager.getInstance().getReward();
+ player.addItem("Battle with Balok", reward, count, player, true);
+ player.getVariables().set(PlayerVariables.BALOK_AVAILABLE_REWARD, -1);
+ player.sendPacket(new BalrogWarGetReward(true));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java
new file mode 100644
index 0000000000..8375096414
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowRanking.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarShowRanking;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarShowRanking implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (!BattleWithBalokManager.getInstance().getInBattle())
+ {
+ return;
+ }
+
+ player.sendPacket(new BalrogWarShowRanking());
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java
new file mode 100644
index 0000000000..7f98be49fe
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarShowUI.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.balok.BalrogWarShowUI;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarShowUI implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.sendPacket(new BalrogWarShowUI(player));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java
new file mode 100644
index 0000000000..df847e5bae
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/balok/ExBalrogWarTeleport.java
@@ -0,0 +1,88 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.clientpackets.balok;
+
+import org.l2jmobius.gameserver.model.Location;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.effects.EffectFlag;
+import org.l2jmobius.gameserver.model.skill.CommonSkill;
+import org.l2jmobius.gameserver.model.zone.ZoneId;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExBalrogWarTeleport implements ClientPacket
+{
+ private static final Location BALOK_LOCATION = new Location(-18414, 180442, -3862);
+ private static final int TELEPORT_COST = 50000;
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ // Dead characters cannot use teleports.
+ if (player.isDead())
+ {
+ player.sendPacket(SystemMessageId.DEAD_CHARACTERS_CANNOT_USE_TELEPORTS);
+ return;
+ }
+
+ // Players should not be able to teleport if in a special location.
+ if ((player.getMovieHolder() != null) || player.isFishing() || player.isInInstance() || player.isOnEvent() || player.isInOlympiadMode() || player.inObserverMode() || player.isInTraingCamp() || player.isInsideZone(ZoneId.TIMED_HUNTING))
+ {
+ player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_RIGHT_NOW);
+ return;
+ }
+
+ // Cannot teleport in combat.
+ if ((player.isInCombat() || player.isCastingNow()))
+ {
+ player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_WHILE_IN_COMBAT);
+ return;
+ }
+
+ // Cannot escape effect.
+ if (player.isAffected(EffectFlag.CANNOT_ESCAPE))
+ {
+ player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_RIGHT_NOW);
+ return;
+ }
+
+ // Take teleport fee.
+ if (!player.destroyItemByItemId("Battle with Balok Teleport", 57, TELEPORT_COST, player, true))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_MONEY_TO_USE_THE_FUNCTION);
+ return;
+ }
+
+ // Stop moving.
+ player.abortCast();
+ player.stopMove(null);
+
+ // Teleport to Balok location.
+ player.setTeleportLocation(BALOK_LOCATION);
+ player.doCast(CommonSkill.TELEPORT.getSkill());
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java
new file mode 100644
index 0000000000..da92d36bf5
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarBossInfo.java
@@ -0,0 +1,93 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty, NasSeKa
+ */
+public class BalrogWarBossInfo extends ServerPacket
+{
+ private final int _bossState1;
+ private final int _bossState2;
+ private final int _bossState3;
+ private final int _bossState4;
+ private final int _bossState5;
+ private final int _finalBossId;
+ private final int _finalState;
+
+ public BalrogWarBossInfo(int balokid, int balokstatus, int boss1, int boss2, int boss3, int boss4, int boss5)
+ {
+ _finalBossId = balokid + 1000000;
+ _finalState = balokstatus;
+ _bossState1 = boss1;
+ _bossState2 = boss2;
+ _bossState3 = boss3;
+ _bossState4 = boss4;
+ _bossState5 = boss5;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_BOSSINFO.writeId(this);
+ final long globalpoints = BattleWithBalokManager.getInstance().getGlobalPoints();
+ final int globalstage = BattleWithBalokManager.getInstance().getGlobalStage();
+ if ((globalpoints < 320000) && (globalstage <= 2))
+ {
+ writeInt(1);
+ writeInt(1);
+ writeInt(1);
+ writeInt(1);
+ writeInt(1);
+ writeInt(0);
+ writeInt(0);
+ writeInt(0);
+ writeInt(0);
+ writeInt(0);
+ }
+ else
+ {
+ final int bossId1 = 25956 + 1000000;
+ final int bossId2 = 25957 + 1000000;
+ final int bossId3 = 25958 + 1000000;
+ int bossId4 = 0;
+ int bossId5 = 0;
+ if ((globalpoints >= 800000) && (globalstage >= 3))
+ {
+ bossId4 = 25959 + 1000000;
+ bossId5 = 25960 + 1000000;
+ }
+
+ writeInt(bossId1);
+ writeInt(bossId2);
+ writeInt(bossId3);
+ writeInt(bossId4);
+ writeInt(bossId5);
+ writeInt(_bossState1);
+ writeInt(_bossState2);
+ writeInt(_bossState3);
+ writeInt(_bossState4);
+ writeInt(_bossState5);
+ writeInt(_finalBossId);
+ writeInt(_finalState);
+ }
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java
new file mode 100644
index 0000000000..4d1f08c366
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarGetReward.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class BalrogWarGetReward extends ServerPacket
+{
+ private final boolean _available;
+
+ public BalrogWarGetReward(boolean available)
+ {
+ _available = available;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_GET_REWARD.writeId(this);
+ writeByte(_available);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java
new file mode 100644
index 0000000000..6e9e851ac4
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarHud.java
@@ -0,0 +1,49 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import java.util.concurrent.TimeUnit;
+
+import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Mobius, Serenitty
+ */
+public class BalrogWarHud extends ServerPacket
+{
+ private final int _state;
+ private final int _stage;
+
+ public BalrogWarHud(int state, int stage)
+ {
+ _state = state;
+ _stage = stage;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_HUD.writeId(this);
+ final long remainTime = GlobalVariablesManager.getInstance().getLong(GlobalVariablesManager.BALOK_REMAIN_TIME, 0);
+ final long currentTime = System.currentTimeMillis();
+ writeInt(_state); // State
+ writeInt(_stage); // Progress Step
+ writeInt((int) TimeUnit.MILLISECONDS.toSeconds(remainTime - currentTime)); // Time (in seconds)
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java
new file mode 100644
index 0000000000..7f64a3c7db
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowRanking.java
@@ -0,0 +1,53 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.l2jmobius.gameserver.data.sql.CharNameTable;
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty, Index
+ */
+public class BalrogWarShowRanking extends ServerPacket
+{
+ private final Map _rankingData;
+
+ public BalrogWarShowRanking()
+ {
+ _rankingData = BattleWithBalokManager.getInstance().getTopPlayers(150);
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_SHOW_RANKING.writeId(this);
+ writeInt(_rankingData.size());
+ int rank = 0;
+ for (Entry entry : _rankingData.entrySet())
+ {
+ rank++;
+ writeInt(rank); // Rank
+ writeSizedString(CharNameTable.getInstance().getNameById(entry.getKey())); // Name
+ writeInt(entry.getValue()); // Score
+ }
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java
new file mode 100644
index 0000000000..8b34a18baf
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/balok/BalrogWarShowUI.java
@@ -0,0 +1,49 @@
+/*
+ * 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 org.l2jmobius.gameserver.network.serverpackets.balok;
+
+import org.l2jmobius.gameserver.instancemanager.BattleWithBalokManager;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class BalrogWarShowUI extends ServerPacket
+{
+ private final Player _player;
+
+ public BalrogWarShowUI(Player player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_BALROGWAR_SHOW_UI.writeId(this);
+ final int personalPoints = BattleWithBalokManager.getInstance().getMonsterPoints(_player);
+ writeInt(personalPoints < 1 ? 0 : BattleWithBalokManager.getInstance().getPlayerRank(_player)); // personal rank
+ writeInt(personalPoints); // personal points
+ writeLong(BattleWithBalokManager.getInstance().getGlobalPoints()); // total points of players
+ writeInt(_player.getVariables().getInt(PlayerVariables.BALOK_AVAILABLE_REWARD, 0)); // reward activated or not
+ writeInt(BattleWithBalokManager.getInstance().getReward()); // RewardItemID
+ writeLong(1); // unknown
+ }
+}