/* 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 2, 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * http://www.gnu.org/copyleft/gpl.html */ package de.dc.l2j.gameserver.object.duel; import java.util.Calendar; import java.util.logging.Logger; import de.dc.l2j.gameserver.character.ai.CtrlIntention; import de.dc.l2j.gameserver.character.player.L2PcInstance; import de.dc.l2j.gameserver.instancemanager.EventDuelManager; import de.dc.l2j.gameserver.network.enums.SystemMessageId; import de.dc.l2j.gameserver.network.server.ActionFailed; import de.dc.l2j.gameserver.network.server.ExDuelEnd; import de.dc.l2j.gameserver.network.server.ExDuelReady; import de.dc.l2j.gameserver.network.server.ExDuelStart; import de.dc.l2j.gameserver.network.server.ExDuelUpdateUserInfo; import de.dc.l2j.gameserver.network.server.L2GameServerPacket; import de.dc.l2j.gameserver.network.server.PlaySound; import de.dc.l2j.gameserver.network.server.SystemMessage; import de.dc.l2j.gameserver.network.server.ValidateLocation; import de.dc.l2j.gameserver.object.L2Party; import de.dc.l2j.gameserver.system.ThreadPoolManager; /** * * @author Noctarius */ public abstract class L2EventDuel { protected static final Logger _log = Logger.getLogger(L2EventDuel.class.getName()); private class DuelTimeoutTask implements Runnable { L2EventDuel _duel; public DuelTimeoutTask(L2EventDuel duel) { _duel = duel; } public void run() { _duel.onDuelTimeout(); } } private class DuelStartTask implements Runnable { L2EventDuel _duel; public DuelStartTask(L2EventDuel duel) { _duel = duel; _duel.setDuelState(DuelState.Prepare); } public void run() { int waitTime = _duel.onDuelPrepare(); if (waitTime > 0) { ThreadPoolManager.getInstance().scheduleGeneral(this, waitTime); } else { broadcastPacket(new SystemMessage(SystemMessageId.LET_THE_DUEL_BEGIN)); _duel.setDuelState(DuelState.Start); _duel.onDuelStart(); } } } public enum DuelState { NoDuel, Prepare, Start, Duelling, Winner, Surrender, Draw } protected enum DuelType { Deathmatch, Training, TVT } private Integer _duelId; protected DuelType _duelType; protected DuelState _duelState; protected Calendar _duelEndTime; protected boolean _partyDuel = false; protected boolean _canSurrender = true; protected boolean _willSurrender = true; protected boolean _canDisqualify = true; protected L2PcInstance _playerA; protected L2PcInstance _playerB; protected int _eventTime = 3; public L2EventDuel(L2PcInstance playerA, L2PcInstance playerB, boolean partyDuel) { _playerA = playerA; _playerB = playerB; _partyDuel = partyDuel; _duelId = EventDuelManager.getInstance().getNextDuelId(); _duelState = DuelState.NoDuel; // Hole die eigentlichen Typewerte setWillSurrender(); setCanSurrender(); setCanDisqualify(); ThreadPoolManager.getInstance().scheduleGeneral(new DuelStartTask(this), 100); } /*------------------------------------------------------------ *| Public functions area *| *------------------------------------------------------------ */ public final Integer getDuelId() { return _duelId; } public final boolean isPartyDuel() { return _partyDuel; } public final DuelState getDuelState() { return _duelState; } public final L2PcInstance playerA() { return _playerA; } public final L2PcInstance playerB() { return _playerB; } public final void broadcastToOpponentTeam(L2PcInstance player, L2GameServerPacket packet) { if (_partyDuel) { L2PcInstance partyLeader = getPlayersPartyLeader(player); if (partyLeader == null) return; for (L2PcInstance opPlayer : getOpponent(partyLeader).getParty().getPartyMembers()) { opPlayer.sendPacket(packet); } } else getOpponent(player).sendPacket(packet); } public final int getRemainingTime() { return (int)(_duelEndTime.getTimeInMillis() - Calendar.getInstance().getTimeInMillis()); } public final void setEventTime(int time) { _eventTime = time; } public final synchronized void changePartyLeader(L2PcInstance oldLeader, L2PcInstance newLeader) { ExDuelEnd duelEnd = new ExDuelEnd(0); ActionFailed af = new ActionFailed(); oldLeader.abortCast(); oldLeader.abortAttack(); oldLeader.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); oldLeader.setTarget(null); oldLeader.sendPacket(af); oldLeader.sendPacket(duelEnd); if (oldLeader == _playerA) _playerA = newLeader; else _playerB = newLeader; } public final synchronized void removeFromDuel(L2PcInstance player) { if (isPartyDuel()) { ExDuelEnd duelEnd = new ExDuelEnd(0); ActionFailed af = new ActionFailed(); player.setIsInDuel(null); player.abortCast(); player.abortAttack(); player.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); player.setTarget(null); player.sendPacket(af); player.sendPacket(duelEnd); } else { onDuelEnd(getOpponent(player), player); } } public final L2PcInstance getOpponent(L2PcInstance player) { if (player == _playerA) return _playerB; return _playerA; } public final L2PcInstance getPlayersPartyLeader(L2PcInstance player) { if (!isPartyDuel()) return player; int partyLeaderId = player.getParty().getPartyLeaderOID(); for (L2PcInstance leader : player.getParty().getPartyMembers()) { if (leader.getObjectId() == partyLeaderId) return leader; } // Wird hoffentlich nie erreicht return null; } /*------------------------------------------------------------ *| Public event-functions area *| *------------------------------------------------------------ */ public int onDuelPrepare() { return 0; } public void onDuelStart() { if (_eventTime > -1) { _duelEndTime = Calendar.getInstance(); _duelEndTime.add(Calendar.MINUTE, _eventTime); ThreadPoolManager.getInstance().scheduleGeneral(new DuelTimeoutTask(this), _duelEndTime.getTimeInMillis()); } _duelState = DuelState.Duelling; // Teams setzen setTeams(); // Send duel Start packets ExDuelReady ready = new ExDuelReady(_partyDuel ? 1 : 0); broadcastPacket(ready); ExDuelStart start = new ExDuelStart(_partyDuel ? 1 : 0); broadcastPacket(start); PlaySound ps = new PlaySound(1, "B04_S01", 0, 0, 0, 0, 0); broadcastPacket(ps); // Zeigt die Statusanzeige des Gegners if (isPartyDuel()) { for (L2PcInstance player : _playerA.getParty().getPartyMembers()) { broadcastPacket(new ExDuelUpdateUserInfo(player)); } for (L2PcInstance player : _playerB.getParty().getPartyMembers()) { broadcastPacket(new ExDuelUpdateUserInfo(player)); } } else { _playerA.sendPacket(new ExDuelUpdateUserInfo(_playerB)); _playerB.sendPacket(new ExDuelUpdateUserInfo(_playerA)); } } public void onDuelTimeout() { L2PcInstance winner = getWinner(); onDuelEnd(winner, getOpponent(winner)); sendWinnerMessages(); } public void onDuelSurrender(L2PcInstance survivor) { if (_canSurrender) { _duelState = DuelState.Surrender; sendSurrenderMessages(getOpponent(survivor), survivor); onDuelEnd(getOpponent(survivor), survivor); } else return; } public boolean onDuelDefeat(L2PcInstance player) { boolean surrender = false; if (isPartyDuel()) { L2PcInstance partyLeader = getPlayersPartyLeader(player); if (partyLeader == null) return false; if (allPartyMemberDead(partyLeader.getParty()) && _willSurrender) surrender = true; if (allPartyMemberDead(partyLeader.getParty())) { onDuelEnd(getOpponent(partyLeader), partyLeader); sendWinnerMessages(); } } else { if (!isPartyDuel() && _willSurrender) surrender = true; onDuelEnd(getOpponent(player), player); sendWinnerMessages(); } return surrender; } public void onDuelDraw() { _duelState = DuelState.Draw; broadcastPacket(new SystemMessage(SystemMessageId.THE_DUEL_HAS_ENDED_IN_A_TIE)); onDuelEnd(_playerA, _playerB); } public void onDuelEnd(L2PcInstance winner, L2PcInstance loser) { _duelState = DuelState.Winner; stopFighting(); EventDuelManager.getInstance().removeDuel(this); } public void onDuelDisqualification(L2PcInstance disqulified) { if (_canDisqualify) { stopFighting(); sendDisqualificationMessages(getOpponent(disqulified), disqulified); onDuelEnd(getOpponent(disqulified), disqulified); } else return; } public void onDuelDelete() { if (isPartyDuel()) { for (L2PcInstance player : _playerA.getParty().getPartyMembers()) { if (player != null) { player.cancelActiveTrade(); player.setTeam(0); player.setIsInDuel(null); player.enableAllSkills(); player.getStatus().startHpMpRegeneration(); player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); player.sendPacket(new ActionFailed()); player.broadcastUserInfo(); player.broadcastStatusUpdate(); player.sendPacket(new ValidateLocation(player)); } } for (L2PcInstance player : _playerB.getParty().getPartyMembers()) { if (player != null) { player.cancelActiveTrade(); player.setTeam(0); player.setIsInDuel(null); player.enableAllSkills(); player.getStatus().startHpMpRegeneration(); player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); player.sendPacket(new ActionFailed()); player.broadcastUserInfo(); player.broadcastStatusUpdate(); player.sendPacket(new ValidateLocation(player)); } } } else { _playerA.setTeam(0); _playerA.setIsInDuel(null); _playerA.enableAllSkills(); _playerA.getStatus().startHpMpRegeneration(); _playerA.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); _playerA.sendPacket(new ActionFailed()); _playerA.broadcastStatusUpdate(); _playerA.broadcastUserInfo(); _playerA.sendPacket(new ValidateLocation(_playerA)); _playerB.setTeam(0); _playerB.setIsInDuel(null); _playerB.enableAllSkills(); _playerB.getStatus().startHpMpRegeneration(); _playerB.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); _playerB.sendPacket(new ActionFailed()); _playerB.broadcastStatusUpdate(); _playerB.broadcastUserInfo(); _playerB.sendPacket(new ValidateLocation(_playerB)); } } /*------------------------------------------------------------ *| Protected functions area *| *------------------------------------------------------------ */ protected final void setDuelState(DuelState duelState) { _duelState = duelState; } protected final void sendDisqualificationMessages(L2PcInstance winner, L2PcInstance loser) { SystemMessage msg; // Setze entsprechende Winner Message if (isPartyDuel()) msg = new SystemMessage(SystemMessageId.S1S_WAS_DISQUALIFIED_SO_S2S_HAS_WON); else msg = new SystemMessage(SystemMessageId.S1_WAS_DISQUALIFIED_SO_S2_HAS_WON); // Namen zur Nachricht hinzufügen msg.addString(loser.getName()); msg.addString(winner.getName()); // Broadcast Message broadcastPacket(msg); } protected final void sendSurrenderMessages(L2PcInstance winner, L2PcInstance loser) { SystemMessage msg; // Setze entsprechende Winner Message if (isPartyDuel()) msg = new SystemMessage(SystemMessageId.SINCE_S1S_PARTY_WITHDREW_FROM_THE_DUEL_S1S_PARTY_HAS_WON); else msg = new SystemMessage(SystemMessageId.SINCE_S1_WITHDREW_FROM_THE_DUEL_S2_HAS_WON); // Namen zur Nachricht hinzufügen msg.addString(loser.getName()); msg.addString(winner.getName()); // Broadcast Message broadcastPacket(msg); } protected final L2PcInstance getWinner() { double hpPartyA = 0; double hpPartyB = 0; // Berechne übrige HP beider Parteien if (isPartyDuel()) { for (L2PcInstance player : _playerA.getParty().getPartyMembers()) { if (player != null) { hpPartyA += player.getCurrentHp(); } } for (L2PcInstance player : _playerB.getParty().getPartyMembers()) { if (player != null) { hpPartyB += player.getCurrentHp(); } } } else { hpPartyA = _playerA.getCurrentHp(); hpPartyB = _playerB.getCurrentHp(); } if (hpPartyA > hpPartyB) return _playerA; return _playerB; } protected final void sendWinnerMessages() { SystemMessage msg; // Setze entsprechende Winner Message if (isPartyDuel()) msg = new SystemMessage(SystemMessageId.S1S_PARTY_HAS_WON_THE_DUEL); else msg = new SystemMessage(SystemMessageId.S1_HAS_WON_THE_DUEL); // Füge Spielername der Message hinzu if (getWinner() == _playerA) msg.addString(_playerA.getName()); else msg.addString(_playerB.getName()); // Broadcast Message broadcastPacket(msg); } protected final void broadcastPacket(L2GameServerPacket packet) { if (isPartyDuel()) { for (L2PcInstance player : _playerA.getParty().getPartyMembers()) { if (player != null) { player.sendPacket(packet); } } for (L2PcInstance player : _playerB.getParty().getPartyMembers()) { if (player != null) { player.sendPacket(packet); } } } else { _playerA.sendPacket(packet); _playerB.sendPacket(packet); } } protected final void broadcastPacket(SystemMessage msg) { if (isPartyDuel()) { for (L2PcInstance player : _playerA.getParty().getPartyMembers()) { if (player != null) { player.sendSystemMessage(msg); } } for (L2PcInstance player : _playerB.getParty().getPartyMembers()) { if (player != null) { player.sendSystemMessage(msg); } } } else { _playerA.sendSystemMessage(msg); _playerB.sendSystemMessage(msg); } } protected final void stopFighting() { ExDuelEnd duelEnd; if (isPartyDuel()) duelEnd = new ExDuelEnd(1); else duelEnd = new ExDuelEnd(0); ActionFailed af = new ActionFailed(); if (isPartyDuel()) { for (L2PcInstance player : _playerA.getParty().getPartyMembers()) { if (player != null) { player.sendPacket(af); player.abortCast(); player.abortAttack(); player.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); player.setTarget(null); player.sendPacket(duelEnd); } } for (L2PcInstance player : _playerB.getParty().getPartyMembers()) { if (player != null) { player.sendPacket(af); player.abortCast(); player.abortAttack(); player.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); player.setTarget(null); player.sendPacket(duelEnd); } } } else { _playerA.sendPacket(af); _playerB.sendPacket(af); _playerA.abortCast(); _playerB.abortCast(); _playerA.abortAttack(); _playerB.abortAttack(); _playerA.sendPacket(duelEnd); _playerB.sendPacket(duelEnd); _playerA.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); _playerB.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); _playerA.setTarget(null); _playerB.setTarget(null); } } protected final boolean allPartyMemberDead(L2Party party) { for (L2PcInstance player : party.getPartyMembers()) { if (player != null && !player.isDead()) return false; } return true; } protected final void setTeams() { if (isPartyDuel()) { for (L2PcInstance player : _playerA.getParty().getPartyMembers()) { if (player != null) { player.cancelActiveTrade(); player.setTeam(1); player.setIsInDuel(this); player.broadcastStatusUpdate(); player.broadcastUserInfo(); } } for (L2PcInstance player : _playerB.getParty().getPartyMembers()) { if (player != null) { player.cancelActiveTrade(); player.setTeam(2); player.setIsInDuel(this); player.broadcastStatusUpdate(); player.broadcastUserInfo(); } } } else { _playerA.setTeam(1); _playerA.setIsInDuel(this); _playerA.broadcastStatusUpdate(); _playerA.broadcastUserInfo(); _playerB.setTeam(2); _playerB.setIsInDuel(this); _playerB.broadcastStatusUpdate(); _playerB.broadcastUserInfo(); } } /*------------------------------------------------------------ *| Protected abstract functions area *| *------------------------------------------------------------ */ protected abstract void setWillSurrender(); protected abstract void setCanSurrender(); protected abstract void setCanDisqualify(); protected abstract void setDuelType(); }