Noticias:

No tienes permiso para ver los enlaces. Para poder verlos Registrate o Conectate.

Menú Principal

Evento Boss - Acis 398

Iniciado por Jerry, Ago 02, 2025, 08:13 PM

Tema anterior - Siguiente tema

Jerry

diff --git a/config/CustomMods/Events/BossEvent.ini b/config/CustomMods/Events/BossEvent.ini
new file mode 100644
index 0000000..cc4a763
--- /dev/null
+++ b/config/CustomMods/Events/BossEvent.ini
@@ -0,0 +1,42 @@
+# ================================================
+# 		 BossEvent			 #
+# ================================================
+#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 a/java/net/sf/l2j/Config.java b/java/net/sf/l2j/Config.java
index 9a2f099..c1b9fa7 100644
--- a/java/net/sf/l2j/Config.java
+++ b/java/net/sf/l2j/Config.java
@@ -19,6 +19,7 @@
 import net.sf.l2j.gameserver.data.manager.RewardHolder;
 import net.sf.l2j.gameserver.enums.GeoType;
 import net.sf.l2j.gameserver.model.holder.IntIntHolder;
+import net.sf.l2j.gameserver.model.location.Location;
 
 /**
  * This class contains global server configuration.<br>
@@ -49,6 +50,7 @@
 	public static final String PCBANGEVENT = "./config/CustomMods/Events/PcBangEvent.ini";
 	public static final String PARTYFARMEVENT = "./config/CustomMods/Events/PartyFarmEvent.ini";
 	public static final String TVTEVENT = "./config/CustomMods/Events/TvT.ini";
+	public static final String BOSS_EVENT_INSTANCED = "./config/CustomMods/Events/BossEvent.ini";
 	// --------------------------------------------------
 	// Clans settings
 	// --------------------------------------------------
@@ -391,7 +393,26 @@
 	public static boolean SHOW_NPC_LVL;
 	public static boolean SHOW_NPC_CREST;
 	public static boolean SHOW_SUMMON_CREST;
-
+	/** 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;
 	/** Wyvern Manager */
 	public static boolean WYVERN_ALLOW_UPGRADER;
 	public static int WYVERN_REQUIRED_LEVEL;
@@ -1372,6 +1393,55 @@
 		VIP_DAYS_ID3 = Integer.parseInt(Donate.getProperty("VipCoinDays3", "3"));
 	}
 	
+	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));
+		}
+		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 = Integer.parseInt(bossEvent.getProperty("MinPlayers", "1"));
+		BOSS_EVENT_MIN_DAMAGE_TO_OBTAIN_REWARD = Integer.parseInt(bossEvent.getProperty("MinDamage", "2000"));
+		BOSS_EVENT_REGISTRATION_TIME = Integer.parseInt(bossEvent.getProperty("RegistrationTime", "120"));
+		BOSS_EVENT_REWARD_ID = Integer.parseInt(bossEvent.getProperty("RewardId", "3470"));
+		BOSS_EVENT_REWARD_COUNT = Integer.parseInt(bossEvent.getProperty("RewardCount", "10"));
+		BOSS_EVENT_TIME_TO_WAIT = Integer.parseInt(bossEvent.getProperty("WaitTime", "30"));
+		BOSS_EVENT_TIME_TO_TELEPORT_PLAYERS = Integer.parseInt(bossEvent.getProperty("TeleportTime", "15"));
+		BOSS_EVENT_REWARD_LAST_ATTACKER = Boolean.parseBoolean(bossEvent.getProperty("RewardLastAttacker", "true"));
+		BOSS_EVENT_REWARD_MAIN_DAMAGE_DEALER = Boolean.parseBoolean(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 = Integer.parseInt(bossEvent.getProperty("RegisterNpcID", "10003"));
+		BOSS_EVENT_TIME_TO_DESPAWN_BOSS = Integer.parseInt(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 = Boolean.parseBoolean(bossEvent.getProperty("EventTimeOnScreen", "true"));
+	}
+	
 	private static final void loadFlag()
 	{
 		final ExProperties flagzone = initProperties(FLAGZONEMOD);
@@ -2015,7 +2085,7 @@
 		loadTvTConfig();
 		// siege settings
 		loadSieges();
-		
+		loadBossEvent();
 		// OffShop settings
 		loadOff();
 		ProtectionMods();
diff --git a/java/net/sf/l2j/gameserver/GameServer.java b/java/net/sf/l2j/gameserver/GameServer.java
index 000e3d6..3cfc5b7 100644
--- a/java/net/sf/l2j/gameserver/GameServer.java
+++ b/java/net/sf/l2j/gameserver/GameServer.java
@@ -21,6 +21,7 @@
 import net.sf.l2j.gameserver.data.cache.CrestCache;
 import net.sf.l2j.gameserver.data.cache.HtmCache;
 import net.sf.l2j.gameserver.data.manager.BoatManager;
+import net.sf.l2j.gameserver.data.manager.BossEvent;
 import net.sf.l2j.gameserver.data.manager.BufferManager;
 import net.sf.l2j.gameserver.data.manager.BuyListManager;
 import net.sf.l2j.gameserver.data.manager.CastleManager;
@@ -271,6 +272,7 @@
 		StringUtil.printSection("Seven Signs");
 		SevenSignsManager.getInstance().spawnSevenSignsNPC();
 		FestivalOfDarknessManager.getInstance();
+		BossEvent.getInstance();
 		
 		StringUtil.printSection("Manor Manager");
 		CastleManorManager.getInstance();
diff --git a/java/net/sf/l2j/gameserver/data/manager/BossEvent.java b/java/net/sf/l2j/gameserver/data/manager/BossEvent.java
new file mode 100644
index 0000000..949bc78
--- /dev/null
+++ b/java/net/sf/l2j/gameserver/data/manager/BossEvent.java
@@ -0,0 +1,637 @@
+package net.sf.l2j.gameserver.data.manager;
+
+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.commons.pool.ThreadPool;
+import net.sf.l2j.commons.random.Rnd;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.data.sql.SpawnTable;
+import net.sf.l2j.gameserver.data.xml.NpcData;
+import net.sf.l2j.gameserver.enums.SayType;
+import net.sf.l2j.gameserver.handler.VoicedCommandHandler;
+import net.sf.l2j.gameserver.handler.voicedcommandhandlers.BossEventCMD;
+import net.sf.l2j.gameserver.model.World;
+import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
+import net.sf.l2j.gameserver.model.location.Location;
+import net.sf.l2j.gameserver.model.spawn.Spawn;
+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 Spawn 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<>();
+	@SuppressWarnings("unused")
+	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 Spawn eventNpc = null;
+	public long startTime;
+
+	public enum EventState
+	{
+		REGISTRATION, TELEPORTING, WAITING, FIGHTING, FINISHING, INACTIVE
+	}
+
+	public BossEvent()
+	{
+		VoicedCommandHandler.getInstance().registerVoicedCommandHandler(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));
+		}
+		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);
+
+						}
+					}, 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().sendMessage("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(Spawn spawn)
+	{
+		if (spawn != null)
+		{
+			spawn.getNpc().deleteMe();
+			spawn.setRespawnState(false);
+			SpawnTable.getInstance().deleteSpawn(spawn, true);
+		}
+
+	}
+
+	class DespawnBossTask implements Runnable
+	{
+		Spawn spawn;
+
+		public DespawnBossTask(Spawn 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 (NpcData.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 = NpcData.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 = NpcData.getInstance().getTemplate(npcId);
+		try
+		{
+			bossSpawn = new Spawn(tmpl);
+
+			bossSpawn.setLoc(x, y, z, Rnd.get(65535));
+			bossSpawn.setRespawnDelay(1);
+
+			SpawnTable.getInstance().addSpawn(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 Spawn spawnEventNpc(int x, int y, int z)
+	{
+		Spawn spawn = null;
+		NpcTemplate tmpl = NpcData.getInstance().getTemplate(Config.BOSS_EVENT_REGISTRATION_NPC_ID);
+		try
+		{
+			spawn = new Spawn(tmpl);
+
+			spawn.setLoc(x, y, z, Rnd.get(65535));
+			spawn.setRespawnDelay(1);
+
+			SpawnTable.getInstance().addSpawn(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, SayType.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, SayType.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, SayType.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;
+				}
+
+			}
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/data/manager/NextBossEvent.java b/java/net/sf/l2j/gameserver/data/manager/NextBossEvent.java
new file mode 100644
index 0000000..b3ef180
--- /dev/null
+++ b/java/net/sf/l2j/gameserver/data/manager/NextBossEvent.java
@@ -0,0 +1,96 @@
+package net.sf.l2j.gameserver.data.manager;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Logger;
+
+import net.sf.l2j.commons.pool.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();
+		}
+	}
+}
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java b/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java
index 55c8191..66cf2a3 100644
--- a/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java
+++ b/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java
@@ -26,6 +26,7 @@
 
 import net.sf.l2j.Config;
 import net.sf.l2j.gameserver.GameServer;
+import net.sf.l2j.gameserver.handler.voicedcommandhandlers.BossEventCMD;
 import net.sf.l2j.gameserver.handler.voicedcommandhandlers.GainXpSp;
 import net.sf.l2j.gameserver.handler.voicedcommandhandlers.Shiff_Mod;
 import net.sf.l2j.gameserver.handler.voicedcommandhandlers.TvTEventCommand;
@@ -60,6 +61,7 @@
 	private VoicedCommandHandler()
 	{
 		_datatable = new HashMap<>();
+		registerVoicedCommandHandler(new BossEventCMD());
 		registerVoicedCommandHandler(new TvTEventCommand());
 		registerVoicedCommandHandler(new Shiff_Mod());
 		if(Config.ENABLE_COMMAND_RAID)
diff --git a/java/net/sf/l2j/gameserver/handler/voicedcommandhandlers/BossEventCMD.java b/java/net/sf/l2j/gameserver/handler/voicedcommandhandlers/BossEventCMD.java
new file mode 100644
index 0000000..5959be2
--- /dev/null
+++ b/java/net/sf/l2j/gameserver/handler/voicedcommandhandlers/BossEventCMD.java
@@ -0,0 +1,49 @@
+package net.sf.l2j.gameserver.handler.voicedcommandhandlers;
+
+import net.sf.l2j.gameserver.data.manager.BossEvent;
+import net.sf.l2j.gameserver.data.manager.BossEvent.EventState;
+import net.sf.l2j.gameserver.handler.IVoicedCommandHandler;
+import net.sf.l2j.gameserver.model.actor.Player;
+
+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"
+			};
+	}
+	
+}
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/model/actor/Creature.java b/java/net/sf/l2j/gameserver/model/actor/Creature.java
index c669703..bf710ee 100644
--- a/java/net/sf/l2j/gameserver/model/actor/Creature.java
+++ b/java/net/sf/l2j/gameserver/model/actor/Creature.java
@@ -10,12 +10,15 @@
 import net.sf.l2j.commons.random.Rnd;
 
 import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.data.manager.BossEvent;
+import net.sf.l2j.gameserver.data.manager.BossEvent.EventState;
 import net.sf.l2j.gameserver.data.manager.BotsPreventionManager;
 import net.sf.l2j.gameserver.data.manager.ZoneManager;
 import net.sf.l2j.gameserver.data.xml.MapRegionData;
 import net.sf.l2j.gameserver.data.xml.MapRegionData.TeleportType;
 import net.sf.l2j.gameserver.data.xml.NpcData;
 import net.sf.l2j.gameserver.enums.AiEventType;
+import net.sf.l2j.gameserver.enums.SayType;
 import net.sf.l2j.gameserver.enums.StatusType;
 import net.sf.l2j.gameserver.enums.ZoneId;
 import net.sf.l2j.gameserver.enums.actors.MoveType;
@@ -50,6 +53,7 @@
 import net.sf.l2j.gameserver.network.serverpackets.AbstractNpcInfo.NpcInfo;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.ChangeMoveType;
+import net.sf.l2j.gameserver.network.serverpackets.CreatureSay;
 import net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket;
 import net.sf.l2j.gameserver.network.serverpackets.Revive;
 import net.sf.l2j.gameserver.network.serverpackets.ServerObjectInfo;
@@ -484,6 +488,34 @@
 		stopAllEffectsExceptThoseThatLastThroughDeath();
 		
 		calculateRewards(killer);
+		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);
+					LOGGER.info("Boss Event Finished. Last Attacker : " + lastAttacker.getName());
+					LOGGER.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.sendPacket(new CreatureSay(0, SayType.CRITICAL_ANNOUNCE, "[Boss Event]", "Congratulations, you was the last attacker! So you will receive wonderful 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);
diff --git a/java/net/sf/l2j/gameserver/model/actor/Player.java b/java/net/sf/l2j/gameserver/model/actor/Player.java
index 290b545..ca38b35 100644
--- a/java/net/sf/l2j/gameserver/model/actor/Player.java
+++ b/java/net/sf/l2j/gameserver/model/actor/Player.java
@@ -33,6 +33,8 @@
 import net.sf.l2j.gameserver.communitybbs.model.Forum;
 import net.sf.l2j.gameserver.data.SkillTable;
 import net.sf.l2j.gameserver.data.SkillTable.FrequentSkill;
+import net.sf.l2j.gameserver.data.manager.BossEvent;
+import net.sf.l2j.gameserver.data.manager.BossEvent.EventState;
 import net.sf.l2j.gameserver.data.manager.CastleManager;
 import net.sf.l2j.gameserver.data.manager.CoupleManager;
 import net.sf.l2j.gameserver.data.manager.CursedWeaponManager;
@@ -6968,7 +6970,13 @@
 			sendPacket(SystemMessageId.MISSED_TARGET);
 			return;
 		}
-		
+		if (BossEvent.getInstance().getState() == EventState.FIGHTING && BossEvent.getInstance().eventPlayers.contains(this))
+		{
+			if (target.getObjectId() == BossEvent.getInstance().objectId)
+			{
+				bossEventDamage += damage;
+			}
+		}
 		// Check if hit is critical
 		if (pcrit)
 			sendPacket(SystemMessageId.CRITICAL_HIT);
@@ -6988,7 +6996,22 @@
 		if (isInOlympiadMode() && target instanceof Player && ((Player) target).isInOlympiadMode() && ((Player) target).getOlympiadGameId() == getOlympiadGameId())
 			OlympiadGameManager.getInstance().notifyCompetitorDamage(this, damage);
 	}
+	private int bossEventDamage = 0;
+	/**
+	 * @return the bossEventDamage
+	 */
+	public int getBossEventDamage()
+	{
+		return bossEventDamage;
+	}
 	
+	/**
+	 * @param bossEventDamage the bossEventDamage to set
+	 */
+	public void setBossEventDamage(int bossEventDamage)
+	{
+		this.bossEventDamage = bossEventDamage;
+	}
 	public void checkItemRestriction()
 	{
 		for (final ItemInstance item : getInventory().getPaperdollItems())
diff --git a/java/net/sf/l2j/gameserver/model/actor/instance/BossEventNpc.java b/java/net/sf/l2j/gameserver/model/actor/instance/BossEventNpc.java
new file mode 100644
index 0000000..3e7f1b8
--- /dev/null
+++ b/java/net/sf/l2j/gameserver/model/actor/instance/BossEventNpc.java
@@ -0,0 +1,61 @@
+package net.sf.l2j.gameserver.model.actor.instance;
+
+import net.sf.l2j.gameserver.data.manager.BossEvent;
+import net.sf.l2j.gameserver.data.manager.BossEvent.EventState;
+import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
+import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
+
+public class BossEventNpc extends Folk
+{
+	/**
+	 * @param objectId
+	 * @param template
+	 */
+	public BossEventNpc(int objectId, NpcTemplate template)
+	{
+		super(objectId, template);
+	}
+	
+	@Override
+	public void showChatWindow(Player player, int val)
+	{
+		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!");
+				}
+			}
+		}
+	}
+	
+}
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/model/location/Location.java b/java/net/sf/l2j/gameserver/model/location/Location.java
index 1ebbe9c..754c007 100644
--- a/java/net/sf/l2j/gameserver/model/location/Location.java
+++ b/java/net/sf/l2j/gameserver/model/location/Location.java
@@ -12,7 +12,7 @@
 {
 	public static final Location DUMMY_LOC = new Location(0, 0, 0);
 	
-	protected volatile int _z;
+	public volatile int _z;
 	
 	public Location(int x, int y, int z)
 	{
diff --git a/java/net/sf/l2j/gameserver/model/location/Point2D.java b/java/net/sf/l2j/gameserver/model/location/Point2D.java
index 9e6e470..bc1e3a5 100644
--- a/java/net/sf/l2j/gameserver/model/location/Point2D.java
+++ b/java/net/sf/l2j/gameserver/model/location/Point2D.java
@@ -7,8 +7,8 @@
  */
 public class Point2D
 {
-	protected volatile int _x;
-	protected volatile int _y;
+	public volatile int _x;
+	public volatile int _y;
 	
 	public Point2D(int x, int y)
 	{