U3Games

Games | Desarrollo & Soporte => L2 | Implementaciones => L2 | Sección de Servidores => Lineage => L2 | Eventos => Mensaje iniciado por: Jerry en Ago 02, 2025, 07:38 PM

Título: Kill The Boss Event - Interlude aCis
Publicado por: Jerry en Ago 02, 2025, 07:38 PM
+++ /config/BossEvent.properties
@@ -0,0 +1,42 @@
+# ================================================
+# BossEvent (by Zaun) #
+# ================================================
+#General
+# Event Hour
+EventTime = 20:55,00:00
+# List of bosses randomly selected
+# e.g 29046;29029
+BossList = 29046
+# Id of registration NPC
+RegisterNpcID = 10003
+# Npc location
+RegisterNpcLocation = 82727,148605,-3471
+# List of locations randomly selected
+# e.g 10468,-24569,-3645;174229,-88032,-5116
+LocationsList = 174229,-88032,-5116
+# Min players to start event
+MinPlayers = 1
+# Min damage to boss to receive rewards
+MinDamage = 2000
+# if true countdown will be shown on screen
+EventTimeOnScreen = True
+
+# Timing
+# reg time in seconds
+RegistrationTime = 30
+# Wait time in seconds
+WaitTime = 15
+# Teleport time in seconds
+TeleportTime = 10
+# time to despawn boss
+TimeToDespawnBoss = 300
+
+# Rewards
+# Rewards for players who hitted min damage on boss
+GeneralRewards = 57,100000;3470,10
+# Reward last hit player
+RewardLastAttacker = True
+LastAttackerRewards = 3470,5;3470,5
+# Reward Player with bigger dmg
+RewardMainDamageDealer = True
+MainDamageDealerRewards = 3470,5;3470,5
\ No newline at end of file
diff --git /java/dev/bossInstancedEvent/BossEvent.java /java/dev/bossInstancedEvent/BossEvent.java
new file mode 100644
index 0000000..5f4175a
--- /dev/null
+++ /java/dev/bossInstancedEvent/BossEvent.java
@@ -0,0 +1,634 @@
+package dev.bossInstancedEvent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Logger;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.commons.concurrent.ThreadPool;
+import net.sf.l2j.commons.random.Rnd;
+import net.sf.l2j.gameserver.data.NpcTable;
+import net.sf.l2j.gameserver.data.SpawnTable;
+import net.sf.l2j.gameserver.handler.VoicedCommandHandler;
+import net.sf.l2j.gameserver.model.L2Spawn;
+import net.sf.l2j.gameserver.model.World;
+import net.sf.l2j.gameserver.model.actor.instance.Player;
+import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
+import net.sf.l2j.gameserver.model.location.Location;
+import net.sf.l2j.gameserver.network.clientpackets.Say2;
+import net.sf.l2j.gameserver.network.serverpackets.CreatureSay;
+import net.sf.l2j.gameserver.network.serverpackets.ExShowScreenMessage;
+import net.sf.l2j.gameserver.network.serverpackets.ExShowScreenMessage.SMPOS;
+import net.sf.l2j.gameserver.network.serverpackets.MagicSkillUse;
+
+/**
+ * @author Zaun
+ */
+public class BossEvent
+{
+ public L2Spawn bossSpawn;
+ public List<Location> locList = new ArrayList<>();
+ public Location loc;
+ public List<Integer> bossList = new ArrayList<>();
+ public int bossId;
+ public int objectId;
+ public List<Player> eventPlayers = new ArrayList<>();
+ protected static final Logger _log = Logger.getLogger(BossEvent.class.getName());
+ private EventState state = EventState.INACTIVE;
+ public boolean started = false;
+ public boolean aborted = false;
+ private Player lastAttacker = null;
+ private Map<Integer, Integer> generalRewards = new HashMap<>();
+ private Map<Integer, Integer> lastAttackerRewards = new HashMap<>();
+ private Map<Integer, Integer> mainDamageDealerRewards = new HashMap<>();
+ public ScheduledFuture<?> despawnBoss = null;
+ public ScheduledFuture<?> countDownTask = null;
+ private String bossName = "";
+ public boolean bossKilled = false;
+ public L2Spawn eventNpc = null;
+ public long startTime;
+
+ public enum EventState
+ {
+ REGISTRATION, TELEPORTING, WAITING, FIGHTING, FINISHING, INACTIVE
+ }
+
+ public BossEvent()
+ {
+ VoicedCommandHandler.getInstance().registerHandler(new BossEventCMD());
+ NextBossEvent.getInstance().startCalculationOfNextEventTime();
+ _log.info("Boss Event loaded.");
+
+ }
+
+ public boolean addPlayer(Player player)
+ {
+ return eventPlayers.add(player);
+ }
+
+ public boolean removePlayer(Player player)
+ {
+ return eventPlayers.remove(player);
+ }
+
+ public boolean isRegistered(Player player)
+ {
+ return eventPlayers.contains(player);
+ }
+
+ class Registration implements Runnable
+ {
+ @Override
+ public void run()
+ {
+ startRegistration();
+
+ }
+
+ }
+
+ public void teleToTown()
+ {
+ for (Player p : eventPlayers)
+ {
+ p.teleToLocation(new Location(83374, 148081, -3407), 300);
+ }
+ setState(EventState.INACTIVE);
+ }
+
+ public void delay(int delay)
+ {
+ try
+ {
+ Thread.sleep(delay);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ class Teleporting implements Runnable
+ {
+ Location teleTo;
+ List<Player> toTeleport = new ArrayList<>();
+
+ public Teleporting(List<Player> toTeleport, Location teleTo)
+ {
+ this.teleTo = teleTo;
+ this.toTeleport = toTeleport;
+ }
+
+ @Override
+ public void run()
+ {
+ if (eventPlayers.size() >= Config.BOSS_EVENT_MIN_PLAYERS)
+ {
+ despawnNpc(eventNpc);
+ setState(EventState.TELEPORTING);
+ announce("Event Started!", false);
+ startCountDown(Config.BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS, true);
+
+ for (Player p : toTeleport)
+ {
+ ThreadPool.schedule(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ p.teleToLocation(teleTo, 300);
+
+ }
+ }, Config.BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS * 1000);
+
+ }
+ delay(Config.BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS * 1000);
+ setState(EventState.WAITING);
+ startCountDown(Config.BOSS_EVENT_TIME_TO_WAIT, true);
+ ThreadPool.schedule(new Fighting(bossId, teleTo), Config.BOSS_EVENT_TIME_TO_WAIT * 1000);
+
+ }
+ else
+ {
+ announce("Event was cancelled due to lack of participation!", false);
+ setState(EventState.INACTIVE);
+ despawnNpc(eventNpc);
+ eventPlayers.clear();
+ objectId = 0;
+
+ }
+
+ }
+
+ }
+
+ public void reward(Player p, Map<Integer, Integer> rewardType)
+ {
+
+ for (Map.Entry<Integer, Integer> entry : rewardType.entrySet())
+ {
+ p.addItem("BossEventReward", entry.getKey(), entry.getValue(), null, true);
+ }
+
+ }
+
+ public void rewardPlayers()
+ {
+ for (Player p : eventPlayers)
+ {
+ if (p.getBossEventDamage() > Config.BOSS_EVENT_MIN_DAMAGE_TO_OBTAIN_REWARD)
+ {
+ reward(p, generalRewards);
+ }
+ else
+ {
+ p.sendPacket(new ExShowScreenMessage("You didn't caused min damage to receive rewards!", 5000));
+ p.sendMessage("You didn't caused min damage to receive rewards! Min. Damage: " + Config.BOSS_EVENT_MIN_DAMAGE_TO_OBTAIN_REWARD + ". Your Damage: " + p.getBossEventDamage());
+ }
+ }
+
+ if (Config.BOSS_EVENT_REWARD_MAIN_DAMAGE_DEALER)
+ {
+ if (getMainDamageDealer() != null)
+ {
+ reward(getMainDamageDealer(), mainDamageDealerRewards);
+ getMainDamageDealer().sendChatMessage(0, Say2.CRITICAL_ANNOUNCE, "[Boss Event]", "Congratulations, you was the damage dealer! So you will receive wonderful rewards.");
+ }
+
+ }
+ }
+
+ public void finishEvent()
+ {
+ started = false;
+ // if (!AdminBossEvent.manual)
+ // {
+ NextBossEvent.getInstance().startCalculationOfNextEventTime();
+ // }
+ // else
+ // {
+ // AdminBossEvent.manual = false;
+ // }
+ rewardPlayers();
+ if (bossKilled) announce(bossName + " has been defeated!", false);
+ if (Config.BOSS_EVENT_REWARD_LAST_ATTACKER)
+ {
+ if (lastAttacker != null)
+ {
+ announce("LastAttacker: " + lastAttacker.getName(), false);
+ }
+ }
+
+ if (Config.BOSS_EVENT_REWARD_MAIN_DAMAGE_DEALER)
+ {
+ if (getMainDamageDealer() != null)
+ {
+ announce("Main Damage Dealer: " + getMainDamageDealer().getName() + ". Total Damage = " + getMainDamageDealer().getBossEventDamage(), false);
+ }
+ }
+ ThreadPool.schedule(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ teleToTown();
+ eventPlayers.clear();
+
+ }
+ }, Config.BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS * 1000);
+
+ setState(EventState.FINISHING);
+ startCountDown(Config.BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS, true);
+ if (despawnBoss != null)
+ {
+ despawnBoss.cancel(true);
+ despawnBoss = null;
+ }
+ objectId = 0;
+
+ }
+
+ class Fighting implements Runnable
+ {
+ int bossId;
+ Location spawnLoc;
+
+ public Fighting(int bossId, Location spawnLoc)
+ {
+ this.bossId = bossId;
+ this.spawnLoc = spawnLoc;
+ }
+
+ @Override
+ public void run()
+ {
+ if (spawnNpc(bossId, loc.getX(), loc.getY(), loc.getZ()))
+ {
+ setState(EventState.FIGHTING);
+ if (Config.BOSS_EVENT_TIME_ON_SCREEN)
+ {
+ startCountDown(Config.BOSS_EVENT_TIME_TO_DESPAWN_BOSS, true);
+ }
+ despawnBoss = ThreadPool.schedule(new DespawnBossTask(bossSpawn), Config.BOSS_EVENT_TIME_TO_DESPAWN_BOSS * 1000);
+ objectId = bossSpawn.getNpc().getObjectId();
+ for (Player p : eventPlayers)
+ {
+ p.sendPacket(new ExShowScreenMessage("Boss " + bossSpawn.getNpc().getName() + " has been spawned. Go and Defeat him!", 5000));
+ }
+
+ }
+
+ }
+
+ }
+
+ public void despawnNpc(L2Spawn spawn)
+ {
+ if (spawn != null)
+ {
+ spawn.getNpc().deleteMe();
+ spawn.setRespawnState(false);
+ SpawnTable.getInstance().deleteSpawn(spawn, true);
+ }
+
+ }
+
+ class DespawnBossTask implements Runnable
+ {
+ L2Spawn spawn;
+
+ public DespawnBossTask(L2Spawn spawn)
+ {
+ this.spawn = spawn;
+ }
+
+ @Override
+ public void run()
+ {
+ if (spawn != null)
+ {
+ announceScreen("Your time is over " + spawn.getNpc().getName() + " returned to his home!", true);
+ announce("Your time is over " + spawn.getNpc().getName() + " returned to his home!", true);
+ announce("You will be teleported to town.", true);
+ despawnNpc(spawn);
+ ThreadPool.schedule(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ teleToTown();
+ eventPlayers.clear();
+ setState(EventState.INACTIVE);
+ objectId = 0;
+
+ }
+ }, 10000);
+ }
+ }
+
+ }
+
+ public void startRegistration()
+ {
+ try
+ {
+ resetPlayersDamage();
+ bossKilled = false;
+ bossList = Config.BOSS_EVENT_ID;
+ bossId = bossList.get(Rnd.get(bossList.size()));
+ locList = Config.BOSS_EVENT_LOCATION;
+ loc = locList.get(Rnd.get(locList.size()));
+ if (NpcTable.getInstance().getTemplate(bossId) != null)
+ {
+ startTime = System.currentTimeMillis() + Config.BOSS_EVENT_REGISTRATION_TIME * 1000;
+ eventNpc = spawnEventNpc(Config.BOSS_EVENT_NPC_REGISTER_LOC._x, Config.BOSS_EVENT_NPC_REGISTER_LOC._y, Config.BOSS_EVENT_NPC_REGISTER_LOC._z);
+ generalRewards = Config.BOSS_EVENT_GENERAL_REWARDS;
+ lastAttackerRewards = Config.BOSS_EVENT_LAST_ATTACKER_REWARDS;
+ mainDamageDealerRewards = Config.BOSS_EVENT_MAIN_DAMAGE_DEALER_REWARDS;
+ started = true;
+ aborted = false;
+ bossName = NpcTable.getInstance().getTemplate(bossId).getName();
+ setState(EventState.REGISTRATION);
+ announce("Registration started!", false);
+ announce("Joinable in giran or use command \".bossevent\" to register to event", false);
+ startCountDown(Config.BOSS_EVENT_REGISTRATION_TIME, false);
+
+ ThreadPool.schedule(new Teleporting(eventPlayers, loc), Config.BOSS_EVENT_REGISTRATION_TIME * 1000);
+
+ }
+ else
+ {
+ _log.warning(getClass().getName() + ": cannot be started. Invalid BossId: " + bossList);
+ return;
+ }
+ }
+ catch (Exception e)
+ {
+ _log.warning("[Boss Event]: Couldn't be started");
+ e.printStackTrace();
+ }
+
+ }
+
+ public int timeInMillisToStart()
+ {
+ return (int) (startTime - System.currentTimeMillis()) / 1000;
+ }
+
+ public void startCountDownEnterWorld(Player player)
+ {
+ if (getState() == EventState.REGISTRATION)
+ {
+ ThreadPool.schedule(new Countdown(player, timeInMillisToStart(), getState()), 0);
+ }
+ }
+
+ public boolean spawnNpc(int npcId, int x, int y, int z)
+ {
+ NpcTemplate tmpl = NpcTable.getInstance().getTemplate(npcId);
+ try
+ {
+ bossSpawn = new L2Spawn(tmpl);
+
+ bossSpawn.setLoc(x, y, z, Rnd.get(65535));
+ bossSpawn.setRespawnDelay(1);
+
+ SpawnTable.getInstance().addNewSpawn(bossSpawn, false);
+
+ bossSpawn.setRespawnState(false);
+ bossSpawn.doSpawn(false);
+ bossSpawn.getNpc().isAggressive();
+ bossSpawn.getNpc().decayMe();
+ bossSpawn.getNpc().spawnMe(bossSpawn.getNpc().getX(), bossSpawn.getNpc().getY(), bossSpawn.getNpc().getZ());
+ bossSpawn.getNpc().broadcastPacket(new MagicSkillUse(bossSpawn.getNpc(), bossSpawn.getNpc(), 1034, 1, 1, 1));
+ return true;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public void resetPlayersDamage()
+ {
+ for (Player p : World.getInstance().getPlayers())
+ {
+ p.setBossEventDamage(0);
+ }
+ }
+
+ public L2Spawn spawnEventNpc(int x, int y, int z)
+ {
+ L2Spawn spawn = null;
+ NpcTemplate tmpl = NpcTable.getInstance().getTemplate(Config.BOSS_EVENT_REGISTRATION_NPC_ID);
+ try
+ {
+ spawn = new L2Spawn(tmpl);
+
+ spawn.setLoc(x, y, z, Rnd.get(65535));
+ spawn.setRespawnDelay(1);
+
+ SpawnTable.getInstance().addNewSpawn(spawn, false);
+
+ spawn.setRespawnState(false);
+ spawn.doSpawn(false);
+ spawn.getNpc().isAggressive();
+ spawn.getNpc().decayMe();
+ spawn.getNpc().spawnMe(spawn.getNpc().getX(), spawn.getNpc().getY(), spawn.getNpc().getZ());
+ spawn.getNpc().broadcastPacket(new MagicSkillUse(spawn.getNpc(), spawn.getNpc(), 1034, 1, 1, 1));
+ return spawn;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return spawn;
+ }
+ }
+
+ public final Player getMainDamageDealer()
+ {
+ int dmg = 0;
+ Player mainDamageDealer = null;
+ for (Player p : eventPlayers)
+ {
+ if (p.getBossEventDamage() > dmg)
+ {
+ dmg = p.getBossEventDamage();
+ mainDamageDealer = p;
+ }
+ }
+ return mainDamageDealer;
+ }
+
+ public static BossEvent getInstance()
+ {
+ return SingleTonHolder._instance;
+ }
+
+ private static class SingleTonHolder
+ {
+ protected static final BossEvent _instance = new BossEvent();
+ }
+
+ public void startCountDown(int time, boolean eventOnly)
+ {
+ Collection<Player> players = new ArrayList<>();
+ players = eventOnly ? eventPlayers : World.getInstance().getPlayers();
+ for (Player player : players)
+ {
+ ThreadPool.schedule(new Countdown(player, time, getState()), 0L);
+ }
+
+ }
+
+ public void announce(String text, boolean eventOnly)
+ {
+ Collection<Player> players = new ArrayList<>();
+ players = eventOnly ? eventPlayers : World.getInstance().getPlayers();
+ for (Player player : players)
+ {
+ player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "[Boss Event]", text));
+ }
+ }
+
+ public void announceScreen(String text, boolean eventOnly)
+ {
+ Collection<Player> players = new ArrayList<>();
+ players = eventOnly ? eventPlayers : World.getInstance().getPlayers();
+ for (Player player : players)
+ {
+ player.sendPacket(new ExShowScreenMessage(text, 4000));
+ }
+ }
+
+ /**
+ * @return the state
+ */
+ public EventState getState()
+ {
+ return state;
+ }
+
+ /**
+ * @param state the state to set
+ */
+ public void setState(EventState state)
+ {
+ this.state = state;
+ }
+
+ /**
+ * @return the lastAttacker
+ */
+ public Player getLastAttacker()
+ {
+ return lastAttacker;
+ }
+
+ /**
+ * @param lastAttacker the lastAttacker to set
+ */
+ public void setLastAttacker(Player lastAttacker)
+ {
+ this.lastAttacker = lastAttacker;
+ }
+
+ protected class Countdown implements Runnable
+ {
+ private final Player _player;
+ private final int _time;
+ private String text = "";
+ EventState evtState;
+
+ public Countdown(Player player, int time, EventState evtState)
+ {
+ _time = time;
+ _player = player;
+ switch (evtState)
+ {
+ case REGISTRATION:
+ text = "Boss Event registration ends in: ";
+ break;
+ case TELEPORTING:
+ text = "You will be teleported to Boss Event in: ";
+ break;
+ case WAITING:
+ text = "Boss will spawn in: ";
+ break;
+ case FINISHING:
+ text = "You will be teleported to City in: ";
+ break;
+ }
+ this.evtState = evtState;
+ }
+
+ @Override
+ public void run()
+ {
+ if (getState() == EventState.INACTIVE)
+ {
+ return;
+ }
+ if (_player.isOnline())
+ {
+ switch (evtState)
+ {
+ case REGISTRATION:
+ case TELEPORTING:
+ case WAITING:
+ case FINISHING:
+ switch (_time)
+ {
+
+ case 60:
+ case 120:
+ case 180:
+ case 240:
+ case 300:
+ _player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "[Boss Event]", text + _time / 60 + " minute(s)"));
+ break;
+ case 45:
+ case 30:
+ case 15:
+ case 10:
+ case 5:
+ case 4:
+ case 3:
+ case 2:
+ case 1:
+ _player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "[Boss Event]", text + _time + " second(s)"));
+ break;
+
+ }
+ if (_time > 1)
+ {
+ ThreadPool.schedule(new Countdown(_player, _time - 1, evtState), 1000L);
+ }
+ break;
+ case FIGHTING:
+ int minutes = _time / 60;
+ int second = _time % 60;
+ String timing = ((minutes < 10) ? ("0" + minutes) : minutes) + ":" + ((second < 10) ? ("0" + second) : second);
+
+ _player.sendPacket(new ExShowScreenMessage("Time Left: " + timing, 1100, SMPOS.BOTTOM_RIGHT, true));
+ if (_time > 1)
+ {
+ ThreadPool.schedule(new Countdown(_player, _time - 1, evtState), 1000L);
+ }
+ break;
+ }
+
+ }
+ }
+ }
+
+}
diff --git /java/dev/bossInstancedEvent/BossEventCMD.java /java/dev/bossInstancedEvent/BossEventCMD.java
new file mode 100644
index 0000000..284d342
--- /dev/null
+++ /java/dev/bossInstancedEvent/BossEventCMD.java
@@ -0,0 +1,55 @@
+package dev.bossInstancedEvent;
+
+
+
+import net.sf.l2j.gameserver.handler.IVoicedCommandHandler;
+import net.sf.l2j.gameserver.model.actor.instance.Player;
+
+import dev.bossInstancedEvent.BossEvent.EventState;
+
+/**
+ * @author Zaun
+ */
+public class BossEventCMD implements IVoicedCommandHandler
+{
+
+ @Override
+ public boolean useVoicedCommand(String command, Player activeChar, String params)
+ {
+ if (command.startsWith("bossevent"))
+ {
+ if (BossEvent.getInstance().getState() != EventState.REGISTRATION)
+ {
+ activeChar.sendMessage("Boss Event is not running!");
+ return false;
+ }
+ if (!BossEvent.getInstance().isRegistered(activeChar))
+ {
+ if (BossEvent.getInstance().addPlayer(activeChar))
+ {
+ activeChar.sendMessage("You have been successfully registered in Boss Event!");
+ }
+
+ }
+ else
+ {
+ if (BossEvent.getInstance().removePlayer(activeChar))
+ {
+ activeChar.sendMessage("You have been successfully removed of Boss Event!");
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String[] getVoicedCommandList()
+ {
+
+ return new String[]
+ {
+ "bossevent"
+ };
+ }
+
+}
diff --git /java/dev/bossInstancedEvent/NextBossEvent.java /java/dev/bossInstancedEvent/NextBossEvent.java
new file mode 100644
index 0000000..fa9186f
--- /dev/null
+++ /java/dev/bossInstancedEvent/NextBossEvent.java
@@ -0,0 +1,98 @@
+package dev.bossInstancedEvent;
+
+
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Logger;
+
+import net.sf.l2j.commons.concurrent.ThreadPool;
+
+import net.sf.l2j.Config;
+
+public class NextBossEvent
+{
+ private static NextBossEvent _instance = null;
+ protected static final Logger _log = Logger.getLogger(NextBossEvent.class.getName());
+ private Calendar nextEvent;
+ private final SimpleDateFormat format = new SimpleDateFormat("HH:mm");
+ public ScheduledFuture<?> task = null;
+
+ public static NextBossEvent getInstance()
+ {
+ if (_instance == null)
+ {
+ _instance = new NextBossEvent();
+ }
+ return _instance;
+ }
+
+ public String getNextTime()
+ {
+ if (nextEvent.getTime() != null)
+ {
+ return format.format(nextEvent.getTime());
+ }
+ return "Erro";
+ }
+
+ public void startCalculationOfNextEventTime()
+ {
+ try
+ {
+ Calendar currentTime = Calendar.getInstance();
+ Calendar testStartTime = null;
+ long flush2 = 0L;
+ long timeL = 0L;
+ int count = 0;
+ for (String timeOfDay : Config.BOSS_EVENT_BY_TIME_OF_DAY)
+ {
+ testStartTime = Calendar.getInstance();
+ testStartTime.setLenient(true);
+ String[] splitTimeOfDay = timeOfDay.split(":");
+ testStartTime.set(11, Integer.parseInt(splitTimeOfDay[0]));
+ testStartTime.set(12, Integer.parseInt(splitTimeOfDay[1]));
+ testStartTime.set(13, 0);
+ if (testStartTime.getTimeInMillis() < currentTime.getTimeInMillis())
+ {
+ testStartTime.add(5, 1);
+ }
+ timeL = testStartTime.getTimeInMillis() - currentTime.getTimeInMillis();
+ if (count == 0)
+ {
+ flush2 = timeL;
+ nextEvent = testStartTime;
+ }
+ if (timeL < flush2)
+ {
+ flush2 = timeL;
+ nextEvent = testStartTime;
+ }
+ count++;
+ }
+ _log.info("[Boss Event]: Next Event Time -> " + nextEvent.getTime().toString());
+ ThreadPool.schedule(new StartEventTask(), flush2);
+ }
+ catch (Exception e)
+ {
+ System.out.println("[Boss Event]: " + e);
+ }
+ }
+
+ class StartEventTask implements Runnable
+ {
+ StartEventTask()
+ {
+ }
+
+ @Override
+ public void run()
+ {
+ NextBossEvent._log.info("----------------------------------------------------------------------------");
+ NextBossEvent._log.info("[Boss Event]: Event Started.");
+ NextBossEvent._log.info("----------------------------------------------------------------------------");
+ BossEvent.getInstance().startRegistration();
+ }
+ }
+}
diff --git /java/net/sf/l2j/Config.java /java/net/sf/l2j/Config.java
index 23c317c..2e25061 100644
--- /java/net/sf/l2j/Config.java
+++ /java/net/sf/l2j/Config.java
@@ -70,6 +70,28 @@
 
+ public static final String BOSS_EVENT_INSTANCED = "./config/BossEvent.properties";
+
+ /** Boss Event */
+ public static boolean BOSS_EVENT_TIME_ON_SCREEN;
+ public static int BOSS_EVENT_TIME_TO_DESPAWN_BOSS;
+ public static int BOSS_EVENT_REGISTRATION_NPC_ID;
+ public static Map<Integer, Integer> BOSS_EVENT_GENERAL_REWARDS = new HashMap<>();
+ public static Map<Integer, Integer> BOSS_EVENT_LAST_ATTACKER_REWARDS = new HashMap<>();
+ public static Map<Integer, Integer> BOSS_EVENT_MAIN_DAMAGE_DEALER_REWARDS = new HashMap<>();
+ public static boolean BOSS_EVENT_REWARD_MAIN_DAMAGE_DEALER;
+ public static boolean BOSS_EVENT_REWARD_LAST_ATTACKER;
+ public static List<Location> BOSS_EVENT_LOCATION = new ArrayList<>();
+ public static int BOSS_EVENT_REWARD_ID;
+ public static int BOSS_EVENT_REWARD_COUNT;
+ public static int BOSS_EVENT_MIN_DAMAGE_TO_OBTAIN_REWARD;
+ public static List<Integer> BOSS_EVENT_ID = new ArrayList<>();
+ public static Location BOSS_EVENT_NPC_REGISTER_LOC;
+ public static int BOSS_EVENT_TIME_TO_WAIT;
+ public static int BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS;
+ public static int BOSS_EVENT_MIN_PLAYERS;
+ public static int BOSS_EVENT_REGISTRATION_TIME;
+ public static String[] BOSS_EVENT_BY_TIME_OF_DAY;
 
  public static Map<String, String> NPC_STRING_REPLACES;
 
@@ -1592,6 +1614,55 @@
  return result;
  }
 
+ private static final void loadBossEvent()
+ {
+ final ExProperties bossEvent = initProperties(BOSS_EVENT_INSTANCED);
+ BOSS_EVENT_BY_TIME_OF_DAY = bossEvent.getProperty("EventTime", "20:00").split(",");
+ for (String bossList : bossEvent.getProperty("BossList", "29046;29029").split(";"))
+ {
+ BOSS_EVENT_ID.add(Integer.parseInt(bossList));
+ }
+ String[] loc = bossEvent.getProperty("EventLocation", "174229,-88032,-5116").split(",");
+ for (String locationsList : bossEvent.getProperty("LocationsList", "10468,-24569,-3645;174229,-88032,-5116").split(";"))
+ {
+ String[] coords = locationsList.split(",");
+ int x = Integer.parseInt(coords[0]);
+ int y = Integer.parseInt(coords[1]);
+ int z = Integer.parseInt(coords[2]);
+ BOSS_EVENT_LOCATION.add(new Location(x, y, z));
+ }
+
+ BOSS_EVENT_MIN_PLAYERS = bossEvent.getProperty("MinPlayers", 1);
+ BOSS_EVENT_MIN_DAMAGE_TO_OBTAIN_REWARD = bossEvent.getProperty("MinDamage", 2000);
+ BOSS_EVENT_REGISTRATION_TIME = bossEvent.getProperty("RegistrationTime", 120);
+ BOSS_EVENT_REWARD_ID = bossEvent.getProperty("RewardId", 3470);
+ BOSS_EVENT_REWARD_COUNT = bossEvent.getProperty("RewardCount", 10);
+ BOSS_EVENT_TIME_TO_WAIT = bossEvent.getProperty("WaitTime", 30);
+ BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS = bossEvent.getProperty("TeleportTime", 15);
+ BOSS_EVENT_REWARD_LAST_ATTACKER = bossEvent.getProperty("RewardLastAttacker", true);
+ BOSS_EVENT_REWARD_MAIN_DAMAGE_DEALER = bossEvent.getProperty("RewardMainDamageDealer", true);
+ for (String rewards : bossEvent.getProperty("GeneralRewards", "57,100000;3470,10").split(";"))
+ {
+ String[] reward = rewards.split(",");
+ BOSS_EVENT_GENERAL_REWARDS.put(Integer.parseInt(reward[0]), Integer.parseInt(reward[1]));
+ }
+ for (String rewards : bossEvent.getProperty("MainDamageDealerRewards", "57,100000;3470,10").split(";"))
+ {
+ String[] reward = rewards.split(",");
+ BOSS_EVENT_MAIN_DAMAGE_DEALER_REWARDS.put(Integer.parseInt(reward[0]), Integer.parseInt(reward[1]));
+ }
+ for (String rewards : bossEvent.getProperty("LastAttackerRewards", "57,100000;3470,10").split(";"))
+ {
+ String[] reward = rewards.split(",");
+ BOSS_EVENT_LAST_ATTACKER_REWARDS.put(Integer.parseInt(reward[0]), Integer.parseInt(reward[1]));
+ }
+ BOSS_EVENT_REGISTRATION_NPC_ID = bossEvent.getProperty("RegisterNpcID", 10003);
+ BOSS_EVENT_TIME_TO_DESPAWN_BOSS = bossEvent.getProperty("TimeToDespawnBoss", 300);
+ String[] regLoc = bossEvent.getProperty("RegisterNpcLocation", "82727,148605,-3471").split(",");
+ BOSS_EVENT_NPC_REGISTER_LOC = new Location(Integer.parseInt(regLoc[0]), Integer.parseInt(regLoc[1]), Integer.parseInt(regLoc[2]));
+ BOSS_EVENT_TIME_ON_SCREEN = bossEvent.getProperty("EventTimeOnScreen", true);
+ }
+
  private static final void loadServerMods()
  {
  final ExProperties mods = initProperties(SERVER_MODS);
@@ -4111,7 +4182,7 @@
  public static final void loadGameServer()
  {
 
-
+ loadBossEvent();
  loadServerMods();
  loadPremium();
  initGS();
diff --git /java/net/sf/l2j/gameserver/GameServer.java /java/net/sf/l2j/gameserver/GameServer.java
index 2e8021b..4565359 100644
--- /java/net/sf/l2j/gameserver/GameServer.java
+++ /java/net/sf/l2j/gameserver/GameServer.java
@@ -18,6 +18,7 @@
 import dev.SuperLeague.SuperLeagueManager;
 import dev.SuperLeague.elo.EloData;
 import dev.VoteSystem.VoteSystemGenerator;
+import dev.bossInstancedEvent.BossEvent;
 import dev.comboBox.data.xml.ComboBoxData;
 import dev.dungeon.DungeonManager;
 import dev.instance.InstanceManager;
@@ -436,7 +437,7 @@
  * SuperLeague
  * ------------------------------------------------------------------
  */
-
+ BossEvent.getInstance();
  ClanRankingManager.getInstance();
  VoteSystemGenerator.getInstance().deleteExpiredVars();
  if (Config.CKM_ENABLED) CharacterKillingManager.getInstance().init();
diff --git /java/net/sf/l2j/gameserver/model/actor/Creature.java /java/net/sf/l2j/gameserver/model/actor/Creature.java
index 88217ab..976ff20 100644
--- /java/net/sf/l2j/gameserver/model/actor/Creature.java
+++ /java/net/sf/l2j/gameserver/model/actor/Creature.java
@@ -9,6 +9,8 @@
 import java.util.concurrent.Future;
 import java.util.logging.Level;
 
+import dev.bossInstancedEvent.BossEvent;
+import dev.bossInstancedEvent.BossEvent.EventState;
 import net.sf.l2j.Config;
 import net.sf.l2j.commons.concurrent.ThreadPool;
 import net.sf.l2j.commons.math.MathUtil;
@@ -56,6 +58,7 @@
 import net.sf.l2j.gameserver.model.location.SpawnLocation;
 import net.sf.l2j.gameserver.model.zone.ZoneId;
 import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.network.clientpackets.Say2;
 import net.sf.l2j.gameserver.network.serverpackets.AbstractNpcInfo;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.Attack;
@@ -1655,6 +1658,33 @@
  // }
  //
 
+ if (BossEvent.getInstance().getState() == EventState.FIGHTING)
+ {
+ if (BossEvent.getInstance().bossSpawn.getNpc() == this)
+ {
+ BossEvent.getInstance().finishEvent();
+ BossEvent.getInstance().bossKilled = true;
+ if (killer instanceof Player)
+ {
+ Player lastAttacker = killer.getActingPlayer();
+ BossEvent.getInstance().setLastAttacker(lastAttacker);
+ _log.info("Boss Event Finished. Last Attacker : " + lastAttacker.getName());
+ _log.info("Players rewarded: " + BossEvent.getInstance().eventPlayers.size());
+ if (Config.BOSS_EVENT_REWARD_LAST_ATTACKER)
+ {
+
+ if (lastAttacker.getBossEventDamage() > Config.BOSS_EVENT_MIN_DAMAGE_TO_OBTAIN_REWARD)
+ {
+ BossEvent.getInstance().reward(lastAttacker, Config.BOSS_EVENT_LAST_ATTACKER_REWARDS);
+ lastAttacker.sendChatMessage(0, Say2.CRITICAL_ANNOUNCE, "[Boss Event]", "Congratulations, you was the last attacker! So you will receive wonderful rewards.");
+
+ }
+
+ }
+ }
+
+ }
+ }
  if (Config.BOTS_PREVENTION) BotsPreventionManager.getInstance().updatecounter(killer, this);
 
  // Send the Server->Client packet StatusUpdate with current HP and MP to all
diff --git /java/net/sf/l2j/gameserver/model/actor/instance/BossEventNpc.java /java/net/sf/l2j/gameserver/model/actor/instance/BossEventNpc.java
new file mode 100644
index 0000000..6f6d7d5
--- /dev/null
+++ /java/net/sf/l2j/gameserver/model/actor/instance/BossEventNpc.java
@@ -0,0 +1,103 @@
+package net.sf.l2j.gameserver.model.actor.instance;
+
+
+import net.sf.l2j.commons.random.Rnd;
+
+import net.sf.l2j.gameserver.model.actor.Npc;
+import net.sf.l2j.gameserver.model.actor.ai.CtrlIntention;
+import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
+import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
+import net.sf.l2j.gameserver.network.serverpackets.MoveToPawn;
+import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
+import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
+import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
+
+import dev.bossInstancedEvent.BossEvent;
+import dev.bossInstancedEvent.BossEvent.EventState;
+
+/**
+ * @author Zaun
+ */
+public class BossEventNpc extends Folk
+{
+ /**
+ * @param objectId
+ * @param template
+ */
+ public BossEventNpc(int objectId, NpcTemplate template)
+ {
+ super(objectId, template);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public void onAction(Player player)
+ {
+ if (this != player.getTarget())
+ {
+ player.setTarget(this);
+ player.sendPacket(new MyTargetSelected(getObjectId(), 0));
+ player.sendPacket(new ValidateLocation(this));
+ }
+ else
+ {
+ if (!canInteract(player))
+ player.getAI().setIntention(CtrlIntention.INTERACT, this);
+ else
+ {
+ // Rotate the player to face the instance
+ player.sendPacket(new MoveToPawn(player, this, Npc.INTERACTION_DISTANCE));
+
+ if (hasRandomAnimation())
+ onRandomAnimation(Rnd.get(8));
+
+ showMainWindow(player);
+
+ // Send ActionFailed to the player in order to avoid he stucks
+ player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ }
+ }
+
+ private void showMainWindow(Player player)
+ {
+
+ NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
+ html.setFile("data/html/mods/BossEvent.htm");
+ html.replace("%objectId%", String.valueOf(getObjectId()));
+ html.replace("%npcname%", getName());
+ html.replace("%regCount%", String.valueOf(BossEvent.getInstance().eventPlayers.size()));
+ player.sendPacket(html);
+ }
+
+ @Override
+ public void onBypassFeedback(Player activeChar, String command)
+ {
+
+ super.onBypassFeedback(activeChar, command);
+ if (command.startsWith("register"))
+ {
+ if (BossEvent.getInstance().getState() != EventState.REGISTRATION)
+ {
+ activeChar.sendMessage("Boss Event is not running!");
+ return;
+ }
+ if (!BossEvent.getInstance().isRegistered(activeChar))
+ {
+ if (BossEvent.getInstance().addPlayer(activeChar))
+ {
+ activeChar.sendMessage("You have been successfully registered in Boss Event!");
+ }
+
+ }
+ else
+ {
+ if (BossEvent.getInstance().removePlayer(activeChar))
+ {
+ activeChar.sendMessage("You have been successfully removed of Boss Event!");
+ }
+ }
+ }
+ }
+
+}
diff --git /java/net/sf/l2j/gameserver/model/actor/Player.java /java/net/sf/l2j/gameserver/model/actor/Player.java
index bc0c0d5..8ff7dc8 100644
--- /java/net/sf/l2j/gameserver/model/actor/Player.java
+++ /java/net/sf/l2j/gameserver/model/actor/Player.java
@@ -33,6 +33,8 @@
 import dev.VoteSystem.VoteSystemGenerator;
 import dev.auction.pvpCycleRanking.PvPCycleRankingManager;
 import dev.autofarm.AutofarmManager;
+import dev.bossInstancedEvent.BossEvent;
+import dev.bossInstancedEvent.BossEvent.EventState;
 import dev.dungeon.Dungeon;
 import dev.instance.Instance;
 import dev.instance.InstanceManager;
@@ -10694,6 +10696,13 @@
  addSuperLeagueFightDamage(damage);
 
  }
+ if (BossEvent.getInstance().getState() == EventState.FIGHTING && BossEvent.getInstance().eventPlayers.contains(this))
+ {
+ if (target.getObjectId() == BossEvent.getInstance().objectId)
+ {
+ bossEventDamage += damage;
+ }
+ }
 
  }
 
@@ -13281,8 +13290,26 @@
  this.playerPvps = playerPvps;
  }
 
+ /**
+ * @return the bossEventDamage
+ */
+ public int getBossEventDamage()
+ {
+ return bossEventDamage;
+ }
+
+ /**
+ * @param bossEventDamage the bossEventDamage to set
+ */
+ public void setBossEventDamage(int bossEventDamage)
+ {
+ this.bossEventDamage = bossEventDamage;
+ }
+
  private int playerPvps;
 
+ private int bossEventDamage = 0;
+
  private Location _enterWorldLocation;
 
  public Location getEnterWorldLocation()