/*
* 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 .
*/
package com.l2jserver.gameserver.model.entity;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Future;
import javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.instancemanager.DimensionalRiftManager;
import com.l2jserver.gameserver.instancemanager.QuestManager;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.serverpackets.Earthquake;
import com.l2jserver.util.Rnd;
/**
* Thanks to L2Fortress and balancer.ru - kombat
*/
public class DimensionalRift
{
protected byte _type;
protected L2Party _party;
protected FastList _completedRooms = new FastList();
private static final long seconds_5 = 5000L;
//private static final int MILLISECONDS_IN_MINUTE = 60000;
protected byte jumps_current = 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 deadPlayers = new FastList();
protected FastList revivedInWaitingRoom = new FastList();
private boolean isBossRoom = false;
//private final static Log _log = LogFactory.getLog(DimensionalRift.class.getName());
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())
{
Quest riftQuest = QuestManager.getInstance().getQuest(635);
if (riftQuest != null)
{
QuestState qs = p.getQuestState(riftQuest.getName());
if (qs == null)
qs = riftQuest.newQuestState(p);
if (qs.getInt("cond") != 1)
qs.set("cond", "1");
}
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 && jumps_current < getMaxJumps() && _party.getMemberCount() > deadPlayers.size())
{
jumps_current++;
_completedRooms.add(_choosenRoom);
_choosenRoom = -1;
for (L2PcInstance p : _party.getPartyMembers())
if (!revivedInWaitingRoom.contains(p))
teleportToNextRoom(p);
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, Config.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() < Config.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, "data/html/seven_signs/rift/NotPartyLeader.htm", npc);
return;
}
if (_hasJumped)
{
DimensionalRiftManager.getInstance().showHtmlFile(player, "data/html/seven_signs/rift/AlreadyTeleported.htm", npc);
return;
}
_hasJumped = true;
DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).unspawn().setPartyInside(false);
_completedRooms.add(_choosenRoom);
_choosenRoom = -1;
for (L2PcInstance p : _party.getPartyMembers())
teleportToNextRoom(p);
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, "data/html/seven_signs/rift/NotPartyLeader.htm", npc);
return;
}
for (L2PcInstance p : player.getParty().getPartyMembers())
teleportToWaitingRoom(p);
killRift();
}
protected void teleportToNextRoom(L2PcInstance player)
{
if (_choosenRoom == -1)
{
FastList 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);
_choosenRoom = emptyRooms.get(Rnd.get(1, emptyRooms.size())-1);
}
while (DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).ispartyInside());
}
DimensionalRiftManager.getInstance().getRoom(_type, _choosenRoom).setPartyInside(true);
checkBossRoom(_choosenRoom);
int[] coords = getRoomCoord(_choosenRoom);
player.teleToLocation(coords[0], coords[1], coords[2]);
}
protected void teleportToWaitingRoom(L2PcInstance player)
{
DimensionalRiftManager.getInstance().teleportToWaitingRoom(player);
Quest riftQuest = QuestManager.getInstance().getQuest(635);
if (riftQuest != null)
{
QuestState qs = player.getQuestState(riftQuest.getName());
if (qs != null && qs.getInt("cond") == 1)
qs.set("cond", "0");
}
}
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(Config.RIFT_AUTO_JUMPS_TIME_MIN, Config.RIFT_AUTO_JUMPS_TIME_MAX) * 1000;
if (isBossRoom)
return (long) (time * Config.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() < Config.RIFT_MIN_PARTY_SIZE)
{
//int pcm = _party.getMemberCount();
//int rev = revivedInWaitingRoom.size();
//int min = Config.RIFT_MIN_PARTY_SIZE;
for (L2PcInstance p : _party.getPartyMembers())
if (p != null && !revivedInWaitingRoom.contains(p))
teleportToWaitingRoom(p);
killRift();
}
}
public FastList getDeadMemberList()
{
return deadPlayers;
}
public FastList 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 (Config.RIFT_MAX_JUMPS <= 8 && Config.RIFT_MAX_JUMPS >= 1)
return (byte) Config.RIFT_MAX_JUMPS;
return 4;
}
}