/* * 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 silentium.gameserver.model.entity; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Future; import javolution.util.FastList; import silentium.commons.utils.Rnd; import silentium.gameserver.ThreadPoolManager; import silentium.gameserver.configs.EventsConfig; import silentium.gameserver.data.html.StaticHtmPath; import silentium.gameserver.instancemanager.DimensionalRiftManager; import silentium.gameserver.model.L2Party; import silentium.gameserver.model.actor.L2Npc; import silentium.gameserver.model.actor.instance.L2PcInstance; import silentium.gameserver.network.serverpackets.Earthquake; /** * Thanks to L2Fortress and balancer.ru - kombat */ public class DimensionalRift { protected byte _type; protected L2Party _party; protected FastList<Byte> _completedRooms = new FastList<>(); private static final long seconds_5 = 5000L; protected byte _currentJumps = 0; private Timer teleporterTimer; private TimerTask teleporterTimerTask; private Timer spawnTimer; private TimerTask spawnTimerTask; private Future<?> earthQuakeTask; protected byte _choosenRoom = -1; private boolean _hasJumped = false; protected FastList<L2PcInstance> deadPlayers = new FastList<>(); protected FastList<L2PcInstance> revivedInWaitingRoom = new FastList<>(); private boolean isBossRoom = false; public DimensionalRift(L2Party party, byte type, byte room) { DimensionalRiftManager.getInstance().getRoom(type, room).setPartyInside(true); _type = type; _party = party; _choosenRoom = room; int[] coords = getRoomCoord(room); party.setDimensionalRift(this); for (L2PcInstance p : party.getPartyMembers()) p.teleToLocation(coords[0], coords[1], coords[2]); createSpawnTimer(_choosenRoom); createTeleporterTimer(true); } public byte getType() { return _type; } public byte getCurrentRoom() { return _choosenRoom; } protected void createTeleporterTimer(final boolean reasonTP) { if (teleporterTimerTask != null) { teleporterTimerTask.cancel(); teleporterTimerTask = null; } if (teleporterTimer != null) { teleporterTimer.cancel(); teleporterTimer = null; } if (earthQuakeTask != null) { earthQuakeTask.cancel(false); earthQuakeTask = null; } teleporterTimer = new Timer(); teleporterTimerTask = new TimerTask() { @Override public void run() { if (_choosenRoom > -1) DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).unspawn().setPartyInside(false); if (reasonTP && _currentJumps < getMaxJumps() && _party.getMemberCount() > deadPlayers.size()) { _currentJumps++; _completedRooms.add(_choosenRoom); _choosenRoom = -1; for (L2PcInstance p : _party.getPartyMembers()) if (!revivedInWaitingRoom.contains(p)) teleportToNextRoom(p, false); createTeleporterTimer(true); createSpawnTimer(_choosenRoom); } else { for (L2PcInstance p : _party.getPartyMembers()) if (!revivedInWaitingRoom.contains(p)) teleportToWaitingRoom(p); killRift(); cancel(); } } }; if (reasonTP) { long jumpTime = calcTimeToNextJump(); teleporterTimer.schedule(teleporterTimerTask, jumpTime); // Teleporter task, 8-10 minutes earthQuakeTask = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() { @Override public void run() { for (L2PcInstance p : _party.getPartyMembers()) if (!revivedInWaitingRoom.contains(p)) p.sendPacket(new Earthquake(p.getX(), p.getY(), p.getZ(), 65, 9)); } }, jumpTime - 7000); } else teleporterTimer.schedule(teleporterTimerTask, seconds_5); // incorrect party member invited. } public void createSpawnTimer(final byte room) { if (spawnTimerTask != null) { spawnTimerTask.cancel(); spawnTimerTask = null; } if (spawnTimer != null) { spawnTimer.cancel(); spawnTimer = null; } spawnTimer = new Timer(); spawnTimerTask = new TimerTask() { @Override public void run() { DimensionalRiftManager.getInstance().getRoom(_type, room).spawn(); } }; spawnTimer.schedule(spawnTimerTask, EventsConfig.RIFT_SPAWN_DELAY); } public void partyMemberInvited() { createTeleporterTimer(false); } public void partyMemberExited(L2PcInstance player) { if (deadPlayers.contains(player)) deadPlayers.remove(player); if (revivedInWaitingRoom.contains(player)) revivedInWaitingRoom.remove(player); if (_party.getMemberCount() < EventsConfig.RIFT_MIN_PARTY_SIZE || _party.getMemberCount() == 1) { for (L2PcInstance p : _party.getPartyMembers()) teleportToWaitingRoom(p); killRift(); } } public void manualTeleport(L2PcInstance player, L2Npc npc) { if (!player.isInParty() || !player.getParty().isInDimensionalRift()) return; if (player.getObjectId() != player.getParty().getPartyLeaderOID()) { DimensionalRiftManager.getInstance().showHtmlFile(player, StaticHtmPath.SevenSignsHtmPath + "rift/NotPartyLeader.htm", npc); return; } if (_currentJumps == EventsConfig.RIFT_MAX_JUMPS) { DimensionalRiftManager.getInstance().showHtmlFile(player, StaticHtmPath.SevenSignsHtmPath + "rift/UsedAllJumps.htm", npc); return; } if (_hasJumped) { DimensionalRiftManager.getInstance().showHtmlFile(player, StaticHtmPath.SevenSignsHtmPath + "rift/AlreadyTeleported.htm", npc); return; } _hasJumped = true; DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).unspawn(); _completedRooms.add(_choosenRoom); _choosenRoom = -1; for (L2PcInstance p : _party.getPartyMembers()) teleportToNextRoom(p, true); DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).setPartyInside(true); createSpawnTimer(_choosenRoom); createTeleporterTimer(true); } public void manualExitRift(L2PcInstance player, L2Npc npc) { if (!player.isInParty() || !player.getParty().isInDimensionalRift()) return; if (player.getObjectId() != player.getParty().getPartyLeaderOID()) { DimensionalRiftManager.getInstance().showHtmlFile(player, StaticHtmPath.SevenSignsHtmPath + "rift/NotPartyLeader.htm", npc); return; } for (L2PcInstance p : player.getParty().getPartyMembers()) teleportToWaitingRoom(p); killRift(); } /** * This method allows to jump from one room to another. It calculates the next roomId. * * @param player * to teleport * @param cantJumpToBossRoom * if true, Anakazel room can't be choosen (case of manual teleport). */ protected void teleportToNextRoom(L2PcInstance player, boolean cantJumpToBossRoom) { if (_choosenRoom == -1) { FastList<Byte> emptyRooms; do { emptyRooms = DimensionalRiftManager.getInstance().getFreeRooms(_type); // Do not tp in the same room a second time emptyRooms.removeAll(_completedRooms); // If no room left, find any empty if (emptyRooms.isEmpty()) emptyRooms = DimensionalRiftManager.getInstance().getFreeRooms(_type); // Pickup a random room _choosenRoom = emptyRooms.get(Rnd.get(1, emptyRooms.size()) - 1); // This code handles Anakazel's room special behavior. if (cantJumpToBossRoom) { while (_choosenRoom == 9) { _choosenRoom = emptyRooms.get(Rnd.get(1, emptyRooms.size()) - 1); } } } while (DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).ispartyInside()); } DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).setPartyInside(true); int[] coords = getRoomCoord(_choosenRoom); player.teleToLocation(coords[0], coords[1], coords[2]); } protected void teleportToWaitingRoom(L2PcInstance player) { DimensionalRiftManager.getInstance().teleportToWaitingRoom(player); } public void killRift() { _completedRooms = null; if (_party != null) _party.setDimensionalRift(null); _party = null; revivedInWaitingRoom = null; deadPlayers = null; if (earthQuakeTask != null) { earthQuakeTask.cancel(false); earthQuakeTask = null; } DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).unspawn().setPartyInside(false); DimensionalRiftManager.getInstance().killRift(this); } public Timer getTeleportTimer() { return teleporterTimer; } public TimerTask getTeleportTimerTask() { return teleporterTimerTask; } public Timer getSpawnTimer() { return spawnTimer; } public TimerTask getSpawnTimerTask() { return spawnTimerTask; } public void setTeleportTimer(Timer t) { teleporterTimer = t; } public void setTeleportTimerTask(TimerTask tt) { teleporterTimerTask = tt; } public void setSpawnTimer(Timer t) { spawnTimer = t; } public void setSpawnTimerTask(TimerTask st) { spawnTimerTask = st; } private long calcTimeToNextJump() { int time = Rnd.get(EventsConfig.RIFT_AUTO_JUMPS_TIME_MIN, EventsConfig.RIFT_AUTO_JUMPS_TIME_MAX) * 1000; if (isBossRoom) return (long) (time * EventsConfig.RIFT_BOSS_ROOM_TIME_MUTIPLY); return time; } public void memberDead(L2PcInstance player) { if (!deadPlayers.contains(player)) deadPlayers.add(player); } public void memberRessurected(L2PcInstance player) { if (deadPlayers.contains(player)) deadPlayers.remove(player); } public void usedTeleport(L2PcInstance player) { if (!revivedInWaitingRoom.contains(player)) revivedInWaitingRoom.add(player); if (!deadPlayers.contains(player)) deadPlayers.add(player); if (_party.getMemberCount() - revivedInWaitingRoom.size() < EventsConfig.RIFT_MIN_PARTY_SIZE) { for (L2PcInstance p : _party.getPartyMembers()) if (p != null && !revivedInWaitingRoom.contains(p)) teleportToWaitingRoom(p); killRift(); } } public FastList<L2PcInstance> getDeadMemberList() { return deadPlayers; } public FastList<L2PcInstance> getRevivedAtWaitingRoom() { return revivedInWaitingRoom; } public void checkBossRoom(byte room) { isBossRoom = DimensionalRiftManager.getInstance().getRoom(_type, room).isBossRoom(); } public int[] getRoomCoord(byte room) { return DimensionalRiftManager.getInstance().getRoom(_type, room).getTeleportCoords(); } public byte getMaxJumps() { if (EventsConfig.RIFT_MAX_JUMPS <= 8 && EventsConfig.RIFT_MAX_JUMPS >= 1) return (byte) EventsConfig.RIFT_MAX_JUMPS; return 4; } }