/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.l2jserver.gameserver.model.actor.instance;
import java.util.concurrent.Future;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.actor.stat.ControllableAirShipStat;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.DeleteObject;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
public class L2ControllableAirShipInstance extends L2AirShipInstance
{
private static final int HELM = 13556;
private static final int LOW_FUEL = 40;
private int _fuel = 0;
private int _maxFuel = 0;
private final int _ownerId;
private int _helmId;
private L2PcInstance _captain = null;
private Future<?> _consumeFuelTask;
private Future<?> _checkTask;
/**
* Creates a controllable air ship.
* @param template the controllable air ship template
* @param ownerId the owner ID
*/
public L2ControllableAirShipInstance(L2CharTemplate template, int ownerId)
{
super(template);
setInstanceType(InstanceType.L2ControllableAirShipInstance);
_ownerId = ownerId;
_helmId = IdFactory.getInstance().getNextId(); // not forget to release !
}
@Override
public ControllableAirShipStat getStat()
{
return (ControllableAirShipStat) super.getStat();
}
@Override
public void initCharStat()
{
setStat(new ControllableAirShipStat(this));
}
@Override
public boolean canBeControlled()
{
return super.canBeControlled() && !isInDock();
}
@Override
public boolean isOwner(L2PcInstance player)
{
if (_ownerId == 0)
{
return false;
}
return (player.getClanId() == _ownerId) || (player.getObjectId() == _ownerId);
}
@Override
public int getOwnerId()
{
return _ownerId;
}
@Override
public boolean isCaptain(L2PcInstance player)
{
return (_captain != null) && (player == _captain);
}
@Override
public int getCaptainId()
{
return _captain != null ? _captain.getObjectId() : 0;
}
@Override
public int getHelmObjectId()
{
return _helmId;
}
@Override
public int getHelmItemId()
{
return HELM;
}
@Override
public boolean setCaptain(L2PcInstance player)
{
if (player == null)
{
_captain = null;
}
else
{
if ((_captain == null) && (player.getAirShip() == this))
{
final int x = player.getInVehiclePosition().getX() - 0x16e;
final int y = player.getInVehiclePosition().getY();
final int z = player.getInVehiclePosition().getZ() - 0x6b;
if (((x * x) + (y * y) + (z * z)) > 2500)
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_BECAUSE_YOU_ARE_TOO_FAR);
return false;
}
// TODO: Missing message ID: 2739 Message: You cannot control the helm because you do not meet the requirements.
else if (player.isInCombat())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_IN_A_BATTLE);
return false;
}
else if (player.isSitting())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_IN_A_SITTING_POSITION);
return false;
}
else if (player.isParalyzed())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_YOU_ARE_PETRIFIED);
return false;
}
else if (player.isCursedWeaponEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_A_CURSED_WEAPON_IS_EQUIPPED);
return false;
}
else if (player.isFishing())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_FISHING);
return false;
}
else if (player.isDead() || player.isFakeDeath())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHEN_YOU_ARE_DEAD);
return false;
}
else if (player.isCastingNow())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_USING_A_SKILL);
return false;
}
else if (player.isTransformed())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_TRANSFORMED);
return false;
}
else if (player.isCombatFlagEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_HOLDING_A_FLAG);
return false;
}
else if (player.isInDuel())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_CONTROL_THE_HELM_WHILE_IN_A_DUEL);
return false;
}
_captain = player;
player.broadcastUserInfo();
}
else
{
return false;
}
}
updateAbnormalVisualEffects();
return true;
}
@Override
public int getFuel()
{
return _fuel;
}
@Override
public void setFuel(int f)
{
final int old = _fuel;
if (f < 0)
{
_fuel = 0;
}
else if (f > _maxFuel)
{
_fuel = _maxFuel;
}
else
{
_fuel = f;
}
if ((_fuel == 0) && (old > 0))
{
broadcastToPassengers(SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_S_FUEL_EP_HAS_RUN_OUT_THE_AIRSHIP_S_SPEED_WILL_BE_GREATLY_DECREASED_IN_THIS_CONDITION));
}
else if (_fuel < LOW_FUEL)
{
broadcastToPassengers(SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_S_FUEL_EP_WILL_SOON_RUN_OUT));
}
}
@Override
public int getMaxFuel()
{
return _maxFuel;
}
@Override
public void setMaxFuel(int mf)
{
_maxFuel = mf;
}
@Override
public void oustPlayer(L2PcInstance player)
{
if (player == _captain)
{
setCaptain(null); // no need to broadcast userinfo here
}
super.oustPlayer(player);
}
@Override
public void onSpawn()
{
super.onSpawn();
_checkTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckTask(), 60000, 10000);
_consumeFuelTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new ConsumeFuelTask(), 60000, 60000);
}
@Override
public boolean deleteMe()
{
if (!super.deleteMe())
{
return false;
}
if (_checkTask != null)
{
_checkTask.cancel(false);
_checkTask = null;
}
if (_consumeFuelTask != null)
{
_consumeFuelTask.cancel(false);
_consumeFuelTask = null;
}
broadcastPacket(new DeleteObject(_helmId));
return true;
}
@Override
public void refreshID()
{
super.refreshID();
IdFactory.getInstance().releaseId(_helmId);
_helmId = IdFactory.getInstance().getNextId();
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
super.sendInfo(activeChar);
if (_captain != null)
{
_captain.sendInfo(activeChar);
}
}
protected final class ConsumeFuelTask implements Runnable
{
@Override
public void run()
{
int fuel = getFuel();
if (fuel > 0)
{
fuel -= 10;
if (fuel < 0)
{
fuel = 0;
}
setFuel(fuel);
updateAbnormalVisualEffects();
}
}
}
protected final class CheckTask implements Runnable
{
@Override
public void run()
{
if (isVisible() && isEmpty() && !isInDock())
{
// deleteMe() can't be called from CheckTask because task should not cancel itself
ThreadPoolManager.getInstance().executeGeneral(new DecayTask());
}
}
}
protected final class DecayTask implements Runnable
{
@Override
public void run()
{
deleteMe();
}
}
}