Merged with released L2J-Unity files.
This commit is contained in:
@ -0,0 +1,523 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.ceremonyofchaos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.CeremonyOfChaosResult;
|
||||
import com.l2jmobius.gameserver.instancemanager.CeremonyOfChaosManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
|
||||
import com.l2jmobius.gameserver.model.L2Party;
|
||||
import com.l2jmobius.gameserver.model.L2Party.MessageType;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.appearance.PcAppearance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.eventengine.AbstractEvent;
|
||||
import com.l2jmobius.gameserver.model.events.EventDispatcher;
|
||||
import com.l2jmobius.gameserver.model.events.EventType;
|
||||
import com.l2jmobius.gameserver.model.events.ListenerRegisterType;
|
||||
import com.l2jmobius.gameserver.model.events.annotations.RegisterEvent;
|
||||
import com.l2jmobius.gameserver.model.events.annotations.RegisterType;
|
||||
import com.l2jmobius.gameserver.model.events.impl.ceremonyofchaos.OnCeremonyOfChaosMatchResult;
|
||||
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureDeath;
|
||||
import com.l2jmobius.gameserver.model.holders.ItemHolder;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||
import com.l2jmobius.gameserver.model.instancezone.InstanceTemplate;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.network.SystemMessageId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.DeleteObject;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ExUserInfoAbnormalVisualEffect;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.appearance.ExCuriousHouseMemberUpdate;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ceremonyofchaos.ExCuriousHouseEnter;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ceremonyofchaos.ExCuriousHouseLeave;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ceremonyofchaos.ExCuriousHouseMemberList;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ceremonyofchaos.ExCuriousHouseObserveMode;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ceremonyofchaos.ExCuriousHouseRemainTime;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ceremonyofchaos.ExCuriousHouseResult;
|
||||
|
||||
/**
|
||||
* @author UnAfraid
|
||||
*/
|
||||
public class CeremonyOfChaosEvent extends AbstractEvent<CeremonyOfChaosMember>
|
||||
{
|
||||
private static final Logger LOGGER = Logger.getLogger(CeremonyOfChaosEvent.class.getName());
|
||||
|
||||
private final int _id;
|
||||
private final Instance _instance;
|
||||
private final Set<L2MonsterInstance> _monsters = ConcurrentHashMap.newKeySet();
|
||||
private long _battleStartTime = 0;
|
||||
|
||||
public CeremonyOfChaosEvent(int id, InstanceTemplate template)
|
||||
{
|
||||
_id = id;
|
||||
_instance = InstanceManager.getInstance().createInstance(template, null);
|
||||
if (_instance.getEnterLocations().size() < CeremonyOfChaosManager.getInstance().getMaxPlayersInArena())
|
||||
{
|
||||
LOGGER.warning("There are more member slots: " + _instance.getEnterLocations().size() + " then instance entrance positions: " + CeremonyOfChaosManager.getInstance().getMaxPlayersInArena() + "!");
|
||||
}
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public int getInstanceId()
|
||||
{
|
||||
return _instance.getId();
|
||||
}
|
||||
|
||||
public Instance getInstance()
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public Set<L2MonsterInstance> getMonsters()
|
||||
{
|
||||
return _monsters;
|
||||
}
|
||||
|
||||
public void preparePlayers()
|
||||
{
|
||||
final ExCuriousHouseMemberList membersList = new ExCuriousHouseMemberList(_id, CeremonyOfChaosManager.getInstance().getMaxPlayersInArena(), getMembers().values());
|
||||
final NpcHtmlMessage msg = new NpcHtmlMessage(0);
|
||||
|
||||
int index = 0;
|
||||
for (CeremonyOfChaosMember member : getMembers().values())
|
||||
{
|
||||
final L2PcInstance player = member.getPlayer();
|
||||
|
||||
if (player.inObserverMode())
|
||||
{
|
||||
player.leaveObserverMode();
|
||||
}
|
||||
|
||||
if (player.isInDuel())
|
||||
{
|
||||
player.setIsInDuel(0);
|
||||
}
|
||||
|
||||
// Remember player's last location
|
||||
player.setLastLocation();
|
||||
|
||||
// Hide player information
|
||||
final PcAppearance app = player.getAppearance();
|
||||
app.setVisibleName("Challenger" + member.getPosition());
|
||||
app.setVisibleTitle("");
|
||||
app.setVisibleClanData(0, 0, 0, 0, 0);
|
||||
|
||||
// Register the event instance
|
||||
player.registerOnEvent(this);
|
||||
|
||||
// Load the html
|
||||
msg.setFile(player.getHtmlPrefix(), "data/html/CeremonyOfChaos/started.htm");
|
||||
|
||||
// Remove buffs
|
||||
player.stopAllEffectsExceptThoseThatLastThroughDeath();
|
||||
|
||||
// Player shouldn't be able to move and is hidden
|
||||
player.setIsImmobilized(true);
|
||||
player.setInvisible(true);
|
||||
|
||||
// Same goes for summon
|
||||
player.getServitors().values().forEach(s ->
|
||||
{
|
||||
s.stopAllEffectsExceptThoseThatLastThroughDeath();
|
||||
s.setInvisible(true);
|
||||
s.setIsImmobilized(true);
|
||||
});
|
||||
|
||||
if (player.isFlyingMounted())
|
||||
{
|
||||
player.untransform();
|
||||
}
|
||||
|
||||
// If player is dead, revive it
|
||||
if (player.isDead())
|
||||
{
|
||||
player.doRevive();
|
||||
}
|
||||
|
||||
// If player is sitting, stand up
|
||||
if (player.isSitting())
|
||||
{
|
||||
player.standUp();
|
||||
}
|
||||
|
||||
// If player in party, leave it
|
||||
final L2Party party = player.getParty();
|
||||
if (party != null)
|
||||
{
|
||||
party.removePartyMember(player, MessageType.EXPELLED);
|
||||
}
|
||||
|
||||
// Cancel any started action
|
||||
player.abortAttack();
|
||||
player.abortCast();
|
||||
player.stopMove(null);
|
||||
player.setTarget(null);
|
||||
|
||||
// Unsummon pet
|
||||
final L2Summon pet = player.getPet();
|
||||
if (pet != null)
|
||||
{
|
||||
pet.unSummon(player);
|
||||
}
|
||||
|
||||
// Unsummon agathion
|
||||
if (player.getAgathionId() > 0)
|
||||
{
|
||||
player.setAgathionId(0);
|
||||
}
|
||||
|
||||
// The character’s HP, MP, and CP are fully recovered.
|
||||
player.setCurrentHp(player.getMaxHp());
|
||||
player.setCurrentMp(player.getMaxMp());
|
||||
player.setCurrentCp(player.getMaxCp());
|
||||
|
||||
// Skill reuse timers for all skills that have less than 15 minutes of cooldown time are reset.
|
||||
for (Skill skill : player.getAllSkills())
|
||||
{
|
||||
if (skill.getReuseDelay() <= 900000)
|
||||
{
|
||||
player.enableSkill(skill);
|
||||
}
|
||||
}
|
||||
|
||||
player.sendSkillList();
|
||||
player.sendPacket(new SkillCoolTime(player));
|
||||
|
||||
// Apply the Energy of Chaos skill
|
||||
for (SkillHolder holder : CeremonyOfChaosManager.getInstance().getVariables().getList(CeremonyOfChaosManager.INITIAL_BUFF_KEY, SkillHolder.class))
|
||||
{
|
||||
holder.getSkill().activateSkill(player, player);
|
||||
}
|
||||
|
||||
// Send Enter packet
|
||||
player.sendPacket(ExCuriousHouseEnter.STATIC_PACKET);
|
||||
|
||||
// Send all members
|
||||
player.sendPacket(membersList);
|
||||
|
||||
// Send the entrance html
|
||||
player.sendPacket(msg);
|
||||
|
||||
// Send support items to player
|
||||
for (ItemHolder holder : CeremonyOfChaosManager.getInstance().getRewards(CeremonyOfChaosManager.INITIAL_ITEMS_KEY).calculateDrops())
|
||||
{
|
||||
player.addItem("CoC", holder, null, true);
|
||||
}
|
||||
|
||||
// Teleport player to the arena
|
||||
player.teleToLocation(_instance.getEnterLocations().get(index++), 0, _instance);
|
||||
}
|
||||
|
||||
getTimers().addTimer("match_start_countdown", StatsSet.valueOf("time", 60), 100, null, null);
|
||||
|
||||
getTimers().addTimer("teleport_message1", 10000, null, null);
|
||||
getTimers().addTimer("teleport_message2", 14000, null, null);
|
||||
getTimers().addTimer("teleport_message3", 18000, null, null);
|
||||
}
|
||||
|
||||
public void startFight()
|
||||
{
|
||||
for (CeremonyOfChaosMember member : getMembers().values())
|
||||
{
|
||||
final L2PcInstance player = member.getPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
player.sendPacket(SystemMessageId.THE_MATCH_HAS_STARTED_FIGHT);
|
||||
player.setIsImmobilized(false);
|
||||
player.setInvisible(false);
|
||||
player.broadcastInfo();
|
||||
player.sendPacket(new ExUserInfoAbnormalVisualEffect(player));
|
||||
player.getServitors().values().forEach(s ->
|
||||
{
|
||||
s.setInvisible(false);
|
||||
s.setIsImmobilized(false);
|
||||
s.broadcastInfo();
|
||||
});
|
||||
}
|
||||
}
|
||||
_battleStartTime = System.currentTimeMillis();
|
||||
getTimers().addRepeatingTimer("update", 1000, null, null);
|
||||
}
|
||||
|
||||
public void stopFight()
|
||||
{
|
||||
getMembers().values().stream().filter(p -> p.getLifeTime() == 0).forEach(this::updateLifeTime);
|
||||
validateWinner();
|
||||
|
||||
final List<CeremonyOfChaosMember> winners = getWinners();
|
||||
final List<CeremonyOfChaosMember> members = new ArrayList<>(getMembers().size());
|
||||
final SystemMessage msg;
|
||||
if (winners.isEmpty() || (winners.size() > 1))
|
||||
{
|
||||
msg = SystemMessage.getSystemMessage(SystemMessageId.THERE_IS_NO_VICTOR_THE_MATCH_ENDS_IN_A_TIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = SystemMessage.getSystemMessage(SystemMessageId.CONGRATULATIONS_C1_YOU_WIN_THE_MATCH);
|
||||
msg.addCharName(winners.get(0).getPlayer());
|
||||
}
|
||||
|
||||
for (CeremonyOfChaosMember member : getMembers().values())
|
||||
{
|
||||
final L2PcInstance player = member.getPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
// Send winner message
|
||||
player.sendPacket(msg);
|
||||
|
||||
// Send result
|
||||
player.sendPacket(new ExCuriousHouseResult(member.getResultType(), this));
|
||||
|
||||
members.add(member);
|
||||
}
|
||||
}
|
||||
getTimers().cancelTimer("update", null, null);
|
||||
getTimers().addTimer("match_end_countdown", StatsSet.valueOf("time", 30), 30 * 1000, null, null);
|
||||
|
||||
EventDispatcher.getInstance().notifyEvent(new OnCeremonyOfChaosMatchResult(winners, members));
|
||||
}
|
||||
|
||||
private void teleportPlayersOut()
|
||||
{
|
||||
for (CeremonyOfChaosMember member : getMembers().values())
|
||||
{
|
||||
final L2PcInstance player = member.getPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
// Leaves observer mode
|
||||
if (player.inObserverMode())
|
||||
{
|
||||
player.setObserving(false);
|
||||
}
|
||||
|
||||
// Revive the player
|
||||
player.doRevive();
|
||||
|
||||
// Remove Energy of Chaos
|
||||
for (SkillHolder holder : CeremonyOfChaosManager.getInstance().getVariables().getList(CeremonyOfChaosManager.INITIAL_BUFF_KEY, SkillHolder.class))
|
||||
{
|
||||
player.stopSkillEffects(holder.getSkill());
|
||||
}
|
||||
|
||||
// Apply buffs on players
|
||||
for (SkillHolder holder : CeremonyOfChaosManager.getInstance().getVariables().getList(CeremonyOfChaosManager.END_BUFFS_KEYH, SkillHolder.class))
|
||||
{
|
||||
holder.getSkill().activateSkill(player, player);
|
||||
}
|
||||
|
||||
// Remove quit button
|
||||
player.sendPacket(ExCuriousHouseLeave.STATIC_PACKET);
|
||||
|
||||
// Remove spectator mode
|
||||
player.setObserving(false);
|
||||
player.sendPacket(ExCuriousHouseObserveMode.STATIC_DISABLED);
|
||||
|
||||
// Teleport player back
|
||||
player.teleToLocation(player.getLastLocation(), null);
|
||||
|
||||
// Restore player information
|
||||
final PcAppearance app = player.getAppearance();
|
||||
app.setVisibleName(null);
|
||||
app.setVisibleTitle(null);
|
||||
app.setVisibleClanData(-1, -1, -1, -1, -1);
|
||||
|
||||
// Remove player from event
|
||||
player.removeFromEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
getMembers().clear();
|
||||
_instance.destroy();
|
||||
}
|
||||
|
||||
private void updateLifeTime(CeremonyOfChaosMember member)
|
||||
{
|
||||
member.setLifeTime(((int) (System.currentTimeMillis() - _battleStartTime) / 1000));
|
||||
}
|
||||
|
||||
public List<CeremonyOfChaosMember> getWinners()
|
||||
{
|
||||
final List<CeremonyOfChaosMember> winners = new ArrayList<>();
|
||||
//@formatter:off
|
||||
final OptionalInt winnerLifeTime = getMembers().values().stream()
|
||||
.mapToInt(CeremonyOfChaosMember::getLifeTime)
|
||||
.max();
|
||||
|
||||
if(winnerLifeTime.isPresent())
|
||||
{
|
||||
getMembers().values().stream()
|
||||
.sorted(Comparator.comparingLong(CeremonyOfChaosMember::getLifeTime)
|
||||
.reversed()
|
||||
.thenComparingInt(CeremonyOfChaosMember::getScore)
|
||||
.reversed())
|
||||
.filter(member -> member.getLifeTime() == winnerLifeTime.getAsInt())
|
||||
.collect(Collectors.toCollection(() -> winners));
|
||||
}
|
||||
|
||||
//@formatter:on
|
||||
return winners;
|
||||
}
|
||||
|
||||
private void validateWinner()
|
||||
{
|
||||
final List<CeremonyOfChaosMember> winners = getWinners();
|
||||
winners.forEach(winner -> winner.setResultType(winners.size() > 1 ? CeremonyOfChaosResult.TIE : CeremonyOfChaosResult.WIN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "update":
|
||||
{
|
||||
final int time = (int) CeremonyOfChaosManager.getInstance().getScheduler("stopFight").getRemainingTime(TimeUnit.SECONDS);
|
||||
broadcastPacket(new ExCuriousHouseRemainTime(time));
|
||||
getMembers().values().forEach(p -> broadcastPacket(new ExCuriousHouseMemberUpdate(p)));
|
||||
|
||||
// Validate winner
|
||||
if (getMembers().values().stream().filter(member -> !member.isDefeated()).count() <= 1)
|
||||
{
|
||||
stopFight();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "teleport_message1":
|
||||
{
|
||||
broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.PROVE_YOUR_ABILITIES));
|
||||
break;
|
||||
}
|
||||
case "teleport_message2":
|
||||
{
|
||||
broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.THERE_ARE_NO_ALLIES_HERE_EVERYONE_IS_AN_ENEMY));
|
||||
break;
|
||||
}
|
||||
case "teleport_message3":
|
||||
{
|
||||
broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.IT_WILL_BE_A_LONELY_BATTLE_BUT_I_WISH_YOU_VICTORY));
|
||||
break;
|
||||
}
|
||||
case "match_start_countdown":
|
||||
{
|
||||
final int time = params.getInt("time", 0);
|
||||
|
||||
final SystemMessage countdown = SystemMessage.getSystemMessage(SystemMessageId.THE_MATCH_WILL_START_IN_S1_SECOND_S);
|
||||
countdown.addByte(time);
|
||||
broadcastPacket(countdown);
|
||||
|
||||
// Reschedule
|
||||
if (time == 60)
|
||||
{
|
||||
getTimers().addTimer(event, params.set("time", 30), 30 * 1000, null, null);
|
||||
}
|
||||
else if ((time == 30) || (time == 20))
|
||||
{
|
||||
getTimers().addTimer(event, params.set("time", time - 10), 10 * 1000, null, null);
|
||||
}
|
||||
else if (time == 10)
|
||||
{
|
||||
getTimers().addTimer(event, params.set("time", 5), 5 * 1000, null, null);
|
||||
}
|
||||
else if ((time > 1) && (time <= 5))
|
||||
{
|
||||
getTimers().addTimer(event, params.set("time", time - 1), 1000, null, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "match_end_countdown":
|
||||
{
|
||||
final int time = params.getInt("time", 0);
|
||||
final SystemMessage countdown = SystemMessage.getSystemMessage(SystemMessageId.IN_S1_SECOND_S_YOU_WILL_BE_MOVED_TO_WHERE_YOU_WERE_BEFORE_PARTICIPATING_IN_THE_CEREMONY_OF_CHAOS);
|
||||
countdown.addByte(time);
|
||||
broadcastPacket(countdown);
|
||||
|
||||
// Reschedule
|
||||
if ((time == 30) || (time == 20))
|
||||
{
|
||||
getTimers().addTimer(event, params.set("time", time - 10), 10 * 1000, null, null);
|
||||
}
|
||||
else if ((time > 0) && (time <= 10))
|
||||
{
|
||||
getTimers().addTimer(event, params.set("time", time - 1), 1000, null, null);
|
||||
}
|
||||
else if (time == 0)
|
||||
{
|
||||
teleportPlayersOut();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterEvent(EventType.ON_CREATURE_DEATH)
|
||||
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
|
||||
public void onPlayerDeath(OnCreatureDeath event)
|
||||
{
|
||||
if (event.getAttacker().isPlayer() && event.getTarget().isPlayer())
|
||||
{
|
||||
final L2PcInstance attackerPlayer = event.getAttacker().getActingPlayer();
|
||||
final L2PcInstance targetPlayer = event.getTarget().getActingPlayer();
|
||||
|
||||
final CeremonyOfChaosMember attackerMember = getMembers().get(attackerPlayer.getObjectId());
|
||||
final CeremonyOfChaosMember targetMember = getMembers().get(targetPlayer.getObjectId());
|
||||
|
||||
final DeleteObject deleteObject = new DeleteObject(targetPlayer);
|
||||
|
||||
if ((attackerMember != null) && (targetMember != null))
|
||||
{
|
||||
attackerMember.incrementScore();
|
||||
updateLifeTime(targetMember);
|
||||
|
||||
// Mark player as defeated
|
||||
targetMember.setDefeated(true);
|
||||
|
||||
// Delete target player
|
||||
//@formatter:off
|
||||
getMembers().values().stream()
|
||||
.filter(member -> member.getObjectId() != targetPlayer.getObjectId())
|
||||
.map(CeremonyOfChaosMember::getPlayer)
|
||||
.forEach(deleteObject::sendTo);
|
||||
//@formatter:on
|
||||
|
||||
// Make the target observer
|
||||
targetPlayer.setObserving(true);
|
||||
|
||||
// Make the target spectator
|
||||
targetPlayer.sendPacket(ExCuriousHouseObserveMode.STATIC_ENABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user