Noticias:

Debes de estar registrado para poder ver el contenido indicado. Registrate o Conectate

Menú Principal

Evento Deathmatch (by Intrepid)

Iniciado por Swarlog, Ago 06, 2022, 02:23 AM

Tema anterior - Siguiente tema

Swarlog

/*
 * 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 <http://www.gnu.org/licenses/>.
 */
package com.azaria.events;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;

import javolution.util.FastMap;

import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2CubicInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.util.Broadcast;
import com.l2jserver.tools.random.Rnd;

/**
 * @author Intrepid
 *
 */
public class DeathMatch
{
// declare logger
private static final Logger _log = Logger.getLogger(DeathMatch.class.getName());

// event name
private static final String _eventName = "DeathMatch";

// event finished and not started yet
private static final int STATUS_NOT_IN_PROGRESS = 0;

// event registration allowed
private static final int STATUS_REGISTRATION = 1;

// event registration ended and combat not started yet
private static final int STATUS_PREPARATION = 2;

// event players teleported to the event and combat starter
private static final int STATUS_COMBAT = 3;

// event combat ended wait setup for next event
private static final int STATUS_NEXT_EVENT = 4;

private static final String REMOVE_DISCONNECTED = "UPDATE characters SET heading=?,x=?,y=?,z=? WHERE charId=?";

/**
* Initialize new/Returns the one and only instance<br><br>
*
* @return DeathMatch<br>
*/
public static DeathMatch getInstance()
{
return SingletonHolder._instance;
}

private static class SingletonHolder
{
protected static final DeathMatch _instance = new DeathMatch();
}

private final ThreadPoolManager tpm;

private final autoEventTask task;
private final reviveTask taskDuring;
private ScheduledFuture<?> reviver;
private ScheduledFuture<?> event;
private int announced;

private static FastMap<Integer,L2PcInstance> players;

private volatile int status;
private volatile boolean active;

/**
* private constructor
*/
private DeathMatch()
{
tpm = ThreadPoolManager.getInstance();
status = STATUS_NOT_IN_PROGRESS;
announced = 0;
players = new FastMap<Integer,L2PcInstance>(Config.DM_MAX_PARTICIPANT);
task = new autoEventTask();
taskDuring = new reviveTask();
reviver = null;
active = Config.DM_ALLOWED;
if (active)
{
tpm.scheduleGeneral(task, Config.DM_DELAY_INITIAL_REGISTRATION);
_log.info("DeathMatch: Initialized event enabled.");
}
else
_log.info("DeathMatch: Initialized but not enabled.");
}

private class autoEventTask implements Runnable
{
@Override
public void run()
{
switch (status)
{
case STATUS_NOT_IN_PROGRESS:
if (Config.DM_ALLOWED)
registrationStart();
else
active = false;
break;
case STATUS_REGISTRATION:
if (announced < (Config.DM_REGISTRATION_ANNOUNCEMENT_COUNT + 2))
registrationAnnounce();
else
registrationEnd();
break;
case STATUS_PREPARATION:
startEvent();
break;
case STATUS_COMBAT:
endEvent();
break;
case STATUS_NEXT_EVENT:
status = STATUS_NOT_IN_PROGRESS;
tpm.scheduleGeneral(task, Config.DM_DELAY_BETWEEN_EVENTS);
break;
default:
_log.severe("Incorrect status set in Automated " + _eventName + ", terminating the event!");
}
}
}

private class reviveTask implements Runnable
{
@Override
public void run()
{
L2PcInstance player;
for (L2PcInstance p : players.values())
{
player = p.getActingPlayer();
if (player != null && player.isDead())
revive(player);
}
}
}


public void registerPlayer(L2PcInstance player)
{
if (!active)
return;

if (status != STATUS_REGISTRATION || players.size() >= Config.DM_MAX_PARTICIPANT)
player.sendPacket(SystemMessageId.REGISTRATION_PERIOD_OVER);
else if(!players.containsValue(player))
{
if (!canJoin(player))
{
player.sendMessage("You can't join to the" + _eventName + " because you dont meet with the requirements!");
return;
}
players.put(player.getObjectId(), player);
player.sendMessage("You are successfully registered to: " + _eventName);
if (Config.DM_REG_CANCEL)
player.sendMessage("If you decide to cancel your registration use .leavedm!");
}
else
player.sendMessage("You are alredy registered");
}

public void cancelRegistration(L2PcInstance player)
{
if (!active)
return;

if (status != STATUS_REGISTRATION)
player.sendPacket(SystemMessageId.REGISTRATION_PERIOD_OVER);
else if (players.containsValue(player))
{
players.remove(player);
player.sendMessage("You successfully cancelled your registration in " + _eventName);
}
else
player.sendMessage("You are not a participant in" + _eventName);
}

public void registrationStart()
{
status = STATUS_REGISTRATION;
Announcements.getInstance().announceToAll(new SystemMessage(SystemMessageId.REGISTRATION_PERIOD));
SystemMessage time = new SystemMessage(SystemMessageId.REGISTRATION_TIME_S1_S2_S3);
long timeLeft = Config.DM_REGISTRATION_LENGHT/ 1000;
time.addNumber((int) (timeLeft / 3600));
time.addNumber((int) (timeLeft % 3600 / 60));
time.addNumber((int) (timeLeft % 3600 % 60));
Broadcast.toAllOnlinePlayers(time);
Announcements.getInstance().announceToAll("To join the " + _eventName + " you must type .joindm");
tpm.scheduleGeneral(task, Config.DM_REGISTRATION_LENGHT / (Config.DM_REGISTRATION_ANNOUNCEMENT_COUNT + 2));
}

public void registrationAnnounce()
{
SystemMessage time = new SystemMessage(SystemMessageId.REGISTRATION_TIME_S1_S2_S3);
long timeLeft = Config.DM_REGISTRATION_LENGHT;
long elapsed = timeLeft / (Config.DM_REGISTRATION_ANNOUNCEMENT_COUNT + 2) * announced;
timeLeft -= elapsed;
timeLeft /= 1000;
time.addNumber((int) (timeLeft / 3600));
time.addNumber((int) (timeLeft % 3600 / 60));
time.addNumber((int) (timeLeft % 3600 % 60));
Broadcast.toAllOnlinePlayers(time);
Announcements.getInstance().announceToAll("To join the " + _eventName + " you must type .joindm");
announced++;
tpm.scheduleGeneral(task, Config.DM_REGISTRATION_LENGHT / (Config.DM_REGISTRATION_ANNOUNCEMENT_COUNT + 2));
}

public void registrationEnd()
{
announced = 0;
status = STATUS_PREPARATION;

for (L2PcInstance p : players.values())
{
if (p == null)
continue;
if (!canJoin(p))
{
p.sendMessage("You can't join to the" + _eventName + " because you dont meet with the requirements!");
players.remove(p);
}
}

if (players.size() <= Config.DM_MIN_PLAYER)
{
Announcements.getInstance().announceToAll(_eventName + "aborted not enough players!");
players.clear();
status = STATUS_NOT_IN_PROGRESS;
tpm.scheduleGeneral(task, Config.DM_DELAY_BETWEEN_EVENTS);
return;
}

SystemMessage time = new SystemMessage(SystemMessageId.BATTLE_BEGINS_S1_S2_S3);
long timeLeft = Config.DM_PREPARATION_LENGHT / 1000;
time.addNumber((int) (timeLeft / 3600));
time.addNumber((int) (timeLeft % 3600 / 60));
time.addNumber((int) (timeLeft % 3600 % 60));

for (L2PcInstance p : players.values())
{
if (p == null)
continue;

p.setIsParalyzed(true);
p.sendPacket(time);
checkEquipment(p);
if (Config.DM_CANCEL_PARTY_ONSTART && p.getParty() != null)
p.getParty().removePartyMember(p);
if (Config.DM_CANCEL_BUFF_ONSTART)
p.stopAllEffects();
if (Config.DM_CANCEL_CUBIC_ONSTART && !p.getCubics().isEmpty())
{
for (L2CubicInstance cubic : p.getCubics().values())
{
cubic.stopAction();
cubic.cancelDisappear();
}
p.getCubics().clear();
}
if (Config.DM_UNSUMMON_PET_ONSTART && p.getPet() != null)
p.getPet().unSummon(p);
if (Config.DM_CANCEL_TRANSFORM_ONSTART && p.isTransformed())
p.untransform();
if (p.isDead())
p.setIsPendingRevive(true);

int spawn = Rnd.get(2);
if (spawn == 0)
p.teleToLocation(Config.DM_LOCX1,Config.DM_LOCY1,Config.DM_LOCZ1);
if (spawn == 1)
p.teleToLocation(Config.DM_LOCX2,Config.DM_LOCY2,Config.DM_LOCZ2);

if (Config.DM_RECOVER_ONSTART && p.getCurrentCp() != p.getMaxCp() || p.getCurrentHp() != p.getMaxHp() || p.getCurrentMp() != p.getMaxMp())
{
p.getStatus().setCurrentCp(p.getMaxCp());
p.getStatus().setCurrentHpMp(p.getMaxHp(), p.getMaxMp());
}
}
tpm.scheduleGeneral(task, Config.DM_PREPARATION_LENGHT);
}

public void startEvent()
{
status = STATUS_COMBAT;
SystemMessage time = new SystemMessage(SystemMessageId.BATTLE_ENDS_S1_S2_S3);
long timeLeft = Config.DM_EVENT_LENGHT / 1000;
time.addNumber((int) (timeLeft / 3600));
time.addNumber((int) (timeLeft % 3600 / 60));
time.addNumber((int) (timeLeft % 3600 % 60));
L2PcInstance player;
for (L2PcInstance p : players.values())
{
player = p.getActingPlayer();
if (player == null)
continue;
player.setIsParalyzed(false);
player.sendPacket(time);
}
reviver = tpm.scheduleGeneralAtFixedRate(taskDuring, Config.DM_REVIVE_DELAY, Config.DM_REVIVE_DELAY);
event = tpm.scheduleGeneral(task, Config.DM_EVENT_LENGHT);
}

public void endEvent()
{
if (status != STATUS_COMBAT)
return;
status = STATUS_NEXT_EVENT;
reviver.cancel(true);
if (!event.cancel(false))
return;

Announcements.getInstance().announceToAll(_eventName + " is finished!");

L2PcInstance player;
for (L2PcInstance p : players.values())
{
player = p.getActingPlayer();
if (player == null)
{
removeDisconnected(p.getObjectId(), p);
continue;
}
removeFromEvent(player);
}
players.clear();
tpm.scheduleGeneral(task, Config.DM_ENDING_LENGHT);
}

private void revive(L2PcInstance player)
{
player.setIsPendingRevive(true);
int teleTo = Rnd.get(1);
if (teleTo == 1)
player.teleToLocation(Config.DM_RANDOM_RESPAWN1_X, Config.DM_RANDOM_RESPAWN1_Y, Config.DM_RANDOM_RESPAWN1_Z);
if (teleTo == 2)
player.teleToLocation(Config.DM_RANDOM_RESPAWN2_X, Config.DM_RANDOM_RESPAWN2_Y, Config.DM_RANDOM_RESPAWN2_Z);
}

private boolean canJoin(L2PcInstance player)
{
// level restriction
boolean can = player.getLevel() <= Config.DM_MAX_LVL;
can &= player.getLevel() >= Config.DM_MIN_LVL;
// hero restriction
if (!Config.DM_HERO_JOIN)
can &= !player.isHero();
// cw owner restriction
if (Config.DM_CWOWNER_JOIN)
can &= !player.isCursedWeaponEquipped();
return can;
}

private final void checkEquipment(L2PcInstance player)
{
L2ItemInstance item;
for (int i = 0; i < 25; i++)
{
synchronized (player.getInventory())
{
item = player.getInventory().getPaperdollItem(i);
if (item != null && !canUse(item.getItemId()))
player.useEquippableItem(item, true);
}
}
}

public static final boolean canUse(int itemId)
{
for (int id : Config.DM_DISALLOWED_ITEMS)
if (itemId == id)
return false;
return true;
}

private void removeFromEvent(L2PcInstance player)
{
if (!player.isDead())
{
player.getStatus().setCurrentCp(player.getMaxCp());
player.getStatus().setCurrentHpMp(player.getMaxHp(), player.getMaxMp());
}
else
player.setIsPendingRevive(true);
player.teleToLocation(Config.DM_TELE_BACK_X, Config.DM_TELE_BACK_Y, Config.DM_TELE_BACK_Z);
}

public final void removeDisconnected(int objID,L2PcInstance player)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(REMOVE_DISCONNECTED);
ps.setInt(1, player.getHeading());
ps.setInt(2, Config.DM_TELE_BACK_X);
ps.setInt(3, Config.DM_TELE_BACK_Y);
ps.setInt(4, Config.DM_TELE_BACK_Z);
ps.setInt(5, objID);
ps.executeUpdate();
ps.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING,"Could not remove a disconnected DM player!", e);
}
finally
{
L2DatabaseFactory.close(con);
}
}

public final void addDisconnected(L2PcInstance participant)
{
switch (status)
{
case STATUS_REGISTRATION:
if (Config.DM_REGISTER_AFTER_RELOG && !players.containsValue(participant))
registerPlayer(participant);
break;
case STATUS_COMBAT:
L2PcInstance p = players.get(participant.getObjectId());
if (p == null)
break;
players.put(participant.getObjectId(), participant);
checkEquipment(participant);
int spawn = Rnd.get(2);
if (spawn == 0)
participant.teleToLocation(Config.DM_LOCX1,Config.DM_LOCY1,Config.DM_LOCZ1);
if (spawn == 1)
participant.teleToLocation(Config.DM_LOCX2,Config.DM_LOCY2,Config.DM_LOCZ2);
break;
}
}

public final void onKill(L2Character killer,L2PcInstance killed)
{
if (status != STATUS_COMBAT)
return;

((L2PcInstance) killer).addItem("DEATHMACH", Config.DM_REWARD_ID, Config.DM_REWARD_COUNT, killer, false);
killer.sendMessage(killer + "killed: " + killed);
killed.sendMessage(killed + "killed by: " + killer);
}


public static final boolean isInProgress()
{
switch (getInstance().status)
{
case STATUS_PREPARATION:
case STATUS_COMBAT:
return true;
default:
return false;
}
}

public static final boolean isPlaying(L2PcInstance player)
{
return isInProgress() && isMember(player);
}

public static final boolean isMember(L2PcInstance player)
{
if (player == null)
return false;

switch (getInstance().status)
{
case STATUS_NOT_IN_PROGRESS:
return false;
case STATUS_REGISTRATION:
return players.containsValue(player);
case STATUS_PREPARATION:
return players.containsValue(player) || isMember(player.getObjectId());
case STATUS_COMBAT:
case STATUS_NEXT_EVENT:
return isMember(player.getObjectId());
default:
return false;
}
}

private final static boolean isMember(int oID)
{
return players.get(oID) != null;
}
}