This commit is contained in:
mobius
2015-01-01 20:02:50 +00:00
parent eeae660458
commit a6a3718849
17894 changed files with 2818932 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
/*
* Copyright (C) 2004-2014 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;
import java.util.Collection;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.items.L2Weapon;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.CharInfo;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.taskmanager.DecayTaskManager;
public abstract class L2Decoy extends L2Character
{
private final L2PcInstance _owner;
public L2Decoy(int objectId, L2CharTemplate template, L2PcInstance owner)
{
super(objectId, template);
setInstanceType(InstanceType.L2Decoy);
_owner = owner;
setXYZInvisible(owner.getX(), owner.getY(), owner.getZ());
setIsInvul(false);
}
@Override
public void onSpawn()
{
super.onSpawn();
sendPacket(new CharInfo(this));
}
@Override
public void updateAbnormalEffect()
{
Collection<L2PcInstance> plrs = getKnownList().getKnownPlayers().values();
for (L2PcInstance player : plrs)
{
if (player != null)
{
player.sendPacket(new CharInfo(this));
}
}
}
public void stopDecay()
{
DecayTaskManager.getInstance().cancel(this);
}
@Override
public void onDecay()
{
deleteMe(_owner);
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return _owner.isAutoAttackable(attacker);
}
@Override
public L2ItemInstance getActiveWeaponInstance()
{
return null;
}
@Override
public L2Weapon getActiveWeaponItem()
{
return null;
}
@Override
public L2ItemInstance getSecondaryWeaponInstance()
{
return null;
}
@Override
public L2Weapon getSecondaryWeaponItem()
{
return null;
}
@Override
public final int getId()
{
return getTemplate().getId();
}
@Override
public int getLevel()
{
return getTemplate().getLevel();
}
public void deleteMe(L2PcInstance owner)
{
decayMe();
getKnownList().removeAllKnownObjects();
owner.setDecoy(null);
}
public synchronized void unSummon(L2PcInstance owner)
{
if (isVisible() && !isDead())
{
if (getWorldRegion() != null)
{
getWorldRegion().removeFromZones(this);
}
owner.setDecoy(null);
decayMe();
getKnownList().removeAllKnownObjects();
}
}
public final L2PcInstance getOwner()
{
return _owner;
}
@Override
public L2PcInstance getActingPlayer()
{
return _owner;
}
@Override
public L2NpcTemplate getTemplate()
{
return (L2NpcTemplate) super.getTemplate();
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
activeChar.sendPacket(new CharInfo(this));
}
@Override
public void sendPacket(L2GameServerPacket mov)
{
if (getOwner() != null)
{
getOwner().sendPacket(mov);
}
}
@Override
public void sendPacket(SystemMessageId id)
{
if (getOwner() != null)
{
getOwner().sendPacket(id);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,360 @@
/*
* Copyright (C) 2004-2014 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;
import com.l2jserver.gameserver.ai.CtrlEvent;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.knownlist.PlayableKnownList;
import com.l2jserver.gameserver.model.actor.stat.PlayableStat;
import com.l2jserver.gameserver.model.actor.status.PlayableStatus;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.model.effects.EffectFlag;
import com.l2jserver.gameserver.model.effects.L2EffectType;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.impl.character.OnCreatureKill;
import com.l2jserver.gameserver.model.events.returns.TerminateReturn;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.serverpackets.EtcStatusUpdate;
/**
* This class represents all Playable characters in the world.<br>
* L2Playable:
* <ul>
* <li>L2PcInstance</li>
* <li>L2Summon</li>
* </ul>
*/
public abstract class L2Playable extends L2Character
{
private L2Character _lockedTarget = null;
private L2PcInstance transferDmgTo = null;
/**
* Constructor of L2Playable.<br>
* <B><U> Actions</U> :</B>
* <ul>
* <li>Call the L2Character constructor to create an empty _skills slot and link copy basic Calculator set to this L2Playable</li>
* </ul>
* @param objectId Identifier of the object to initialized
* @param template The L2CharTemplate to apply to the L2Playable
*/
public L2Playable(int objectId, L2CharTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2Playable);
setIsInvul(false);
}
@Override
public PlayableKnownList getKnownList()
{
return (PlayableKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new PlayableKnownList(this));
}
@Override
public PlayableStat getStat()
{
return (PlayableStat) super.getStat();
}
@Override
public void initCharStat()
{
setStat(new PlayableStat(this));
}
@Override
public PlayableStatus getStatus()
{
return (PlayableStatus) super.getStatus();
}
@Override
public void initCharStatus()
{
setStatus(new PlayableStatus(this));
}
@Override
public boolean doDie(L2Character killer)
{
final TerminateReturn returnBack = EventDispatcher.getInstance().notifyEvent(new OnCreatureKill(killer, this), this, TerminateReturn.class);
if ((returnBack != null) && returnBack.terminate())
{
return false;
}
// killing is only possible one time
synchronized (this)
{
if (isDead())
{
return false;
}
// now reset currentHp to zero
setCurrentHp(0);
setIsDead(true);
}
// Set target to null and cancel Attack or Cast
setTarget(null);
// Stop movement
stopMove(null);
// Stop HP/MP/CP Regeneration task
getStatus().stopHpMpRegeneration();
boolean deleteBuffs = true;
if (isNoblesseBlessedAffected())
{
stopEffects(L2EffectType.NOBLESSE_BLESSING);
deleteBuffs = false;
}
if (isResurrectSpecialAffected())
{
stopEffects(L2EffectType.RESURRECTION_SPECIAL);
deleteBuffs = false;
}
if (isPlayer())
{
L2PcInstance activeChar = getActingPlayer();
if (activeChar.hasCharmOfCourage())
{
if (activeChar.isInSiege())
{
getActingPlayer().reviveRequest(getActingPlayer(), null, false, 0);
}
activeChar.setCharmOfCourage(false);
activeChar.sendPacket(new EtcStatusUpdate(activeChar));
}
}
if (deleteBuffs)
{
stopAllEffectsExceptThoseThatLastThroughDeath();
}
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
broadcastStatusUpdate();
if (getWorldRegion() != null)
{
getWorldRegion().onDeath(this);
}
// Notify Quest of L2Playable's death
L2PcInstance actingPlayer = getActingPlayer();
if (!actingPlayer.isNotifyQuestOfDeathEmpty())
{
for (QuestState qs : actingPlayer.getNotifyQuestOfDeath())
{
qs.getQuest().notifyDeath((killer == null ? this : killer), this, qs);
}
}
// Notify instance
if (getInstanceId() > 0)
{
final Instance instance = InstanceManager.getInstance().getInstance(getInstanceId());
if (instance != null)
{
instance.notifyDeath(killer, this);
}
}
if (killer != null)
{
L2PcInstance player = killer.getActingPlayer();
if (player != null)
{
player.onKillUpdatePvPKarma(this);
}
}
// Notify L2Character AI
getAI().notifyEvent(CtrlEvent.EVT_DEAD);
super.updateEffectIcons();
return true;
}
public boolean checkIfPvP(L2Character target)
{
if (target == null)
{
return false; // Target is null
}
if (target == this)
{
return false; // Target is self
}
if (!target.isPlayable())
{
return false; // Target is not a L2Playable
}
final L2PcInstance player = getActingPlayer();
if (player == null)
{
return false; // Active player is null
}
if (player.getKarma() != 0)
{
return false; // Active player has karma
}
final L2PcInstance targetPlayer = target.getActingPlayer();
if (targetPlayer == null)
{
return false; // Target player is null
}
if (targetPlayer == this)
{
return false; // Target player is self
}
if (targetPlayer.getKarma() != 0)
{
return false; // Target player has karma
}
if (targetPlayer.getPvpFlag() == 0)
{
return false;
}
return true;
// Even at war, there should be PvP flag
// if(
// player.getClan() == null ||
// targetPlayer.getClan() == null ||
// (
// !targetPlayer.getClan().isAtWarWith(player.getClanId()) &&
// targetPlayer.getWantsPeace() == 0 &&
// player.getWantsPeace() == 0
// )
// )
// {
// return true;
// }
// return false;
}
/**
* Return True.
*/
@Override
public boolean canBeAttacked()
{
return true;
}
// Support for Noblesse Blessing skill, where buffs are retained after resurrect
public final boolean isNoblesseBlessedAffected()
{
return isAffected(EffectFlag.NOBLESS_BLESSING);
}
/**
* @return {@code true} if char can resurrect by himself, {@code false} otherwise
*/
public final boolean isResurrectSpecialAffected()
{
return isAffected(EffectFlag.RESURRECTION_SPECIAL);
}
/**
* @return {@code true} if the Silent Moving mode is active, {@code false} otherwise
*/
public boolean isSilentMovingAffected()
{
return isAffected(EffectFlag.SILENT_MOVE);
}
/**
* For Newbie Protection Blessing skill, keeps you safe from an attack by a chaotic character >= 10 levels apart from you.
* @return
*/
public final boolean isProtectionBlessingAffected()
{
return isAffected(EffectFlag.PROTECTION_BLESSING);
}
@Override
public void updateEffectIcons(boolean partyOnly)
{
getEffectList().updateEffectIcons(partyOnly);
}
public boolean isLockedTarget()
{
return _lockedTarget != null;
}
public L2Character getLockedTarget()
{
return _lockedTarget;
}
public void setLockedTarget(L2Character cha)
{
_lockedTarget = cha;
}
public void setTransferDamageTo(L2PcInstance val)
{
transferDmgTo = val;
}
public L2PcInstance getTransferingDamageTo()
{
return transferDmgTo;
}
public abstract int getKarma();
public abstract byte getPvpFlag();
public abstract boolean useMagic(Skill skill, boolean forceUse, boolean dontMove);
public abstract void storeMe();
public abstract void storeEffect(boolean storeEffects);
public abstract void restoreEffects();
@Override
public boolean isPlayable()
{
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2004-2014 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;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
/**
* This class is a super-class for L2ControlTowerInstance and L2FlameTowerInstance.
* @author Zoey76
*/
public abstract class L2Tower extends L2Npc
{
public L2Tower(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setIsInvul(false);
}
@Override
public boolean canBeAttacked()
{
// Attackable during siege by attacker only
return ((getCastle() != null) && (getCastle().getResidenceId() > 0) && getCastle().getSiege().isInProgress());
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
// Attackable during siege by attacker only
return ((attacker != null) && attacker.isPlayer() && (getCastle() != null) && (getCastle().getResidenceId() > 0) && getCastle().getSiege().isInProgress() && getCastle().getSiege().checkIsAttacker(((L2PcInstance) attacker).getClan()));
}
@Override
public void onAction(L2PcInstance player, boolean interact)
{
if (!canTarget(player))
{
return;
}
if (this != player.getTarget())
{
// Set the target of the L2PcInstance player
player.setTarget(this);
}
else if (interact)
{
if (isAutoAttackable(player) && (Math.abs(player.getZ() - getZ()) < 100) && GeoData.getInstance().canSeeTarget(player, this))
{
// Notify the L2PcInstance AI with AI_INTENTION_INTERACT
player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
}
}
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public void onForcedAttack(L2PcInstance player)
{
onAction(player);
}
}

View File

@ -0,0 +1,522 @@
/*
* Copyright (C) 2004-2014 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;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.gameserver.GameTimeController;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.MapRegionManager;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.L2WorldRegion;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.TeleportWhereType;
import com.l2jserver.gameserver.model.VehiclePathPoint;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.knownlist.VehicleKnownList;
import com.l2jserver.gameserver.model.actor.stat.VehicleStat;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.model.interfaces.ILocational;
import com.l2jserver.gameserver.model.items.L2Weapon;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.util.Util;
/**
* @author DS
*/
public abstract class L2Vehicle extends L2Character
{
protected int _dockId = 0;
protected final FastList<L2PcInstance> _passengers = new FastList<>();
protected Location _oustLoc = null;
private Runnable _engine = null;
protected VehiclePathPoint[] _currentPath = null;
protected int _runState = 0;
public L2Vehicle(int objectId, L2CharTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2Vehicle);
setIsFlying(true);
}
public boolean isBoat()
{
return false;
}
public boolean isAirShip()
{
return false;
}
public boolean canBeControlled()
{
return _engine == null;
}
public void registerEngine(Runnable r)
{
_engine = r;
}
public void runEngine(int delay)
{
if (_engine != null)
{
ThreadPoolManager.getInstance().scheduleGeneral(_engine, delay);
}
}
public void executePath(VehiclePathPoint[] path)
{
_runState = 0;
_currentPath = path;
if ((_currentPath != null) && (_currentPath.length > 0))
{
final VehiclePathPoint point = _currentPath[0];
if (point.getMoveSpeed() > 0)
{
getStat().setMoveSpeed(point.getMoveSpeed());
}
if (point.getRotationSpeed() > 0)
{
getStat().setRotationSpeed(point.getRotationSpeed());
}
getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(point.getX(), point.getY(), point.getZ(), 0));
return;
}
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
@Override
public boolean moveToNextRoutePoint()
{
_move = null;
if (_currentPath != null)
{
_runState++;
if (_runState < _currentPath.length)
{
final VehiclePathPoint point = _currentPath[_runState];
if (!isMovementDisabled())
{
if (point.getMoveSpeed() == 0)
{
point.setHeading(point.getRotationSpeed());
teleToLocation(point, false);
_currentPath = null;
}
else
{
if (point.getMoveSpeed() > 0)
{
getStat().setMoveSpeed(point.getMoveSpeed());
}
if (point.getRotationSpeed() > 0)
{
getStat().setRotationSpeed(point.getRotationSpeed());
}
MoveData m = new MoveData();
m.disregardingGeodata = false;
m.onGeodataPathIndex = -1;
m._xDestination = point.getX();
m._yDestination = point.getY();
m._zDestination = point.getZ();
m._heading = 0;
final double dx = point.getX() - getX();
final double dy = point.getY() - getY();
final double distance = Math.sqrt((dx * dx) + (dy * dy));
if (distance > 1)
{
setHeading(Util.calculateHeadingFrom(getX(), getY(), point.getX(), point.getY()));
}
m._moveStartTime = GameTimeController.getInstance().getGameTicks();
_move = m;
GameTimeController.getInstance().registerMovingObject(this);
return true;
}
}
}
else
{
_currentPath = null;
}
}
runEngine(10);
return false;
}
@Override
public void initKnownList()
{
setKnownList(new VehicleKnownList(this));
}
@Override
public VehicleStat getStat()
{
return (VehicleStat) super.getStat();
}
@Override
public void initCharStat()
{
setStat(new VehicleStat(this));
}
public boolean isInDock()
{
return _dockId > 0;
}
public int getDockId()
{
return _dockId;
}
public void setInDock(int d)
{
_dockId = d;
}
public void setOustLoc(Location loc)
{
_oustLoc = loc;
}
public Location getOustLoc()
{
return _oustLoc != null ? _oustLoc : MapRegionManager.getInstance().getTeleToLocation(this, TeleportWhereType.TOWN);
}
public void oustPlayers()
{
L2PcInstance player;
// Use iterator because oustPlayer will try to remove player from _passengers
final Iterator<L2PcInstance> iter = _passengers.iterator();
while (iter.hasNext())
{
player = iter.next();
iter.remove();
if (player != null)
{
oustPlayer(player);
}
}
}
public void oustPlayer(L2PcInstance player)
{
player.setVehicle(null);
player.setInVehiclePosition(null);
removePassenger(player);
}
public boolean addPassenger(L2PcInstance player)
{
if ((player == null) || _passengers.contains(player))
{
return false;
}
// already in other vehicle
if ((player.getVehicle() != null) && (player.getVehicle() != this))
{
return false;
}
_passengers.add(player);
return true;
}
public void removePassenger(L2PcInstance player)
{
try
{
_passengers.remove(player);
}
catch (Exception e)
{
}
}
public boolean isEmpty()
{
return _passengers.isEmpty();
}
public List<L2PcInstance> getPassengers()
{
return _passengers;
}
public void broadcastToPassengers(L2GameServerPacket sm)
{
for (L2PcInstance player : _passengers)
{
if (player != null)
{
player.sendPacket(sm);
}
}
}
/**
* Consume ticket(s) and teleport player from boat if no correct ticket
* @param itemId Ticket itemId
* @param count Ticket count
* @param oustX
* @param oustY
* @param oustZ
*/
public void payForRide(int itemId, int count, int oustX, int oustY, int oustZ)
{
final Collection<L2PcInstance> passengers = getKnownList().getKnownPlayersInRadius(1000);
if ((passengers != null) && !passengers.isEmpty())
{
L2ItemInstance ticket;
InventoryUpdate iu;
for (L2PcInstance player : passengers)
{
if (player == null)
{
continue;
}
if (player.isInBoat() && (player.getBoat() == this))
{
if (itemId > 0)
{
ticket = player.getInventory().getItemByItemId(itemId);
if ((ticket == null) || (player.getInventory().destroyItem("Boat", ticket, count, player, this) == null))
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_POSSESS_THE_CORRECT_TICKET_TO_BOARD_THE_BOAT);
player.teleToLocation(new Location(oustX, oustY, oustZ), true);
continue;
}
iu = new InventoryUpdate();
iu.addModifiedItem(ticket);
player.sendPacket(iu);
}
addPassenger(player);
}
}
}
}
@Override
public boolean updatePosition(int gameTicks)
{
final boolean result = super.updatePosition(gameTicks);
for (L2PcInstance player : _passengers)
{
if ((player != null) && (player.getVehicle() == this))
{
player.setXYZ(getX(), getY(), getZ());
player.revalidateZone(false);
}
}
return result;
}
@Override
public void teleToLocation(ILocational loc, boolean allowRandomOffset)
{
if (isMoving())
{
stopMove(null, false);
}
setIsTeleporting(true);
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
for (L2PcInstance player : _passengers)
{
if (player != null)
{
player.teleToLocation(loc, false);
}
}
decayMe();
setXYZ(loc.getX(), loc.getY(), loc.getZ());
// temporary fix for heading on teleports
if (loc.getHeading() != 0)
{
setHeading(loc.getHeading());
}
onTeleported();
revalidateZone(true);
}
@Override
public void stopMove(Location loc, boolean updateKnownObjects)
{
_move = null;
if (loc != null)
{
setXYZ(loc.getX(), loc.getY(), loc.getZ());
setHeading(loc.getHeading());
revalidateZone(true);
}
if (Config.MOVE_BASED_KNOWNLIST && updateKnownObjects)
{
getKnownList().findObjects();
}
}
@Override
public boolean deleteMe()
{
_engine = null;
try
{
if (isMoving())
{
stopMove(null);
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Failed stopMove().", e);
}
try
{
oustPlayers();
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Failed oustPlayers().", e);
}
final L2WorldRegion oldRegion = getWorldRegion();
try
{
decayMe();
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Failed decayMe().", e);
}
if (oldRegion != null)
{
oldRegion.removeFromZones(this);
}
try
{
getKnownList().removeAllKnownObjects();
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Failed cleaning knownlist.", e);
}
// Remove L2Object object from _allObjects of L2World
L2World.getInstance().removeObject(this);
return super.deleteMe();
}
@Override
public void updateAbnormalEffect()
{
}
@Override
public L2ItemInstance getActiveWeaponInstance()
{
return null;
}
@Override
public L2Weapon getActiveWeaponItem()
{
return null;
}
@Override
public L2ItemInstance getSecondaryWeaponInstance()
{
return null;
}
@Override
public L2Weapon getSecondaryWeaponItem()
{
return null;
}
@Override
public int getLevel()
{
return 0;
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return false;
}
public class AIAccessor extends L2Character.AIAccessor
{
@Override
public void detachAI()
{
}
}
@Override
public boolean isVehicle()
{
return true;
}
}

View File

@ -0,0 +1,229 @@
/*
* Copyright (C) 2004-2014 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.appearance;
import com.l2jserver.gameserver.enums.Sex;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
public class PcAppearance
{
public static final int DEFAULT_TITLE_COLOR = 0xECF9A2;
private L2PcInstance _owner;
private byte _face;
private byte _hairColor;
private byte _hairStyle;
private boolean _sex; // Female true(1)
/** true if the player is invisible */
private boolean _ghostmode = false;
/** The current visible name of this player, not necessarily the real one */
private String _visibleName;
/** The current visible title of this player, not necessarily the real one */
private String _visibleTitle;
/** The default name color is 0xFFFFFF. */
private int _nameColor = 0xFFFFFF;
/** The default title color is 0xECF9A2. */
private int _titleColor = DEFAULT_TITLE_COLOR;
public PcAppearance(byte face, byte hColor, byte hStyle, boolean sex)
{
_face = face;
_hairColor = hColor;
_hairStyle = hStyle;
_sex = sex;
}
/**
* @param visibleName The visibleName to set.
*/
public final void setVisibleName(String visibleName)
{
_visibleName = visibleName;
}
/**
* @return Returns the visibleName.
*/
public final String getVisibleName()
{
if (_visibleName == null)
{
return getOwner().getName();
}
return _visibleName;
}
/**
* @param visibleTitle The visibleTitle to set.
*/
public final void setVisibleTitle(String visibleTitle)
{
_visibleTitle = visibleTitle;
}
/**
* @return Returns the visibleTitle.
*/
public final String getVisibleTitle()
{
if (_visibleTitle == null)
{
return getOwner().getTitle();
}
return _visibleTitle;
}
public final byte getFace()
{
return _face;
}
/**
* @param value
*/
public final void setFace(int value)
{
_face = (byte) value;
}
public final byte getHairColor()
{
return _hairColor;
}
/**
* @param value
*/
public final void setHairColor(int value)
{
_hairColor = (byte) value;
}
public final byte getHairStyle()
{
return _hairStyle;
}
/**
* @param value
*/
public final void setHairStyle(int value)
{
_hairStyle = (byte) value;
}
/**
* @return true if char is female
*/
public final boolean getSex()
{
return _sex;
}
/**
* @return Sex of the char
*/
public Sex getSexType()
{
return _sex ? Sex.FEMALE : Sex.MALE;
}
/**
* @param isfemale
*/
public final void setSex(boolean isfemale)
{
_sex = isfemale;
}
public void setGhostMode(boolean b)
{
_ghostmode = b;
}
public boolean isGhost()
{
return _ghostmode;
}
public int getNameColor()
{
return _nameColor;
}
public void setNameColor(int nameColor)
{
if (nameColor < 0)
{
return;
}
_nameColor = nameColor;
}
public void setNameColor(int red, int green, int blue)
{
_nameColor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16);
}
public int getTitleColor()
{
return _titleColor;
}
public void setTitleColor(int titleColor)
{
if (titleColor < 0)
{
return;
}
_titleColor = titleColor;
}
public void setTitleColor(int red, int green, int blue)
{
_titleColor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16);
}
/**
* @param owner The owner to set.
*/
public void setOwner(L2PcInstance owner)
{
_owner = owner;
}
/**
* @return Returns the owner.
*/
public L2PcInstance getOwner()
{
return _owner;
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
/**
* This class ...
* @version $Revision: $ $Date: $
* @author LBaldi
*/
public class L2AdventurerInstance extends L2NpcInstance
{
public L2AdventurerInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2AdventurerInstance);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/adventurer_guildsman/" + pom + ".htm";
}
}

View File

@ -0,0 +1,194 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.ai.L2AirShipAI;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.AirShipManager;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Vehicle;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.network.serverpackets.ExAirShipInfo;
import com.l2jserver.gameserver.network.serverpackets.ExGetOffAirShip;
import com.l2jserver.gameserver.network.serverpackets.ExGetOnAirShip;
import com.l2jserver.gameserver.network.serverpackets.ExMoveToLocationAirShip;
import com.l2jserver.gameserver.network.serverpackets.ExStopMoveAirShip;
/**
* Flying airships. Very similar to Maktakien boats (see L2BoatInstance) but these do fly :P
* @author DrHouse, DS
*/
public class L2AirShipInstance extends L2Vehicle
{
public L2AirShipInstance(int objectId, L2CharTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2AirShipInstance);
setAI(new L2AirShipAI(new AIAccessor()));
}
@Override
public boolean isAirShip()
{
return true;
}
public boolean isOwner(L2PcInstance player)
{
return false;
}
public int getOwnerId()
{
return 0;
}
public boolean isCaptain(L2PcInstance player)
{
return false;
}
public int getCaptainId()
{
return 0;
}
public int getHelmObjectId()
{
return 0;
}
public int getHelmItemId()
{
return 0;
}
public boolean setCaptain(L2PcInstance player)
{
return false;
}
public int getFuel()
{
return 0;
}
public void setFuel(int f)
{
}
public int getMaxFuel()
{
return 0;
}
public void setMaxFuel(int mf)
{
}
@Override
public int getId()
{
return 0;
}
@Override
public boolean moveToNextRoutePoint()
{
final boolean result = super.moveToNextRoutePoint();
if (result)
{
broadcastPacket(new ExMoveToLocationAirShip(this));
}
return result;
}
@Override
public boolean addPassenger(L2PcInstance player)
{
if (!super.addPassenger(player))
{
return false;
}
player.setVehicle(this);
player.setInVehiclePosition(new Location(0, 0, 0));
player.broadcastPacket(new ExGetOnAirShip(player, this));
player.getKnownList().removeAllKnownObjects();
player.setXYZ(getX(), getY(), getZ());
player.revalidateZone(true);
return true;
}
@Override
public void oustPlayer(L2PcInstance player)
{
super.oustPlayer(player);
final Location loc = getOustLoc();
if (player.isOnline())
{
player.broadcastPacket(new ExGetOffAirShip(player, this, loc.getX(), loc.getY(), loc.getZ()));
player.getKnownList().removeAllKnownObjects();
player.setXYZ(loc.getX(), loc.getY(), loc.getZ());
player.revalidateZone(true);
}
else
{
player.setXYZInvisible(loc.getX(), loc.getY(), loc.getZ());
}
}
@Override
public boolean deleteMe()
{
if (!super.deleteMe())
{
return false;
}
AirShipManager.getInstance().removeAirShip(this);
return true;
}
@Override
public void stopMove(Location loc, boolean updateKnownObjects)
{
super.stopMove(loc, updateKnownObjects);
broadcastPacket(new ExStopMoveAirShip(this));
}
@Override
public void updateAbnormalEffect()
{
broadcastPacket(new ExAirShipInfo(this));
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
if (isVisibleFor(activeChar))
{
activeChar.sendPacket(new ExAirShipInfo(this));
}
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
/**
* This class manages all Castle Siege Artefacts.<BR>
* <BR>
* @version $Revision: 1.11.2.1.2.7 $ $Date: 2005/04/06 16:13:40 $
*/
public final class L2ArtefactInstance extends L2Npc
{
/**
* Constructor of L2ArtefactInstance (use L2Character and L2NpcInstance constructor).<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Call the L2Character constructor to set the _template of the L2ArtefactInstance (copy skills from template to object and link _calculators to NPC_STD_CALCULATOR)</li> <li>Set the name of the L2ArtefactInstance</li> <li>Create a RandomAnimation Task that will be launched after the
* calculated delay if the server allow it</li><BR>
* <BR>
* @param objectId the identifier of the object to initialized
* @param template to apply to the NPC
*/
public L2ArtefactInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2ArtefactInstance);
}
@Override
public void onSpawn()
{
super.onSpawn();
getCastle().registerArtefact(this);
}
/**
* Return False.
*/
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return false;
}
@Override
public boolean canBeAttacked()
{
return false;
}
@Override
public void onForcedAttack(L2PcInstance player)
{
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public void reduceCurrentHp(double damage, L2Character attacker, Skill skill)
{
}
@Override
public void reduceCurrentHp(double damage, L2Character attacker, boolean awake, boolean isDOT, Skill skill)
{
}
}

View File

@ -0,0 +1,728 @@
/*
* Copyright (C) 2004-2014 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 static com.l2jserver.gameserver.model.itemcontainer.Inventory.MAX_ADENA;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.AuctionManager;
import com.l2jserver.gameserver.instancemanager.ClanHallManager;
import com.l2jserver.gameserver.instancemanager.MapRegionManager;
import com.l2jserver.gameserver.model.ClanPrivilege;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.Auction;
import com.l2jserver.gameserver.model.entity.Auction.Bidder;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
public final class L2AuctioneerInstance extends L2Npc
{
private static final int COND_ALL_FALSE = 0;
private static final int COND_BUSY_BECAUSE_OF_SIEGE = 1;
private static final int COND_REGULAR = 3;
private final Map<Integer, Auction> _pendingAuctions = new FastMap<>();
public L2AuctioneerInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2AuctioneerInstance);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
int condition = validateCondition(player);
if (condition <= COND_ALL_FALSE)
{
// TODO: html
player.sendMessage("Wrong conditions.");
return;
}
else if (condition == COND_BUSY_BECAUSE_OF_SIEGE)
{
String filename = "data/html/auction/auction-busy.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
else if (condition == COND_REGULAR)
{
StringTokenizer st = new StringTokenizer(command, " ");
String actualCommand = st.nextToken(); // Get actual command
String val = "";
if (st.countTokens() >= 1)
{
val = st.nextToken();
}
if (actualCommand.equalsIgnoreCase("auction"))
{
if (val.isEmpty())
{
return;
}
try
{
int days = Integer.parseInt(val);
try
{
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
long bid = 0;
if (st.countTokens() >= 1)
{
bid = Math.min(Long.parseLong(st.nextToken()), MAX_ADENA);
}
Auction a = new Auction(player.getClan().getHideoutId(), player.getClan(), days * 86400000L, bid, ClanHallManager.getInstance().getClanHallByOwner(player.getClan()).getName());
if (_pendingAuctions.get(a.getId()) != null)
{
_pendingAuctions.remove(a.getId());
}
_pendingAuctions.put(a.getId(), a);
String filename = "data/html/auction/AgitSale3.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%x%", val);
html.replace("%AGIT_AUCTION_END%", String.valueOf(format.format(a.getEndDate())));
html.replace("%AGIT_AUCTION_MINBID%", String.valueOf(a.getStartingBid()));
html.replace("%AGIT_AUCTION_MIN%", String.valueOf(a.getStartingBid()));
html.replace("%AGIT_AUCTION_DESC%", ClanHallManager.getInstance().getClanHallByOwner(player.getClan()).getDesc());
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_sale2");
html.replace("%objectId%", String.valueOf((getObjectId())));
player.sendPacket(html);
}
catch (Exception e)
{
player.sendMessage("Invalid bid!");
}
}
catch (Exception e)
{
player.sendMessage("Invalid auction duration!");
}
return;
}
else if (actualCommand.equalsIgnoreCase("confirmAuction"))
{
try
{
Auction a = _pendingAuctions.get(player.getClan().getHideoutId());
a.confirmAuction();
_pendingAuctions.remove(player.getClan().getHideoutId());
}
catch (Exception e)
{
player.sendMessage("Invalid auction");
}
return;
}
else if (actualCommand.equalsIgnoreCase("bidding"))
{
if (val.isEmpty())
{
return;
}
if (Config.DEBUG)
{
_log.warning("bidding show successful");
}
try
{
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
int auctionId = Integer.parseInt(val);
if (Config.DEBUG)
{
_log.warning("auction test started");
}
String filename = "data/html/auction/AgitAuctionInfo.htm";
Auction a = AuctionManager.getInstance().getAuction(auctionId);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
if (a != null)
{
html.replace("%AGIT_NAME%", a.getItemName());
html.replace("%OWNER_PLEDGE_NAME%", a.getSellerClanName());
html.replace("%OWNER_PLEDGE_MASTER%", a.getSellerName());
html.replace("%AGIT_SIZE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getGrade() * 10));
html.replace("%AGIT_LEASE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getLease()));
html.replace("%AGIT_LOCATION%", ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getLocation());
html.replace("%AGIT_AUCTION_END%", String.valueOf(format.format(a.getEndDate())));
html.replace("%AGIT_AUCTION_REMAIN%", String.valueOf((a.getEndDate() - System.currentTimeMillis()) / 3600000) + " hours " + String.valueOf((((a.getEndDate() - System.currentTimeMillis()) / 60000) % 60)) + " minutes");
html.replace("%AGIT_AUCTION_MINBID%", String.valueOf(a.getStartingBid()));
html.replace("%AGIT_AUCTION_COUNT%", String.valueOf(a.getBidders().size()));
html.replace("%AGIT_AUCTION_DESC%", ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getDesc());
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_list");
html.replace("%AGIT_LINK_BIDLIST%", "bypass -h npc_" + getObjectId() + "_bidlist " + a.getId());
html.replace("%AGIT_LINK_RE%", "bypass -h npc_" + getObjectId() + "_bid1 " + a.getId());
}
else
{
_log.warning("Auctioneer Auction null for AuctionId : " + auctionId);
}
player.sendPacket(html);
}
catch (Exception e)
{
player.sendMessage("Invalid auction!");
}
return;
}
else if (actualCommand.equalsIgnoreCase("bid"))
{
if (val.isEmpty())
{
return;
}
try
{
int auctionId = Integer.parseInt(val);
try
{
long bid = 0;
if (st.countTokens() >= 1)
{
bid = Math.min(Long.parseLong(st.nextToken()), MAX_ADENA);
}
AuctionManager.getInstance().getAuction(auctionId).setBid(player, bid);
}
catch (Exception e)
{
player.sendMessage("Invalid bid!");
}
}
catch (Exception e)
{
player.sendMessage("Invalid auction!");
}
return;
}
else if (actualCommand.equalsIgnoreCase("bid1"))
{
if ((player.getClan() == null) || (player.getClan().getLevel() < 2))
{
player.sendPacket(SystemMessageId.ONLY_A_CLAN_LEADER_WHOSE_CLAN_IS_OF_LEVEL_2_OR_ABOVE_IS_ALLOWED_TO_PARTICIPATE_IN_A_CLAN_HALL_AUCTION);
return;
}
if (val.isEmpty())
{
return;
}
if (((player.getClan().getAuctionBiddedAt() > 0) && (player.getClan().getAuctionBiddedAt() != Integer.parseInt(val))) || (player.getClan().getHideoutId() > 0))
{
player.sendPacket(SystemMessageId.SINCE_YOU_HAVE_ALREADY_SUBMITTED_A_BID_YOU_ARE_NOT_ALLOWED_TO_PARTICIPATE_IN_ANOTHER_AUCTION_AT_THIS_TIME);
return;
}
try
{
String filename = "data/html/auction/AgitBid1.htm";
long minimumBid = AuctionManager.getInstance().getAuction(Integer.parseInt(val)).getHighestBidderMaxBid();
if (minimumBid == 0)
{
minimumBid = AuctionManager.getInstance().getAuction(Integer.parseInt(val)).getStartingBid();
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_bidding " + val);
html.replace("%PLEDGE_ADENA%", String.valueOf(player.getClan().getWarehouse().getAdena()));
html.replace("%AGIT_AUCTION_MINBID%", String.valueOf(minimumBid));
html.replace("npc_%objectId%_bid", "npc_" + getObjectId() + "_bid " + val);
player.sendPacket(html);
return;
}
catch (Exception e)
{
player.sendMessage("Invalid auction!");
}
return;
}
else if (actualCommand.equalsIgnoreCase("list"))
{
List<Auction> auctions = AuctionManager.getInstance().getAuctions();
SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd");
/** Limit for make new page, prevent client crash **/
int limit = 15;
int start;
int i = 1;
double npage = Math.ceil((float) auctions.size() / limit);
if (val.isEmpty())
{
start = 1;
}
else
{
start = (limit * (Integer.parseInt(val) - 1)) + 1;
limit *= Integer.parseInt(val);
}
if (Config.DEBUG)
{
_log.warning("cmd list: auction test started");
}
StringBuilder items = new StringBuilder();
items.append("<table width=280 border=0><tr>");
for (int j = 1; j <= npage; j++)
{
items.append("<td><center><a action=\"bypass -h npc_");
items.append(getObjectId());
items.append("_list ");
items.append(j);
items.append("\"> Page ");
items.append(j);
items.append(" </a></center></td>");
}
items.append("</tr></table>");
items.append("<table width=280 border=0>");
for (Auction a : auctions)
{
if (a == null)
{
continue;
}
if (i > limit)
{
break;
}
else if (i < start)
{
i++;
continue;
}
else
{
i++;
}
items.append("<tr>");
items.append("<td>");
items.append(ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getLocation());
items.append("</td>");
items.append("<td><a action=\"bypass -h npc_");
items.append(getObjectId());
items.append("_bidding ");
items.append(a.getId());
items.append("\">");
items.append(a.getItemName());
items.append("</a></td>");
items.append("<td>" + format.format(a.getEndDate()));
items.append("</td>");
items.append("<td>");
items.append(a.getStartingBid());
items.append("</td>");
items.append("</tr>");
}
items.append("</table>");
String filename = "data/html/auction/AgitAuctionList.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_start");
html.replace("%itemsField%", items.toString());
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("bidlist"))
{
int auctionId = 0;
if (val.isEmpty())
{
if (player.getClan().getAuctionBiddedAt() <= 0)
{
return;
}
auctionId = player.getClan().getAuctionBiddedAt();
}
else
{
auctionId = Integer.parseInt(val);
}
if (Config.DEBUG)
{
_log.warning("cmd bidlist: auction test started");
}
String biders = "";
Map<Integer, Bidder> bidders = AuctionManager.getInstance().getAuction(auctionId).getBidders();
for (Bidder b : bidders.values())
{
biders += "<tr>" + "<td>" + b.getClanName() + "</td><td>" + b.getName() + "</td><td>" + b.getTimeBid().get(Calendar.YEAR) + "/" + (b.getTimeBid().get(Calendar.MONTH) + 1) + "/" + b.getTimeBid().get(Calendar.DATE) + "</td><td>" + b.getBid() + "</td>" + "</tr>";
}
String filename = "data/html/auction/AgitBidderList.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%AGIT_LIST%", biders);
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_selectedItems");
html.replace("%x%", val);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("selectedItems"))
{
if ((player.getClan() != null) && (player.getClan().getHideoutId() == 0) && (player.getClan().getAuctionBiddedAt() > 0))
{
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
String filename = "data/html/auction/AgitBidInfo.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
Auction a = AuctionManager.getInstance().getAuction(player.getClan().getAuctionBiddedAt());
if (a != null)
{
html.replace("%AGIT_NAME%", a.getItemName());
html.replace("%OWNER_PLEDGE_NAME%", a.getSellerClanName());
html.replace("%OWNER_PLEDGE_MASTER%", a.getSellerName());
html.replace("%AGIT_SIZE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getGrade() * 10));
html.replace("%AGIT_LEASE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getLease()));
html.replace("%AGIT_LOCATION%", ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getLocation());
html.replace("%AGIT_AUCTION_END%", String.valueOf(format.format(a.getEndDate())));
html.replace("%AGIT_AUCTION_REMAIN%", String.valueOf((a.getEndDate() - System.currentTimeMillis()) / 3600000) + " hours " + String.valueOf((((a.getEndDate() - System.currentTimeMillis()) / 60000) % 60)) + " minutes");
html.replace("%AGIT_AUCTION_MINBID%", String.valueOf(a.getStartingBid()));
html.replace("%AGIT_AUCTION_MYBID%", String.valueOf(a.getBidders().get(player.getClanId()).getBid()));
html.replace("%AGIT_AUCTION_DESC%", ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getDesc());
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_start");
}
else
{
_log.warning("Auctioneer Auction null for AuctionBiddedAt : " + player.getClan().getAuctionBiddedAt());
}
player.sendPacket(html);
return;
}
else if ((player.getClan() != null) && (AuctionManager.getInstance().getAuction(player.getClan().getHideoutId()) != null))
{
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
String filename = "data/html/auction/AgitSaleInfo.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
Auction a = AuctionManager.getInstance().getAuction(player.getClan().getHideoutId());
if (a != null)
{
html.replace("%AGIT_NAME%", a.getItemName());
html.replace("%AGIT_OWNER_PLEDGE_NAME%", a.getSellerClanName());
html.replace("%OWNER_PLEDGE_MASTER%", a.getSellerName());
html.replace("%AGIT_SIZE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getGrade() * 10));
html.replace("%AGIT_LEASE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getLease()));
html.replace("%AGIT_LOCATION%", ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getLocation());
html.replace("%AGIT_AUCTION_END%", String.valueOf(format.format(a.getEndDate())));
html.replace("%AGIT_AUCTION_REMAIN%", String.valueOf((a.getEndDate() - System.currentTimeMillis()) / 3600000) + " hours " + String.valueOf((((a.getEndDate() - System.currentTimeMillis()) / 60000) % 60)) + " minutes");
html.replace("%AGIT_AUCTION_MINBID%", String.valueOf(a.getStartingBid()));
html.replace("%AGIT_AUCTION_BIDCOUNT%", String.valueOf(a.getBidders().size()));
html.replace("%AGIT_AUCTION_DESC%", ClanHallManager.getInstance().getAuctionableHallById(a.getItemId()).getDesc());
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_start");
html.replace("%id%", String.valueOf(a.getId()));
html.replace("%objectId%", String.valueOf(getObjectId()));
}
else
{
_log.warning("Auctioneer Auction null for getHasHideout : " + player.getClan().getHideoutId());
}
player.sendPacket(html);
return;
}
else if ((player.getClan() != null) && (player.getClan().getHideoutId() != 0))
{
int ItemId = player.getClan().getHideoutId();
String filename = "data/html/auction/AgitInfo.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
if (ClanHallManager.getInstance().getAuctionableHallById(ItemId) != null)
{
html.replace("%AGIT_NAME%", ClanHallManager.getInstance().getAuctionableHallById(ItemId).getName());
html.replace("%AGIT_OWNER_PLEDGE_NAME%", player.getClan().getName());
html.replace("%OWNER_PLEDGE_MASTER%", player.getClan().getLeaderName());
html.replace("%AGIT_SIZE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(ItemId).getGrade() * 10));
html.replace("%AGIT_LEASE%", String.valueOf(ClanHallManager.getInstance().getAuctionableHallById(ItemId).getLease()));
html.replace("%AGIT_LOCATION%", ClanHallManager.getInstance().getAuctionableHallById(ItemId).getLocation());
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_start");
html.replace("%objectId%", String.valueOf(getObjectId()));
}
else
{
_log.warning("Clan Hall ID NULL : " + ItemId + " Can be caused by concurent write in ClanHallManager");
}
player.sendPacket(html);
return;
}
else if ((player.getClan() != null) && (player.getClan().getHideoutId() == 0))
{
player.sendPacket(SystemMessageId.THERE_ARE_NO_OFFERINGS_I_OWN_OR_I_MADE_A_BID_FOR);
return;
}
else if (player.getClan() == null)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_REQUIREMENTS_TO_PARTICIPATE_IN_AN_AUCTION);
return;
}
}
else if (actualCommand.equalsIgnoreCase("cancelBid"))
{
long bid = AuctionManager.getInstance().getAuction(player.getClan().getAuctionBiddedAt()).getBidders().get(player.getClanId()).getBid();
String filename = "data/html/auction/AgitBidCancel.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%AGIT_BID%", String.valueOf(bid));
html.replace("%AGIT_BID_REMAIN%", String.valueOf((long) (bid * 0.9)));
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_selectedItems");
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("doCancelBid"))
{
if (AuctionManager.getInstance().getAuction(player.getClan().getAuctionBiddedAt()) != null)
{
AuctionManager.getInstance().getAuction(player.getClan().getAuctionBiddedAt()).cancelBid(player.getClanId());
player.sendPacket(SystemMessageId.YOU_HAVE_CANCELED_YOUR_BID);
}
return;
}
else if (actualCommand.equalsIgnoreCase("cancelAuction"))
{
if (!player.hasClanPrivilege(ClanPrivilege.CH_AUCTION))
{
String filename = "data/html/auction/not_authorized.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
String filename = "data/html/auction/AgitSaleCancel.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%AGIT_DEPOSIT%", String.valueOf(ClanHallManager.getInstance().getClanHallByOwner(player.getClan()).getLease()));
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_selectedItems");
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("doCancelAuction"))
{
if (AuctionManager.getInstance().getAuction(player.getClan().getHideoutId()) != null)
{
AuctionManager.getInstance().getAuction(player.getClan().getHideoutId()).cancelAuction();
player.sendMessage("Your auction has been canceled");
}
return;
}
else if (actualCommand.equalsIgnoreCase("sale2"))
{
String filename = "data/html/auction/AgitSale2.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%AGIT_LAST_PRICE%", String.valueOf(ClanHallManager.getInstance().getClanHallByOwner(player.getClan()).getLease()));
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_sale");
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("sale"))
{
if (!player.hasClanPrivilege(ClanPrivilege.CH_AUCTION))
{
String filename = "data/html/auction/not_authorized.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
String filename = "data/html/auction/AgitSale1.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%AGIT_DEPOSIT%", String.valueOf(ClanHallManager.getInstance().getClanHallByOwner(player.getClan()).getLease()));
html.replace("%AGIT_PLEDGE_ADENA%", String.valueOf(player.getClan().getWarehouse().getAdena()));
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_selectedItems");
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("rebid"))
{
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
if (!player.hasClanPrivilege(ClanPrivilege.CH_AUCTION))
{
String filename = "data/html/auction/not_authorized.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
return;
}
try
{
String filename = "data/html/auction/AgitBid2.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
Auction a = AuctionManager.getInstance().getAuction(player.getClan().getAuctionBiddedAt());
if (a != null)
{
html.replace("%AGIT_AUCTION_BID%", String.valueOf(a.getBidders().get(player.getClanId()).getBid()));
html.replace("%AGIT_AUCTION_MINBID%", String.valueOf(a.getStartingBid()));
html.replace("%AGIT_AUCTION_END%", String.valueOf(format.format(a.getEndDate())));
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_selectedItems");
html.replace("npc_%objectId%_bid1", "npc_" + getObjectId() + "_bid1 " + a.getId());
}
else
{
_log.warning("Auctioneer Auction null for AuctionBiddedAt : " + player.getClan().getAuctionBiddedAt());
}
player.sendPacket(html);
}
catch (Exception e)
{
player.sendMessage("Invalid auction!");
}
return;
}
else if (actualCommand.equalsIgnoreCase("location"))
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/auction/location.htm");
html.replace("%location%", MapRegionManager.getInstance().getClosestTownName(player));
html.replace("%LOCATION%", getPictureName(player));
html.replace("%AGIT_LINK_BACK%", "bypass -h npc_" + getObjectId() + "_start");
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("start"))
{
showChatWindow(player);
return;
}
}
super.onBypassFeedback(player, command);
}
@Override
public void showChatWindow(L2PcInstance player)
{
String filename = "data/html/auction/auction-no.htm";
int condition = validateCondition(player);
if (condition == COND_BUSY_BECAUSE_OF_SIEGE)
{
filename = "data/html/auction/auction-busy.htm"; // Busy because of siege
}
else
{
filename = "data/html/auction/auction.htm";
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcId%", String.valueOf(getId()));
html.replace("%npcname%", getName());
player.sendPacket(html);
}
private int validateCondition(L2PcInstance player)
{
if ((getCastle() != null) && (getCastle().getResidenceId() > 0))
{
if (getCastle().getSiege().isInProgress())
{
return COND_BUSY_BECAUSE_OF_SIEGE; // Busy because of siege
}
return COND_REGULAR;
}
return COND_ALL_FALSE;
}
private String getPictureName(L2PcInstance plyr)
{
int nearestTownId = MapRegionManager.getInstance().getMapRegionLocId(plyr);
String nearestTown;
switch (nearestTownId)
{
case 911:
nearestTown = "GLUDIN";
break;
case 912:
nearestTown = "GLUDIO";
break;
case 916:
nearestTown = "DION";
break;
case 918:
nearestTown = "GIRAN";
break;
case 1537:
nearestTown = "RUNE";
break;
case 1538:
nearestTown = "GODARD";
break;
case 1714:
nearestTown = "SCHUTTGART";
break;
default:
nearestTown = "ADEN";
break;
}
return nearestTown;
}
}

View File

@ -0,0 +1,356 @@
/*
* Copyright (C) 2004-2014 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.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.PetDataTable;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2PetData.L2PetSkillLearn;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.effects.L2EffectType;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.BuffInfo;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
public final class L2BabyPetInstance extends L2PetInstance
{
private static final int BUFF_CONTROL = 5771;
private static final int AWAKENING = 5753;
protected List<SkillHolder> _buffs = null;
protected SkillHolder _majorHeal = null;
protected SkillHolder _minorHeal = null;
protected SkillHolder _recharge = null;
private Future<?> _castTask;
protected boolean _bufferMode = true;
public L2BabyPetInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, L2ItemInstance control)
{
super(objectId, template, owner, control);
setInstanceType(InstanceType.L2BabyPetInstance);
}
public L2BabyPetInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, L2ItemInstance control, byte level)
{
super(objectId, template, owner, control, level);
setInstanceType(InstanceType.L2BabyPetInstance);
}
@Override
public void onSpawn()
{
super.onSpawn();
double healPower = 0;
for (L2PetSkillLearn psl : PetDataTable.getInstance().getPetData(getId()).getAvailableSkills())
{
int id = psl.getSkillId();
int lvl = PetDataTable.getInstance().getPetData(getId()).getAvailableLevel(id, getLevel());
if (lvl == 0)
{
continue;
}
final Skill skill = SkillData.getInstance().getSkill(id, lvl);
if (skill == null)
{
continue;
}
if ((skill.getId() == BUFF_CONTROL) || (skill.getId() == AWAKENING))
{
continue;
}
if (skill.hasEffectType(L2EffectType.MANAHEAL_BY_LEVEL))
{
_recharge = new SkillHolder(skill);
continue;
}
if (skill.hasEffectType(L2EffectType.HEAL))
{
if (healPower == 0)
{
// set both heal types to the same skill
_majorHeal = new SkillHolder(skill);
_minorHeal = _majorHeal;
healPower = skill.getPower();
}
else
{
// another heal skill found - search for most powerful
if (skill.getPower() > healPower)
{
_majorHeal = new SkillHolder(skill);
}
else
{
_minorHeal = new SkillHolder(skill);
}
}
continue;
}
if (skill.isContinuous() && !skill.isDebuff())
{
if (_buffs == null)
{
_buffs = new ArrayList<>();
}
_buffs.add(new SkillHolder(skill));
}
}
startCastTask();
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
stopCastTask();
abortCast();
return true;
}
@Override
public synchronized void unSummon(L2PcInstance owner)
{
stopCastTask();
abortCast();
super.unSummon(owner);
}
@Override
public void doRevive()
{
super.doRevive();
startCastTask();
}
@Override
public void onDecay()
{
super.onDecay();
if (_buffs != null)
{
_buffs.clear();
}
}
private final void startCastTask()
{
if ((_majorHeal != null) || (_buffs != null) || ((_recharge != null) && (_castTask == null) && !isDead()))
{
_castTask = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new CastTask(this), 3000, 2000);
}
}
@Override
public void switchMode()
{
_bufferMode = !_bufferMode;
}
/**
* Verify if this pet is in support mode.
* @return {@code true} if this baby pet is in support mode, {@code false} otherwise
*/
public boolean isInSupportMode()
{
return _bufferMode;
}
private final void stopCastTask()
{
if (_castTask != null)
{
_castTask.cancel(false);
_castTask = null;
}
}
protected void castSkill(Skill skill)
{
// casting automatically stops any other action (such as autofollow or a move-to).
// We need to gather the necessary info to restore the previous state.
final boolean previousFollowStatus = getFollowStatus();
// pet not following and owner outside cast range
if (!previousFollowStatus && !isInsideRadius(getOwner(), skill.getCastRange(), true, true))
{
return;
}
setTarget(getOwner());
useMagic(skill, false, false);
SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_USES_S1);
msg.addSkillName(skill);
sendPacket(msg);
// calling useMagic changes the follow status, if the babypet actually casts
// (as opposed to failing due some factors, such as too low MP, etc).
// if the status has actually been changed, revert it. Else, allow the pet to
// continue whatever it was trying to do.
// NOTE: This is important since the pet may have been told to attack a target.
// reverting the follow status will abort this attack! While aborting the attack
// in order to heal is natural, it is not acceptable to abort the attack on its own,
// merely because the timer stroke and without taking any other action...
if (previousFollowStatus != getFollowStatus())
{
setFollowStatus(previousFollowStatus);
}
}
private class CastTask implements Runnable
{
private final L2BabyPetInstance _baby;
private final List<Skill> _currentBuffs = new ArrayList<>();
public CastTask(L2BabyPetInstance baby)
{
_baby = baby;
}
@Override
public void run()
{
final L2PcInstance owner = _baby.getOwner();
// If the owner doesn't meet the conditions avoid casting.
if ((owner == null) || owner.isDead() || owner.isInvul())
{
return;
}
// If the pet doesn't meet the conditions avoid casting.
if (_baby.isCastingNow() || _baby.isBetrayed() || _baby.isMuted() || _baby.isOutOfControl() || !_bufferMode || (_baby.getAI().getIntention() == CtrlIntention.AI_INTENTION_CAST))
{
return;
}
Skill skill = null;
if (_majorHeal != null)
{
// If the owner's HP is more than 80% for Baby Pets and 70% for Improved Baby pets, do nothing.
// If the owner's HP is very low, under 15% for Baby pets and under 30% for Improved Baby Pets, have 75% chances of using a strong heal.
// Otherwise, have 25% chances for weak heal.
final double hpPercent = owner.getCurrentHp() / owner.getMaxHp();
final boolean isImprovedBaby = isInCategory(CategoryType.BABY_PET_GROUP);
if ((isImprovedBaby && (hpPercent < 0.3)) || (!isImprovedBaby && (hpPercent < 0.15)))
{
skill = _majorHeal.getSkill();
if (!_baby.isSkillDisabled(skill) && (Rnd.get(100) <= 75))
{
if (_baby.getCurrentMp() >= skill.getMpConsume())
{
castSkill(skill);
return;
}
}
}
else if ((_majorHeal.getSkill() != _minorHeal.getSkill()) && ((isImprovedBaby && (hpPercent < 0.7)) || (!isImprovedBaby && (hpPercent < 0.8))))
{
// Cast _minorHeal only if it's different than _majorHeal, then pet has two heals available.
skill = _minorHeal.getSkill();
if (!_baby.isSkillDisabled(skill) && (Rnd.get(100) <= 25))
{
if (_baby.getCurrentMp() >= skill.getMpConsume())
{
castSkill(skill);
return;
}
}
}
}
// Buff Control is not active
if (!_baby.isAffectedBySkill(BUFF_CONTROL))
{
// searching for usable buffs
if ((_buffs != null) && !_buffs.isEmpty())
{
for (SkillHolder buff : _buffs)
{
skill = buff.getSkill();
if (_baby.isSkillDisabled(skill))
{
continue;
}
if (_baby.getCurrentMp() < skill.getMpConsume())
{
continue;
}
// If owner already have the buff, continue.
final BuffInfo buffInfo = owner.getEffectList().getBuffInfoByAbnormalType(skill.getAbnormalType());
if ((buffInfo != null) && (skill.getAbnormalLvl() <= buffInfo.getSkill().getAbnormalLvl()))
{
continue;
}
// If owner have the buff blocked, continue.
if ((owner.getEffectList().getAllBlockedBuffSlots() != null) && owner.getEffectList().getAllBlockedBuffSlots().contains(skill.getAbnormalType()))
{
continue;
}
_currentBuffs.add(skill);
}
}
if (!_currentBuffs.isEmpty())
{
skill = _currentBuffs.get(Rnd.get(_currentBuffs.size()));
castSkill(skill);
_currentBuffs.clear();
return;
}
}
// buffs/heal not casted, trying recharge, if exist recharge casted only if owner in combat stance.
if ((_recharge != null) && owner.isInCombat() && ((owner.getCurrentMp() / owner.getMaxMp()) < 0.6) && (Rnd.get(100) <= 60))
{
skill = _recharge.getSkill();
if (!_baby.isSkillDisabled(skill) && (_baby.getCurrentMp() >= skill.getMpConsume()))
{
castSkill(skill);
}
}
}
}
}

View File

@ -0,0 +1,171 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.datatables.ItemTable;
import com.l2jserver.gameserver.model.ArenaParticipantsHolder;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.BlockCheckerEngine;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.ExCubeGameChangePoints;
import com.l2jserver.gameserver.network.serverpackets.ExCubeGameExtendedChangePoints;
import com.l2jserver.gameserver.network.serverpackets.NpcInfo;
import com.l2jserver.util.Rnd;
/**
* @author BiggBoss
*/
public class L2BlockInstance extends L2MonsterInstance
{
private int _colorEffect;
/**
* @param objectId
* @param template
*/
public L2BlockInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
/**
* Will change the color of the block and update the appearance in the known players clients
* @param attacker
* @param holder
* @param team
*/
public void changeColor(L2PcInstance attacker, ArenaParticipantsHolder holder, int team)
{
// Do not update color while sending old info
synchronized (this)
{
final BlockCheckerEngine event = holder.getEvent();
if (_colorEffect == 0x53)
{
// Change color
_colorEffect = 0x00;
// BroadCast to all known players
broadcastPacket(new NpcInfo(this));
increaseTeamPointsAndSend(attacker, team, event);
}
else
{
// Change color
_colorEffect = 0x53;
// BroadCast to all known players
broadcastPacket(new NpcInfo(this));
increaseTeamPointsAndSend(attacker, team, event);
}
// 30% chance to drop the event items
int random = Rnd.get(100);
// Bond
if ((random > 69) && (random <= 84))
{
dropItem(13787, event, attacker);
}
else if (random > 84)
{
dropItem(13788, event, attacker);
}
}
}
/**
* Sets if the block is red or blue. Mainly used in block spawn
* @param isRed
*/
public void setRed(boolean isRed)
{
_colorEffect = isRed ? 0x53 : 0x00;
}
/**
* @return {@code true} if the block is red at this moment, {@code false} otherwise
*/
@Override
public int getColorEffect()
{
return _colorEffect;
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
if (attacker instanceof L2PcInstance)
{
return (attacker.getActingPlayer() != null) && (attacker.getActingPlayer().getBlockCheckerArena() > -1);
}
return true;
}
@Override
public boolean doDie(L2Character killer)
{
return false;
}
@Override
public void onAction(L2PcInstance player, boolean interact)
{
if (!canTarget(player))
{
return;
}
player.setLastFolkNPC(this);
if (player.getTarget() != this)
{
player.setTarget(this);
getAI(); // wake up ai
}
else if (interact)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
private void increaseTeamPointsAndSend(L2PcInstance player, int team, BlockCheckerEngine eng)
{
eng.increasePlayerPoints(player, team);
int timeLeft = (int) ((eng.getStarterTime() - System.currentTimeMillis()) / 1000);
boolean isRed = eng.getHolder().getRedPlayers().contains(player);
ExCubeGameChangePoints changePoints = new ExCubeGameChangePoints(timeLeft, eng.getBluePoints(), eng.getRedPoints());
ExCubeGameExtendedChangePoints secretPoints = new ExCubeGameExtendedChangePoints(timeLeft, eng.getBluePoints(), eng.getRedPoints(), isRed, player, eng.getPlayerPoints(player, isRed));
eng.getHolder().broadCastPacketToTeam(changePoints);
eng.getHolder().broadCastPacketToTeam(secretPoints);
}
private void dropItem(int id, BlockCheckerEngine eng, L2PcInstance player)
{
L2ItemInstance drop = ItemTable.getInstance().createItem("Loot", id, 1, player, this);
int x = getX() + Rnd.get(50);
int y = getY() + Rnd.get(50);
int z = getZ();
drop.dropMe(this, x, y, z);
eng.addNewDrop(drop);
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright (C) 2004-2014 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.logging.Logger;
import com.l2jserver.gameserver.ai.L2BoatAI;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Vehicle;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.network.serverpackets.VehicleDeparture;
import com.l2jserver.gameserver.network.serverpackets.VehicleInfo;
import com.l2jserver.gameserver.network.serverpackets.VehicleStarted;
/**
* @author Maktakien, DS
*/
public class L2BoatInstance extends L2Vehicle
{
protected static final Logger _logBoat = Logger.getLogger(L2BoatInstance.class.getName());
public L2BoatInstance(int objectId, L2CharTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2BoatInstance);
setAI(new L2BoatAI(new AIAccessor()));
}
@Override
public boolean isBoat()
{
return true;
}
@Override
public int getId()
{
return 0;
}
@Override
public boolean moveToNextRoutePoint()
{
final boolean result = super.moveToNextRoutePoint();
if (result)
{
broadcastPacket(new VehicleDeparture(this));
}
return result;
}
@Override
public void oustPlayer(L2PcInstance player)
{
super.oustPlayer(player);
final Location loc = getOustLoc();
if (player.isOnline())
{
player.teleToLocation(loc.getX(), loc.getY(), loc.getZ());
}
else
{
player.setXYZInvisible(loc.getX(), loc.getY(), loc.getZ()); // disconnects handling
}
}
@Override
public void stopMove(Location loc, boolean updateKnownObjects)
{
super.stopMove(loc, updateKnownObjects);
broadcastPacket(new VehicleStarted(this, 0));
broadcastPacket(new VehicleInfo(this));
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
activeChar.sendPacket(new VehicleInfo(this));
}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2004-2014 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.StringTokenizer;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.ClanPrivilege;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
public class L2CastleDoormenInstance extends L2DoormenInstance
{
public L2CastleDoormenInstance(int objectID, L2NpcTemplate template)
{
super(objectID, template);
setInstanceType(InstanceType.L2CastleDoormenInstance);
}
@Override
protected final void openDoors(L2PcInstance player, String command)
{
StringTokenizer st = new StringTokenizer(command.substring(10), ", ");
st.nextToken();
while (st.hasMoreTokens())
{
if (getConquerableHall() != null)
{
getConquerableHall().openCloseDoor(Integer.parseInt(st.nextToken()), true);
}
else
{
getCastle().openDoor(player, Integer.parseInt(st.nextToken()));
}
}
}
@Override
protected final void closeDoors(L2PcInstance player, String command)
{
StringTokenizer st = new StringTokenizer(command.substring(11), ", ");
st.nextToken();
while (st.hasMoreTokens())
{
if (getConquerableHall() != null)
{
getConquerableHall().openCloseDoor(Integer.parseInt(st.nextToken()), false);
}
else
{
getCastle().closeDoor(player, Integer.parseInt(st.nextToken()));
}
}
}
@Override
protected final boolean isOwnerClan(L2PcInstance player)
{
if ((player.getClan() != null) && player.hasClanPrivilege(ClanPrivilege.CS_OPEN_DOOR))
{
SiegableHall hall = getConquerableHall();
// save in variable because it's a costly call
if (hall != null)
{
if (player.getClanId() == hall.getOwnerId())
{
return true;
}
}
else if (getCastle() != null)
{
if (player.getClanId() == getCastle().getOwnerId())
{
return true;
}
}
}
return false;
}
@Override
protected final boolean isUnderSiege()
{
SiegableHall hall = getConquerableHall();
if (hall != null)
{
return hall.isInSiege();
}
return getCastle().getZone().isActive();
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
/**
* This class manages all chest.
* @author Julian
*/
public final class L2ChestInstance extends L2MonsterInstance
{
private volatile boolean _specialDrop;
public L2ChestInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2ChestInstance);
setIsNoRndWalk(true);
_specialDrop = false;
}
@Override
public void onSpawn()
{
super.onSpawn();
_specialDrop = false;
setMustRewardExpSp(true);
}
public synchronized void setSpecialDrop()
{
_specialDrop = true;
}
@Override
public void doItemDrop(L2NpcTemplate npcTemplate, L2Character lastAttacker)
{
int id = getTemplate().getId();
if (!_specialDrop)
{
if ((id >= 18265) && (id <= 18286))
{
id += 3536;
}
else if ((id == 18287) || (id == 18288))
{
id = 21671;
}
else if ((id == 18289) || (id == 18290))
{
id = 21694;
}
else if ((id == 18291) || (id == 18292))
{
id = 21717;
}
else if ((id == 18293) || (id == 18294))
{
id = 21740;
}
else if ((id == 18295) || (id == 18296))
{
id = 21763;
}
else if ((id == 18297) || (id == 18298))
{
id = 21786;
}
}
super.doItemDrop(NpcData.getInstance().getTemplate(id), lastAttacker);
}
@Override
public boolean isMovementDisabled()
{
return true;
}
@Override
public boolean hasRandomAnimation()
{
return false;
}
}

View File

@ -0,0 +1,212 @@
/*
* Copyright (C) 2004-2014 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.Arrays;
import java.util.StringTokenizer;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.ClanHallManager;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.ClanHall;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.util.Evolve;
public class L2ClanHallDoormenInstance extends L2DoormenInstance
{
private volatile boolean _init = false;
private ClanHall _clanHall = null;
private boolean _hasEvolve = false;
// list of clan halls with evolve function, should be sorted
private static final int[] CH_WITH_EVOLVE =
{
36,
37,
38,
39,
40,
41,
51,
52,
53,
54,
55,
56,
57
};
public L2ClanHallDoormenInstance(int objectID, L2NpcTemplate template)
{
super(objectID, template);
setInstanceType(InstanceType.L2ClanHallDoormenInstance);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (_hasEvolve && command.startsWith("evolve"))
{
if (isOwnerClan(player))
{
StringTokenizer st = new StringTokenizer(command, " ");
if (st.countTokens() < 2)
{
return;
}
st.nextToken();
boolean ok = false;
switch (Integer.parseInt(st.nextToken()))
{
case 1:
ok = Evolve.doEvolve(player, this, 9882, 10307, 55);
break;
case 2:
ok = Evolve.doEvolve(player, this, 4422, 10308, 55);
break;
case 3:
ok = Evolve.doEvolve(player, this, 4423, 10309, 55);
break;
case 4:
ok = Evolve.doEvolve(player, this, 4424, 10310, 55);
break;
case 5:
ok = Evolve.doEvolve(player, this, 10426, 10611, 70);
break;
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (ok)
{
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/evolve-ok.htm");
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/evolve-no.htm");
}
player.sendPacket(html);
return;
}
}
super.onBypassFeedback(player, command);
}
@Override
public void showChatWindow(L2PcInstance player)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (getClanHall() != null)
{
L2Clan owner = ClanTable.getInstance().getClan(getClanHall().getOwnerId());
if (isOwnerClan(player))
{
if (_hasEvolve)
{
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/doormen2.htm");
html.replace("%clanname%", owner.getName());
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/doormen1.htm");
html.replace("%clanname%", owner.getName());
}
}
else
{
if ((owner != null) && (owner.getLeader() != null))
{
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/doormen-no.htm");
html.replace("%leadername%", owner.getLeaderName());
html.replace("%clanname%", owner.getName());
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/emptyowner.htm");
html.replace("%hallname%", getClanHall().getName());
}
}
}
else
{
return;
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
@Override
protected final void openDoors(L2PcInstance player, String command)
{
getClanHall().openCloseDoors(true);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/doormen-opened.htm");
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
@Override
protected final void closeDoors(L2PcInstance player, String command)
{
getClanHall().openCloseDoors(false);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/clanHallDoormen/doormen-closed.htm");
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
private final ClanHall getClanHall()
{
if (!_init)
{
synchronized (this)
{
if (!_init)
{
_clanHall = ClanHallManager.getInstance().getNearbyClanHall(getX(), getY(), 500);
if (_clanHall != null)
{
_hasEvolve = Arrays.binarySearch(CH_WITH_EVOLVE, _clanHall.getId()) >= 0;
}
_init = true;
}
}
}
return _clanHall;
}
@Override
protected final boolean isOwnerClan(L2PcInstance player)
{
if ((player.getClan() != null) && (getClanHall() != null))
{
if (player.getClanId() == getClanHall().getOwnerId())
{
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,480 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.Config;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.ClassListData;
import com.l2jserver.gameserver.datatables.ItemTable;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.ClassId;
import com.l2jserver.gameserver.model.holders.ItemHolder;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.network.serverpackets.TutorialCloseHtml;
import com.l2jserver.gameserver.network.serverpackets.TutorialShowHtml;
import com.l2jserver.gameserver.network.serverpackets.TutorialShowQuestionMark;
import com.l2jserver.gameserver.network.serverpackets.UserInfo;
import com.l2jserver.util.StringUtil;
/**
* This class ...
* @version $Revision: 1.4.2.1.2.7 $ $Date: 2005/03/27 15:29:32 $
*/
public final class L2ClassMasterInstance extends L2MerchantInstance
{
/**
* @param objectId
* @param template
*/
public L2ClassMasterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2ClassMasterInstance);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/classmaster/" + pom + ".htm";
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (command.startsWith("1stClass"))
{
showHtmlMenu(player, getObjectId(), 1);
}
else if (command.startsWith("2ndClass"))
{
showHtmlMenu(player, getObjectId(), 2);
}
else if (command.startsWith("3rdClass"))
{
showHtmlMenu(player, getObjectId(), 3);
}
else if (command.startsWith("change_class"))
{
int val = Integer.parseInt(command.substring(13));
if (checkAndChangeClass(player, val))
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/ok.htm");
html.replace("%name%", ClassListData.getInstance().getClass(val).getClientCode());
player.sendPacket(html);
}
}
else if (command.startsWith("become_noble"))
{
if (!player.isNoble())
{
player.setNoble(true);
player.sendPacket(new UserInfo(player));
player.sendPacket(new ExBrExtraUserInfo(player));
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/nobleok.htm");
player.sendPacket(html);
}
}
else if (command.startsWith("learn_skills"))
{
player.giveAvailableSkills(Config.AUTO_LEARN_FS_SKILLS, true);
}
else if (command.startsWith("increase_clan_level"))
{
if (!player.isClanLeader())
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/noclanleader.htm");
player.sendPacket(html);
}
else if (player.getClan().getLevel() >= 5)
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/noclanlevel.htm");
player.sendPacket(html);
}
else
{
player.getClan().changeLevel(5);
}
}
else
{
super.onBypassFeedback(player, command);
}
}
public static final void onTutorialLink(L2PcInstance player, String request)
{
if (!Config.ALTERNATE_CLASS_MASTER || (request == null) || !request.startsWith("CO"))
{
return;
}
if (!player.getFloodProtectors().getServerBypass().tryPerformAction("changeclass"))
{
return;
}
try
{
int val = Integer.parseInt(request.substring(2));
checkAndChangeClass(player, val);
}
catch (NumberFormatException e)
{
}
player.sendPacket(TutorialCloseHtml.STATIC_PACKET);
}
public static final void onTutorialQuestionMark(L2PcInstance player, int number)
{
if (!Config.ALTERNATE_CLASS_MASTER || (number != 1001))
{
return;
}
showTutorialHtml(player);
}
public static final void showQuestionMark(L2PcInstance player)
{
if (!Config.ALTERNATE_CLASS_MASTER)
{
return;
}
final ClassId classId = player.getClassId();
if (getMinLevel(classId.level()) > player.getLevel())
{
return;
}
if (!Config.CLASS_MASTER_SETTINGS.isAllowed(classId.level() + 1))
{
return;
}
player.sendPacket(new TutorialShowQuestionMark(1001));
}
private static final void showHtmlMenu(L2PcInstance player, int objectId, int level)
{
final NpcHtmlMessage html = new NpcHtmlMessage(objectId);
if (!Config.ALLOW_CLASS_MASTERS)
{
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/disabled.htm");
}
else if (!Config.CLASS_MASTER_SETTINGS.isAllowed(level))
{
final int jobLevel = player.getClassId().level();
final StringBuilder sb = new StringBuilder(100);
sb.append("<html><body>");
switch (jobLevel)
{
case 0:
if (Config.CLASS_MASTER_SETTINGS.isAllowed(1))
{
sb.append("Come back here when you reached level 20 to change your class.<br>");
}
else if (Config.CLASS_MASTER_SETTINGS.isAllowed(2))
{
sb.append("Come back after your first occupation change.<br>");
}
else if (Config.CLASS_MASTER_SETTINGS.isAllowed(3))
{
sb.append("Come back after your second occupation change.<br>");
}
else
{
sb.append("I can't change your occupation.<br>");
}
break;
case 1:
if (Config.CLASS_MASTER_SETTINGS.isAllowed(2))
{
sb.append("Come back here when you reached level 40 to change your class.<br>");
}
else if (Config.CLASS_MASTER_SETTINGS.isAllowed(3))
{
sb.append("Come back after your second occupation change.<br>");
}
else
{
sb.append("I can't change your occupation.<br>");
}
break;
case 2:
if (Config.CLASS_MASTER_SETTINGS.isAllowed(3))
{
sb.append("Come back here when you reached level 76 to change your class.<br>");
}
else
{
sb.append("I can't change your occupation.<br>");
}
break;
case 3:
sb.append("There is no class change available for you anymore.<br>");
break;
}
sb.append("</body></html>");
html.setHtml(sb.toString());
}
else
{
final ClassId currentClassId = player.getClassId();
if (currentClassId.level() >= level)
{
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/nomore.htm");
}
else
{
final int minLevel = getMinLevel(currentClassId.level());
if ((player.getLevel() >= minLevel) || Config.ALLOW_ENTIRE_TREE)
{
final StringBuilder menu = new StringBuilder(100);
for (ClassId cid : ClassId.values())
{
if ((cid == ClassId.INSPECTOR) && (player.getTotalSubClasses() < 2))
{
continue;
}
if (validateClassId(currentClassId, cid) && (cid.level() == level))
{
StringUtil.append(menu, "<a action=\"bypass -h npc_%objectId%_change_class ", String.valueOf(cid.getId()), "\">", ClassListData.getInstance().getClass(cid).getClientCode(), "</a><br>");
}
}
if (menu.length() > 0)
{
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/template.htm");
html.replace("%name%", ClassListData.getInstance().getClass(currentClassId).getClientCode());
html.replace("%menu%", menu.toString());
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/comebacklater.htm");
html.replace("%level%", String.valueOf(getMinLevel(level - 1)));
}
}
else
{
if (minLevel < Integer.MAX_VALUE)
{
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/comebacklater.htm");
html.replace("%level%", String.valueOf(minLevel));
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/classmaster/nomore.htm");
}
}
}
}
html.replace("%objectId%", String.valueOf(objectId));
html.replace("%req_items%", getRequiredItems(level));
player.sendPacket(html);
}
private static final void showTutorialHtml(L2PcInstance player)
{
final ClassId currentClassId = player.getClassId();
if ((getMinLevel(currentClassId.level()) > player.getLevel()) && !Config.ALLOW_ENTIRE_TREE)
{
return;
}
String msg = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/classmaster/tutorialtemplate.htm");
msg = msg.replaceAll("%name%", ClassListData.getInstance().getClass(currentClassId).getEscapedClientCode());
final StringBuilder menu = new StringBuilder(100);
for (ClassId cid : ClassId.values())
{
if ((cid == ClassId.INSPECTOR) && (player.getTotalSubClasses() < 2))
{
continue;
}
if (validateClassId(currentClassId, cid))
{
StringUtil.append(menu, "<a action=\"link CO", String.valueOf(cid.getId()), "\">", ClassListData.getInstance().getClass(cid).getEscapedClientCode(), "</a><br>");
}
}
msg = msg.replaceAll("%menu%", menu.toString());
msg = msg.replace("%req_items%", getRequiredItems(currentClassId.level() + 1));
player.sendPacket(new TutorialShowHtml(msg));
}
private static final boolean checkAndChangeClass(L2PcInstance player, int val)
{
final ClassId currentClassId = player.getClassId();
if ((getMinLevel(currentClassId.level()) > player.getLevel()) && !Config.ALLOW_ENTIRE_TREE)
{
return false;
}
if (!validateClassId(currentClassId, val))
{
return false;
}
final int newJobLevel = currentClassId.level() + 1;
// Weight/Inventory check
if (!Config.CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).isEmpty() && !player.isInventoryUnder90(false))
{
player.sendPacket(SystemMessageId.UNABLE_TO_PROCESS_THIS_REQUEST_UNTIL_YOUR_INVENTORY_S_WEIGHT_AND_SLOT_COUNT_ARE_LESS_THAN_80_PERCENT_OF_CAPACITY);
return false;
}
// check if player have all required items for class transfer
for (ItemHolder holder : Config.CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel))
{
if (player.getInventory().getInventoryItemCount(holder.getId(), -1) < holder.getCount())
{
player.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT2);
return false;
}
}
// get all required items for class transfer
for (ItemHolder holder : Config.CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel))
{
if (!player.destroyItemByItemId("ClassMaster", holder.getId(), holder.getCount(), player, true))
{
return false;
}
}
// reward player with items
for (ItemHolder holder : Config.CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel))
{
player.addItem("ClassMaster", holder.getId(), holder.getCount(), player, true);
}
player.setClassId(val);
if (player.isSubClassActive())
{
player.getSubClasses().get(player.getClassIndex()).setClassId(player.getActiveClass());
}
else
{
player.setBaseClass(player.getActiveClass());
}
player.broadcastUserInfo();
if (Config.CLASS_MASTER_SETTINGS.isAllowed(player.getClassId().level() + 1) && Config.ALTERNATE_CLASS_MASTER && (((player.getClassId().level() == 1) && (player.getLevel() >= 40)) || ((player.getClassId().level() == 2) && (player.getLevel() >= 76))))
{
showQuestionMark(player);
}
return true;
}
/**
* @param level - current skillId level (0 - start, 1 - first, etc)
* @return minimum player level required for next class transfer
*/
private static final int getMinLevel(int level)
{
switch (level)
{
case 0:
return 20;
case 1:
return 40;
case 2:
return 76;
default:
return Integer.MAX_VALUE;
}
}
/**
* Returns true if class change is possible
* @param oldCID current player ClassId
* @param val new class index
* @return
*/
private static final boolean validateClassId(ClassId oldCID, int val)
{
return validateClassId(oldCID, ClassId.getClassId(val));
}
/**
* Returns true if class change is possible
* @param oldCID current player ClassId
* @param newCID new ClassId
* @return true if class change is possible
*/
private static final boolean validateClassId(ClassId oldCID, ClassId newCID)
{
if ((newCID == null) || (newCID.getRace() == null))
{
return false;
}
if (oldCID.equals(newCID.getParent()))
{
return true;
}
if (Config.ALLOW_ENTIRE_TREE && newCID.childOf(oldCID))
{
return true;
}
return false;
}
private static String getRequiredItems(int level)
{
if ((Config.CLASS_MASTER_SETTINGS.getRequireItems(level) == null) || Config.CLASS_MASTER_SETTINGS.getRequireItems(level).isEmpty())
{
return "<tr><td>none</td></tr>";
}
final StringBuilder sb = new StringBuilder();
for (ItemHolder holder : Config.CLASS_MASTER_SETTINGS.getRequireItems(level))
{
sb.append("<tr><td><font color=\"LEVEL\">" + holder.getCount() + "</font></td><td>" + ItemTable.getInstance().getTemplate(holder.getId()).getName() + "</td></tr>");
}
return sb.toString();
}
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2004-2014 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.List;
import java.util.logging.Level;
import javolution.util.FastList;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Tower;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
/**
* Class for Control Tower instance.
*/
public class L2ControlTowerInstance extends L2Tower
{
private volatile List<L2Spawn> _guards;
public L2ControlTowerInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2ControlTowerInstance);
}
@Override
public boolean doDie(L2Character killer)
{
if (getCastle().getSiege().isInProgress())
{
getCastle().getSiege().killedCT(this);
if ((_guards != null) && !_guards.isEmpty())
{
for (L2Spawn spawn : _guards)
{
if (spawn == null)
{
continue;
}
try
{
spawn.stopRespawn();
// spawn.getLastSpawn().doDie(spawn.getLastSpawn());
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error at L2ControlTowerInstance", e);
}
}
_guards.clear();
}
}
return super.doDie(killer);
}
public void registerGuard(L2Spawn guard)
{
getGuards().add(guard);
}
private final List<L2Spawn> getGuards()
{
if (_guards == null)
{
synchronized (this)
{
if (_guards == null)
{
_guards = new FastList<>();
}
}
}
return _guards;
}
}

View File

@ -0,0 +1,343 @@
/*
* Copyright (C) 2004-2014 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;
public L2ControllableAirShipInstance(int objectId, L2CharTemplate template, int ownerId)
{
super(objectId, 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;
}
}
updateAbnormalEffect();
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);
updateAbnormalEffect();
}
}
}
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();
}
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.ai.L2CharacterAI;
import com.l2jserver.gameserver.ai.L2ControllableMobAI;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
/**
* @author littlecrow
*/
public class L2ControllableMobInstance extends L2MonsterInstance
{
private boolean _isInvul;
protected class ControllableAIAcessor extends AIAccessor
{
@Override
public void detachAI()
{
// do nothing, AI of controllable mobs can't be detached automatically
}
}
@Override
public boolean isAggressive()
{
return true;
}
@Override
public int getAggroRange()
{
// force mobs to be aggro
return 500;
}
public L2ControllableMobInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2ControllableMobInstance);
}
@Override
protected L2CharacterAI initAI()
{
return new L2ControllableMobAI(new ControllableAIAcessor());
}
@Override
public boolean isInvul()
{
return _isInvul;
}
public void setInvul(boolean isInvul)
{
_isInvul = isInvul;
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
setAI(null);
return true;
}
}

View File

@ -0,0 +1,782 @@
/*
* Copyright (C) 2004-2014 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.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlEvent;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.instancemanager.DuelManager;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.tasks.cubics.CubicAction;
import com.l2jserver.gameserver.model.actor.tasks.cubics.CubicDisappear;
import com.l2jserver.gameserver.model.actor.tasks.cubics.CubicHeal;
import com.l2jserver.gameserver.model.effects.L2EffectType;
import com.l2jserver.gameserver.model.entity.TvTEvent;
import com.l2jserver.gameserver.model.entity.TvTEventTeam;
import com.l2jserver.gameserver.model.interfaces.IIdentifiable;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.stats.Formulas;
import com.l2jserver.gameserver.model.stats.Stats;
import com.l2jserver.gameserver.model.zone.ZoneId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.util.Rnd;
public final class L2CubicInstance implements IIdentifiable
{
private static final Logger _log = Logger.getLogger(L2CubicInstance.class.getName());
// Type of Cubics
public static final int STORM_CUBIC = 1;
public static final int VAMPIRIC_CUBIC = 2;
public static final int LIFE_CUBIC = 3;
public static final int VIPER_CUBIC = 4;
public static final int POLTERGEIST_CUBIC = 5;
public static final int BINDING_CUBIC = 6;
public static final int AQUA_CUBIC = 7;
public static final int SPARK_CUBIC = 8;
public static final int ATTRACT_CUBIC = 9;
public static final int SMART_CUBIC_EVATEMPLAR = 10;
public static final int SMART_CUBIC_SHILLIENTEMPLAR = 11;
public static final int SMART_CUBIC_ARCANALORD = 12;
public static final int SMART_CUBIC_ELEMENTALMASTER = 13;
public static final int SMART_CUBIC_SPECTRALMASTER = 14;
// Max range of cubic skills
// TODO: Check/fix the max range
public static final int MAX_MAGIC_RANGE = 900;
// Cubic skills
public static final int SKILL_CUBIC_HEAL = 4051;
public static final int SKILL_CUBIC_CURE = 5579;
private final L2PcInstance _owner;
private L2Character _target;
private final int _cubicId;
private final int _cubicPower;
private final int _cubicDelay;
private final int _cubicSkillChance;
private final int _cubicMaxCount;
private boolean _active;
private final boolean _givenByOther;
private final List<Skill> _skills = new ArrayList<>();
private Future<?> _disappearTask;
private Future<?> _actionTask;
public L2CubicInstance(L2PcInstance owner, int cubicId, int level, int cubicPower, int cubicDelay, int cubicSkillChance, int cubicMaxCount, int cubicDuration, boolean givenByOther)
{
_owner = owner;
_cubicId = cubicId;
_cubicPower = cubicPower;
_cubicDelay = cubicDelay * 1000;
_cubicSkillChance = cubicSkillChance;
_cubicMaxCount = cubicMaxCount;
_active = false;
_givenByOther = givenByOther;
switch (_cubicId)
{
case STORM_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4049, level));
break;
case VAMPIRIC_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4050, level));
break;
case LIFE_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4051, level));
doAction();
break;
case VIPER_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4052, level));
break;
case POLTERGEIST_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4053, level));
_skills.add(SkillData.getInstance().getSkill(4054, level));
_skills.add(SkillData.getInstance().getSkill(4055, level));
break;
case BINDING_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4164, level));
break;
case AQUA_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4165, level));
break;
case SPARK_CUBIC:
_skills.add(SkillData.getInstance().getSkill(4166, level));
break;
case ATTRACT_CUBIC:
_skills.add(SkillData.getInstance().getSkill(5115, level));
_skills.add(SkillData.getInstance().getSkill(5116, level));
break;
case SMART_CUBIC_ARCANALORD:
_skills.add(SkillData.getInstance().getSkill(4051, 7));
_skills.add(SkillData.getInstance().getSkill(4165, 9));
break;
case SMART_CUBIC_ELEMENTALMASTER:
_skills.add(SkillData.getInstance().getSkill(4049, 8));
_skills.add(SkillData.getInstance().getSkill(4166, 9));
break;
case SMART_CUBIC_SPECTRALMASTER:
_skills.add(SkillData.getInstance().getSkill(4049, 8));
_skills.add(SkillData.getInstance().getSkill(4052, 6));
break;
case SMART_CUBIC_EVATEMPLAR:
_skills.add(SkillData.getInstance().getSkill(4053, 8));
_skills.add(SkillData.getInstance().getSkill(4165, 9));
break;
case SMART_CUBIC_SHILLIENTEMPLAR:
_skills.add(SkillData.getInstance().getSkill(4049, 8));
_skills.add(SkillData.getInstance().getSkill(5115, 4));
break;
}
_disappearTask = ThreadPoolManager.getInstance().scheduleGeneral(new CubicDisappear(this), cubicDuration * 1000); // disappear
}
public synchronized void doAction()
{
if (_active)
{
return;
}
_active = true;
switch (_cubicId)
{
case AQUA_CUBIC:
case BINDING_CUBIC:
case SPARK_CUBIC:
case STORM_CUBIC:
case POLTERGEIST_CUBIC:
case VAMPIRIC_CUBIC:
case VIPER_CUBIC:
case ATTRACT_CUBIC:
case SMART_CUBIC_ARCANALORD:
case SMART_CUBIC_ELEMENTALMASTER:
case SMART_CUBIC_SPECTRALMASTER:
case SMART_CUBIC_EVATEMPLAR:
case SMART_CUBIC_SHILLIENTEMPLAR:
_actionTask = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new CubicAction(this, _cubicSkillChance), 0, _cubicDelay);
break;
case LIFE_CUBIC:
_actionTask = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new CubicHeal(this), 0, _cubicDelay);
break;
}
}
@Override
public int getId()
{
return _cubicId;
}
public L2PcInstance getOwner()
{
return _owner;
}
public int getCubicPower()
{
return _cubicPower;
}
public L2Character getTarget()
{
return _target;
}
public void setTarget(L2Character target)
{
_target = target;
}
public List<Skill> getSkills()
{
return _skills;
}
public int getCubicMaxCount()
{
return _cubicMaxCount;
}
public void stopAction()
{
_target = null;
if (_actionTask != null)
{
_actionTask.cancel(true);
_actionTask = null;
}
_active = false;
}
public void cancelDisappear()
{
if (_disappearTask != null)
{
_disappearTask.cancel(true);
_disappearTask = null;
}
}
/** this sets the enemy target for a cubic */
public void getCubicTarget()
{
try
{
_target = null;
L2Object ownerTarget = _owner.getTarget();
if (ownerTarget == null)
{
return;
}
// TvT event targeting
if (TvTEvent.isStarted() && TvTEvent.isPlayerParticipant(_owner.getObjectId()))
{
TvTEventTeam enemyTeam = TvTEvent.getParticipantEnemyTeam(_owner.getObjectId());
if (ownerTarget.getActingPlayer() != null)
{
L2PcInstance target = ownerTarget.getActingPlayer();
if (enemyTeam.containsPlayer(target.getObjectId()) && !(target.isDead()))
{
_target = (L2Character) ownerTarget;
}
}
return;
}
// Duel targeting
if (_owner.isInDuel())
{
L2PcInstance PlayerA = DuelManager.getInstance().getDuel(_owner.getDuelId()).getPlayerA();
L2PcInstance PlayerB = DuelManager.getInstance().getDuel(_owner.getDuelId()).getPlayerB();
if (DuelManager.getInstance().getDuel(_owner.getDuelId()).isPartyDuel())
{
L2Party partyA = PlayerA.getParty();
L2Party partyB = PlayerB.getParty();
L2Party partyEnemy = null;
if (partyA != null)
{
if (partyA.getMembers().contains(_owner))
{
if (partyB != null)
{
partyEnemy = partyB;
}
else
{
_target = PlayerB;
}
}
else
{
partyEnemy = partyA;
}
}
else
{
if (PlayerA == _owner)
{
if (partyB != null)
{
partyEnemy = partyB;
}
else
{
_target = PlayerB;
}
}
else
{
_target = PlayerA;
}
}
if ((_target == PlayerA) || (_target == PlayerB))
{
if (_target == ownerTarget)
{
return;
}
}
if (partyEnemy != null)
{
if (partyEnemy.getMembers().contains(ownerTarget))
{
_target = (L2Character) ownerTarget;
}
return;
}
}
if ((PlayerA != _owner) && (ownerTarget == PlayerA))
{
_target = PlayerA;
return;
}
if ((PlayerB != _owner) && (ownerTarget == PlayerB))
{
_target = PlayerB;
return;
}
_target = null;
return;
}
// Olympiad targeting
if (_owner.isInOlympiadMode())
{
if (_owner.isOlympiadStart())
{
if (ownerTarget instanceof L2Playable)
{
final L2PcInstance targetPlayer = ownerTarget.getActingPlayer();
if ((targetPlayer != null) && (targetPlayer.getOlympiadGameId() == _owner.getOlympiadGameId()) && (targetPlayer.getOlympiadSide() != _owner.getOlympiadSide()))
{
_target = (L2Character) ownerTarget;
}
}
}
return;
}
// test owners target if it is valid then use it
if ((ownerTarget instanceof L2Character) && (ownerTarget != _owner.getSummon()) && (ownerTarget != _owner))
{
// target mob which has aggro on you or your summon
if (ownerTarget instanceof L2Attackable)
{
if ((((L2Attackable) ownerTarget).getAggroList().get(_owner) != null) && !((L2Attackable) ownerTarget).isDead())
{
_target = (L2Character) ownerTarget;
return;
}
if (_owner.hasSummon())
{
if ((((L2Attackable) ownerTarget).getAggroList().get(_owner.getSummon()) != null) && !((L2Attackable) ownerTarget).isDead())
{
_target = (L2Character) ownerTarget;
return;
}
}
}
// get target in pvp or in siege
L2PcInstance enemy = null;
if (((_owner.getPvpFlag() > 0) && !_owner.isInsideZone(ZoneId.PEACE)) || _owner.isInsideZone(ZoneId.PVP))
{
if (!((L2Character) ownerTarget).isDead())
{
enemy = ownerTarget.getActingPlayer();
}
if (enemy != null)
{
boolean targetIt = true;
if (_owner.getParty() != null)
{
if (_owner.getParty().getMembers().contains(enemy))
{
targetIt = false;
}
else if (_owner.getParty().getCommandChannel() != null)
{
if (_owner.getParty().getCommandChannel().getMembers().contains(enemy))
{
targetIt = false;
}
}
}
if ((_owner.getClan() != null) && !_owner.isInsideZone(ZoneId.PVP))
{
if (_owner.getClan().isMember(enemy.getObjectId()))
{
targetIt = false;
}
if ((_owner.getAllyId() > 0) && (enemy.getAllyId() > 0))
{
if (_owner.getAllyId() == enemy.getAllyId())
{
targetIt = false;
}
}
}
if ((enemy.getPvpFlag() == 0) && !enemy.isInsideZone(ZoneId.PVP))
{
targetIt = false;
}
if (enemy.isInsideZone(ZoneId.PEACE))
{
targetIt = false;
}
if ((_owner.getSiegeState() > 0) && (_owner.getSiegeState() == enemy.getSiegeState()))
{
targetIt = false;
}
if (!enemy.isVisible())
{
targetIt = false;
}
if (targetIt)
{
_target = enemy;
return;
}
}
}
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "", e);
}
}
public void useCubicContinuous(Skill skill, L2Object[] targets)
{
for (L2Character target : (L2Character[]) targets)
{
if ((target == null) || target.isDead())
{
continue;
}
if (skill.isBad())
{
byte shld = Formulas.calcShldUse(getOwner(), target, skill);
boolean acted = Formulas.calcCubicSkillSuccess(this, target, skill, shld);
if (!acted)
{
getOwner().sendPacket(SystemMessageId.YOUR_ATTACK_HAS_FAILED);
continue;
}
}
// Apply effects
skill.applyEffects(getOwner(), this, target, false, false, true, 0);
// If this is a bad skill notify the duel manager, so it can be removed after the duel (player & target must be in the same duel).
if (target.isPlayer() && target.getActingPlayer().isInDuel() && skill.isBad() && (getOwner().getDuelId() == target.getActingPlayer().getDuelId()))
{
DuelManager.getInstance().onBuff(target.getActingPlayer(), skill);
}
}
}
/**
* @param activeCubic
* @param skill
* @param targets
*/
public void useCubicMdam(L2CubicInstance activeCubic, Skill skill, L2Object[] targets)
{
for (L2Character target : (L2Character[]) targets)
{
if (target == null)
{
continue;
}
if (target.isAlikeDead())
{
if (target.isPlayer())
{
target.stopFakeDeath(true);
}
else
{
continue;
}
}
boolean mcrit = Formulas.calcMCrit(activeCubic.getOwner().getMCriticalHit(target, skill));
byte shld = Formulas.calcShldUse(activeCubic.getOwner(), target, skill);
int damage = (int) Formulas.calcMagicDam(activeCubic, target, skill, mcrit, shld);
if (Config.DEBUG)
{
_log.info("L2SkillMdam: useCubicSkill() -> damage = " + damage);
}
if (damage > 0)
{
// Manage attack or cast break of the target (calculating rate, sending message...)
if (!target.isRaid() && Formulas.calcAtkBreak(target, damage))
{
target.breakAttack();
target.breakCast();
}
// Shield Deflect Magic: If target is reflecting the skill then no damage is done.
if (target.getStat().calcStat(Stats.VENGEANCE_SKILL_MAGIC_DAMAGE, 0, target, skill) > Rnd.get(100))
{
damage = 0;
}
else
{
activeCubic.getOwner().sendDamageMessage(target, damage, mcrit, false, false);
target.reduceCurrentHp(damage, activeCubic.getOwner(), skill);
}
}
}
}
public void useCubicDrain(L2CubicInstance activeCubic, Skill skill, L2Object[] targets)
{
if (Config.DEBUG)
{
_log.info("L2SkillDrain: useCubicSkill()");
}
for (L2Character target : (L2Character[]) targets)
{
if (target.isAlikeDead())
{
continue;
}
boolean mcrit = Formulas.calcMCrit(activeCubic.getOwner().getMCriticalHit(target, skill));
byte shld = Formulas.calcShldUse(activeCubic.getOwner(), target, skill);
int damage = (int) Formulas.calcMagicDam(activeCubic, target, skill, mcrit, shld);
if (Config.DEBUG)
{
_log.info("L2SkillDrain: useCubicSkill() -> damage = " + damage);
}
// TODO: Unhardcode fixed value
double hpAdd = (0.4 * damage);
L2PcInstance owner = activeCubic.getOwner();
double hp = ((owner.getCurrentHp() + hpAdd) > owner.getMaxHp() ? owner.getMaxHp() : (owner.getCurrentHp() + hpAdd));
owner.setCurrentHp(hp);
// Check to see if we should damage the target
if ((damage > 0) && !target.isDead())
{
target.reduceCurrentHp(damage, activeCubic.getOwner(), skill);
// Manage attack or cast break of the target (calculating rate, sending message...)
if (!target.isRaid() && Formulas.calcAtkBreak(target, damage))
{
target.breakAttack();
target.breakCast();
}
owner.sendDamageMessage(target, damage, mcrit, false, false);
}
}
}
public void useCubicDisabler(Skill skill, L2Object[] targets)
{
if (Config.DEBUG)
{
_log.info("Disablers: useCubicSkill()");
}
for (L2Character target : (L2Character[]) targets)
{
if ((target == null) || target.isDead())
{
continue;
}
byte shld = Formulas.calcShldUse(getOwner(), target, skill);
if (skill.hasEffectType(L2EffectType.STUN, L2EffectType.PARALYZE, L2EffectType.ROOT))
{
if (Formulas.calcCubicSkillSuccess(this, target, skill, shld))
{
// Apply effects
skill.applyEffects(getOwner(), this, target, false, false, true, 0);
// If this is a bad skill notify the duel manager, so it can be removed after the duel (player & target must be in the same duel).
if (target.isPlayer() && target.getActingPlayer().isInDuel() && skill.isBad() && (getOwner().getDuelId() == target.getActingPlayer().getDuelId()))
{
DuelManager.getInstance().onBuff(target.getActingPlayer(), skill);
}
if (Config.DEBUG)
{
_log.info("Disablers: useCubicSkill() -> success");
}
}
else
{
if (Config.DEBUG)
{
_log.info("Disablers: useCubicSkill() -> failed");
}
}
}
if (skill.hasEffectType(L2EffectType.AGGRESSION))
{
if (Formulas.calcCubicSkillSuccess(this, target, skill, shld))
{
if (target.isAttackable())
{
target.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, getOwner(), (int) ((150 * skill.getPower()) / (target.getLevel() + 7)));
}
// Apply effects
skill.applyEffects(getOwner(), this, target, false, false, true, 0);
if (Config.DEBUG)
{
_log.info("Disablers: useCubicSkill() -> success");
}
}
else
{
if (Config.DEBUG)
{
_log.info("Disablers: useCubicSkill() -> failed");
}
}
}
}
}
/**
* @param owner
* @param target
* @return true if the target is inside of the owner's max Cubic range
*/
public static boolean isInCubicRange(L2Character owner, L2Character target)
{
if ((owner == null) || (target == null))
{
return false;
}
int x, y, z;
// temporary range check until real behavior of cubics is known/coded
int range = MAX_MAGIC_RANGE;
x = (owner.getX() - target.getX());
y = (owner.getY() - target.getY());
z = (owner.getZ() - target.getZ());
return (((x * x) + (y * y) + (z * z)) <= (range * range));
}
/** this sets the friendly target for a cubic */
public void cubicTargetForHeal()
{
L2Character target = null;
double percentleft = 100.0;
L2Party party = _owner.getParty();
// if owner is in a duel but not in a party duel, then it is the same as he does not have a party
if (_owner.isInDuel())
{
if (!DuelManager.getInstance().getDuel(_owner.getDuelId()).isPartyDuel())
{
party = null;
}
}
if ((party != null) && !_owner.isInOlympiadMode())
{
// Get all visible objects in a spheric area near the L2Character
// Get a list of Party Members
for (L2Character partyMember : party.getMembers())
{
if (!partyMember.isDead())
{
// if party member not dead, check if he is in cast range of heal cubic
if (isInCubicRange(_owner, partyMember))
{
// member is in cubic casting range, check if he need heal and if he have
// the lowest HP
if (partyMember.getCurrentHp() < partyMember.getMaxHp())
{
if (percentleft > (partyMember.getCurrentHp() / partyMember.getMaxHp()))
{
percentleft = (partyMember.getCurrentHp() / partyMember.getMaxHp());
target = partyMember;
}
}
}
}
if (partyMember.getSummon() != null)
{
if (partyMember.getSummon().isDead())
{
continue;
}
// If party member's pet not dead, check if it is in cast range of heal cubic.
if (!isInCubicRange(_owner, partyMember.getSummon()))
{
continue;
}
// member's pet is in cubic casting range, check if he need heal and if he have
// the lowest HP
if (partyMember.getSummon().getCurrentHp() < partyMember.getSummon().getMaxHp())
{
if (percentleft > (partyMember.getSummon().getCurrentHp() / partyMember.getSummon().getMaxHp()))
{
percentleft = (partyMember.getSummon().getCurrentHp() / partyMember.getSummon().getMaxHp());
target = partyMember.getSummon();
}
}
}
}
}
else
{
if (_owner.getCurrentHp() < _owner.getMaxHp())
{
percentleft = (_owner.getCurrentHp() / _owner.getMaxHp());
target = _owner;
}
if (_owner.hasSummon())
{
if (!_owner.getSummon().isDead() && (_owner.getSummon().getCurrentHp() < _owner.getSummon().getMaxHp()) && (percentleft > (_owner.getSummon().getCurrentHp() / _owner.getSummon().getMaxHp())) && isInCubicRange(_owner, _owner.getSummon()))
{
target = _owner.getSummon();
}
}
}
_target = target;
}
public boolean givenByOther()
{
return _givenByOther;
}
}

View File

@ -0,0 +1,168 @@
/*
* Copyright (C) 2004-2014 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 java.util.logging.Level;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Decoy;
import com.l2jserver.gameserver.model.actor.knownlist.DecoyKnownList;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.taskmanager.DecayTaskManager;
public class L2DecoyInstance extends L2Decoy
{
private int _totalLifeTime;
private int _timeRemaining;
private Future<?> _DecoyLifeTask;
private Future<?> _HateSpam;
public L2DecoyInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, int totalLifeTime)
{
super(objectId, template, owner);
setInstanceType(InstanceType.L2DecoyInstance);
_totalLifeTime = totalLifeTime;
_timeRemaining = _totalLifeTime;
int skilllevel = getTemplate().getDisplayId() - 13070;
_DecoyLifeTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new DecoyLifetime(getOwner(), this), 1000, 1000);
_HateSpam = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new HateSpam(this, SkillData.getInstance().getSkill(5272, skilllevel)), 2000, 5000);
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
if (_HateSpam != null)
{
_HateSpam.cancel(true);
_HateSpam = null;
}
_totalLifeTime = 0;
DecayTaskManager.getInstance().add(this);
return true;
}
@Override
public DecoyKnownList getKnownList()
{
return (DecoyKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new DecoyKnownList(this));
}
static class DecoyLifetime implements Runnable
{
private final L2PcInstance _activeChar;
private final L2DecoyInstance _Decoy;
DecoyLifetime(L2PcInstance activeChar, L2DecoyInstance Decoy)
{
_activeChar = activeChar;
_Decoy = Decoy;
}
@Override
public void run()
{
try
{
_Decoy.decTimeRemaining(1000);
double newTimeRemaining = _Decoy.getTimeRemaining();
if (newTimeRemaining < 0)
{
_Decoy.unSummon(_activeChar);
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Decoy Error: ", e);
}
}
}
private static class HateSpam implements Runnable
{
private final L2DecoyInstance _activeChar;
private final Skill _skill;
HateSpam(L2DecoyInstance activeChar, Skill Hate)
{
_activeChar = activeChar;
_skill = Hate;
}
@Override
public void run()
{
try
{
_activeChar.setTarget(_activeChar);
_activeChar.doCast(_skill);
}
catch (Throwable e)
{
_log.log(Level.SEVERE, "Decoy Error: ", e);
}
}
}
@Override
public void unSummon(L2PcInstance owner)
{
if (_DecoyLifeTask != null)
{
_DecoyLifeTask.cancel(true);
_DecoyLifeTask = null;
}
if (_HateSpam != null)
{
_HateSpam.cancel(true);
_HateSpam = null;
}
super.unSummon(owner);
}
public void decTimeRemaining(int value)
{
_timeRemaining -= value;
}
public int getTimeRemaining()
{
return _timeRemaining;
}
public int getTotalLifeTime()
{
return _totalLifeTime;
}
}

View File

@ -0,0 +1,228 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.Config;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.ai.L2CharacterAI;
import com.l2jserver.gameserver.ai.L2FortSiegeGuardAI;
import com.l2jserver.gameserver.ai.L2SiegeGuardAI;
import com.l2jserver.gameserver.ai.L2SpecialSiegeGuardAI;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.CastleManager;
import com.l2jserver.gameserver.instancemanager.FortManager;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.knownlist.DefenderKnownList;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.entity.Fort;
import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
public class L2DefenderInstance extends L2Attackable
{
private Castle _castle = null; // the castle which the instance should defend
private Fort _fort = null; // the fortress which the instance should defend
private SiegableHall _hall = null; // the siegable hall which the instance should defend
public L2DefenderInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2DefenderInstance);
}
@Override
public DefenderKnownList getKnownList()
{
return (DefenderKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new DefenderKnownList(this));
}
@Override
protected L2CharacterAI initAI()
{
if ((getConquerableHall() == null) && (getCastle(10000) == null))
{
return new L2FortSiegeGuardAI(new AIAccessor());
}
else if (getCastle(10000) != null)
{
return new L2SiegeGuardAI(new AIAccessor());
}
return new L2SpecialSiegeGuardAI(new AIAccessor());
}
/**
* Return True if a siege is in progress and the L2Character attacker isn't a Defender.
* @param attacker The L2Character that the L2SiegeGuardInstance try to attack
*/
@Override
public boolean isAutoAttackable(L2Character attacker)
{
// Attackable during siege by all except defenders
if (!(attacker instanceof L2Playable))
{
return false;
}
L2PcInstance player = attacker.getActingPlayer();
// Check if siege is in progress
if (((_fort != null) && _fort.getZone().isActive()) || ((_castle != null) && _castle.getZone().isActive()) || ((_hall != null) && _hall.getSiegeZone().isActive()))
{
int activeSiegeId = (_fort != null ? _fort.getResidenceId() : (_castle != null ? _castle.getResidenceId() : (_hall != null ? _hall.getId() : 0)));
// Check if player is an enemy of this defender npc
if ((player != null) && (((player.getSiegeState() == 2) && !player.isRegisteredOnThisSiegeField(activeSiegeId)) || ((player.getSiegeState() == 1)) || (player.getSiegeState() == 0)))
{
return true;
}
}
return false;
}
@Override
public boolean hasRandomAnimation()
{
return false;
}
/**
* This method forces guard to return to home location previously set
*/
@Override
public void returnHome()
{
if (getWalkSpeed() <= 0)
{
return;
}
if (getSpawn() == null)
{
return;
}
if (!isInsideRadius(getSpawn(), 40, false, false))
{
if (Config.DEBUG)
{
_log.info(getObjectId() + ": moving home");
}
setisReturningToSpawnPoint(true);
clearAggroList();
if (hasAI())
{
getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, getSpawn().getLocation());
}
}
}
@Override
public void onSpawn()
{
super.onSpawn();
_fort = FortManager.getInstance().getFort(getX(), getY(), getZ());
_castle = CastleManager.getInstance().getCastle(getX(), getY(), getZ());
_hall = getConquerableHall();
if ((_fort == null) && (_castle == null) && (_hall == null))
{
_log.warning("L2DefenderInstance spawned outside of Fortress, Castle or Siegable hall Zone! NpcId: " + getId() + " x=" + getX() + " y=" + getY() + " z=" + getZ());
}
}
/**
* Custom onAction behaviour. Note that super() is not called because guards need extra check to see if a player should interact or ATTACK them when clicked.
*/
@Override
public void onAction(L2PcInstance player, boolean interact)
{
if (!canTarget(player))
{
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Check if the L2PcInstance already target the L2NpcInstance
if (this != player.getTarget())
{
if (Config.DEBUG)
{
_log.info("new target selected:" + getObjectId());
}
// Set the target of the L2PcInstance player
player.setTarget(this);
}
else if (interact)
{
if (isAutoAttackable(player) && !isAlikeDead())
{
if (Math.abs(player.getZ() - getZ()) < 600) // this max heigth difference might need some tweaking
{
player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
}
}
if (!isAutoAttackable(player))
{
if (!canInteract(player))
{
// Notify the L2PcInstance AI with AI_INTENTION_INTERACT
player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
}
}
}
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public void addDamageHate(L2Character attacker, int damage, int aggro)
{
if (attacker == null)
{
return;
}
if (!(attacker instanceof L2DefenderInstance))
{
if ((damage == 0) && (aggro <= 1) && (attacker instanceof L2Playable))
{
L2PcInstance player = attacker.getActingPlayer();
// Check if siege is in progress
if (((_fort != null) && _fort.getZone().isActive()) || ((_castle != null) && _castle.getZone().isActive()) || ((_hall != null) && _hall.getSiegeZone().isActive()))
{
int activeSiegeId = (_fort != null ? _fort.getResidenceId() : (_castle != null ? _castle.getResidenceId() : (_hall != null ? _hall.getId() : 0)));
if ((player != null) && (((player.getSiegeState() == 2) && player.isRegisteredOnThisSiegeField(activeSiegeId)) || ((player.getSiegeState() == 1))))
{
return;
}
}
}
super.addDamageHate(attacker, damage, aggro);
}
}
}

View File

@ -0,0 +1,812 @@
/*
* Copyright (C) 2004-2014 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.Collection;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.logging.Level;
import javolution.util.FastList;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.L2CharacterAI;
import com.l2jserver.gameserver.ai.L2DoorAI;
import com.l2jserver.gameserver.datatables.DoorTable;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.instancemanager.CastleManager;
import com.l2jserver.gameserver.instancemanager.ClanHallManager;
import com.l2jserver.gameserver.instancemanager.FortManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.knownlist.DoorKnownList;
import com.l2jserver.gameserver.model.actor.stat.DoorStat;
import com.l2jserver.gameserver.model.actor.status.DoorStatus;
import com.l2jserver.gameserver.model.actor.templates.L2DoorTemplate;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.entity.ClanHall;
import com.l2jserver.gameserver.model.entity.Fort;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
import com.l2jserver.gameserver.model.items.L2Weapon;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.DoorStatusUpdate;
import com.l2jserver.gameserver.network.serverpackets.OnEventTrigger;
import com.l2jserver.gameserver.network.serverpackets.StaticObject;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
public class L2DoorInstance extends L2Character
{
public static final byte OPEN_BY_CLICK = 1;
public static final byte OPEN_BY_TIME = 2;
public static final byte OPEN_BY_ITEM = 4;
public static final byte OPEN_BY_SKILL = 8;
public static final byte OPEN_BY_CYCLE = 16;
/** The castle index in the array of L2Castle this L2NpcInstance belongs to */
private int _castleIndex = -2;
/** The fort index in the array of L2Fort this L2NpcInstance belongs to */
private int _fortIndex = -2;
private ClanHall _clanHall;
private boolean _open = false;
private boolean _isAttackableDoor = false;
private boolean _isTargetable;
private int _meshindex = 1;
// used for autoclose on open
private Future<?> _autoCloseTask;
/**
* @param objectId
* @param template
*/
public L2DoorInstance(int objectId, L2DoorTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2DoorInstance);
setIsInvul(false);
setLethalable(false);
_open = template.isOpenByDefault();
_isAttackableDoor = template.isAttackable();
_isTargetable = template.isTargetable();
if (getGroupName() != null)
{
DoorTable.addDoorGroup(getGroupName(), getId());
}
if (isOpenableByTime())
{
startTimerOpen();
}
int clanhallId = template.getClanHallId();
if (clanhallId > 0)
{
ClanHall hall = ClanHallManager.getAllClanHalls().get(clanhallId);
if (hall != null)
{
setClanHall(hall);
hall.getDoors().add(this);
}
}
}
/** This class may be created only by L2Character and only for AI */
public class AIAccessor extends L2Character.AIAccessor
{
@Override
public L2DoorInstance getActor()
{
return L2DoorInstance.this;
}
@Override
public void moveTo(int x, int y, int z, int offset)
{
}
@Override
public void moveTo(int x, int y, int z)
{
}
@Override
public void stopMove(Location loc)
{
}
@Override
public void doAttack(L2Character target)
{
}
@Override
public void doCast(Skill skill)
{
}
}
@Override
protected L2CharacterAI initAI()
{
return new L2DoorAI(new AIAccessor());
}
private void startTimerOpen()
{
int delay = _open ? getTemplate().getOpenTime() : getTemplate().getCloseTime();
if (getTemplate().getRandomTime() > 0)
{
delay += Rnd.get(getTemplate().getRandomTime());
}
ThreadPoolManager.getInstance().scheduleGeneral(new TimerOpen(), delay * 1000);
}
@Override
public final DoorKnownList getKnownList()
{
return (DoorKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new DoorKnownList(this));
}
@Override
public L2DoorTemplate getTemplate()
{
return (L2DoorTemplate) super.getTemplate();
}
@Override
public final DoorStatus getStatus()
{
return (DoorStatus) super.getStatus();
}
@Override
public void initCharStatus()
{
setStatus(new DoorStatus(this));
}
@Override
public void initCharStat()
{
setStat(new DoorStat(this));
}
@Override
public DoorStat getStat()
{
return (DoorStat) super.getStat();
}
/**
* @return {@code true} if door is open-able by skill.
*/
public final boolean isOpenableBySkill()
{
return (getTemplate().getOpenType() & OPEN_BY_SKILL) == OPEN_BY_SKILL;
}
/**
* @return {@code true} if door is open-able by item.
*/
public final boolean isOpenableByItem()
{
return (getTemplate().getOpenType() & OPEN_BY_ITEM) == OPEN_BY_ITEM;
}
/**
* @return {@code true} if door is open-able by double-click.
*/
public final boolean isOpenableByClick()
{
return (getTemplate().getOpenType() & OPEN_BY_CLICK) == OPEN_BY_CLICK;
}
/**
* @return {@code true} if door is open-able by time.
*/
public final boolean isOpenableByTime()
{
return (getTemplate().getOpenType() & OPEN_BY_TIME) == OPEN_BY_TIME;
}
/**
* @return {@code true} if door is open-able by Field Cycle system.
*/
public final boolean isOpenableByCycle()
{
return (getTemplate().getOpenType() & OPEN_BY_CYCLE) == OPEN_BY_CYCLE;
}
@Override
public final int getLevel()
{
return getTemplate().getLevel();
}
/**
* Gets the door ID.
* @return the door ID
*/
@Override
public int getId()
{
return getTemplate().getId();
}
/**
* @return Returns the open.
*/
public boolean getOpen()
{
return _open;
}
/**
* @param open The open to set.
*/
public void setOpen(boolean open)
{
_open = open;
if (getChildId() > 0)
{
L2DoorInstance sibling = getSiblingDoor(getChildId());
if (sibling != null)
{
sibling.notifyChildEvent(open);
}
else
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": cannot find child id: " + getChildId());
}
}
}
public boolean getIsAttackableDoor()
{
return _isAttackableDoor;
}
public boolean getIsShowHp()
{
return getTemplate().isShowHp();
}
public void setIsAttackableDoor(boolean val)
{
_isAttackableDoor = val;
}
public int getDamage()
{
int dmg = 6 - (int) Math.ceil((getCurrentHp() / getMaxHp()) * 6);
if (dmg > 6)
{
return 6;
}
if (dmg < 0)
{
return 0;
}
return dmg;
}
// TODO: Replace index with the castle id itself.
public final Castle getCastle()
{
if (_castleIndex < 0)
{
_castleIndex = CastleManager.getInstance().getCastleIndex(this);
}
if (_castleIndex < 0)
{
return null;
}
return CastleManager.getInstance().getCastles().get(_castleIndex);
}
// TODO: Replace index with the fort id itself.
public final Fort getFort()
{
if (_fortIndex < 0)
{
_fortIndex = FortManager.getInstance().getFortIndex(this);
}
if (_fortIndex < 0)
{
return null;
}
return FortManager.getInstance().getForts().get(_fortIndex);
}
public void setClanHall(ClanHall clanhall)
{
_clanHall = clanhall;
}
public ClanHall getClanHall()
{
return _clanHall;
}
public boolean isEnemy()
{
if ((getCastle() != null) && (getCastle().getResidenceId() > 0) && getCastle().getZone().isActive() && getIsShowHp())
{
return true;
}
if ((getFort() != null) && (getFort().getResidenceId() > 0) && getFort().getZone().isActive() && getIsShowHp())
{
return true;
}
if ((getClanHall() != null) && getClanHall().isSiegableHall() && ((SiegableHall) getClanHall()).getSiegeZone().isActive() && getIsShowHp())
{
return true;
}
return false;
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
// Doors can`t be attacked by NPCs
if (!(attacker instanceof L2Playable))
{
return false;
}
if (getIsAttackableDoor())
{
return true;
}
if (!getIsShowHp())
{
return false;
}
L2PcInstance actingPlayer = attacker.getActingPlayer();
if (getClanHall() != null)
{
SiegableHall hall = (SiegableHall) getClanHall();
if (!hall.isSiegableHall())
{
return false;
}
return hall.isInSiege() && hall.getSiege().doorIsAutoAttackable() && hall.getSiege().checkIsAttacker(actingPlayer.getClan());
}
// Attackable only during siege by everyone (not owner)
boolean isCastle = ((getCastle() != null) && (getCastle().getResidenceId() > 0) && getCastle().getZone().isActive());
boolean isFort = ((getFort() != null) && (getFort().getResidenceId() > 0) && getFort().getZone().isActive());
if (isFort)
{
L2Clan clan = actingPlayer.getClan();
if ((clan != null) && (clan == getFort().getOwnerClan()))
{
return false;
}
}
else if (isCastle)
{
L2Clan clan = actingPlayer.getClan();
if ((clan != null) && (clan.getId() == getCastle().getOwnerId()))
{
return false;
}
}
return (isCastle || isFort);
}
@Override
public void updateAbnormalEffect()
{
}
/**
* Return null.
*/
@Override
public L2ItemInstance getActiveWeaponInstance()
{
return null;
}
@Override
public L2Weapon getActiveWeaponItem()
{
return null;
}
@Override
public L2ItemInstance getSecondaryWeaponInstance()
{
return null;
}
@Override
public L2Weapon getSecondaryWeaponItem()
{
return null;
}
@Override
public void broadcastStatusUpdate()
{
Collection<L2PcInstance> knownPlayers = getKnownList().getKnownPlayers().values();
if ((knownPlayers == null) || knownPlayers.isEmpty())
{
return;
}
StaticObject su = new StaticObject(this, false);
StaticObject targetableSu = new StaticObject(this, true);
DoorStatusUpdate dsu = new DoorStatusUpdate(this);
OnEventTrigger oe = null;
if (getEmitter() > 0)
{
oe = new OnEventTrigger(this, getOpen());
}
for (L2PcInstance player : knownPlayers)
{
if ((player == null) || !isVisibleFor(player))
{
continue;
}
if (player.isGM() || (((getCastle() != null) && (getCastle().getResidenceId() > 0)) || ((getFort() != null) && (getFort().getResidenceId() > 0))))
{
player.sendPacket(targetableSu);
}
else
{
player.sendPacket(su);
}
player.sendPacket(dsu);
if (oe != null)
{
player.sendPacket(oe);
}
}
}
public final void openMe()
{
if (getGroupName() != null)
{
manageGroupOpen(true, getGroupName());
return;
}
setOpen(true);
broadcastStatusUpdate();
startAutoCloseTask();
}
public final void closeMe()
{
// remove close task
Future<?> oldTask = _autoCloseTask;
if (oldTask != null)
{
_autoCloseTask = null;
oldTask.cancel(false);
}
if (getGroupName() != null)
{
manageGroupOpen(false, getGroupName());
return;
}
setOpen(false);
broadcastStatusUpdate();
}
private void manageGroupOpen(boolean open, String groupName)
{
Set<Integer> set = DoorTable.getDoorsByGroup(groupName);
L2DoorInstance first = null;
for (Integer id : set)
{
L2DoorInstance door = getSiblingDoor(id);
if (first == null)
{
first = door;
}
if (door.getOpen() != open)
{
door.setOpen(open);
door.broadcastStatusUpdate();
}
}
if ((first != null) && open)
{
first.startAutoCloseTask(); // only one from group
}
}
/**
* Door notify child about open state change
* @param open true if opened
*/
private void notifyChildEvent(boolean open)
{
byte openThis = open ? getTemplate().getMasterDoorOpen() : getTemplate().getMasterDoorClose();
if (openThis == 0)
{
return;
}
else if (openThis == 1)
{
openMe();
}
else if (openThis == -1)
{
closeMe();
}
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + getTemplate().getId() + "](" + getObjectId() + ")";
}
public String getDoorName()
{
return getTemplate().getName();
}
public int getX(int i)
{
return getTemplate().getNodeX()[i];
}
public int getY(int i)
{
return getTemplate().getNodeY()[i];
}
public int getZMin()
{
return getTemplate().getNodeZ();
}
public int getZMax()
{
return getTemplate().getNodeZ() + getTemplate().getHeight();
}
public Collection<L2DefenderInstance> getKnownDefenders()
{
FastList<L2DefenderInstance> result = new FastList<>();
Collection<L2Object> objs = getKnownList().getKnownObjects().values();
for (L2Object obj : objs)
{
if (obj instanceof L2DefenderInstance)
{
result.add((L2DefenderInstance) obj);
}
}
return result;
}
public void setMeshIndex(int mesh)
{
_meshindex = mesh;
}
public int getMeshIndex()
{
return _meshindex;
}
public int getEmitter()
{
return getTemplate().getEmmiter();
}
public boolean isWall()
{
return getTemplate().isWall();
}
public String getGroupName()
{
return getTemplate().getGroupName();
}
public int getChildId()
{
return getTemplate().getChildDoorId();
}
@Override
public void reduceCurrentHp(double damage, L2Character attacker, boolean awake, boolean isDOT, Skill skill)
{
if (isWall() && (getInstanceId() == 0))
{
if (!attacker.isServitor())
{
return;
}
final L2ServitorInstance servitor = (L2ServitorInstance) attacker;
if (servitor.getTemplate().getRace() != Race.SIEGE_WEAPON)
{
return;
}
}
super.reduceCurrentHp(damage, attacker, awake, isDOT, skill);
}
@Override
public void reduceCurrentHpByDOT(double i, L2Character attacker, Skill skill)
{
// doors can't be damaged by DOTs
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
boolean isFort = ((getFort() != null) && (getFort().getResidenceId() > 0) && getFort().getSiege().isInProgress());
boolean isCastle = ((getCastle() != null) && (getCastle().getResidenceId() > 0) && getCastle().getSiege().isInProgress());
boolean isHall = ((getClanHall() != null) && getClanHall().isSiegableHall() && ((SiegableHall) getClanHall()).isInSiege());
if (isFort || isCastle || isHall)
{
broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_CASTLE_GATE_HAS_BEEN_DESTROYED));
}
return true;
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
if (isVisibleFor(activeChar))
{
if (getEmitter() > 0)
{
activeChar.sendPacket(new OnEventTrigger(this, getOpen()));
}
activeChar.sendPacket(new StaticObject(this, activeChar.isGM()));
}
}
public void setTargetable(boolean b)
{
_isTargetable = b;
broadcastStatusUpdate();
}
@Override
public boolean isTargetable()
{
return _isTargetable;
}
public boolean checkCollision()
{
return getTemplate().isCheckCollision();
}
/**
* All doors are stored at DoorTable except instance doors
* @param doorId
* @return
*/
private L2DoorInstance getSiblingDoor(int doorId)
{
if (getInstanceId() == 0)
{
return DoorTable.getInstance().getDoor(doorId);
}
Instance inst = InstanceManager.getInstance().getInstance(getInstanceId());
if (inst != null)
{
return inst.getDoor(doorId);
}
return null; // 2 late
}
private void startAutoCloseTask()
{
if ((getTemplate().getCloseTime() < 0) || isOpenableByTime())
{
return;
}
Future<?> oldTask = _autoCloseTask;
if (oldTask != null)
{
_autoCloseTask = null;
oldTask.cancel(false);
}
_autoCloseTask = ThreadPoolManager.getInstance().scheduleGeneral(new AutoClose(), getTemplate().getCloseTime() * 1000);
}
class AutoClose implements Runnable
{
@Override
public void run()
{
if (getOpen())
{
closeMe();
}
}
}
class TimerOpen implements Runnable
{
@Override
public void run()
{
boolean open = getOpen();
if (open)
{
closeMe();
}
else
{
openMe();
}
int delay = open ? getTemplate().getCloseTime() : getTemplate().getOpenTime();
if (getTemplate().getRandomTime() > 0)
{
delay += Rnd.get(getTemplate().getRandomTime());
}
ThreadPoolManager.getInstance().scheduleGeneral(this, delay * 1000);
}
}
@Override
public boolean isDoor()
{
return true;
}
}

View File

@ -0,0 +1,175 @@
/*
* Copyright (C) 2004-2014 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.StringTokenizer;
import com.l2jserver.gameserver.datatables.DoorTable;
import com.l2jserver.gameserver.datatables.TeleportLocationTable;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2TeleportLocation;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
/**
* This class ...
* @version $Revision$ $Date$
*/
public class L2DoormenInstance extends L2NpcInstance
{
/**
* @param objectID
* @param template
*/
public L2DoormenInstance(int objectID, L2NpcTemplate template)
{
super(objectID, template);
setInstanceType(InstanceType.L2DoormenInstance);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (command.startsWith("Chat"))
{
showChatWindow(player);
return;
}
else if (command.startsWith("open_doors"))
{
if (isOwnerClan(player))
{
if (isUnderSiege())
{
cannotManageDoors(player);
}
else
{
openDoors(player, command);
}
}
return;
}
else if (command.startsWith("close_doors"))
{
if (isOwnerClan(player))
{
if (isUnderSiege())
{
cannotManageDoors(player);
}
else
{
closeDoors(player, command);
}
}
return;
}
else if (command.startsWith("tele"))
{
if (isOwnerClan(player))
{
doTeleport(player, command);
}
return;
}
super.onBypassFeedback(player, command);
}
@Override
public void showChatWindow(L2PcInstance player)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (!isOwnerClan(player))
{
html.setFile(player.getHtmlPrefix(), "data/html/doormen/" + getTemplate().getId() + "-no.htm");
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/doormen/" + getTemplate().getId() + ".htm");
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
protected void openDoors(L2PcInstance player, String command)
{
StringTokenizer st = new StringTokenizer(command.substring(10), ", ");
st.nextToken();
while (st.hasMoreTokens())
{
DoorTable.getInstance().getDoor(Integer.parseInt(st.nextToken())).openMe();
}
}
protected void closeDoors(L2PcInstance player, String command)
{
StringTokenizer st = new StringTokenizer(command.substring(11), ", ");
st.nextToken();
while (st.hasMoreTokens())
{
DoorTable.getInstance().getDoor(Integer.parseInt(st.nextToken())).closeMe();
}
}
protected void cannotManageDoors(L2PcInstance player)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/doormen/" + getTemplate().getId() + "-busy.htm");
player.sendPacket(html);
}
protected void doTeleport(L2PcInstance player, String command)
{
final int whereTo = Integer.parseInt(command.substring(5).trim());
L2TeleportLocation list = TeleportLocationTable.getInstance().getTemplate(whereTo);
if (list != null)
{
if (!player.isAlikeDead())
{
player.teleToLocation(list.getLocX(), list.getLocY(), list.getLocZ(), false);
}
}
else
{
_log.warning("No teleport destination with id:" + whereTo);
}
player.sendPacket(ActionFailed.STATIC_PACKET);
}
protected boolean isOwnerClan(L2PcInstance player)
{
return true;
}
protected boolean isUnderSiege()
{
return false;
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
public class L2EffectPointInstance extends L2Npc
{
private final L2PcInstance _owner;
public L2EffectPointInstance(int objectId, L2NpcTemplate template, L2Character owner)
{
super(objectId, template);
setInstanceType(InstanceType.L2EffectPointInstance);
setIsInvul(false);
_owner = owner == null ? null : owner.getActingPlayer();
if (owner != null)
{
setInstanceId(owner.getInstanceId());
}
}
@Override
public L2PcInstance getActingPlayer()
{
return _owner;
}
/**
* this is called when a player interacts with this NPC
* @param player
*/
@Override
public void onAction(L2PcInstance player, boolean interact)
{
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public void onActionShift(L2PcInstance player)
{
if (player == null)
{
return;
}
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
/**
* @author Gnacik
*/
public class L2EventMonsterInstance extends L2MonsterInstance
{
// Block offensive skills usage on event mobs
// mainly for AoE skills, disallow kill many event mobs
// with one skill
public boolean block_skill_attack = false;
// Event mobs should drop items to ground
// but item pickup must be protected to killer
// Todo: Some mobs need protect drop for spawner
public boolean drop_on_ground = false;
public L2EventMonsterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2EventMobInstance);
}
public void eventSetBlockOffensiveSkills(boolean value)
{
block_skill_attack = value;
}
public void eventSetDropOnGround(boolean value)
{
drop_on_ground = value;
}
public boolean eventDropOnGround()
{
return drop_on_ground;
}
public boolean eventSkillAttackBlocked()
{
return block_skill_attack;
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
// This class is here mostly for convenience and for avoidance of hardcoded IDs.
// It refers to Beast (mobs) that can be attacked but can also be fed
// For example, the Beast Farm's Alpen Buffalo.
// This class is only truly used by the handlers in order to check the correctness
// of the target. However, no additional tasks are needed, since they are all
// handled by scripted AI.
public class L2FeedableBeastInstance extends L2MonsterInstance
{
public L2FeedableBeastInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FeedableBeastInstance);
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2004-2014 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.List;
import com.l2jserver.gameserver.datatables.SkillTreesData;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2SkillLearn;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.AcquireSkillType;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExAcquirableSkillListByClass;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
public final class L2FishermanInstance extends L2MerchantInstance
{
public L2FishermanInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FishermanInstance);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/fisherman/" + pom + ".htm";
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (command.equalsIgnoreCase("FishSkillList"))
{
showFishSkillList(player);
}
else
{
super.onBypassFeedback(player, command);
}
}
public static void showFishSkillList(L2PcInstance player)
{
final List<L2SkillLearn> skills = SkillTreesData.getInstance().getAvailableFishingSkills(player);
if (skills.isEmpty())
{
final int minlLevel = SkillTreesData.getInstance().getMinLevelForNewSkill(player, SkillTreesData.getInstance().getFishingSkillTree());
if (minlLevel > 0)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_DO_NOT_HAVE_ANY_FURTHER_SKILLS_TO_LEARN_COME_BACK_WHEN_YOU_HAVE_REACHED_LEVEL_S1);
sm.addInt(minlLevel);
player.sendPacket(sm);
}
else
{
player.sendPacket(SystemMessageId.THERE_ARE_NO_OTHER_SKILLS_TO_LEARN);
}
}
else
{
player.sendPacket(new ExAcquirableSkillListByClass(skills, AcquireSkillType.FISHING));
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2004-2014 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.List;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Tower;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
/**
* Class for Flame Control Tower instance.
* @author JIV
*/
public class L2FlameTowerInstance extends L2Tower
{
private int _upgradeLevel = 0;
private List<Integer> _zoneList;
public L2FlameTowerInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FlameTowerInstance);
}
@Override
public boolean doDie(L2Character killer)
{
enableZones(false);
return super.doDie(killer);
}
@Override
public boolean deleteMe()
{
enableZones(false);
return super.deleteMe();
}
public final void enableZones(boolean state)
{
if ((_zoneList != null) && (_upgradeLevel != 0))
{
final int maxIndex = _upgradeLevel * 2;
for (int i = 0; i < maxIndex; i++)
{
final L2ZoneType zone = ZoneManager.getInstance().getZoneById(_zoneList.get(i));
if (zone != null)
{
zone.setEnabled(state);
}
}
}
}
public final void setUpgradeLevel(int level)
{
_upgradeLevel = level;
}
public final void setZoneList(List<Integer> list)
{
_zoneList = list;
enableZones(true);
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
public final class L2FlyMonsterInstance extends L2MonsterInstance
{
public L2FlyMonsterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FlyMonsterInstance);
setIsFlying(true);
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
public final class L2FlyNpcInstance extends L2NpcInstance
{
public L2FlyNpcInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FlyNpcInstance);
setIsFlying(true);
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
public final class L2FlyRaidBossInstance extends L2RaidBossInstance
{
public L2FlyRaidBossInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FlyRaidBossInstance);
setIsFlying(true);
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
public final class L2FlyTerrainObjectInstance extends L2Npc
{
public L2FlyTerrainObjectInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FlyTerrainObjectInstance);
setIsFlying(true);
}
@Override
public void onAction(L2PcInstance player, boolean interact)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public void onActionShift(L2PcInstance player)
{
if (player.isGM())
{
super.onActionShift(player);
}
else
{
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
}

View File

@ -0,0 +1,196 @@
/*
* Copyright (C) 2004-2014 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 javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.FortSiegeManager;
import com.l2jserver.gameserver.model.FortSiegeSpawn;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
public class L2FortCommanderInstance extends L2DefenderInstance
{
private boolean _canTalk;
public L2FortCommanderInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FortCommanderInstance);
_canTalk = true;
}
/**
* Return True if a siege is in progress and the L2Character attacker isn't a Defender.
* @param attacker The L2Character that the L2CommanderInstance try to attack
*/
@Override
public boolean isAutoAttackable(L2Character attacker)
{
if ((attacker == null) || !(attacker instanceof L2PcInstance))
{
return false;
}
boolean isFort = ((getFort() != null) && (getFort().getResidenceId() > 0) && getFort().getSiege().isInProgress() && !getFort().getSiege().checkIsDefender(((L2PcInstance) attacker).getClan()));
// Attackable during siege by all except defenders
return (isFort);
}
@Override
public void addDamageHate(L2Character attacker, int damage, int aggro)
{
if (attacker == null)
{
return;
}
if (!(attacker instanceof L2FortCommanderInstance))
{
super.addDamageHate(attacker, damage, aggro);
}
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
if (getFort().getSiege().isInProgress())
{
getFort().getSiege().killedCommander(this);
}
return true;
}
/**
* This method forces guard to return to home location previously set
*/
@Override
public void returnHome()
{
if (!isInsideRadius(getSpawn(), 200, false, false))
{
if (Config.DEBUG)
{
_log.info(getObjectId() + ": moving home");
}
setisReturningToSpawnPoint(true);
clearAggroList();
if (hasAI())
{
getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, getSpawn().getLocation());
}
}
}
@Override
public final void addDamage(L2Character attacker, int damage, Skill skill)
{
L2Spawn spawn = getSpawn();
if ((spawn != null) && canTalk())
{
FastList<FortSiegeSpawn> commanders = FortSiegeManager.getInstance().getCommanderSpawnList(getFort().getResidenceId());
for (FortSiegeSpawn spawn2 : commanders)
{
if (spawn2.getId() == spawn.getId())
{
NpcStringId npcString = null;
switch (spawn2.getMessageId())
{
case 1:
npcString = NpcStringId.ATTACKING_THE_ENEMY_S_REINFORCEMENTS_IS_NECESSARY_TIME_TO_DIE;
break;
case 2:
if (attacker instanceof L2Summon)
{
attacker = ((L2Summon) attacker).getOwner();
}
npcString = NpcStringId.EVERYONE_CONCENTRATE_YOUR_ATTACKS_ON_S1_SHOW_THE_ENEMY_YOUR_RESOLVE;
break;
case 3:
npcString = NpcStringId.FIRE_SPIRIT_UNLEASH_YOUR_POWER_BURN_THE_ENEMY;
break;
}
if (npcString != null)
{
NpcSay ns = new NpcSay(getObjectId(), Say2.NPC_SHOUT, getId(), npcString);
if (npcString.getParamCount() == 1)
{
ns.addStringParameter(attacker.getName());
}
broadcastPacket(ns);
setCanTalk(false);
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleTalkTask(), 10000);
}
}
}
}
super.addDamage(attacker, damage, skill);
}
private class ScheduleTalkTask implements Runnable
{
public ScheduleTalkTask()
{
}
@Override
public void run()
{
setCanTalk(true);
}
}
void setCanTalk(boolean val)
{
_canTalk = val;
}
private boolean canTalk()
{
return _canTalk;
}
@Override
public boolean hasRandomAnimation()
{
return false;
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2004-2014 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.StringTokenizer;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
public class L2FortDoormenInstance extends L2DoormenInstance
{
public L2FortDoormenInstance(int objectID, L2NpcTemplate template)
{
super(objectID, template);
setInstanceType(InstanceType.L2FortDoormenInstance);
}
@Override
public void showChatWindow(L2PcInstance player)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (!isOwnerClan(player))
{
html.setFile(player.getHtmlPrefix(), "data/html/doormen/" + getTemplate().getId() + "-no.htm");
}
else if (isUnderSiege())
{
html.setFile(player.getHtmlPrefix(), "data/html/doormen/" + getTemplate().getId() + "-busy.htm");
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/doormen/" + getTemplate().getId() + ".htm");
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
@Override
protected final void openDoors(L2PcInstance player, String command)
{
StringTokenizer st = new StringTokenizer(command.substring(10), ", ");
st.nextToken();
while (st.hasMoreTokens())
{
getFort().openDoor(player, Integer.parseInt(st.nextToken()));
}
}
@Override
protected final void closeDoors(L2PcInstance player, String command)
{
StringTokenizer st = new StringTokenizer(command.substring(11), ", ");
st.nextToken();
while (st.hasMoreTokens())
{
getFort().closeDoor(player, Integer.parseInt(st.nextToken()));
}
}
@Override
protected final boolean isOwnerClan(L2PcInstance player)
{
if ((player.getClan() != null) && (getFort() != null) && (getFort().getOwnerClan() != null))
{
if (player.getClanId() == getFort().getOwnerClan().getId())
{
return true;
}
}
return false;
}
@Override
protected final boolean isUnderSiege()
{
return getFort().getZone().isActive();
}
}

View File

@ -0,0 +1,239 @@
/*
* Copyright (C) 2004-2014 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.StringTokenizer;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
/**
* @author Vice, Zoey76
*/
public class L2FortLogisticsInstance extends L2MerchantInstance
{
private static final int[] SUPPLY_BOX_IDS =
{
35665,
35697,
35734,
35766,
35803,
35834,
35866,
35903,
35935,
35973,
36010,
36042,
36080,
36117,
36148,
36180,
36218,
36256,
36293,
36325,
36363
};
public L2FortLogisticsInstance(int objectID, L2NpcTemplate template)
{
super(objectID, template);
setInstanceType(InstanceType.L2FortLogisticsInstance);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (player.getLastFolkNPC().getObjectId() != getObjectId())
{
return;
}
StringTokenizer st = new StringTokenizer(command, " ");
String actualCommand = st.nextToken(); // Get actual command
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (actualCommand.equalsIgnoreCase("rewards"))
{
if (isMyLord(player))
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-rewards.htm");
html.replace("%bloodoath%", String.valueOf(player.getClan().getBloodOathCount()));
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-noprivs.htm");
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
else if (actualCommand.equalsIgnoreCase("blood"))
{
if (isMyLord(player))
{
final int blood = player.getClan().getBloodOathCount();
if (blood > 0)
{
player.addItem("Quest", 9910, blood, this, true);
player.getClan().resetBloodOathCount();
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-blood.htm");
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-noblood.htm");
}
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-noprivs.htm");
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
else if (actualCommand.equalsIgnoreCase("supplylvl"))
{
if (getFort().getFortState() == 2)
{
if (player.isClanLeader())
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-supplylvl.htm");
html.replace("%supplylvl%", String.valueOf(getFort().getSupplyLvL()));
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-noprivs.htm");
}
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-1.htm"); // TODO: Missing HTML?
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
else if (actualCommand.equalsIgnoreCase("supply"))
{
if (isMyLord(player))
{
if (getFort().getSiege().isInProgress())
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-siege.htm");
}
else
{
final int level = getFort().getSupplyLvL();
if (level > 0)
{
// spawn box
L2NpcTemplate BoxTemplate = NpcData.getInstance().getTemplate(SUPPLY_BOX_IDS[level - 1]);
L2MonsterInstance box = new L2MonsterInstance(IdFactory.getInstance().getNextId(), BoxTemplate);
box.setCurrentHp(box.getMaxHp());
box.setCurrentMp(box.getMaxMp());
box.setHeading(0);
box.spawnMe(getX() - 23, getY() + 41, getZ());
getFort().setSupplyLvL(0);
getFort().saveFortVariables();
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-supply.htm");
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-nosupply.htm");
}
}
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/fortress/logistics-noprivs.htm");
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
else
{
super.onBypassFeedback(player, command);
}
}
@Override
public void showChatWindow(L2PcInstance player)
{
showMessageWindow(player, 0);
}
private void showMessageWindow(L2PcInstance player, int val)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
String filename;
if (val == 0)
{
filename = "data/html/fortress/logistics.htm";
}
else
{
filename = "data/html/fortress/logistics-" + val + ".htm";
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcId%", String.valueOf(getId()));
if (getFort().getOwnerClan() != null)
{
html.replace("%clanname%", getFort().getOwnerClan().getName());
}
else
{
html.replace("%clanname%", "NPC");
}
player.sendPacket(html);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "logistics";
}
else
{
pom = "logistics-" + val;
}
return "data/html/fortress/" + pom + ".htm";
}
@Override
public boolean hasRandomAnimation()
{
return false;
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.knownlist.FriendlyMobKnownList;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
/**
* This class represents Friendly Mobs lying over the world.<br>
* These friendly mobs should only attack players with karma > 0 and it is always aggro, since it just attacks players with karma.
*/
public class L2FriendlyMobInstance extends L2Attackable
{
public L2FriendlyMobInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2FriendlyMobInstance);
}
@Override
public final FriendlyMobKnownList getKnownList()
{
return (FriendlyMobKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new FriendlyMobKnownList(this));
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
if (attacker instanceof L2PcInstance)
{
return ((L2PcInstance) attacker).getKarma() > 0;
}
return false;
}
@Override
public boolean isAggressive()
{
return true;
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.RaidBossPointsManager;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.Hero;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
/**
* This class manages all Grand Bosses.
* @version $Revision: 1.0.0.0 $ $Date: 2006/06/16 $
*/
public final class L2GrandBossInstance extends L2MonsterInstance
{
private static final int BOSS_MAINTENANCE_INTERVAL = 10000;
private boolean _useRaidCurse = true;
/**
* Constructor for L2GrandBossInstance. This represent all grandbosses.
* @param objectId ID of the instance
* @param template L2NpcTemplate of the instance
*/
public L2GrandBossInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2GrandBossInstance);
setIsRaid(true);
setLethalable(false);
}
@Override
protected int getMaintenanceInterval()
{
return BOSS_MAINTENANCE_INTERVAL;
}
@Override
public void onSpawn()
{
setIsNoRndWalk(true);
super.onSpawn();
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
L2PcInstance player = null;
if (killer instanceof L2PcInstance)
{
player = (L2PcInstance) killer;
}
else if (killer instanceof L2Summon)
{
player = ((L2Summon) killer).getOwner();
}
if (player != null)
{
broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.CONGRATULATIONS_YOUR_RAID_WAS_SUCCESSFUL));
if (player.getParty() != null)
{
for (L2PcInstance member : player.getParty().getMembers())
{
RaidBossPointsManager.getInstance().addPoints(member, getId(), (getLevel() / 2) + Rnd.get(-5, 5));
if (member.isNoble())
{
Hero.getInstance().setRBkilled(member.getObjectId(), getId());
}
}
}
else
{
RaidBossPointsManager.getInstance().addPoints(player, getId(), (getLevel() / 2) + Rnd.get(-5, 5));
if (player.isNoble())
{
Hero.getInstance().setRBkilled(player.getObjectId(), getId());
}
}
}
return true;
}
@Override
public float getVitalityPoints(int damage)
{
return -super.getVitalityPoints(damage) / 100;
}
@Override
public boolean useVitalityRate()
{
return false;
}
public void setUseRaidCurse(boolean val)
{
_useRaidCurse = val;
}
@Override
public boolean giveRaidCurse()
{
return _useRaidCurse;
}
}

View File

@ -0,0 +1,209 @@
/*
* Copyright (C) 2004-2014 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.logging.Logger;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.L2WorldRegion;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.knownlist.GuardKnownList;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.EventType;
import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcFirstTalk;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.util.Rnd;
/**
* This class manages all Guards in the world. It inherits all methods from L2Attackable and adds some more such as tracking PK and aggressive L2MonsterInstance.
*/
public class L2GuardInstance extends L2Attackable
{
private static Logger _log = Logger.getLogger(L2GuardInstance.class.getName());
/**
* Constructor of L2GuardInstance (use L2Character and L2NpcInstance constructor).<br>
* <B><U> Actions</U> :</B>
* <ul>
* <li>Call the L2Character constructor to set the _template of the L2GuardInstance (copy skills from template to object and link _calculators to NPC_STD_CALCULATOR)</li>
* <li>Set the name of the L2GuardInstance</li>
* <li>Create a RandomAnimation Task that will be launched after the calculated delay if the server allow it</li>
* </ul>
* @param objectId the identifier of the object to initialized
* @param template to apply to the NPC
*/
public L2GuardInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2GuardInstance);
}
@Override
public final GuardKnownList getKnownList()
{
return (GuardKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new GuardKnownList(this));
}
/**
* Return True if hte attacker is a L2MonsterInstance.
*/
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return attacker instanceof L2MonsterInstance;
}
/**
* Set the home location of its L2GuardInstance.
*/
@Override
public void onSpawn()
{
setIsNoRndWalk(true);
super.onSpawn();
// check the region where this mob is, do not activate the AI if region is inactive.
L2WorldRegion region = L2World.getInstance().getRegion(getX(), getY());
if ((region != null) && (!region.isActive()))
{
getAI().stopAITask();
}
}
/**
* Return the pathfile of the selected HTML file in function of the L2GuardInstance Identifier and of the page number.<br>
* <B><U> Format of the pathfile </U> :</B>
* <ul>
* <li>if page number = 0 : <B>data/html/guard/12006.htm</B> (npcId-page number)</li>
* <li>if page number > 0 : <B>data/html/guard/12006-1.htm</B> (npcId-page number)</li>
* </ul>
* @param npcId The Identifier of the L2NpcInstance whose text must be display
* @param val The number of the page to display
*/
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/guard/" + pom + ".htm";
}
/**
* Manage actions when a player click on the L2GuardInstance.<br>
* <B><U> Actions on first click on the L2GuardInstance (Select it)</U> :</B>
* <ul>
* <li>Set the L2GuardInstance as target of the L2PcInstance player (if necessary)</li>
* <li>Send a Server->Client packet MyTargetSelected to the L2PcInstance player (display the select window)</li>
* <li>Set the L2PcInstance Intention to AI_INTENTION_IDLE</li>
* <li>Send a Server->Client packet ValidateLocation to correct the L2GuardInstance position and heading on the client</li>
* </ul>
* <B><U> Actions on second click on the L2GuardInstance (Attack it/Interact with it)</U> :</B>
* <ul>
* <li>If L2PcInstance is in the _aggroList of the L2GuardInstance, set the L2PcInstance Intention to AI_INTENTION_ATTACK</li>
* <li>If L2PcInstance is NOT in the _aggroList of the L2GuardInstance, set the L2PcInstance Intention to AI_INTENTION_INTERACT (after a distance verification) and show message</li>
* </ul>
* <B><U> Example of use </U> :</B>
* <ul>
* <li>Client packet : Action, AttackRequest</li>
* </ul>
* @param player The L2PcInstance that start an action on the L2GuardInstance
*/
@Override
public void onAction(L2PcInstance player, boolean interact)
{
if (!canTarget(player))
{
return;
}
// Check if the L2PcInstance already target the L2GuardInstance
if (getObjectId() != player.getTargetId())
{
// Set the target of the L2PcInstance player
player.setTarget(this);
}
else if (interact)
{
// Check if the L2PcInstance is in the _aggroList of the L2GuardInstance
if (containsTarget(player))
{
if (Config.DEBUG)
{
_log.fine(player.getObjectId() + ": Attacked guard " + getObjectId());
}
// Set the L2PcInstance Intention to AI_INTENTION_ATTACK
player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
}
else
{
// Calculate the distance between the L2PcInstance and the L2NpcInstance
if (!canInteract(player))
{
// Set the L2PcInstance Intention to AI_INTENTION_INTERACT
player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
}
else
{
// Send a Server->Client packet SocialAction to the all L2PcInstance on the _knownPlayer of the L2NpcInstance
// to display a social action of the L2GuardInstance on their client
broadcastPacket(new SocialAction(getObjectId(), Rnd.nextInt(8)));
player.setLastFolkNPC(this);
// Open a chat window on client with the text of the L2GuardInstance
if (hasListener(EventType.ON_NPC_QUEST_START))
{
player.setLastQuestNpcObject(getObjectId());
}
if (hasListener(EventType.ON_NPC_FIRST_TALK))
{
EventDispatcher.getInstance().notifyEventAsync(new OnNpcFirstTalk(this, player), this);
}
else
{
showChatWindow(player, 0);
}
}
}
}
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.datatables.BuyListData;
import com.l2jserver.gameserver.datatables.MerchantPriceConfigTable;
import com.l2jserver.gameserver.datatables.MerchantPriceConfigTable.MerchantPriceConfig;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.buylist.L2BuyList;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.BuyList;
import com.l2jserver.gameserver.network.serverpackets.ExBuySellList;
/**
* This class ...
* @version $Revision: 1.10.4.9 $ $Date: 2005/04/11 10:06:08 $
*/
public class L2MerchantInstance extends L2NpcInstance
{
private MerchantPriceConfig _mpc;
/**
* @param objectId
* @param template
*/
public L2MerchantInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2MerchantInstance);
}
@Override
public void onSpawn()
{
super.onSpawn();
_mpc = MerchantPriceConfigTable.getInstance().getMerchantPriceConfig(this);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/merchant/" + pom + ".htm";
}
/**
* @return Returns the mpc.
*/
public MerchantPriceConfig getMpc()
{
return _mpc;
}
public final void showBuyWindow(L2PcInstance player, int val)
{
showBuyWindow(player, val, true);
}
public final void showBuyWindow(L2PcInstance player, int val, boolean applyTax)
{
final L2BuyList buyList = BuyListData.getInstance().getBuyList(val);
if (buyList == null)
{
_log.warning("BuyList not found! BuyListId:" + val);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (!buyList.isNpcAllowed(getId()))
{
_log.warning("Npc not allowed in BuyList! BuyListId:" + val + " NpcId:" + getId());
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
final double taxRate = (applyTax) ? getMpc().getTotalTaxRate() : 0;
player.setInventoryBlockingStatus(true);
player.sendPacket(new BuyList(buyList, player.getAdena(), taxRate));
player.sendPacket(new ExBuySellList(player, false));
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}

View File

@ -0,0 +1,240 @@
/*
* Copyright (C) 2004-2014 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.ScheduledFuture;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.knownlist.MonsterKnownList;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.util.MinionList;
/**
* This class manages all Monsters. L2MonsterInstance:
* <ul>
* <li>L2MinionInstance</li>
* <li>L2RaidBossInstance</li>
* <li>L2GrandBossInstance</li>
* </ul>
*/
public class L2MonsterInstance extends L2Attackable
{
protected boolean _enableMinions = true;
private L2MonsterInstance _master = null;
private volatile MinionList _minionList = null;
protected ScheduledFuture<?> _maintenanceTask = null;
private static final int MONSTER_MAINTENANCE_INTERVAL = 1000;
/**
* Constructor of L2MonsterInstance (use L2Character and L2NpcInstance constructor).<br>
* <B><U> Actions</U> :</B>
* <ul>
* <li>Call the L2Character constructor to set the _template of the L2MonsterInstance (copy skills from template to object and link _calculators to NPC_STD_CALCULATOR)</li>
* <li>Set the name of the L2MonsterInstance</li>
* <li>Create a RandomAnimation Task that will be launched after the calculated delay if the server allow it</li>
* </ul>
* @param objectId the identifier of the object to initialized
* @param template to apply to the NPC
*/
public L2MonsterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2MonsterInstance);
setAutoAttackable(true);
}
@Override
public final MonsterKnownList getKnownList()
{
return (MonsterKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new MonsterKnownList(this));
}
/**
* Return True if the attacker is not another L2MonsterInstance.
*/
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return super.isAutoAttackable(attacker) && !isEventMob();
}
/**
* Return True if the L2MonsterInstance is Aggressive (aggroRange > 0).
*/
@Override
public boolean isAggressive()
{
return getTemplate().isAggressive() && !isEventMob();
}
@Override
public void onSpawn()
{
if (!isTeleporting())
{
if (getLeader() != null)
{
setIsNoRndWalk(true);
setIsRaidMinion(getLeader().isRaid());
getLeader().getMinionList().onMinionSpawn(this);
}
// delete spawned minions before dynamic minions spawned by script
if (hasMinions())
{
getMinionList().onMasterSpawn();
}
startMaintenanceTask();
}
// dynamic script-based minions spawned here, after all preparations.
super.onSpawn();
}
@Override
public void onTeleported()
{
super.onTeleported();
if (hasMinions())
{
getMinionList().onMasterTeleported();
}
}
protected int getMaintenanceInterval()
{
return MONSTER_MAINTENANCE_INTERVAL;
}
protected void startMaintenanceTask()
{
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
if (_maintenanceTask != null)
{
_maintenanceTask.cancel(false); // doesn't do it?
_maintenanceTask = null;
}
return true;
}
@Override
public boolean deleteMe()
{
if (_maintenanceTask != null)
{
_maintenanceTask.cancel(false);
_maintenanceTask = null;
}
if (hasMinions())
{
getMinionList().onMasterDie(true);
}
if (getLeader() != null)
{
getLeader().getMinionList().onMinionDie(this, 0);
}
return super.deleteMe();
}
@Override
public L2MonsterInstance getLeader()
{
return _master;
}
public void setLeader(L2MonsterInstance leader)
{
_master = leader;
}
public void enableMinions(boolean b)
{
_enableMinions = b;
}
public boolean hasMinions()
{
return _minionList != null;
}
public MinionList getMinionList()
{
if (_minionList == null)
{
synchronized (this)
{
if (_minionList == null)
{
_minionList = new MinionList(this);
}
}
}
return _minionList;
}
@Override
public boolean isMonster()
{
return true;
}
/**
* @return true if this L2MonsterInstance (or its master) is registered in WalkingManager
*/
@Override
public boolean isWalker()
{
return ((getLeader() == null) ? super.isWalker() : getLeader().isWalker());
}
/**
* @return {@code true} if this L2MonsterInstance is not raid minion, master state otherwise.
*/
@Override
public boolean giveRaidCurse()
{
return (isRaidMinion() && (getLeader() != null)) ? getLeader().giveRaidCurse() : super.giveRaidCurse();
}
}

View File

@ -0,0 +1,152 @@
/*
* Copyright (C) 2004-2014 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.List;
import java.util.Map;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.SkillTreesData;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2SkillLearn;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.status.FolkStatus;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.AcquireSkillType;
import com.l2jserver.gameserver.model.base.ClassId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExAcquirableSkillListByClass;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.StringUtil;
public class L2NpcInstance extends L2Npc
{
public L2NpcInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2NpcInstance);
setIsInvul(false);
}
@Override
public FolkStatus getStatus()
{
return (FolkStatus) super.getStatus();
}
@Override
public void initCharStatus()
{
setStatus(new FolkStatus(this));
}
public List<ClassId> getClassesToTeach()
{
return getTemplate().getTeachInfo();
}
/**
* Displays Skill Tree for a given player, npc and class Id.
* @param player the active character.
* @param npc the last folk.
* @param classId player's active class id.
*/
public static void showSkillList(L2PcInstance player, L2Npc npc, ClassId classId)
{
if (Config.DEBUG)
{
_log.fine("SkillList activated on: " + npc.getObjectId());
}
final int npcId = npc.getTemplate().getId();
if (npcId == 32611) // Tolonis (Officer)
{
final List<L2SkillLearn> skills = SkillTreesData.getInstance().getAvailableCollectSkills(player);
if (skills.isEmpty()) // No more skills to learn, come back when you level.
{
final int minLevel = SkillTreesData.getInstance().getMinLevelForNewSkill(player, SkillTreesData.getInstance().getCollectSkillTree());
if (minLevel > 0)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_DO_NOT_HAVE_ANY_FURTHER_SKILLS_TO_LEARN_COME_BACK_WHEN_YOU_HAVE_REACHED_LEVEL_S1);
sm.addInt(minLevel);
player.sendPacket(sm);
}
else
{
player.sendPacket(SystemMessageId.THERE_ARE_NO_OTHER_SKILLS_TO_LEARN);
}
}
else
{
player.sendPacket(new ExAcquirableSkillListByClass(skills, AcquireSkillType.COLLECT));
}
return;
}
if (!npc.getTemplate().canTeach(classId))
{
npc.showNoTeachHtml(player);
return;
}
if (((L2NpcInstance) npc).getClassesToTeach().isEmpty())
{
final NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
final String sb = StringUtil.concat("<html><body>I cannot teach you. My class list is empty.<br>Ask admin to fix it. Need add my npcid and classes to skill_learn.sql.<br>NpcId:", String.valueOf(npcId), ", Your classId:", String.valueOf(player.getClassId().getId()), "</body></html>");
html.setHtml(sb);
player.sendPacket(html);
return;
}
// Normal skills, No LearnedByFS, no AutoGet skills.
final List<L2SkillLearn> skills = SkillTreesData.getInstance().getAvailableSkills(player, classId, false, false);
player.setLearningClass(classId);
if (skills.isEmpty())
{
final Map<Integer, L2SkillLearn> skillTree = SkillTreesData.getInstance().getCompleteClassSkillTree(classId);
final int minLevel = SkillTreesData.getInstance().getMinLevelForNewSkill(player, skillTree);
if (minLevel > 0)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_DO_NOT_HAVE_ANY_FURTHER_SKILLS_TO_LEARN_COME_BACK_WHEN_YOU_HAVE_REACHED_LEVEL_S1);
sm.addInt(minLevel);
player.sendPacket(sm);
}
else
{
if (player.getClassId().level() == 1)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THERE_ARE_NO_OTHER_SKILLS_TO_LEARN_PLEASE_COME_BACK_AFTER_S1ND_CLASS_CHANGE);
sm.addInt(2);
player.sendPacket(sm);
}
else
{
player.sendPacket(SystemMessageId.THERE_ARE_NO_OTHER_SKILLS_TO_LEARN);
}
}
}
else
{
player.sendPacket(new ExAcquirableSkillListByClass(skills, AcquireSkillType.CLASS));
}
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
/**
* @author NightMarez
* @version $Revision: 1.3.2.2.2.5 $ $Date: 2005/03/27 15:29:32 $
*/
public final class L2ObservationInstance extends L2Npc
{
public L2ObservationInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2ObservationInstance);
}
@Override
public void showChatWindow(L2PcInstance player, int val)
{
String filename = null;
if (isInsideRadius(-79884, 86529, 0, 50, false, true) || isInsideRadius(-78858, 111358, 0, 50, false, true) || isInsideRadius(-76973, 87136, 0, 50, false, true) || isInsideRadius(-75850, 111968, 0, 50, false, true))
{
if (val == 0)
{
filename = "data/html/observation/" + getId() + "-Oracle.htm";
}
else
{
filename = "data/html/observation/" + getId() + "-Oracle-" + val + ".htm";
}
}
else
{
if (val == 0)
{
filename = "data/html/observation/" + getId() + ".htm";
}
else
{
filename = "data/html/observation/" + getId() + "-" + val + ".htm";
}
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.olympiad.Olympiad;
/**
* Olympiad Npc's Instance
* @author godson
*/
public class L2OlympiadManagerInstance extends L2Npc
{
public L2OlympiadManagerInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2OlympiadManagerInstance);
}
public void showChatWindow(L2PcInstance player, int val, String suffix)
{
String filename = Olympiad.OLYMPIAD_HTML_PATH;
filename += "noble_desc" + val;
filename += (suffix != null) ? suffix + ".htm" : ".htm";
if (filename.equals(Olympiad.OLYMPIAD_HTML_PATH + "noble_desc0.htm"))
{
filename = Olympiad.OLYMPIAD_HTML_PATH + "noble_main.htm";
}
showChatWindow(player, filename);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.Config;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.util.Evolve;
public class L2PetManagerInstance extends L2MerchantInstance
{
public L2PetManagerInstance(int objectID, L2NpcTemplate template)
{
super(objectID, template);
setInstanceType(InstanceType.L2PetManagerInstance);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/petmanager/" + pom + ".htm";
}
@Override
public void showChatWindow(L2PcInstance player)
{
String filename = "data/html/petmanager/" + getId() + ".htm";
if ((getId() == 36478) && player.hasSummon())
{
filename = "data/html/petmanager/restore-unsummonpet.htm";
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
if (Config.ALLOW_RENTPET && Config.LIST_PET_RENT_NPC.contains(getId()))
{
html.replace("_Quest", "_RentPet\">Rent Pet</a><br><a action=\"bypass -h npc_%objectId%_Quest");
}
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcname%", getName());
player.sendPacket(html);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (command.startsWith("exchange"))
{
String[] params = command.split(" ");
int val = Integer.parseInt(params[1]);
switch (val)
{
case 1:
exchange(player, 7585, 6650);
break;
case 2:
exchange(player, 7583, 6648);
break;
case 3:
exchange(player, 7584, 6649);
break;
}
return;
}
else if (command.startsWith("evolve"))
{
String[] params = command.split(" ");
int val = Integer.parseInt(params[1]);
boolean ok = false;
switch (val)
{
// Info evolve(player, "curent pet summon item", "new pet summon item", "lvl required to evolve")
// To ignore evolve just put value 0 where do you like example: evolve(player, 0, 9882, 55);
case 1:
ok = Evolve.doEvolve(player, this, 2375, 9882, 55);
break;
case 2:
ok = Evolve.doEvolve(player, this, 9882, 10426, 70);
break;
case 3:
ok = Evolve.doEvolve(player, this, 6648, 10311, 55);
break;
case 4:
ok = Evolve.doEvolve(player, this, 6650, 10313, 55);
break;
case 5:
ok = Evolve.doEvolve(player, this, 6649, 10312, 55);
break;
}
if (!ok)
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/petmanager/evolve_no.htm");
player.sendPacket(html);
}
return;
}
else if (command.startsWith("restore"))
{
String[] params = command.split(" ");
int val = Integer.parseInt(params[1]);
boolean ok = false;
switch (val)
{
// Info evolve(player, "curent pet summon item", "new pet summon item", "lvl required to evolve")
case 1:
ok = Evolve.doRestore(player, this, 10307, 9882, 55);
break;
case 2:
ok = Evolve.doRestore(player, this, 10611, 10426, 70);
break;
case 3:
ok = Evolve.doRestore(player, this, 10308, 4422, 55);
break;
case 4:
ok = Evolve.doRestore(player, this, 10309, 4423, 55);
break;
case 5:
ok = Evolve.doRestore(player, this, 10310, 4424, 55);
break;
}
if (!ok)
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/petmanager/restore_no.htm");
player.sendPacket(html);
}
return;
}
else
{
super.onBypassFeedback(player, command);
}
}
public final void exchange(L2PcInstance player, int itemIdtake, int itemIdgive)
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (player.destroyItemByItemId("Consume", itemIdtake, 1, this, true))
{
player.addItem("", itemIdgive, 1, this, true);
html.setFile(player.getHtmlPrefix(), "data/html/petmanager/" + getId() + ".htm");
player.sendPacket(html);
}
else
{
html.setFile(player.getHtmlPrefix(), "data/html/petmanager/exchange_no.htm");
player.sendPacket(html);
}
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.impl.character.npc.attackable.OnAttackableAttack;
import com.l2jserver.gameserver.model.events.impl.character.npc.attackable.OnAttackableKill;
import com.l2jserver.gameserver.model.skills.Skill;
/**
* This class extends Guard class for quests, that require tracking of onAttack and onKill events from monsters' attacks.
* @author GKR
*/
public final class L2QuestGuardInstance extends L2GuardInstance
{
private boolean _isAutoAttackable = true;
private boolean _isPassive = false;
public L2QuestGuardInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2QuestGuardInstance);
}
@Override
public void addDamage(L2Character attacker, int damage, Skill skill)
{
super.addDamage(attacker, damage, skill);
if (attacker instanceof L2Attackable)
{
EventDispatcher.getInstance().notifyEventAsync(new OnAttackableAttack(null, this, damage, skill, false), this);
}
}
@Override
public boolean doDie(L2Character killer)
{
// Kill the L2NpcInstance (the corpse disappeared after 7 seconds)
if (!super.doDie(killer))
{
return false;
}
if (killer instanceof L2Attackable)
{
// Delayed notification
EventDispatcher.getInstance().notifyEventAsyncDelayed(new OnAttackableKill(null, this, false), this, _onKillDelay);
}
return true;
}
@Override
public void addDamageHate(L2Character attacker, int damage, int aggro)
{
if (!_isPassive && !(attacker instanceof L2PcInstance))
{
super.addDamageHate(attacker, damage, aggro);
}
}
public void setPassive(boolean state)
{
_isPassive = state;
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return _isAutoAttackable && !(attacker instanceof L2PcInstance);
}
@Override
public void setAutoAttackable(boolean state)
{
_isAutoAttackable = state;
}
public boolean isPassive()
{
return _isPassive;
}
}

View File

@ -0,0 +1,546 @@
/*
* Copyright (C) 2004-2014 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.List;
import javolution.util.FastList;
import com.l2jserver.gameserver.MonsterRace;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.knownlist.RaceManagerKnownList;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.DeleteObject;
import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.network.serverpackets.MonRaceInfo;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.util.Broadcast;
public class L2RaceManagerInstance extends L2Npc
{
public static final int LANES = 8;
public static final int WINDOW_START = 0;
// private static List<Race> _history;
private static List<L2RaceManagerInstance> _managers;
protected static int _raceNumber = 4;
// Time Constants
private static final long SECOND = 1000;
private static final long MINUTE = 60 * SECOND;
private static int _minutes = 5;
// States
private static final int ACCEPTING_BETS = 0;
private static final int WAITING = 1;
private static final int STARTING_RACE = 2;
private static final int RACE_END = 3;
private static int _state = RACE_END;
protected static final int[][] _codes =
{
{
-1,
0
},
{
0,
15322
},
{
13765,
-1
}
};
private static boolean _notInitialized = true;
protected static MonRaceInfo _packet;
protected static final int _cost[] =
{
100,
500,
1000,
5000,
10000,
20000,
50000,
100000
};
public L2RaceManagerInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2RaceManagerInstance);
if (_notInitialized)
{
_notInitialized = false;
// _history = new FastList<>();
_managers = new FastList<>();
ThreadPoolManager s = ThreadPoolManager.getInstance();
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKETS_ARE_NOW_AVAILABLE_FOR_MONSTER_RACE_S1), 0, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.NOW_SELLING_TICKETS_FOR_MONSTER_RACE_S1), 30 * SECOND, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKETS_ARE_NOW_AVAILABLE_FOR_MONSTER_RACE_S1), MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.NOW_SELLING_TICKETS_FOR_MONSTER_RACE_S1), MINUTE + (30 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKET_SALES_FOR_THE_MONSTER_RACE_WILL_END_IN_S1_MINUTE_S), 2 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKET_SALES_FOR_THE_MONSTER_RACE_WILL_END_IN_S1_MINUTE_S), 3 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKET_SALES_FOR_THE_MONSTER_RACE_WILL_END_IN_S1_MINUTE_S), 4 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKET_SALES_FOR_THE_MONSTER_RACE_WILL_END_IN_S1_MINUTE_S), 5 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKET_SALES_FOR_THE_MONSTER_RACE_WILL_END_IN_S1_MINUTE_S), 6 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.TICKETS_SALES_ARE_CLOSED_FOR_MONSTER_RACE_S1_ODDS_ARE_POSTED), 7 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.MONSTER_RACE_S2_WILL_BEGIN_IN_S1_MINUTE_S), 7 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.MONSTER_RACE_S2_WILL_BEGIN_IN_S1_MINUTE_S), 8 * MINUTE, 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.MONSTER_RACE_S1_WILL_BEGIN_IN_30_SECONDS), (8 * MINUTE) + (30 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.MONSTER_RACE_S1_IS_ABOUT_TO_BEGIN_COUNTDOWN_IN_FIVE_SECONDS), (8 * MINUTE) + (50 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.THE_RACE_WILL_BEGIN_IN_S1_SECOND_S), (8 * MINUTE) + (55 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.THE_RACE_WILL_BEGIN_IN_S1_SECOND_S), (8 * MINUTE) + (56 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.THE_RACE_WILL_BEGIN_IN_S1_SECOND_S), (8 * MINUTE) + (57 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.THE_RACE_WILL_BEGIN_IN_S1_SECOND_S), (8 * MINUTE) + (58 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.THE_RACE_WILL_BEGIN_IN_S1_SECOND_S), (8 * MINUTE) + (59 * SECOND), 10 * MINUTE);
s.scheduleGeneralAtFixedRate(new Announcement(SystemMessageId.THEY_RE_OFF), 9 * MINUTE, 10 * MINUTE);
// */
}
_managers.add(this);
}
@Override
public final RaceManagerKnownList getKnownList()
{
return (RaceManagerKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new RaceManagerKnownList(this));
}
class Announcement implements Runnable
{
private final SystemMessageId _type;
public Announcement(SystemMessageId pType)
{
_type = pType;
}
@Override
public void run()
{
makeAnnouncement(_type);
}
}
public void makeAnnouncement(SystemMessageId type)
{
SystemMessage sm = SystemMessage.getSystemMessage(type);
switch (type.getId())
{
case 816: // SystemMessageId.TICKETS_ARE_NOW_AVAILABLE_FOR_MONSTER_RACE_S1
case 817: // SystemMessageId.NOW_SELLING_TICKETS_FOR_MONSTER_RACE_S1
if (_state != ACCEPTING_BETS)
{// _log.info("Race Initializing");
_state = ACCEPTING_BETS;
startRace();
}// else{_log.info("Race open");}
sm.addInt(_raceNumber);
break;
case 818: // SystemMessageId.TICKET_SALES_FOR_THE_MONSTER_RACE_WILL_END_IN_S1_MINUTE_S
case 820: // SystemMessageId.MONSTER_RACE_S2_WILL_BEGIN_IN_S1_MINUTE_S
case 823: // SystemMessageId.THE_RACE_WILL_BEGIN_IN_S1_SECOND_S
sm.addInt(_minutes);
if (type.getId() == 820)
{
sm.addInt(_raceNumber);
}
_minutes--;
break;
case 819: // SystemMessageId.TICKETS_SALES_ARE_CLOSED_FOR_MONSTER_RACE_S1_ODDS_ARE_POSTED
// _log.info("Sales closed");
sm.addInt(_raceNumber);
_state = WAITING;
_minutes = 2;
break;
case 821: // SystemMessageId.MONSTER_RACE_S1_WILL_BEGIN_IN_30_SECONDS
case 822: // SystemMessageId.MONSTER_RACE_S1_IS_ABOUT_TO_BEGIN_COUNTDOWN_IN_FIVE_SECONDS
case 825: // SystemMessageId.MONSTER_RACE_S1_IS_FINISHED
sm.addInt(_raceNumber);
_minutes = 5;
break;
case 826: // SystemMessageId.FIRST_PRIZE_GOES_TO_THE_PLAYER_IN_LANE_S1_SECOND_PRIZE_GOES_TO_THE_PLAYER_IN_LANE_S2
// _log.info("Placing");
_state = RACE_END;
sm.addInt(MonsterRace.getInstance().getFirstPlace());
sm.addInt(MonsterRace.getInstance().getSecondPlace());
break;
}
// _logn.info("Counter: "+minutes);
// _log.info("State: "+state);
broadcast(sm);
// _log.info("Player's known: "+getKnownPlayers().size());
if (type == SystemMessageId.THEY_RE_OFF)
{
// _log.info("Starting race");
_state = STARTING_RACE;
startRace();
_minutes = 5;
}
}
protected void broadcast(L2GameServerPacket pkt)
{
for (L2RaceManagerInstance manager : _managers)
{
if (!manager.isDead())
{
Broadcast.toKnownPlayers(manager, pkt);
}
}
}
public void sendMonsterInfo()
{
broadcast(_packet);
}
private void startRace()
{
MonsterRace race = MonsterRace.getInstance();
if (_state == STARTING_RACE)
{
// state++;
PlaySound SRace = new PlaySound(1, "S_Race", 0, 0, 0, 0, 0);
broadcast(SRace);
PlaySound SRace2 = new PlaySound(0, "ItemSound2.race_start", 1, 121209259, 12125, 182487, -3559);
broadcast(SRace2);
_packet = new MonRaceInfo(_codes[1][0], _codes[1][1], race.getMonsters(), race.getSpeeds());
sendMonsterInfo();
ThreadPoolManager.getInstance().scheduleGeneral(new RunRace(), 5000);
}
else
{
// state++;
race.newRace();
race.newSpeeds();
_packet = new MonRaceInfo(_codes[0][0], _codes[0][1], race.getMonsters(), race.getSpeeds());
sendMonsterInfo();
}
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (command.startsWith("BuyTicket") && (_state != ACCEPTING_BETS))
{
player.sendPacket(SystemMessageId.MONSTER_RACE_TICKETS_ARE_NO_LONGER_AVAILABLE);
command = "Chat 0";
}
if (command.startsWith("ShowOdds") && (_state == ACCEPTING_BETS))
{
player.sendPacket(SystemMessageId.MONSTER_RACE_PAYOUT_INFORMATION_IS_NOT_AVAILABLE_WHILE_TICKETS_ARE_BEING_SOLD);
command = "Chat 0";
}
if (command.startsWith("BuyTicket"))
{
int val = Integer.parseInt(command.substring(10));
if (val == 0)
{
player.setRace(0, 0);
player.setRace(1, 0);
}
if (((val == 10) && (player.getRace(0) == 0)) || ((val == 20) && (player.getRace(0) == 0) && (player.getRace(1) == 0)))
{
val = 0;
}
showBuyTicket(player, val);
}
else if (command.equals("ShowOdds"))
{
showOdds(player);
}
else if (command.equals("ShowInfo"))
{
showMonsterInfo(player);
}
else if (command.equals("calculateWin"))
{
// displayCalculateWinnings(player);
}
else if (command.equals("viewHistory"))
{
// displayHistory(player);
}
else
{
// getKnownList().removeKnownObject(player);
super.onBypassFeedback(player, command);
}
}
public void showOdds(L2PcInstance player)
{
if (_state == ACCEPTING_BETS)
{
return;
}
int npcId = getTemplate().getId();
String filename, search;
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
filename = getHtmlPath(npcId, 5);
html.setFile(player.getHtmlPrefix(), filename);
for (int i = 0; i < 8; i++)
{
int n = i + 1;
search = "Mob" + n;
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
}
html.replace("1race", String.valueOf(_raceNumber));
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
player.sendPacket(ActionFailed.STATIC_PACKET);
}
public void showMonsterInfo(L2PcInstance player)
{
int npcId = getTemplate().getId();
String filename, search;
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
filename = getHtmlPath(npcId, 6);
html.setFile(player.getHtmlPrefix(), filename);
for (int i = 0; i < 8; i++)
{
int n = i + 1;
search = "Mob" + n;
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
}
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
player.sendPacket(ActionFailed.STATIC_PACKET);
}
public void showBuyTicket(L2PcInstance player, int val)
{
if (_state != ACCEPTING_BETS)
{
return;
}
int npcId = getTemplate().getId();
SystemMessage sm;
String filename, search, replace;
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (val < 10)
{
filename = getHtmlPath(npcId, 2);
html.setFile(player.getHtmlPrefix(), filename);
for (int i = 0; i < 8; i++)
{
int n = i + 1;
search = "Mob" + n;
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
}
search = "No1";
if (val == 0)
{
html.replace(search, "");
}
else
{
html.replace(search, "" + val);
player.setRace(0, val);
}
}
else if (val < 20)
{
if (player.getRace(0) == 0)
{
return;
}
filename = getHtmlPath(npcId, 3);
html.setFile(player.getHtmlPrefix(), filename);
html.replace("0place", "" + player.getRace(0));
search = "Mob1";
replace = MonsterRace.getInstance().getMonsters()[player.getRace(0) - 1].getTemplate().getName();
html.replace(search, replace);
search = "0adena";
if (val == 10)
{
html.replace(search, "");
}
else
{
html.replace(search, "" + _cost[val - 11]);
player.setRace(1, val - 10);
}
}
else if (val == 20)
{
if ((player.getRace(0) == 0) || (player.getRace(1) == 0))
{
return;
}
filename = getHtmlPath(npcId, 4);
html.setFile(player.getHtmlPrefix(), filename);
html.replace("0place", "" + player.getRace(0));
search = "Mob1";
replace = MonsterRace.getInstance().getMonsters()[player.getRace(0) - 1].getTemplate().getName();
html.replace(search, replace);
search = "0adena";
int price = _cost[player.getRace(1) - 1];
html.replace(search, "" + price);
search = "0tax";
int tax = 0;
html.replace(search, "" + tax);
search = "0total";
int total = price + tax;
html.replace(search, "" + total);
}
else
{
if ((player.getRace(0) == 0) || (player.getRace(1) == 0))
{
return;
}
int ticket = player.getRace(0);
int priceId = player.getRace(1);
if (!player.reduceAdena("Race", _cost[priceId - 1], this, true))
{
return;
}
player.setRace(0, 0);
player.setRace(1, 0);
sm = SystemMessage.getSystemMessage(SystemMessageId.ACQUIRED_S1_S2);
sm.addInt(_raceNumber);
sm.addItemName(4443);
player.sendPacket(sm);
L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), 4443);
item.setCount(1);
item.setEnchantLevel(_raceNumber);
item.setCustomType1(ticket);
item.setCustomType2(_cost[priceId - 1] / 100);
player.getInventory().addItem("Race", item, player, this);
InventoryUpdate iu = new InventoryUpdate();
iu.addItem(item);
L2ItemInstance adenaupdate = player.getInventory().getItemByItemId(Inventory.ADENA_ID);
iu.addModifiedItem(adenaupdate);
player.sendPacket(iu);
return;
}
html.replace("1race", String.valueOf(_raceNumber));
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
player.sendPacket(ActionFailed.STATIC_PACKET);
}
public static class Race
{
private final Info[] _info;
public Race(Info[] pInfo)
{
_info = pInfo;
}
public Info getLaneInfo(int lane)
{
return _info[lane];
}
public class Info
{
private final int _id;
private final int _place;
private final int _odds;
private final int _payout;
public Info(int pId, int pPlace, int pOdds, int pPayout)
{
_id = pId;
_place = pPlace;
_odds = pOdds;
_payout = pPayout;
}
public int getId()
{
return _id;
}
public int getOdds()
{
return _odds;
}
public int getPayout()
{
return _payout;
}
public int getPlace()
{
return _place;
}
}
}
class RunRace implements Runnable
{
@Override
public void run()
{
_packet = new MonRaceInfo(_codes[2][0], _codes[2][1], MonsterRace.getInstance().getMonsters(), MonsterRace.getInstance().getSpeeds());
sendMonsterInfo();
ThreadPoolManager.getInstance().scheduleGeneral(new RunEnd(), 30000);
}
}
class RunEnd implements Runnable
{
@Override
public void run()
{
makeAnnouncement(SystemMessageId.FIRST_PRIZE_GOES_TO_THE_PLAYER_IN_LANE_S1_SECOND_PRIZE_GOES_TO_THE_PLAYER_IN_LANE_S2);
makeAnnouncement(SystemMessageId.MONSTER_RACE_S1_IS_FINISHED);
_raceNumber++;
DeleteObject obj = null;
for (int i = 0; i < 8; i++)
{
obj = new DeleteObject(MonsterRace.getInstance().getMonsters()[i]);
broadcast(obj);
}
}
}
}

View File

@ -0,0 +1,181 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.RaidBossPointsManager;
import com.l2jserver.gameserver.instancemanager.RaidBossSpawnManager;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.Hero;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
/**
* This class manages all RaidBoss.<br>
* In a group mob, there are one master called RaidBoss and several slaves called Minions.
*/
public class L2RaidBossInstance extends L2MonsterInstance
{
private static final int RAIDBOSS_MAINTENANCE_INTERVAL = 30000; // 30 sec
private RaidBossSpawnManager.StatusEnum _raidStatus;
private boolean _useRaidCurse = true;
/**
* Constructor of L2RaidBossInstance (use L2Character and L2NpcInstance constructor).<br>
* <B><U>Actions</U>:</B>
* <ul>
* <li>Call the L2Character constructor to set the _template of the L2RaidBossInstance (copy skills from template to object and link _calculators to NPC_STD_CALCULATOR)</li>
* <li>Set the name of the L2RaidBossInstance</li>
* <li>Create a RandomAnimation Task that will be launched after the calculated delay if the server allow it</li>
* </ul>
* @param objectId the identifier of the object to initialized
* @param template to apply to the NPC
*/
public L2RaidBossInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2RaidBossInstance);
setIsRaid(true);
setLethalable(false);
}
@Override
public void onSpawn()
{
setIsNoRndWalk(true);
super.onSpawn();
}
@Override
protected int getMaintenanceInterval()
{
return RAIDBOSS_MAINTENANCE_INTERVAL;
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
final L2PcInstance player = killer.getActingPlayer();
if (player != null)
{
broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.CONGRATULATIONS_YOUR_RAID_WAS_SUCCESSFUL));
if (player.getParty() != null)
{
for (L2PcInstance member : player.getParty().getMembers())
{
RaidBossPointsManager.getInstance().addPoints(member, getId(), (getLevel() / 2) + Rnd.get(-5, 5));
if (member.isNoble())
{
Hero.getInstance().setRBkilled(member.getObjectId(), getId());
}
}
}
else
{
RaidBossPointsManager.getInstance().addPoints(player, getId(), (getLevel() / 2) + Rnd.get(-5, 5));
if (player.isNoble())
{
Hero.getInstance().setRBkilled(player.getObjectId(), getId());
}
}
}
RaidBossSpawnManager.getInstance().updateStatus(this, true);
return true;
}
/**
* Spawn all minions at a regular interval Also if boss is too far from home location at the time of this check, teleport it home.
*/
@Override
protected void startMaintenanceTask()
{
_maintenanceTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> checkAndReturnToSpawn(), 60000, getMaintenanceInterval() + Rnd.get(5000));
}
protected void checkAndReturnToSpawn()
{
if (isDead() || isMovementDisabled() || !canReturnToSpawnPoint())
{
return;
}
final L2Spawn spawn = getSpawn();
if (spawn == null)
{
return;
}
final int spawnX = spawn.getX();
final int spawnY = spawn.getY();
final int spawnZ = spawn.getZ();
if (!isInCombat() && !isMovementDisabled())
{
if (!isInsideRadius(spawnX, spawnY, spawnZ, Math.max(Config.MAX_DRIFT_RANGE, 200), true, false))
{
teleToLocation(spawnX, spawnY, spawnZ, false);
}
}
}
public void setRaidStatus(RaidBossSpawnManager.StatusEnum status)
{
_raidStatus = status;
}
public RaidBossSpawnManager.StatusEnum getRaidStatus()
{
return _raidStatus;
}
@Override
public float getVitalityPoints(int damage)
{
return -super.getVitalityPoints(damage) / 100;
}
@Override
public boolean useVitalityRate()
{
return false;
}
public void setUseRaidCurse(boolean val)
{
_useRaidCurse = val;
}
@Override
public boolean giveRaidCurse()
{
return _useRaidCurse;
}
}

View File

@ -0,0 +1,524 @@
/*
* Copyright (C) 2004-2014 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.instancemanager.FourSepulchersManager;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
/**
* @author sandman
*/
public class L2SepulcherMonsterInstance extends L2MonsterInstance
{
protected static final SkillHolder FAKE_PETRIFICATION = new SkillHolder(4616, 1);
public int mysteriousBoxId = 0;
protected Future<?> _victimSpawnKeyBoxTask = null;
protected Future<?> _victimShout = null;
protected Future<?> _changeImmortalTask = null;
protected Future<?> _onDeadEventTask = null;
public L2SepulcherMonsterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2SepulcherMonsterInstance);
setShowSummonAnimation(true);
switch (template.getId())
{
case 25339:
case 25342:
case 25346:
case 25349:
setIsRaid(true);
}
}
@Override
public void onSpawn()
{
setShowSummonAnimation(false);
switch (getId())
{
case 18150:
case 18151:
case 18152:
case 18153:
case 18154:
case 18155:
case 18156:
case 18157:
if (_victimSpawnKeyBoxTask != null)
{
_victimSpawnKeyBoxTask.cancel(true);
}
_victimSpawnKeyBoxTask = ThreadPoolManager.getInstance().scheduleEffect(new VictimSpawnKeyBox(this), 300000);
if (_victimShout != null)
{
_victimShout.cancel(true);
}
_victimShout = ThreadPoolManager.getInstance().scheduleEffect(new VictimShout(this), 5000);
break;
case 18196:
case 18197:
case 18198:
case 18199:
case 18200:
case 18201:
case 18202:
case 18203:
case 18204:
case 18205:
case 18206:
case 18207:
case 18208:
case 18209:
case 18210:
case 18211:
break;
case 18231:
case 18232:
case 18233:
case 18234:
case 18235:
case 18236:
case 18237:
case 18238:
case 18239:
case 18240:
case 18241:
case 18242:
case 18243:
if (_changeImmortalTask != null)
{
_changeImmortalTask.cancel(true);
}
_changeImmortalTask = ThreadPoolManager.getInstance().scheduleEffect(new ChangeImmortal(this), 1600);
break;
case 18256:
break;
case 25339:
case 25342:
case 25346:
case 25349:
setIsRaid(true);
break;
}
super.onSpawn();
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
switch (getId())
{
case 18120:
case 18121:
case 18122:
case 18123:
case 18124:
case 18125:
case 18126:
case 18127:
case 18128:
case 18129:
case 18130:
case 18131:
case 18149:
case 18158:
case 18159:
case 18160:
case 18161:
case 18162:
case 18163:
case 18164:
case 18165:
case 18183:
case 18184:
case 18212:
case 18213:
case 18214:
case 18215:
case 18216:
case 18217:
case 18218:
case 18219:
if (_onDeadEventTask != null)
{
_onDeadEventTask.cancel(true);
}
_onDeadEventTask = ThreadPoolManager.getInstance().scheduleEffect(new OnDeadEvent(this), 3500);
break;
case 18150:
case 18151:
case 18152:
case 18153:
case 18154:
case 18155:
case 18156:
case 18157:
if (_victimSpawnKeyBoxTask != null)
{
_victimSpawnKeyBoxTask.cancel(true);
_victimSpawnKeyBoxTask = null;
}
if (_victimShout != null)
{
_victimShout.cancel(true);
_victimShout = null;
}
if (_onDeadEventTask != null)
{
_onDeadEventTask.cancel(true);
}
_onDeadEventTask = ThreadPoolManager.getInstance().scheduleEffect(new OnDeadEvent(this), 3500);
break;
case 18141:
case 18142:
case 18143:
case 18144:
case 18145:
case 18146:
case 18147:
case 18148:
if (FourSepulchersManager.getInstance().isViscountMobsAnnihilated(mysteriousBoxId))
{
if (_onDeadEventTask != null)
{
_onDeadEventTask.cancel(true);
}
_onDeadEventTask = ThreadPoolManager.getInstance().scheduleEffect(new OnDeadEvent(this), 3500);
}
break;
case 18220:
case 18221:
case 18222:
case 18223:
case 18224:
case 18225:
case 18226:
case 18227:
case 18228:
case 18229:
case 18230:
case 18231:
case 18232:
case 18233:
case 18234:
case 18235:
case 18236:
case 18237:
case 18238:
case 18239:
case 18240:
if (FourSepulchersManager.getInstance().isDukeMobsAnnihilated(mysteriousBoxId))
{
if (_onDeadEventTask != null)
{
_onDeadEventTask.cancel(true);
}
_onDeadEventTask = ThreadPoolManager.getInstance().scheduleEffect(new OnDeadEvent(this), 3500);
}
break;
case 25339:
case 25342:
case 25346:
case 25349:
giveCup(killer);
if (_onDeadEventTask != null)
{
_onDeadEventTask.cancel(true);
}
_onDeadEventTask = ThreadPoolManager.getInstance().scheduleEffect(new OnDeadEvent(this), 8500);
break;
}
return true;
}
@Override
public boolean deleteMe()
{
if (_victimSpawnKeyBoxTask != null)
{
_victimSpawnKeyBoxTask.cancel(true);
_victimSpawnKeyBoxTask = null;
}
if (_onDeadEventTask != null)
{
_onDeadEventTask.cancel(true);
_onDeadEventTask = null;
}
return super.deleteMe();
}
private void giveCup(L2Character killer)
{
String questId = "620_FourGoblets";
int cupId = 0;
int oldBrooch = 7262;
switch (getId())
{
case 25339:
cupId = 7256;
break;
case 25342:
cupId = 7257;
break;
case 25346:
cupId = 7258;
break;
case 25349:
cupId = 7259;
break;
}
L2PcInstance player = killer.getActingPlayer();
if (player == null)
{
return;
}
if (player.getParty() != null)
{
for (L2PcInstance mem : player.getParty().getMembers())
{
QuestState qs = mem.getQuestState(questId);
if ((qs != null) && (qs.isStarted() || qs.isCompleted()) && (mem.getInventory().getItemByItemId(oldBrooch) == null))
{
mem.addItem("Quest", cupId, 1, mem, true);
}
}
}
else
{
QuestState qs = player.getQuestState(questId);
if ((qs != null) && (qs.isStarted() || qs.isCompleted()) && (player.getInventory().getItemByItemId(oldBrooch) == null))
{
player.addItem("Quest", cupId, 1, player, true);
}
}
}
private class VictimShout implements Runnable
{
private final L2SepulcherMonsterInstance _activeChar;
public VictimShout(L2SepulcherMonsterInstance activeChar)
{
_activeChar = activeChar;
}
@Override
public void run()
{
if (_activeChar.isDead())
{
return;
}
if (!_activeChar.isVisible())
{
return;
}
broadcastPacket(new NpcSay(getObjectId(), 0, getId(), "forgive me!!"));
}
}
private class VictimSpawnKeyBox implements Runnable
{
private final L2SepulcherMonsterInstance _activeChar;
public VictimSpawnKeyBox(L2SepulcherMonsterInstance activeChar)
{
_activeChar = activeChar;
}
@Override
public void run()
{
if (_activeChar.isDead())
{
return;
}
if (!_activeChar.isVisible())
{
return;
}
FourSepulchersManager.getInstance().spawnKeyBox(_activeChar);
broadcastPacket(new NpcSay(getObjectId(), 0, getId(), "Many thanks for rescue me."));
if (_victimShout != null)
{
_victimShout.cancel(true);
}
}
}
private static class OnDeadEvent implements Runnable
{
L2SepulcherMonsterInstance _activeChar;
public OnDeadEvent(L2SepulcherMonsterInstance activeChar)
{
_activeChar = activeChar;
}
@Override
public void run()
{
switch (_activeChar.getId())
{
case 18120:
case 18121:
case 18122:
case 18123:
case 18124:
case 18125:
case 18126:
case 18127:
case 18128:
case 18129:
case 18130:
case 18131:
case 18149:
case 18158:
case 18159:
case 18160:
case 18161:
case 18162:
case 18163:
case 18164:
case 18165:
case 18183:
case 18184:
case 18212:
case 18213:
case 18214:
case 18215:
case 18216:
case 18217:
case 18218:
case 18219:
FourSepulchersManager.getInstance().spawnKeyBox(_activeChar);
break;
case 18150:
case 18151:
case 18152:
case 18153:
case 18154:
case 18155:
case 18156:
case 18157:
FourSepulchersManager.getInstance().spawnExecutionerOfHalisha(_activeChar);
break;
case 18141:
case 18142:
case 18143:
case 18144:
case 18145:
case 18146:
case 18147:
case 18148:
FourSepulchersManager.getInstance().spawnMonster(_activeChar.mysteriousBoxId);
break;
case 18220:
case 18221:
case 18222:
case 18223:
case 18224:
case 18225:
case 18226:
case 18227:
case 18228:
case 18229:
case 18230:
case 18231:
case 18232:
case 18233:
case 18234:
case 18235:
case 18236:
case 18237:
case 18238:
case 18239:
case 18240:
FourSepulchersManager.getInstance().spawnArchonOfHalisha(_activeChar.mysteriousBoxId);
break;
case 25339:
case 25342:
case 25346:
case 25349:
FourSepulchersManager.getInstance().spawnEmperorsGraveNpc(_activeChar.mysteriousBoxId);
break;
}
}
}
private static class ChangeImmortal implements Runnable
{
L2SepulcherMonsterInstance activeChar;
public ChangeImmortal(L2SepulcherMonsterInstance mob)
{
activeChar = mob;
}
@Override
public void run()
{
// Invulnerable by petrification
FAKE_PETRIFICATION.getSkill().applyEffects(activeChar, activeChar);
}
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return true;
}
}

View File

@ -0,0 +1,453 @@
/*
* Copyright (C) 2004-2014 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.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.DoorTable;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.FourSepulchersManager;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.EventType;
import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcFirstTalk;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.util.Util;
import com.l2jserver.util.Rnd;
/**
* @author sandman
*/
public class L2SepulcherNpcInstance extends L2Npc
{
protected Future<?> _closeTask = null;
protected Future<?> _spawnNextMysteriousBoxTask = null;
protected Future<?> _spawnMonsterTask = null;
private static final String HTML_FILE_PATH = "data/html/SepulcherNpc/";
private static final int HALLS_KEY = 7260;
public L2SepulcherNpcInstance(int objectID, L2NpcTemplate template)
{
super(objectID, template);
setInstanceType(InstanceType.L2SepulcherNpcInstance);
setShowSummonAnimation(true);
if (_closeTask != null)
{
_closeTask.cancel(true);
}
if (_spawnNextMysteriousBoxTask != null)
{
_spawnNextMysteriousBoxTask.cancel(true);
}
if (_spawnMonsterTask != null)
{
_spawnMonsterTask.cancel(true);
}
_closeTask = null;
_spawnNextMysteriousBoxTask = null;
_spawnMonsterTask = null;
}
@Override
public void onSpawn()
{
super.onSpawn();
setShowSummonAnimation(false);
}
@Override
public boolean deleteMe()
{
if (_closeTask != null)
{
_closeTask.cancel(true);
_closeTask = null;
}
if (_spawnNextMysteriousBoxTask != null)
{
_spawnNextMysteriousBoxTask.cancel(true);
_spawnNextMysteriousBoxTask = null;
}
if (_spawnMonsterTask != null)
{
_spawnMonsterTask.cancel(true);
_spawnMonsterTask = null;
}
return super.deleteMe();
}
@Override
public void onAction(L2PcInstance player, boolean interact)
{
if (!canTarget(player))
{
return;
}
// Check if the L2PcInstance already target the L2NpcInstance
if (this != player.getTarget())
{
if (Config.DEBUG)
{
_log.info("new target selected:" + getObjectId());
}
// Set the target of the L2PcInstance player
player.setTarget(this);
}
else if (interact)
{
// Check if the player is attackable (without a forced attack) and
// isn't dead
if (isAutoAttackable(player) && !isAlikeDead())
{
// Check the height difference
if (Math.abs(player.getZ() - getZ()) < 400) // this max heigth
// difference might
// need some tweaking
{
// Set the L2PcInstance Intention to AI_INTENTION_ATTACK
player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
}
else
{
// Send a Server->Client packet ActionFailed (target is out
// of attack range) to the L2PcInstance player
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
if (!isAutoAttackable(player))
{
// Calculate the distance between the L2PcInstance and the
// L2NpcInstance
if (!canInteract(player))
{
// Notify the L2PcInstance AI with AI_INTENTION_INTERACT
player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
}
else
{
// Send a Server->Client packet SocialAction to the all
// L2PcInstance on the _knownPlayer of the L2NpcInstance
// to display a social action of the L2NpcInstance on their
// client
SocialAction sa = new SocialAction(getObjectId(), Rnd.get(8));
broadcastPacket(sa);
doAction(player);
}
}
// Send a Server->Client ActionFailed to the L2PcInstance in order
// to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
private void doAction(L2PcInstance player)
{
if (isDead())
{
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
switch (getId())
{
case 31468:
case 31469:
case 31470:
case 31471:
case 31472:
case 31473:
case 31474:
case 31475:
case 31476:
case 31477:
case 31478:
case 31479:
case 31480:
case 31481:
case 31482:
case 31483:
case 31484:
case 31485:
case 31486:
case 31487:
setIsInvul(false);
reduceCurrentHp(getMaxHp() + 1, player, null);
if (_spawnMonsterTask != null)
{
_spawnMonsterTask.cancel(true);
}
_spawnMonsterTask = ThreadPoolManager.getInstance().scheduleEffect(new SpawnMonster(getId()), 3500);
break;
case 31455:
case 31456:
case 31457:
case 31458:
case 31459:
case 31460:
case 31461:
case 31462:
case 31463:
case 31464:
case 31465:
case 31466:
case 31467:
setIsInvul(false);
reduceCurrentHp(getMaxHp() + 1, player, null);
if ((player.getParty() != null) && !player.getParty().isLeader(player))
{
player = player.getParty().getLeader();
}
player.addItem("Quest", HALLS_KEY, 1, player, true);
break;
default:
{
if (hasListener(EventType.ON_NPC_QUEST_START))
{
player.setLastQuestNpcObject(getObjectId());
}
if (hasListener(EventType.ON_NPC_FIRST_TALK))
{
EventDispatcher.getInstance().notifyEventAsync(new OnNpcFirstTalk(this, player), this);
}
else
{
showChatWindow(player, 0);
}
}
}
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return HTML_FILE_PATH + pom + ".htm";
}
@Override
public void showChatWindow(L2PcInstance player, int val)
{
String filename = getHtmlPath(getId(), val);
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (isBusy())
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/npcbusy.htm");
html.replace("%busymessage%", getBusyMessage());
html.replace("%npcname%", getName());
html.replace("%playername%", player.getName());
player.sendPacket(html);
}
else if (command.startsWith("Chat"))
{
int val = 0;
try
{
val = Integer.parseInt(command.substring(5));
}
catch (IndexOutOfBoundsException ioobe)
{
}
catch (NumberFormatException nfe)
{
}
showChatWindow(player, val);
}
else if (command.startsWith("open_gate"))
{
L2ItemInstance hallsKey = player.getInventory().getItemByItemId(HALLS_KEY);
if (hallsKey == null)
{
showHtmlFile(player, "Gatekeeper-no.htm");
}
else if (FourSepulchersManager.getInstance().isAttackTime())
{
switch (getId())
{
case 31929:
case 31934:
case 31939:
case 31944:
FourSepulchersManager.getInstance().spawnShadow(getId());
default:
{
openNextDoor(getId());
if (player.getParty() != null)
{
for (L2PcInstance mem : player.getParty().getMembers())
{
if ((mem != null) && (mem.getInventory().getItemByItemId(HALLS_KEY) != null))
{
mem.destroyItemByItemId("Quest", HALLS_KEY, mem.getInventory().getItemByItemId(HALLS_KEY).getCount(), mem, true);
}
}
}
else
{
player.destroyItemByItemId("Quest", HALLS_KEY, hallsKey.getCount(), player, true);
}
}
}
}
}
else
{
super.onBypassFeedback(player, command);
}
}
public void openNextDoor(int npcId)
{
int doorId = FourSepulchersManager.getInstance().getHallGateKeepers().get(npcId);
DoorTable _doorTable = DoorTable.getInstance();
_doorTable.getDoor(doorId).openMe();
if (_closeTask != null)
{
_closeTask.cancel(true);
}
_closeTask = ThreadPoolManager.getInstance().scheduleEffect(new CloseNextDoor(doorId), 10000);
if (_spawnNextMysteriousBoxTask != null)
{
_spawnNextMysteriousBoxTask.cancel(true);
}
_spawnNextMysteriousBoxTask = ThreadPoolManager.getInstance().scheduleEffect(new SpawnNextMysteriousBox(npcId), 0);
}
private static class CloseNextDoor implements Runnable
{
final DoorTable _DoorTable = DoorTable.getInstance();
private final int _DoorId;
public CloseNextDoor(int doorId)
{
_DoorId = doorId;
}
@Override
public void run()
{
try
{
_DoorTable.getDoor(_DoorId).closeMe();
}
catch (Exception e)
{
_log.warning(e.getMessage());
}
}
}
private static class SpawnNextMysteriousBox implements Runnable
{
private final int _NpcId;
public SpawnNextMysteriousBox(int npcId)
{
_NpcId = npcId;
}
@Override
public void run()
{
FourSepulchersManager.getInstance().spawnMysteriousBox(_NpcId);
}
}
private static class SpawnMonster implements Runnable
{
private final int _NpcId;
public SpawnMonster(int npcId)
{
_NpcId = npcId;
}
@Override
public void run()
{
FourSepulchersManager.getInstance().spawnMonster(_NpcId);
}
}
public void sayInShout(NpcStringId msg)
{
if (msg == null)
{
return;// wrong usage
}
final CreatureSay creatureSay = new CreatureSay(0, Say2.NPC_SHOUT, getName(), msg);
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
if (Util.checkIfInRange(15000, player, this, true))
{
player.sendPacket(creatureSay);
}
}
}
public void showHtmlFile(L2PcInstance player, String file)
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/SepulcherNpc/" + file);
html.replace("%npcname%", getName());
player.sendPacket(html);
}
}

View File

@ -0,0 +1,570 @@
/*
* Copyright (C) 2004-2014 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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.CharSummonTable;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.datatables.SummonEffectsTable;
import com.l2jserver.gameserver.datatables.SummonEffectsTable.SummonEffect;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.holders.ItemHolder;
import com.l2jserver.gameserver.model.skills.AbnormalType;
import com.l2jserver.gameserver.model.skills.BuffInfo;
import com.l2jserver.gameserver.model.skills.EffectScope;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SetSummonRemainTime;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
/**
* @author UnAfraid
*/
public class L2ServitorInstance extends L2Summon implements Runnable
{
protected static final Logger log = Logger.getLogger(L2ServitorInstance.class.getName());
private static final String ADD_SKILL_SAVE = "INSERT INTO character_summon_skills_save (ownerId,ownerClassIndex,summonSkillId,skill_id,skill_level,remaining_time,buff_index) VALUES (?,?,?,?,?,?,?)";
private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,remaining_time,buff_index FROM character_summon_skills_save WHERE ownerId=? AND ownerClassIndex=? AND summonSkillId=? ORDER BY buff_index ASC";
private static final String DELETE_SKILL_SAVE = "DELETE FROM character_summon_skills_save WHERE ownerId=? AND ownerClassIndex=? AND summonSkillId=?";
private float _expMultiplier = 0;
private ItemHolder _itemConsume;
private int _lifeTime;
private int _lifeTimeRemaining;
private int _consumeItemInterval;
private int _consumeItemIntervalRemaining;
protected Future<?> _summonLifeTask;
private int _referenceSkill;
public L2ServitorInstance(int objectId, L2NpcTemplate template, L2PcInstance owner)
{
super(objectId, template, owner);
setInstanceType(InstanceType.L2ServitorInstance);
setShowSummonAnimation(true);
}
@Override
public void onSpawn()
{
super.onSpawn();
if (_summonLifeTask == null)
{
_summonLifeTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this, 0, 5000);
}
}
@Override
public final int getLevel()
{
return (getTemplate() != null ? getTemplate().getLevel() : 0);
}
@Override
public int getSummonType()
{
return 1;
}
// ************************************/
public void setExpMultiplier(float expMultiplier)
{
_expMultiplier = expMultiplier;
}
public float getExpMultiplier()
{
return _expMultiplier;
}
// ************************************/
public void setItemConsume(ItemHolder item)
{
_itemConsume = item;
}
public ItemHolder getItemConsume()
{
return _itemConsume;
}
// ************************************/
public void setItemConsumeInterval(int interval)
{
_consumeItemInterval = interval;
_consumeItemIntervalRemaining = interval;
}
public int getItemConsumeInterval()
{
return _consumeItemInterval;
}
// ************************************/
public void setLifeTime(int lifeTime)
{
_lifeTime = lifeTime;
_lifeTimeRemaining = lifeTime;
}
public int getLifeTime()
{
return _lifeTime;
}
// ************************************/
public void setLifeTimeRemaining(int time)
{
_lifeTimeRemaining = time;
}
public int getLifeTimeRemaining()
{
return _lifeTimeRemaining;
}
// ************************************/
public void setReferenceSkill(int skillId)
{
_referenceSkill = skillId;
}
public int getReferenceSkill()
{
return _referenceSkill;
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
if (_summonLifeTask != null)
{
_summonLifeTask.cancel(false);
}
CharSummonTable.getInstance().removeServitor(getOwner());
return true;
}
/**
* Servitors' skills automatically change their level based on the servitor's level.<br>
* Until level 70, the servitor gets 1 lv of skill per 10 levels.<br>
* After that, it is 1 skill level per 5 servitor levels.<br>
* If the resulting skill level doesn't exist use the max that does exist!
*/
@Override
public void doCast(Skill skill)
{
final int petLevel = getLevel();
int skillLevel = petLevel / 10;
if (petLevel >= 70)
{
skillLevel += (petLevel - 65) / 10;
}
// Adjust the level for servitors less than level 1.
if (skillLevel < 1)
{
skillLevel = 1;
}
final Skill skillToCast = SkillData.getInstance().getSkill(skill.getId(), skillLevel);
if (skillToCast != null)
{
super.doCast(skillToCast);
}
else
{
super.doCast(skill);
}
}
@Override
public void setRestoreSummon(boolean val)
{
_restoreSummon = val;
}
@Override
public final void stopSkillEffects(boolean removed, int skillId)
{
super.stopSkillEffects(removed, skillId);
final Map<Integer, List<SummonEffect>> servitorEffects = SummonEffectsTable.getInstance().getServitorEffects(getOwner());
if (servitorEffects != null)
{
final List<SummonEffect> effects = servitorEffects.get(getReferenceSkill());
if ((effects != null) && !effects.isEmpty())
{
for (SummonEffect effect : effects)
{
final Skill skill = effect.getSkill();
if ((skill != null) && (skill.getId() == skillId))
{
effects.remove(effect);
}
}
}
}
}
@Override
public void storeMe()
{
if ((_referenceSkill == 0) || isDead())
{
return;
}
if (Config.RESTORE_SERVITOR_ON_RECONNECT)
{
CharSummonTable.getInstance().saveSummon(this);
}
}
@Override
public void storeEffect(boolean storeEffects)
{
if (!Config.SUMMON_STORE_SKILL_COOLTIME)
{
return;
}
if ((getOwner() == null) || getOwner().isInOlympiadMode())
{
return;
}
// Clear list for overwrite
if (SummonEffectsTable.getInstance().getServitorEffectsOwner().containsKey(getOwner().getObjectId()) && SummonEffectsTable.getInstance().getServitorEffectsOwner().get(getOwner().getObjectId()).containsKey(getOwner().getClassIndex()) && SummonEffectsTable.getInstance().getServitorEffects(getOwner()).containsKey(getReferenceSkill()))
{
SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()).clear();
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_SKILL_SAVE))
{
// Delete all current stored effects for summon to avoid dupe
statement.setInt(1, getOwner().getObjectId());
statement.setInt(2, getOwner().getClassIndex());
statement.setInt(3, getReferenceSkill());
statement.execute();
int buff_index = 0;
final List<Integer> storedSkills = new FastList<>();
// Store all effect data along with calculated remaining
if (storeEffects)
{
try (PreparedStatement ps2 = con.prepareStatement(ADD_SKILL_SAVE))
{
for (BuffInfo info : getEffectList().getEffects())
{
if (info == null)
{
continue;
}
final Skill skill = info.getSkill();
// Do not save heals.
if (skill.getAbnormalType() == AbnormalType.LIFE_FORCE_OTHERS)
{
continue;
}
if (skill.isToggle())
{
continue;
}
// Dances and songs are not kept in retail.
if (skill.isDance() && !Config.ALT_STORE_DANCES)
{
continue;
}
if (storedSkills.contains(skill.getReuseHashCode()))
{
continue;
}
storedSkills.add(skill.getReuseHashCode());
ps2.setInt(1, getOwner().getObjectId());
ps2.setInt(2, getOwner().getClassIndex());
ps2.setInt(3, getReferenceSkill());
ps2.setInt(4, skill.getId());
ps2.setInt(5, skill.getLevel());
ps2.setInt(6, info.getTime());
ps2.setInt(7, ++buff_index);
ps2.execute();
// XXX: Rework me!
if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().containsKey(getOwner().getObjectId()))
{
SummonEffectsTable.getInstance().getServitorEffectsOwner().put(getOwner().getObjectId(), new HashMap<Integer, Map<Integer, List<SummonEffect>>>());
}
if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().get(getOwner().getObjectId()).containsKey(getOwner().getClassIndex()))
{
SummonEffectsTable.getInstance().getServitorEffectsOwner().get(getOwner().getObjectId()).put(getOwner().getClassIndex(), new HashMap<Integer, List<SummonEffect>>());
}
if (!SummonEffectsTable.getInstance().getServitorEffects(getOwner()).containsKey(getReferenceSkill()))
{
SummonEffectsTable.getInstance().getServitorEffects(getOwner()).put(getReferenceSkill(), new FastList<SummonEffect>());
}
SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, info.getTime()));
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not store summon effect data: ", e);
}
}
@Override
public void restoreEffects()
{
if (getOwner().isInOlympiadMode())
{
return;
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().containsKey(getOwner().getObjectId()) || !SummonEffectsTable.getInstance().getServitorEffectsOwner().get(getOwner().getObjectId()).containsKey(getOwner().getClassIndex()) || !SummonEffectsTable.getInstance().getServitorEffects(getOwner()).containsKey(getReferenceSkill()))
{
try (PreparedStatement statement = con.prepareStatement(RESTORE_SKILL_SAVE))
{
statement.setInt(1, getOwner().getObjectId());
statement.setInt(2, getOwner().getClassIndex());
statement.setInt(3, getReferenceSkill());
try (ResultSet rset = statement.executeQuery())
{
while (rset.next())
{
int effectCurTime = rset.getInt("remaining_time");
final Skill skill = SkillData.getInstance().getSkill(rset.getInt("skill_id"), rset.getInt("skill_level"));
if (skill == null)
{
continue;
}
// XXX: Rework me!
if (skill.hasEffects(EffectScope.GENERAL))
{
if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().containsKey(getOwner().getObjectId()))
{
SummonEffectsTable.getInstance().getServitorEffectsOwner().put(getOwner().getObjectId(), new HashMap<Integer, Map<Integer, List<SummonEffect>>>());
}
if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().get(getOwner().getObjectId()).containsKey(getOwner().getClassIndex()))
{
SummonEffectsTable.getInstance().getServitorEffectsOwner().get(getOwner().getObjectId()).put(getOwner().getClassIndex(), new HashMap<Integer, List<SummonEffect>>());
}
if (!SummonEffectsTable.getInstance().getServitorEffects(getOwner()).containsKey(getReferenceSkill()))
{
SummonEffectsTable.getInstance().getServitorEffects(getOwner()).put(getReferenceSkill(), new FastList<SummonEffect>());
}
SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, effectCurTime));
}
}
}
}
}
try (PreparedStatement statement = con.prepareStatement(DELETE_SKILL_SAVE))
{
statement.setInt(1, getOwner().getObjectId());
statement.setInt(2, getOwner().getClassIndex());
statement.setInt(3, getReferenceSkill());
statement.executeUpdate();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not restore " + this + " active effect data: " + e.getMessage(), e);
}
finally
{
if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().containsKey(getOwner().getObjectId()) || !SummonEffectsTable.getInstance().getServitorEffectsOwner().get(getOwner().getObjectId()).containsKey(getOwner().getClassIndex()) || !SummonEffectsTable.getInstance().getServitorEffects(getOwner()).containsKey(getReferenceSkill()))
{
return;
}
for (SummonEffect se : SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()))
{
if (se != null)
{
se.getSkill().applyEffects(this, this, false, se.getEffectCurTime());
}
}
}
}
@Override
public void unSummon(L2PcInstance owner)
{
if (_summonLifeTask != null)
{
_summonLifeTask.cancel(false);
}
super.unSummon(owner);
if (!_restoreSummon)
{
CharSummonTable.getInstance().removeServitor(owner);
}
}
@Override
public boolean destroyItem(String process, int objectId, long count, L2Object reference, boolean sendMessage)
{
return getOwner().destroyItem(process, objectId, count, reference, sendMessage);
}
@Override
public boolean destroyItemByItemId(String process, int itemId, long count, L2Object reference, boolean sendMessage)
{
return getOwner().destroyItemByItemId(process, itemId, count, reference, sendMessage);
}
@Override
public byte getAttackElement()
{
if (getOwner() != null)
{
return getOwner().getAttackElement();
}
return super.getAttackElement();
}
@Override
public int getAttackElementValue(byte attackAttribute)
{
if (getOwner() != null)
{
return (getOwner().getAttackElementValue(attackAttribute));
}
return super.getAttackElementValue(attackAttribute);
}
@Override
public int getDefenseElementValue(byte defenseAttribute)
{
if (getOwner() != null)
{
return (getOwner().getDefenseElementValue(defenseAttribute));
}
return super.getDefenseElementValue(defenseAttribute);
}
@Override
public boolean isServitor()
{
return true;
}
@Override
public void run()
{
int usedtime = 5000;
_lifeTimeRemaining -= usedtime;
if (isDead() || !isVisible())
{
if (_summonLifeTask != null)
{
_summonLifeTask.cancel(false);
}
return;
}
// check if the summon's lifetime has ran out
if (_lifeTimeRemaining < 0)
{
sendPacket(SystemMessageId.YOUR_SERVITOR_PASSED_AWAY);
unSummon(getOwner());
return;
}
if (_consumeItemInterval > 0)
{
_consumeItemIntervalRemaining -= usedtime;
// check if it is time to consume another item
if ((_consumeItemIntervalRemaining <= 0) && (getItemConsume().getCount() > 0) && (getItemConsume().getId() > 0) && !isDead())
{
if (destroyItemByItemId("Consume", getItemConsume().getId(), getItemConsume().getCount(), this, false))
{
final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.A_SUMMONED_MONSTER_USES_S1);
msg.addItemName(getItemConsume().getId());
sendPacket(msg);
// Reset
_consumeItemIntervalRemaining = _consumeItemInterval;
}
else
{
sendPacket(SystemMessageId.SINCE_YOU_DO_NOT_HAVE_ENOUGH_ITEMS_TO_MAINTAIN_THE_SERVITOR_S_STAY_THE_SERVITOR_HAS_DISAPPEARED);
unSummon(getOwner());
}
}
}
sendPacket(new SetSummonRemainTime(getLifeTime(), _lifeTimeRemaining));
updateEffectIcons();
}
}

View File

@ -0,0 +1,155 @@
/*
* Copyright (C) 2004-2014 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.Iterator;
import java.util.List;
import com.l2jserver.gameserver.ai.L2ShuttleAI;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Vehicle;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.model.shuttle.L2ShuttleData;
import com.l2jserver.gameserver.model.shuttle.L2ShuttleStop;
import com.l2jserver.gameserver.network.serverpackets.shuttle.ExShuttleGetOff;
import com.l2jserver.gameserver.network.serverpackets.shuttle.ExShuttleGetOn;
import com.l2jserver.gameserver.network.serverpackets.shuttle.ExShuttleInfo;
/**
* @author UnAfraid
*/
public class L2ShuttleInstance extends L2Vehicle
{
private L2ShuttleData _shuttleData;
public L2ShuttleInstance(int objectId, L2CharTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2ShuttleInstance);
setAI(new L2ShuttleAI(new AIAccessor()));
}
public List<L2ShuttleStop> getStops()
{
return _shuttleData.getStops();
}
public void closeDoor(int id)
{
for (L2ShuttleStop stop : getStops())
{
if (stop.getId() == id)
{
stop.closeDoor();
break;
}
}
}
public void openDoor(int id)
{
for (L2ShuttleStop stop : getStops())
{
if (stop.getId() == id)
{
stop.openDoor();
break;
}
}
}
@Override
public int getId()
{
return _shuttleData.getId();
}
@Override
public boolean addPassenger(L2PcInstance player)
{
if (!super.addPassenger(player))
{
return false;
}
player.setVehicle(this);
player.setInVehiclePosition(new Location(0, 0, 0));
player.broadcastPacket(new ExShuttleGetOn(player, this));
player.getKnownList().removeAllKnownObjects();
player.setXYZ(getX(), getY(), getZ());
player.revalidateZone(true);
return true;
}
public void removePassenger(L2PcInstance player, int x, int y, int z)
{
oustPlayer(player);
if (player.isOnline())
{
player.broadcastPacket(new ExShuttleGetOff(player, this, x, y, z));
player.getKnownList().removeAllKnownObjects();
player.setXYZ(x, y, z);
player.revalidateZone(true);
}
else
{
player.setXYZInvisible(x, y, z);
}
}
@Override
public void oustPlayers()
{
L2PcInstance player;
// Use iterator because oustPlayer will try to remove player from _passengers
final Iterator<L2PcInstance> iter = _passengers.iterator();
while (iter.hasNext())
{
player = iter.next();
iter.remove();
if (player != null)
{
oustPlayer(player);
}
}
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
activeChar.sendPacket(new ExShuttleInfo(this));
}
public void broadcastShuttleInfo()
{
broadcastPacket(new ExShuttleInfo(this));
}
public void setData(L2ShuttleData data)
{
_shuttleData = data;
}
public L2ShuttleData getShuttleData()
{
return _shuttleData;
}
}

View File

@ -0,0 +1,202 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.CHSiegeManager;
import com.l2jserver.gameserver.instancemanager.FortSiegeManager;
import com.l2jserver.gameserver.instancemanager.SiegeManager;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2SiegeClan;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.status.SiegeFlagStatus;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.Siegable;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
public class L2SiegeFlagInstance extends L2Npc
{
private final L2Clan _clan;
private Siegable _siege;
private final boolean _isAdvanced;
private boolean _canTalk;
public L2SiegeFlagInstance(L2PcInstance player, int objectId, L2NpcTemplate template, boolean advanced, boolean outPost)
{
super(objectId, template);
setInstanceType(InstanceType.L2SiegeFlagInstance);
_clan = player.getClan();
_canTalk = true;
_siege = SiegeManager.getInstance().getSiege(player.getX(), player.getY(), player.getZ());
if (_siege == null)
{
_siege = FortSiegeManager.getInstance().getSiege(player.getX(), player.getY(), player.getZ());
}
if (_siege == null)
{
_siege = CHSiegeManager.getInstance().getSiege(player);
}
if ((_clan == null) || (_siege == null))
{
throw new NullPointerException(getClass().getSimpleName() + ": Initialization failed.");
}
L2SiegeClan sc = _siege.getAttackerClan(_clan);
if (sc == null)
{
throw new NullPointerException(getClass().getSimpleName() + ": Cannot find siege clan.");
}
sc.addFlag(this);
_isAdvanced = advanced;
getStatus();
setIsInvul(false);
}
@Override
public boolean canBeAttacked()
{
return !isInvul();
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return !isInvul();
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
if ((_siege != null) && (_clan != null))
{
L2SiegeClan sc = _siege.getAttackerClan(_clan);
if (sc != null)
{
sc.removeFlag(this);
}
}
return true;
}
@Override
public void onForcedAttack(L2PcInstance player)
{
onAction(player);
}
@Override
public void onAction(L2PcInstance player, boolean interact)
{
if ((player == null) || !canTarget(player))
{
return;
}
// Check if the L2PcInstance already target the L2NpcInstance
if (this != player.getTarget())
{
// Set the target of the L2PcInstance player
player.setTarget(this);
}
else if (interact)
{
if (isAutoAttackable(player) && (Math.abs(player.getZ() - getZ()) < 100))
{
player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
}
else
{
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
}
public boolean isAdvancedHeadquarter()
{
return _isAdvanced;
}
@Override
public SiegeFlagStatus getStatus()
{
return (SiegeFlagStatus) super.getStatus();
}
@Override
public void initCharStatus()
{
setStatus(new SiegeFlagStatus(this));
}
@Override
public void reduceCurrentHp(double damage, L2Character attacker, Skill skill)
{
super.reduceCurrentHp(damage, attacker, skill);
if (canTalk())
{
if (((getCastle() != null) && getCastle().getSiege().isInProgress()) || ((getFort() != null) && getFort().getSiege().isInProgress()) || ((getConquerableHall() != null) && getConquerableHall().isInSiege()))
{
if (_clan != null)
{
// send warning to owners of headquarters that theirs base is under attack
_clan.broadcastToOnlineMembers(SystemMessage.getSystemMessage(SystemMessageId.YOUR_BASE_IS_BEING_ATTACKED));
setCanTalk(false);
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleTalkTask(), 20000);
}
}
}
}
private class ScheduleTalkTask implements Runnable
{
public ScheduleTalkTask()
{
}
@Override
public void run()
{
setCanTalk(true);
}
}
void setCanTalk(boolean val)
{
_canTalk = val;
}
private boolean canTalk()
{
return _canTalk;
}
}

View File

@ -0,0 +1,242 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.ai.L2CharacterAI;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.knownlist.StaticObjectKnownList;
import com.l2jserver.gameserver.model.actor.stat.StaticObjStat;
import com.l2jserver.gameserver.model.actor.status.StaticObjStatus;
import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.model.items.L2Weapon;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.serverpackets.ShowTownMap;
import com.l2jserver.gameserver.network.serverpackets.StaticObject;
/**
* Static Object instance.
* @author godson
*/
public final class L2StaticObjectInstance extends L2Character
{
/** The interaction distance of the L2StaticObjectInstance */
public static final int INTERACTION_DISTANCE = 150;
private final int _staticObjectId;
private int _meshIndex = 0; // 0 - static objects, alternate static objects
private int _type = -1; // 0 - map signs, 1 - throne , 2 - arena signs
private ShowTownMap _map;
/** This class may be created only by L2Character and only for AI */
public class AIAccessor extends L2Character.AIAccessor
{
@Override
public L2StaticObjectInstance getActor()
{
return L2StaticObjectInstance.this;
}
@Override
public void moveTo(int x, int y, int z, int offset)
{
}
@Override
public void moveTo(int x, int y, int z)
{
}
@Override
public void stopMove(Location loc)
{
}
@Override
public void doAttack(L2Character target)
{
}
@Override
public void doCast(Skill skill)
{
}
}
@Override
protected L2CharacterAI initAI()
{
return null;
}
/**
* Gets the static object ID.
* @return the static object ID
*/
@Override
public int getId()
{
return _staticObjectId;
}
/**
* @param objectId
* @param template
* @param staticId
*/
public L2StaticObjectInstance(int objectId, L2CharTemplate template, int staticId)
{
super(objectId, template);
setInstanceType(InstanceType.L2StaticObjectInstance);
_staticObjectId = staticId;
}
@Override
public final StaticObjectKnownList getKnownList()
{
return (StaticObjectKnownList) super.getKnownList();
}
@Override
public void initKnownList()
{
setKnownList(new StaticObjectKnownList(this));
}
@Override
public final StaticObjStat getStat()
{
return (StaticObjStat) super.getStat();
}
@Override
public void initCharStat()
{
setStat(new StaticObjStat(this));
}
@Override
public final StaticObjStatus getStatus()
{
return (StaticObjStatus) super.getStatus();
}
@Override
public void initCharStatus()
{
setStatus(new StaticObjStatus(this));
}
public int getType()
{
return _type;
}
public void setType(int type)
{
_type = type;
}
public void setMap(String texture, int x, int y)
{
_map = new ShowTownMap("town_map." + texture, x, y);
}
public ShowTownMap getMap()
{
return _map;
}
@Override
public final int getLevel()
{
return 1;
}
@Override
public L2ItemInstance getActiveWeaponInstance()
{
return null;
}
@Override
public L2Weapon getActiveWeaponItem()
{
return null;
}
@Override
public L2ItemInstance getSecondaryWeaponInstance()
{
return null;
}
@Override
public L2Weapon getSecondaryWeaponItem()
{
return null;
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return false;
}
/**
* Set the meshIndex of the object.<br>
* <B><U> Values </U> :</B>
* <ul>
* <li>default textures : 0</li>
* <li>alternate textures : 1</li>
* </ul>
* @param meshIndex
*/
public void setMeshIndex(int meshIndex)
{
_meshIndex = meshIndex;
this.broadcastPacket(new StaticObject(this));
}
/**
* <B><U> Values </U> :</B>
* <ul>
* <li>default textures : 0</li>
* <li>alternate textures : 1</li>
* </ul>
* @return the meshIndex of the object
*/
public int getMeshIndex()
{
return _meshIndex;
}
@Override
public void updateAbnormalEffect()
{
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
activeChar.sendPacket(new StaticObject(this));
}
}

View File

@ -0,0 +1,590 @@
/*
* Copyright (C) 2004-2014 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 static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
import java.util.List;
import java.util.concurrent.Future;
import javolution.util.FastList;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.effects.L2EffectType;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.NpcInfo;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.StopMove;
import com.l2jserver.util.Rnd;
// While a tamed beast behaves a lot like a pet (ingame) and does have
// an owner, in all other aspects, it acts like a mob.
// In addition, it can be fed in order to increase its duration.
// This class handles the running tasks, AI, and feed of the mob.
// The (mostly optional) AI on feeding the spawn is handled by the datapack ai script
public final class L2TamedBeastInstance extends L2FeedableBeastInstance
{
private int _foodSkillId;
private static final int MAX_DISTANCE_FROM_HOME = 30000;
private static final int MAX_DISTANCE_FROM_OWNER = 2000;
private static final int MAX_DURATION = 1200000; // 20 minutes
private static final int DURATION_CHECK_INTERVAL = 60000; // 1 minute
private static final int DURATION_INCREASE_INTERVAL = 20000; // 20 secs (gained upon feeding)
private static final int BUFF_INTERVAL = 5000; // 5 seconds
private int _remainingTime = MAX_DURATION;
private int _homeX, _homeY, _homeZ;
protected L2PcInstance _owner;
private Future<?> _buffTask = null;
private Future<?> _durationCheckTask = null;
protected boolean _isFreyaBeast;
private List<Skill> _beastSkills = null;
public L2TamedBeastInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2TamedBeastInstance);
setHome(this);
}
public L2TamedBeastInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, int foodSkillId, int x, int y, int z)
{
super(objectId, template);
_isFreyaBeast = false;
setInstanceType(InstanceType.L2TamedBeastInstance);
setCurrentHp(getMaxHp());
setCurrentMp(getMaxMp());
setOwner(owner);
setFoodType(foodSkillId);
setHome(x, y, z);
this.spawnMe(x, y, z);
}
public L2TamedBeastInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, int food, int x, int y, int z, boolean isFreyaBeast)
{
super(objectId, template);
_isFreyaBeast = isFreyaBeast;
setInstanceType(InstanceType.L2TamedBeastInstance);
setCurrentHp(getMaxHp());
setCurrentMp(getMaxMp());
setFoodType(food);
setHome(x, y, z);
spawnMe(x, y, z);
setOwner(owner);
if (isFreyaBeast)
{
getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _owner);
}
}
public void onReceiveFood()
{
// Eating food extends the duration by 20secs, to a max of 20minutes
_remainingTime = _remainingTime + DURATION_INCREASE_INTERVAL;
if (_remainingTime > MAX_DURATION)
{
_remainingTime = MAX_DURATION;
}
}
public Location getHome()
{
return new Location(_homeX, _homeY, _homeZ);
}
public void setHome(int x, int y, int z)
{
_homeX = x;
_homeY = y;
_homeZ = z;
}
public void setHome(L2Character c)
{
setHome(c.getX(), c.getY(), c.getZ());
}
public int getRemainingTime()
{
return _remainingTime;
}
public void setRemainingTime(int duration)
{
_remainingTime = duration;
}
public int getFoodType()
{
return _foodSkillId;
}
public void setFoodType(int foodItemId)
{
if (foodItemId > 0)
{
_foodSkillId = foodItemId;
// start the duration checks
// start the buff tasks
if (_durationCheckTask != null)
{
_durationCheckTask.cancel(true);
}
_durationCheckTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckDuration(this), DURATION_CHECK_INTERVAL, DURATION_CHECK_INTERVAL);
}
}
@Override
public boolean doDie(L2Character killer)
{
if (!super.doDie(killer))
{
return false;
}
getAI().stopFollow();
if (_buffTask != null)
{
_buffTask.cancel(true);
}
if (_durationCheckTask != null)
{
_durationCheckTask.cancel(true);
}
// clean up variables
if ((_owner != null) && (_owner.getTrainedBeasts() != null))
{
_owner.getTrainedBeasts().remove(this);
}
_buffTask = null;
_durationCheckTask = null;
_owner = null;
_foodSkillId = 0;
_remainingTime = 0;
return true;
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return !_isFreyaBeast;
}
public boolean isFreyaBeast()
{
return _isFreyaBeast;
}
public void addBeastSkill(Skill skill)
{
if (_beastSkills == null)
{
_beastSkills = new FastList<>();
}
_beastSkills.add(skill);
}
public void castBeastSkills()
{
if ((_owner == null) || (_beastSkills == null))
{
return;
}
int delay = 100;
for (Skill skill : _beastSkills)
{
ThreadPoolManager.getInstance().scheduleGeneral(new buffCast(skill), delay);
delay += (100 + skill.getHitTime());
}
ThreadPoolManager.getInstance().scheduleGeneral(new buffCast(null), delay);
}
private class buffCast implements Runnable
{
private final Skill _skill;
public buffCast(Skill skill)
{
_skill = skill;
}
@Override
public void run()
{
if (_skill == null)
{
getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _owner);
}
else
{
sitCastAndFollow(_skill, _owner);
}
}
}
public L2PcInstance getOwner()
{
return _owner;
}
public void setOwner(L2PcInstance owner)
{
if (owner != null)
{
_owner = owner;
setTitle(owner.getName());
// broadcast the new title
setShowSummonAnimation(true);
broadcastPacket(new NpcInfo(this));
owner.addTrainedBeast(this);
// always and automatically follow the owner.
getAI().startFollow(_owner, 100);
if (!_isFreyaBeast)
{
// instead of calculating this value each time, let's get this now and pass it on
int totalBuffsAvailable = 0;
for (Skill skill : getTemplate().getSkills().values())
{
// if the skill is a buff, check if the owner has it already [ owner.getEffect(L2Skill skill) ]
if (skill.isContinuous() && !skill.isDebuff())
{
totalBuffsAvailable++;
}
}
// start the buff tasks
if (_buffTask != null)
{
_buffTask.cancel(true);
}
_buffTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckOwnerBuffs(this, totalBuffsAvailable), BUFF_INTERVAL, BUFF_INTERVAL);
}
}
else
{
deleteMe(); // despawn if no owner
}
}
public boolean isTooFarFromHome()
{
return !isInsideRadius(_homeX, _homeY, _homeZ, MAX_DISTANCE_FROM_HOME, true, true);
}
@Override
public boolean deleteMe()
{
if (_buffTask != null)
{
_buffTask.cancel(true);
}
_durationCheckTask.cancel(true);
stopHpMpRegeneration();
// clean up variables
if ((_owner != null) && (_owner.getTrainedBeasts() != null))
{
_owner.getTrainedBeasts().remove(this);
}
setTarget(null);
_buffTask = null;
_durationCheckTask = null;
_owner = null;
_foodSkillId = 0;
_remainingTime = 0;
// remove the spawn
return super.deleteMe();
}
// notification triggered by the owner when the owner is attacked.
// tamed mobs will heal/recharge or debuff the enemy according to their skills
public void onOwnerGotAttacked(L2Character attacker)
{
// check if the owner is no longer around...if so, despawn
if ((_owner == null) || !_owner.isOnline())
{
deleteMe();
return;
}
// if the owner is too far away, stop anything else and immediately run towards the owner.
if (!_owner.isInsideRadius(this, MAX_DISTANCE_FROM_OWNER, true, true))
{
getAI().startFollow(_owner);
return;
}
// if the owner is dead, do nothing...
if (_owner.isDead() || _isFreyaBeast)
{
return;
}
// if the tamed beast is currently in the middle of casting, let it complete its skill...
if (isCastingNow())
{
return;
}
float HPRatio = ((float) _owner.getCurrentHp()) / _owner.getMaxHp();
// if the owner has a lot of HP, then debuff the enemy with a random debuff among the available skills
// use of more than one debuff at this moment is acceptable
if (HPRatio >= 0.8)
{
for (Skill skill : getTemplate().getSkills().values())
{
// if the skill is a debuff, check if the attacker has it already [ attacker.getEffect(L2Skill skill) ]
if (skill.isDebuff() && (Rnd.get(3) < 1) && ((attacker != null) && attacker.isAffectedBySkill(skill.getId())))
{
sitCastAndFollow(skill, attacker);
}
}
}
// for HP levels between 80% and 50%, do not react to attack events (so that MP can regenerate a bit)
// for lower HP ranges, heal or recharge the owner with 1 skill use per attack.
else if (HPRatio < 0.5)
{
int chance = 1;
if (HPRatio < 0.25)
{
chance = 2;
}
// if the owner has a lot of HP, then debuff the enemy with a random debuff among the available skills
for (Skill skill : getTemplate().getSkills().values())
{
// if the skill is a buff, check if the owner has it already [ owner.getEffect(L2Skill skill) ]
if ((Rnd.get(5) < chance) && skill.hasEffectType(L2EffectType.CPHEAL, L2EffectType.HEAL, L2EffectType.MANAHEAL_BY_LEVEL, L2EffectType.MANAHEAL_PERCENT))
{
sitCastAndFollow(skill, _owner);
}
}
}
}
/**
* Prepare and cast a skill:<br>
* First smoothly prepare the beast for casting, by abandoning other actions.<br>
* Next, call super.doCast(skill) in order to actually cast the spell.<br>
* Finally, return to auto-following the owner.
* @param skill
* @param target
*/
protected void sitCastAndFollow(Skill skill, L2Character target)
{
stopMove(null);
broadcastPacket(new StopMove(this));
getAI().setIntention(AI_INTENTION_IDLE);
setTarget(target);
doCast(skill);
getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _owner);
}
private static class CheckDuration implements Runnable
{
private final L2TamedBeastInstance _tamedBeast;
CheckDuration(L2TamedBeastInstance tamedBeast)
{
_tamedBeast = tamedBeast;
}
@Override
public void run()
{
int foodTypeSkillId = _tamedBeast.getFoodType();
L2PcInstance owner = _tamedBeast.getOwner();
L2ItemInstance item = null;
if (_tamedBeast._isFreyaBeast)
{
item = owner.getInventory().getItemByItemId(foodTypeSkillId);
if ((item != null) && (item.getCount() >= 1))
{
owner.destroyItem("BeastMob", item, 1, _tamedBeast, true);
_tamedBeast.broadcastPacket(new SocialAction(_tamedBeast.getObjectId(), 3));
}
else
{
_tamedBeast.deleteMe();
}
}
else
{
_tamedBeast.setRemainingTime(_tamedBeast.getRemainingTime() - DURATION_CHECK_INTERVAL);
// I tried to avoid this as much as possible...but it seems I can't avoid hardcoding
// ids further, except by carrying an additional variable just for these two lines...
// Find which food item needs to be consumed.
if (foodTypeSkillId == 2188)
{
item = owner.getInventory().getItemByItemId(6643);
}
else if (foodTypeSkillId == 2189)
{
item = owner.getInventory().getItemByItemId(6644);
}
// if the owner has enough food, call the item handler (use the food and triffer all necessary actions)
if ((item != null) && (item.getCount() >= 1))
{
L2Object oldTarget = owner.getTarget();
owner.setTarget(_tamedBeast);
L2Object[] targets =
{
_tamedBeast
};
// emulate a call to the owner using food, but bypass all checks for range, etc
// this also causes a call to the AI tasks handling feeding, which may call onReceiveFood as required.
owner.callSkill(SkillData.getInstance().getSkill(foodTypeSkillId, 1), targets);
owner.setTarget(oldTarget);
}
else
{
// if the owner has no food, the beast immediately despawns, except when it was only
// newly spawned. Newly spawned beasts can last up to 5 minutes
if (_tamedBeast.getRemainingTime() < (MAX_DURATION - 300000))
{
_tamedBeast.setRemainingTime(-1);
}
}
// There are too many conflicting reports about whether distance from home should be taken into consideration. Disabled for now.
// if (_tamedBeast.isTooFarFromHome())
// _tamedBeast.setRemainingTime(-1);
if (_tamedBeast.getRemainingTime() <= 0)
{
_tamedBeast.deleteMe();
}
}
}
}
private class CheckOwnerBuffs implements Runnable
{
private final L2TamedBeastInstance _tamedBeast;
private final int _numBuffs;
CheckOwnerBuffs(L2TamedBeastInstance tamedBeast, int numBuffs)
{
_tamedBeast = tamedBeast;
_numBuffs = numBuffs;
}
@Override
public void run()
{
L2PcInstance owner = _tamedBeast.getOwner();
// check if the owner is no longer around...if so, despawn
if ((owner == null) || !owner.isOnline())
{
deleteMe();
return;
}
// if the owner is too far away, stop anything else and immediately run towards the owner.
if (!isInsideRadius(owner, MAX_DISTANCE_FROM_OWNER, true, true))
{
getAI().startFollow(owner);
return;
}
// if the owner is dead, do nothing...
if (owner.isDead())
{
return;
}
// if the tamed beast is currently casting a spell, do not interfere (do not attempt to cast anything new yet).
if (isCastingNow())
{
return;
}
int totalBuffsOnOwner = 0;
int i = 0;
int rand = Rnd.get(_numBuffs);
Skill buffToGive = null;
// get this npc's skills: getSkills()
for (Skill skill : _tamedBeast.getTemplate().getSkills().values())
{
// if the skill is a buff, check if the owner has it already [ owner.getEffect(L2Skill skill) ]
if (skill.isContinuous() && !skill.isDebuff())
{
if (i++ == rand)
{
buffToGive = skill;
}
if (owner.isAffectedBySkill(skill.getId()))
{
totalBuffsOnOwner++;
}
}
}
// if the owner has less than 60% of this beast's available buff, cast a random buff
if (((_numBuffs * 2) / 3) > totalBuffsOnOwner)
{
_tamedBeast.sitCastAndFollow(buffToGive, owner);
}
getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _tamedBeast.getOwner());
}
}
@Override
public void onAction(L2PcInstance player, boolean interact)
{
if ((player == null) || !canTarget(player))
{
return;
}
// Check if the L2PcInstance already target the L2NpcInstance
if (this != player.getTarget())
{
// Set the target of the L2PcInstance player
player.setTarget(this);
}
else if (interact)
{
if (isAutoAttackable(player) && (Math.abs(player.getZ() - getZ()) < 100))
{
player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
}
else
{
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
}
}

View File

@ -0,0 +1,576 @@
/*
* Copyright (C) 2004-2014 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.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.stream.Stream;
import com.l2jserver.Config;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.ItemTable;
import com.l2jserver.gameserver.datatables.MultisellData;
import com.l2jserver.gameserver.datatables.TeleportLocationTable;
import com.l2jserver.gameserver.datatables.TeleportersData;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.CastleManager;
import com.l2jserver.gameserver.instancemanager.SiegeManager;
import com.l2jserver.gameserver.instancemanager.TownManager;
import com.l2jserver.gameserver.model.L2TeleportLocation;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
import com.l2jserver.gameserver.model.items.L2Item;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.teleporter.TeleportHolder;
import com.l2jserver.gameserver.model.teleporter.TeleportLocation;
import com.l2jserver.gameserver.model.teleporter.TeleportType;
import com.l2jserver.gameserver.model.zone.ZoneId;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.util.Util;
/**
* @author NightMarez
*/
public final class L2TeleporterInstance extends L2Npc
{
private static final int COND_ALL_FALSE = 0;
private static final int COND_BUSY_BECAUSE_OF_SIEGE = 1;
private static final int COND_OWNER = 2;
private static final int COND_REGULAR = 3;
/**
* @param objectId
* @param template
*/
public L2TeleporterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2TeleporterInstance);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
final StringTokenizer st = new StringTokenizer(command, " ");
final String cmd = st.nextToken();
switch (cmd)
{
case "showNoblesSelect":
{
final NpcHtmlMessage msg = new NpcHtmlMessage(getObjectId());
msg.setFile(player.getHtmlPrefix(), "data/html/teleporter/" + (player.isNoble() ? "nobles_select" : "not_nobles") + ".htm");
msg.replace("%objectId%", getObjectId());
player.sendPacket(msg);
break;
}
case "showTeleports":
{
final TeleportType type = parseTeleportType(st);
if (((type == TeleportType.NOBLES_TOKEN) || (type == TeleportType.NOBLES_ADENA)) && !player.isNoble())
{
_log.log(Level.WARNING, player + " attempted to use nobles teleport without being nobles!");
break;
}
final TeleportHolder holder = TeleportersData.getInstance().getHolder(getId());
if (holder == null)
{
_log.log(Level.WARNING, player + " requested show teleports for npc with no teleport data " + toString());
break;
}
final NpcHtmlMessage msg = new NpcHtmlMessage(getObjectId());
msg.setFile(player.getHtmlPrefix(), "data/html/teleporter/teleports.htm");
final StringBuilder sb = new StringBuilder();
final Collection<TeleportLocation> locs = holder.getLocations(type);
final List<NpcStringId> questLocations = new ArrayList<>();
for (QuestState qs : player.getAllQuestStates())
{
final NpcStringId npcString = qs.getQuestLocation();
if ((npcString != null) && !questLocations.contains(npcString))
{
questLocations.add(npcString);
}
}
final Stream<TeleportLocation> stream = !questLocations.isEmpty() ? locs.stream().sorted((o1, o2) -> questLocations.contains(o1.getNpcStringId()) ? 1 : questLocations.contains(o2.getNpcStringId()) ? -1 : 0) : locs.stream();
stream.forEach(loc ->
{
final int id = loc.getId();
String finalName = loc.getName();
String confirmDesc = loc.getName();
if (loc.getNpcStringId() != null)
{
finalName = "<fstring>" + loc.getNpcStringId().getId() + "</fstring>";
confirmDesc = "F;" + loc.getNpcStringId().getId();
}
if (shouldPayFee(player, loc))
{
finalName += " - " + loc.getFeeCount() + " " + getItemName(loc.getFeeId(), true);
}
sb.append("<button align=left icon=" + (!questLocations.contains(loc.getNpcStringId()) ? "teleport" : "quest") + " action=\"bypass -h npc_" + getObjectId() + "_teleport " + type.ordinal() + " " + id + "\" msg=\"811;" + confirmDesc + "\">" + finalName + "</button>");
});
msg.replace("%locations%", sb.toString());
player.sendPacket(msg);
break;
}
case "teleport":
{
final int typeId = parseNextInt(st, -1);
if ((typeId < 0) || (typeId > TeleportType.values().length))
{
_log.log(Level.WARNING, player + " attempted to use incorrect teleport type: " + typeId);
return;
}
final TeleportType type = TeleportType.values()[typeId];
if (((type == TeleportType.NOBLES_TOKEN) || (type == TeleportType.NOBLES_ADENA)) && !player.isNoble())
{
_log.log(Level.WARNING, player + " attempted to use nobles teleport without being nobles!");
break;
}
final int locId = parseNextInt(st, -1);
final TeleportHolder holder = TeleportersData.getInstance().getHolder(getId());
if (holder == null)
{
_log.log(Level.WARNING, player + " requested show teleports for npc with no teleport data " + toString());
break;
}
final TeleportLocation loc = holder.getLocation(type, locId);
if (loc == null)
{
_log.log(Level.WARNING, player + " attempted to use not existing teleport location id: " + locId);
return;
}
// you cannot teleport to village that is in siege
if (SiegeManager.getInstance().getSiege(loc.getX(), loc.getY(), loc.getZ()) != null)
{
player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_TO_A_VILLAGE_THAT_IS_IN_A_SIEGE);
}
else if (TownManager.townHasCastleInSiege(loc.getX(), loc.getY()) && isInsideZone(ZoneId.TOWN))
{
player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_TO_A_VILLAGE_THAT_IS_IN_A_SIEGE);
}
else if (getCastle().getSiege().isInProgress())
{
final NpcHtmlMessage msg = new NpcHtmlMessage(getObjectId());
msg.setFile(player.getHtmlPrefix(), "data/html/teleporter/castleteleporter-busy.htm");
player.sendPacket(msg);
}
else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_GK && (player.getKarma() != 0)) // TODO: Update me when Karma is replaced with Reputation system!
{
player.sendMessage("Go away, you're not welcome here.");
}
else if (player.isCombatFlagEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_WHILE_IN_POSSESSION_OF_A_WARD);
}
else if (shouldPayFee(player, loc) && !player.destroyItemByItemId("Teleport", loc.getFeeId(), loc.getFeeCount(), this, true))
{
if (loc.getFeeId() == Inventory.ADENA_ID)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
}
else
{
player.sendMessage("You do not have enough " + getItemName(loc.getFeeId(), false));
}
}
else if (!player.isAlikeDead())
{
player.teleToLocation(loc);
}
break;
}
default:
{
processLegacyBypass(player, command);
break;
}
}
}
protected boolean shouldPayFee(L2PcInstance player, TeleportLocation loc)
{
return Config.ALT_GAME_FREE_TELEPORT || ((player.getLevel() >= 76) && ((loc.getFeeId() != 0) && (loc.getFeeCount() > 0)));
}
protected int parseNextInt(StringTokenizer st, int defaultVal)
{
if (st.hasMoreTokens())
{
final String token = st.nextToken();
if (Util.isDigit(token))
{
return Integer.valueOf(token);
}
}
return defaultVal;
}
protected TeleportType parseTeleportType(StringTokenizer st)
{
TeleportType type = TeleportType.NORMAL;
if (st.hasMoreTokens())
{
final String typeToken = st.nextToken();
for (TeleportType teleportType : TeleportType.values())
{
if (teleportType.name().equalsIgnoreCase(typeToken))
{
type = teleportType;
break;
}
}
}
return type;
}
protected String getItemName(int itemId, boolean fstring)
{
if (fstring)
{
if (itemId == Inventory.ADENA_ID)
{
return "<fstring>1000308</fstring>";
}
else if (itemId == Inventory.ANCIENT_ADENA_ID)
{
return "<fstring>1000309</fstring>";
}
}
final L2Item item = ItemTable.getInstance().getTemplate(itemId);
if (item != null)
{
return item.getName();
}
switch (itemId)
{
case MultisellData.PC_BANG_POINTS:
{
return "Player Commendation Points";
}
case MultisellData.CLAN_REPUTATION:
{
return "Clan Reputation Points";
}
case MultisellData.FAME:
{
return "Fame";
}
}
return "Unknown item: " + itemId;
}
private void processLegacyBypass(L2PcInstance player, String command)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
int condition = validateCondition(player);
StringTokenizer st = new StringTokenizer(command, " ");
String actualCommand = st.nextToken(); // Get actual command
if (player.isAffectedBySkill(6201) || player.isAffectedBySkill(6202) || player.isAffectedBySkill(6203))
{
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
String filename = "data/html/teleporter/epictransformed.htm";
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcname%", getName());
player.sendPacket(html);
return;
}
else if (actualCommand.equalsIgnoreCase("goto"))
{
int npcId = getId();
switch (npcId)
{
case 32534: // Seed of Infinity
case 32539:
if (player.isFlyingMounted())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_ENTER_A_SEED_WHILE_IN_A_FLYING_TRANSFORMATION_STATE);
return;
}
break;
}
if (st.countTokens() <= 0)
{
return;
}
int whereTo = Integer.parseInt(st.nextToken());
if (condition == COND_REGULAR)
{
doTeleport(player, whereTo);
return;
}
else if (condition == COND_OWNER)
{
// TODO: Replace 0 with highest level when privilege level is implemented
int minPrivilegeLevel = 0;
if (st.countTokens() >= 1)
{
minPrivilegeLevel = Integer.parseInt(st.nextToken());
}
// TODO: Replace 10 with privilege level of player
if (10 >= minPrivilegeLevel)
{
doTeleport(player, whereTo);
}
else
{
player.sendMessage("You don't have the sufficient access level to teleport there.");
}
return;
}
}
else if (command.startsWith("Chat"))
{
Calendar cal = Calendar.getInstance();
int val = 0;
try
{
val = Integer.parseInt(command.substring(5));
}
catch (IndexOutOfBoundsException ioobe)
{
}
catch (NumberFormatException nfe)
{
}
if ((val == 1) && (player.getLevel() < 41))
{
showNewbieHtml(player);
return;
}
else if ((val == 1) && (cal.get(Calendar.HOUR_OF_DAY) >= 20) && (cal.get(Calendar.HOUR_OF_DAY) <= 23) && ((cal.get(Calendar.DAY_OF_WEEK) == 1) || (cal.get(Calendar.DAY_OF_WEEK) == 7)))
{
showHalfPriceHtml(player);
return;
}
showChatWindow(player, val);
}
super.onBypassFeedback(player, command);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/teleporter/" + pom + ".htm";
}
private void showNewbieHtml(L2PcInstance player)
{
if (player == null)
{
return;
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
String filename = "data/html/teleporter/free/" + getTemplate().getId() + ".htm";
if (!HtmCache.getInstance().isLoadable(filename))
{
filename = "data/html/teleporter/" + getTemplate().getId() + "-1.htm";
}
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcname%", getName());
player.sendPacket(html);
}
private void showHalfPriceHtml(L2PcInstance player)
{
if (player == null)
{
return;
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
String filename = "data/html/teleporter/half/" + getId() + ".htm";
if (!HtmCache.getInstance().isLoadable(filename))
{
filename = "data/html/teleporter/" + getId() + "-1.htm";
}
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcname%", getName());
player.sendPacket(html);
}
@Override
public void showChatWindow(L2PcInstance player)
{
String filename = "data/html/teleporter/castleteleporter-no.htm";
int condition = validateCondition(player);
if (condition == COND_REGULAR)
{
super.showChatWindow(player);
return;
}
else if (condition > COND_ALL_FALSE)
{
if (condition == COND_BUSY_BECAUSE_OF_SIEGE)
{
filename = "data/html/teleporter/castleteleporter-busy.htm"; // Busy because of siege
}
else if (condition == COND_OWNER) // Clan owns castle
{
filename = getHtmlPath(getId(), 0); // Owner message window
}
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcname%", getName());
player.sendPacket(html);
}
private void doTeleport(L2PcInstance player, int val)
{
L2TeleportLocation list = TeleportLocationTable.getInstance().getTemplate(val);
if (list != null)
{
// you cannot teleport to village that is in siege
if (SiegeManager.getInstance().getSiege(list.getLocX(), list.getLocY(), list.getLocZ()) != null)
{
player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_TO_A_VILLAGE_THAT_IS_IN_A_SIEGE);
return;
}
else if (TownManager.townHasCastleInSiege(list.getLocX(), list.getLocY()) && isInsideZone(ZoneId.TOWN))
{
player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_TO_A_VILLAGE_THAT_IS_IN_A_SIEGE);
return;
}
else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_GK && (player.getKarma() > 0)) // karma
{
player.sendMessage("Go away, you're not welcome here.");
return;
}
else if (player.isCombatFlagEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_WHILE_IN_POSSESSION_OF_A_WARD);
return;
}
else if (list.getIsForNoble() && !player.isNoble())
{
String filename = "data/html/teleporter/nobleteleporter-no.htm";
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(player.getHtmlPrefix(), filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
html.replace("%npcname%", getName());
player.sendPacket(html);
return;
}
else if (player.isAlikeDead())
{
return;
}
Calendar cal = Calendar.getInstance();
int price = list.getPrice();
if (player.getLevel() < 41)
{
price = 0;
}
else if (!list.getIsForNoble())
{
if ((cal.get(Calendar.HOUR_OF_DAY) >= 20) && (cal.get(Calendar.HOUR_OF_DAY) <= 23) && ((cal.get(Calendar.DAY_OF_WEEK) == 1) || (cal.get(Calendar.DAY_OF_WEEK) == 7)))
{
price /= 2;
}
}
if (Config.ALT_GAME_FREE_TELEPORT || player.destroyItemByItemId("Teleport " + (list.getIsForNoble() ? " nobless" : ""), list.getItemId(), price, this, true))
{
if (Config.DEBUG)
{
_log.info("Teleporting player " + player.getName() + " to new location: " + list.getLocX() + ":" + list.getLocY() + ":" + list.getLocZ());
}
player.teleToLocation(list.getLocX(), list.getLocY(), list.getLocZ(), false);
}
}
else
{
_log.warning("No teleport destination with id:" + val);
}
player.sendPacket(ActionFailed.STATIC_PACKET);
}
private int validateCondition(L2PcInstance player)
{
// Teleporter isn't on castle ground
if (CastleManager.getInstance().getCastleIndex(this) < 0)
{
return COND_REGULAR; // Regular access
}
// Teleporter is on castle ground and siege is in progress
else if (getCastle().getSiege().isInProgress())
{
return COND_BUSY_BECAUSE_OF_SIEGE; // Busy because of siege
}
// Teleporter is on castle ground and player is in a clan
else if (player.getClan() != null)
{
if (getCastle().getOwnerId() == player.getClanId())
{
return COND_OWNER; // Owner
}
}
return COND_ALL_FALSE;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
public final class L2TerrainObjectInstance extends L2Npc
{
public L2TerrainObjectInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2TerrainObjectInstance);
}
@Override
public void onAction(L2PcInstance player, boolean interact)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
}
@Override
public void onActionShift(L2PcInstance player)
{
if (player.isGM())
{
super.onActionShift(player);
}
else
{
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
public class L2TrainerInstance extends L2NpcInstance
{
public L2TrainerInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2TrainerInstance);
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/trainer/" + pom + ".htm";
}
}

View File

@ -0,0 +1,460 @@
/*
* Copyright (C) 2004-2014 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.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.enums.TrapAction;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.knownlist.TrapKnownList;
import com.l2jserver.gameserver.model.actor.tasks.npc.trap.TrapTask;
import com.l2jserver.gameserver.model.actor.tasks.npc.trap.TrapTriggerTask;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.impl.character.trap.OnTrapAction;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.items.L2Weapon;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.olympiad.OlympiadGameManager;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.ZoneId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.AbstractNpcInfo.TrapInfo;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.taskmanager.DecayTaskManager;
/**
* Trap instance.
* @author Zoey76
*/
public final class L2TrapInstance extends L2Npc
{
private static final int TICK = 1000; // 1s
private boolean _hasLifeTime;
private boolean _isInArena = false;
private boolean _isTriggered;
private final int _lifeTime;
private L2PcInstance _owner;
private final List<Integer> _playersWhoDetectedMe = new ArrayList<>();
private final SkillHolder _skill;
private int _remainingTime;
// Tasks
private ScheduledFuture<?> _trapTask = null;
public L2TrapInstance(int objectId, L2NpcTemplate template, int instanceId, int lifeTime)
{
super(objectId, template);
setInstanceType(InstanceType.L2TrapInstance);
setInstanceId(instanceId);
setName(template.getName());
setIsInvul(false);
_owner = null;
_isTriggered = false;
_skill = getTemplate().getParameters().getObject("trap_skill", SkillHolder.class);
_hasLifeTime = lifeTime >= 0;
_lifeTime = lifeTime != 0 ? lifeTime : 30000;
_remainingTime = _lifeTime;
if (_skill != null)
{
_trapTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new TrapTask(this), TICK, TICK);
}
}
public L2TrapInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, int lifeTime)
{
this(objectId, template, owner.getInstanceId(), lifeTime);
_owner = owner;
}
@Override
public void broadcastPacket(L2GameServerPacket mov)
{
for (L2PcInstance player : getKnownList().getKnownPlayers().values())
{
if ((player != null) && (_isTriggered || canBeSeen(player)))
{
player.sendPacket(mov);
}
}
}
@Override
public void broadcastPacket(L2GameServerPacket mov, int radiusInKnownlist)
{
for (L2PcInstance player : getKnownList().getKnownPlayers().values())
{
if ((player != null) && isInsideRadius(player, radiusInKnownlist, false, false) && (_isTriggered || canBeSeen(player)))
{
player.sendPacket(mov);
}
}
}
/**
* Verify if the character can see the trap.
* @param cha the character to verify
* @return {@code true} if the character can see the trap, {@code false} otherwise
*/
public boolean canBeSeen(L2Character cha)
{
if ((cha != null) && _playersWhoDetectedMe.contains(cha.getObjectId()))
{
return true;
}
if ((_owner == null) || (cha == null))
{
return false;
}
if (cha == _owner)
{
return true;
}
if (cha instanceof L2PcInstance)
{
// observers can't see trap
if (((L2PcInstance) cha).inObserverMode())
{
return false;
}
// olympiad competitors can't see trap
if (_owner.isInOlympiadMode() && ((L2PcInstance) cha).isInOlympiadMode() && (((L2PcInstance) cha).getOlympiadSide() != _owner.getOlympiadSide()))
{
return false;
}
}
if (_isInArena)
{
return true;
}
if (_owner.isInParty() && cha.isInParty() && (_owner.getParty().getLeaderObjectId() == cha.getParty().getLeaderObjectId()))
{
return true;
}
return false;
}
public boolean checkTarget(L2Character target)
{
if (!Skill.checkForAreaOffensiveSkills(this, target, _skill.getSkill(), _isInArena))
{
return false;
}
if (!target.isInsideRadius(this, _skill.getSkill().getEffectRange(), false, false))
{
return false;
}
// observers
if ((target instanceof L2PcInstance) && ((L2PcInstance) target).inObserverMode())
{
return false;
}
// olympiad own team and their summons not attacked
if ((_owner != null) && _owner.isInOlympiadMode())
{
final L2PcInstance player = target.getActingPlayer();
if ((player != null) && player.isInOlympiadMode() && (player.getOlympiadSide() == _owner.getOlympiadSide()))
{
return false;
}
}
if (_isInArena)
{
return true;
}
// trap owned by players not attack non-flagged players
if (_owner != null)
{
if (target instanceof L2Attackable)
{
return true;
}
final L2PcInstance player = target.getActingPlayer();
if ((player == null) || ((player.getPvpFlag() == 0) && (player.getKarma() == 0)))
{
return false;
}
}
return true;
}
@Override
public boolean deleteMe()
{
if (_owner != null)
{
_owner.setTrap(null);
_owner = null;
}
return super.deleteMe();
}
@Override
public L2PcInstance getActingPlayer()
{
return _owner;
}
@Override
public L2Weapon getActiveWeaponItem()
{
return null;
}
public int getKarma()
{
return _owner != null ? _owner.getKarma() : 0;
}
@Override
public TrapKnownList getKnownList()
{
return (TrapKnownList) super.getKnownList();
}
/**
* Get the owner of this trap.
* @return the owner
*/
public L2PcInstance getOwner()
{
return _owner;
}
public byte getPvpFlag()
{
return _owner != null ? _owner.getPvpFlag() : 0;
}
@Override
public L2ItemInstance getSecondaryWeaponInstance()
{
return null;
}
@Override
public L2Weapon getSecondaryWeaponItem()
{
return null;
}
public Skill getSkill()
{
return _skill.getSkill();
}
@Override
public void initKnownList()
{
setKnownList(new TrapKnownList(this));
}
@Override
public boolean isAutoAttackable(L2Character attacker)
{
return !canBeSeen(attacker);
}
@Override
public boolean isTrap()
{
return true;
}
/**
* Checks is triggered
* @return True if trap is triggered.
*/
public boolean isTriggered()
{
return _isTriggered;
}
@Override
public void onSpawn()
{
super.onSpawn();
_isInArena = isInsideZone(ZoneId.PVP) && !isInsideZone(ZoneId.SIEGE);
_playersWhoDetectedMe.clear();
}
@Override
public void sendDamageMessage(L2Character target, int damage, boolean mcrit, boolean pcrit, boolean miss)
{
if (miss || (_owner == null))
{
return;
}
if (_owner.isInOlympiadMode() && (target instanceof L2PcInstance) && ((L2PcInstance) target).isInOlympiadMode() && (((L2PcInstance) target).getOlympiadGameId() == _owner.getOlympiadGameId()))
{
OlympiadGameManager.getInstance().notifyCompetitorDamage(getOwner(), damage);
}
if (target.isInvul() && !(target instanceof L2NpcInstance))
{
_owner.sendPacket(SystemMessageId.THE_ATTACK_HAS_BEEN_BLOCKED);
}
else
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_INFLICTED_S3_DAMAGE_ON_C2_S4);
sm.addCharName(this);
sm.addCharName(target);
sm.addInt(damage);
sm.addPopup(target.getObjectId(), getObjectId(), (damage * -1));
_owner.sendPacket(sm);
}
}
@Override
public void sendInfo(L2PcInstance activeChar)
{
if (_isTriggered || canBeSeen(activeChar))
{
activeChar.sendPacket(new TrapInfo(this, activeChar));
}
}
public void setDetected(L2Character detector)
{
if (_isInArena)
{
if (detector.isPlayable())
{
sendInfo(detector.getActingPlayer());
}
return;
}
if ((_owner != null) && (_owner.getPvpFlag() == 0) && (_owner.getKarma() == 0))
{
return;
}
_playersWhoDetectedMe.add(detector.getObjectId());
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnTrapAction(this, detector, TrapAction.TRAP_DETECTED), this);
if (detector.isPlayable())
{
sendInfo(detector.getActingPlayer());
}
}
public void stopDecay()
{
DecayTaskManager.getInstance().cancel(this);
}
/**
* Trigger the trap.
* @param target the target
*/
public void triggerTrap(L2Character target)
{
if (_trapTask != null)
{
_trapTask.cancel(true);
_trapTask = null;
}
_isTriggered = true;
broadcastPacket(new TrapInfo(this, null));
setTarget(target);
EventDispatcher.getInstance().notifyEventAsync(new OnTrapAction(this, target, TrapAction.TRAP_TRIGGERED), this);
ThreadPoolManager.getInstance().scheduleGeneral(new TrapTriggerTask(this), 300);
}
public void unSummon()
{
if (_trapTask != null)
{
_trapTask.cancel(true);
_trapTask = null;
}
if (_owner != null)
{
_owner.setTrap(null);
_owner = null;
}
if (isVisible() && !isDead())
{
if (getWorldRegion() != null)
{
getWorldRegion().removeFromZones(this);
}
deleteMe();
}
}
@Override
public void updateAbnormalEffect()
{
}
public boolean hasLifeTime()
{
return _hasLifeTime;
}
public void setHasLifeTime(boolean val)
{
_hasLifeTime = val;
}
public int getRemainingTime()
{
return _remainingTime;
}
public void setRemainingTime(int time)
{
_remainingTime = time;
}
public int getLifeTime()
{
return _lifeTime;
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.PlayerClass;
public final class L2VillageMasterDElfInstance extends L2VillageMasterInstance
{
public L2VillageMasterDElfInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
protected final boolean checkVillageMasterRace(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfRace(Race.DARK_ELF);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.PlayerClass;
public final class L2VillageMasterDwarfInstance extends L2VillageMasterInstance
{
public L2VillageMasterDwarfInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
protected final boolean checkVillageMasterRace(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfRace(Race.DWARF);
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.ClassType;
import com.l2jserver.gameserver.model.base.PlayerClass;
public final class L2VillageMasterFighterInstance extends L2VillageMasterInstance
{
public L2VillageMasterFighterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
protected final boolean checkVillageMasterRace(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfRace(Race.HUMAN) || pclass.isOfRace(Race.ELF);
}
@Override
protected final boolean checkVillageMasterTeachType(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfType(ClassType.Fighter);
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.Config;
import com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.PlayerClass;
import com.l2jserver.gameserver.model.quest.QuestState;
public final class L2VillageMasterKamaelInstance extends L2VillageMasterInstance
{
public L2VillageMasterKamaelInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
protected final String getSubClassMenu(Race race)
{
if (Config.ALT_GAME_SUBCLASS_EVERYWHERE || (race == Race.KAMAEL))
{
return "data/html/villagemaster/SubClass.htm";
}
return "data/html/villagemaster/SubClass_NoKamael.htm";
}
@Override
protected final String getSubClassFail()
{
return "data/html/villagemaster/SubClass_Fail_Kamael.htm";
}
@Override
protected final boolean checkQuests(L2PcInstance player)
{
// Noble players can add subbclasses without quests
if (player.isNoble())
{
return true;
}
QuestState qs = player.getQuestState("234_FatesWhisper");
if ((qs == null) || !qs.isCompleted())
{
return false;
}
qs = player.getQuestState("236_SeedsOfChaos");
if ((qs == null) || !qs.isCompleted())
{
return false;
}
return true;
}
@Override
protected final boolean checkVillageMasterRace(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfRace(Race.KAMAEL);
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.ClassType;
import com.l2jserver.gameserver.model.base.PlayerClass;
public final class L2VillageMasterMysticInstance extends L2VillageMasterInstance
{
public L2VillageMasterMysticInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
protected final boolean checkVillageMasterRace(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfRace(Race.HUMAN) || pclass.isOfRace(Race.ELF);
}
@Override
protected final boolean checkVillageMasterTeachType(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfType(ClassType.Mystic);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.PlayerClass;
public final class L2VillageMasterOrcInstance extends L2VillageMasterInstance
{
public L2VillageMasterOrcInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
protected final boolean checkVillageMasterRace(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfRace(Race.ORC);
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.base.ClassType;
import com.l2jserver.gameserver.model.base.PlayerClass;
public final class L2VillageMasterPriestInstance extends L2VillageMasterInstance
{
public L2VillageMasterPriestInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
protected final boolean checkVillageMasterRace(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfRace(Race.HUMAN) || pclass.isOfRace(Race.ELF);
}
@Override
protected final boolean checkVillageMasterTeachType(PlayerClass pclass)
{
if (pclass == null)
{
return false;
}
return pclass.isOfType(ClassType.Priest);
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2004-2014 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 com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
public class L2WarehouseInstance extends L2NpcInstance
{
/**
* @param objectId
* @param template
*/
public L2WarehouseInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
setInstanceType(InstanceType.L2WarehouseInstance);
}
@Override
public boolean isWarehouse()
{
return true;
}
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
if (val == 0)
{
pom = "" + npcId;
}
else
{
pom = npcId + "-" + val;
}
return "data/html/warehouse/" + pom + ".htm";
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import java.util.Collection;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
public class AttackableKnownList extends NpcKnownList
{
public AttackableKnownList(L2Attackable activeChar)
{
super(activeChar);
}
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (!super.removeKnownObject(object, forget))
{
return false;
}
// Remove the L2Object from the _aggrolist of the L2Attackable
if (object instanceof L2Character)
{
getActiveChar().getAggroList().remove(object);
}
// Set the L2Attackable Intention to AI_INTENTION_IDLE
final Collection<L2PcInstance> known = getKnownPlayers().values();
// FIXME: This is a temporary solution && support for Walking Manager
if (getActiveChar().hasAI() && ((known == null) || known.isEmpty()) && !getActiveChar().isWalker())
{
getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null);
}
return true;
}
@Override
public L2Attackable getActiveChar()
{
return (L2Attackable) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
return (int) (getDistanceToWatchObject(object) * 1.5);
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
if (!(object instanceof L2Character))
{
return 0;
}
if (object.isPlayable())
{
return object.getKnownList().getDistanceToWatchObject(getActiveObject());
}
int max = Math.max(300, Math.max(getActiveChar().getAggroRange(), getActiveChar().getTemplate().getClanHelpRange()));
return max;
}
}

View File

@ -0,0 +1,284 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javolution.util.FastList;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.util.Util;
public class CharKnownList extends ObjectKnownList
{
private Map<Integer, L2PcInstance> _knownPlayers;
private Map<Integer, L2Summon> _knownSummons;
private Map<Integer, Integer> _knownRelations;
public CharKnownList(L2Character activeChar)
{
super(activeChar);
}
@Override
public boolean addKnownObject(L2Object object)
{
if (!super.addKnownObject(object))
{
return false;
}
else if (object.isPlayer())
{
getKnownPlayers().put(object.getObjectId(), object.getActingPlayer());
getKnownRelations().put(object.getObjectId(), -1);
}
else if (object.isSummon())
{
getKnownSummons().put(object.getObjectId(), (L2Summon) object);
}
return true;
}
/**
* @param player The L2PcInstance to search in _knownPlayer
* @return {@code true} if the player is in _knownPlayer of the character, {@code false} otherwise
*/
public final boolean knowsThePlayer(L2PcInstance player)
{
return (getActiveChar() == player) || getKnownPlayers().containsKey(player.getObjectId());
}
/** Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attack or Cast and notify AI. */
@Override
public final void removeAllKnownObjects()
{
super.removeAllKnownObjects();
getKnownPlayers().clear();
getKnownRelations().clear();
getKnownSummons().clear();
// Set _target of the L2Character to null
// Cancel Attack or Cast
getActiveChar().setTarget(null);
// Cancel AI Task
if (getActiveChar().hasAI())
{
getActiveChar().setAI(null);
}
}
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (!super.removeKnownObject(object, forget))
{
return false;
}
if (!forget) // on forget objects removed by iterator
{
if (object.isPlayer())
{
getKnownPlayers().remove(object.getObjectId());
getKnownRelations().remove(object.getObjectId());
}
else if (object.isSummon())
{
getKnownSummons().remove(object.getObjectId());
}
}
// If object is targeted by the L2Character, cancel Attack or Cast
if (object == getActiveChar().getTarget())
{
getActiveChar().setTarget(null);
}
return true;
}
@Override
public void forgetObjects(boolean fullCheck)
{
if (!fullCheck)
{
final Collection<L2PcInstance> plrs = getKnownPlayers().values();
final Iterator<L2PcInstance> pIter = plrs.iterator();
L2PcInstance player;
while (pIter.hasNext())
{
player = pIter.next();
if (player == null)
{
pIter.remove();
}
else if (!player.isVisible() || !Util.checkIfInShortRadius(getDistanceToForgetObject(player), getActiveObject(), player, true))
{
pIter.remove();
removeKnownObject(player, true);
getKnownRelations().remove(player.getObjectId());
getKnownObjects().remove(player.getObjectId());
}
}
final Collection<L2Summon> sums = getKnownSummons().values();
final Iterator<L2Summon> sIter = sums.iterator();
L2Summon summon;
while (sIter.hasNext())
{
summon = sIter.next();
if (summon == null)
{
sIter.remove();
}
else if (getActiveChar().isPlayer() && (summon.getOwner() == getActiveChar()))
{
continue;
}
else if (!summon.isVisible() || !Util.checkIfInShortRadius(getDistanceToForgetObject(summon), getActiveObject(), summon, true))
{
sIter.remove();
removeKnownObject(summon, true);
getKnownObjects().remove(summon.getObjectId());
}
}
return;
}
// Go through knownObjects
final Collection<L2Object> objs = getKnownObjects().values();
final Iterator<L2Object> oIter = objs.iterator();
L2Object object;
while (oIter.hasNext())
{
object = oIter.next();
if (object == null)
{
oIter.remove();
}
else if (!object.isVisible() || !Util.checkIfInShortRadius(getDistanceToForgetObject(object), getActiveObject(), object, true))
{
oIter.remove();
removeKnownObject(object, true);
if (object.isPlayer())
{
getKnownPlayers().remove(object.getObjectId());
getKnownRelations().remove(object.getObjectId());
}
else if (object.isSummon())
{
getKnownSummons().remove(object.getObjectId());
}
}
}
}
public L2Character getActiveChar()
{
return (L2Character) super.getActiveObject();
}
public Collection<L2Character> getKnownCharacters()
{
FastList<L2Character> result = new FastList<>();
final Collection<L2Object> objs = getKnownObjects().values();
for (L2Object obj : objs)
{
if (obj instanceof L2Character)
{
result.add((L2Character) obj);
}
}
return result;
}
public Collection<L2Character> getKnownCharactersInRadius(long radius)
{
List<L2Character> result = new ArrayList<>();
final Collection<L2Object> objs = getKnownObjects().values();
for (L2Object obj : objs)
{
if (obj instanceof L2Character)
{
if (Util.checkIfInRange((int) radius, getActiveChar(), obj, true))
{
result.add((L2Character) obj);
}
}
}
return result;
}
public final Map<Integer, L2PcInstance> getKnownPlayers()
{
if (_knownPlayers == null)
{
_knownPlayers = new ConcurrentHashMap<>();
}
return _knownPlayers;
}
public final Map<Integer, Integer> getKnownRelations()
{
if (_knownRelations == null)
{
_knownRelations = new ConcurrentHashMap<>();
}
return _knownRelations;
}
public final Map<Integer, L2Summon> getKnownSummons()
{
if (_knownSummons == null)
{
_knownSummons = new ConcurrentHashMap<>();
}
return _knownSummons;
}
public final Collection<L2PcInstance> getKnownPlayersInRadius(long radius)
{
List<L2PcInstance> result = new ArrayList<>();
final Collection<L2PcInstance> plrs = getKnownPlayers().values();
for (L2PcInstance player : plrs)
{
if (Util.checkIfInRange((int) radius, getActiveChar(), player, true))
{
result.add(player);
}
}
return result;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Decoy;
public class DecoyKnownList extends CharKnownList
{
public DecoyKnownList(L2Decoy activeChar)
{
super(activeChar);
}
@Override
public final L2Decoy getActiveChar()
{
return (L2Decoy) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
if ((object == getActiveChar().getOwner()) || (object == getActiveChar().getTarget()))
{
return 6000;
}
return 3000;
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
return 1500;
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.entity.Fort;
import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
public class DefenderKnownList extends AttackableKnownList
{
public DefenderKnownList(L2DefenderInstance activeChar)
{
super(activeChar);
}
@Override
public boolean addKnownObject(L2Object object)
{
if (!super.addKnownObject(object))
{
return false;
}
Castle castle = getActiveChar().getCastle();
Fort fortress = getActiveChar().getFort();
SiegableHall hall = getActiveChar().getConquerableHall();
// Check if siege is in progress
if (((fortress != null) && fortress.getZone().isActive()) || ((castle != null) && castle.getZone().isActive()) || ((hall != null) && hall.getSiegeZone().isActive()))
{
L2PcInstance player = null;
if (object.isPlayable())
{
player = object.getActingPlayer();
}
int activeSiegeId = (fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : hall != null ? hall.getId() : 0));
// Check if player is an enemy of this defender npc
if ((player != null) && (((player.getSiegeState() == 2) && !player.isRegisteredOnThisSiegeField(activeSiegeId)) || ((player.getSiegeState() == 1)) || (player.getSiegeState() == 0)))
{
if (getActiveChar().getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE)
{
getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null);
}
}
}
return true;
}
@Override
public final L2DefenderInstance getActiveChar()
{
return (L2DefenderInstance) super.getActiveChar();
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
public class DoorKnownList extends CharKnownList
{
public DoorKnownList(L2DoorInstance activeChar)
{
super(activeChar);
}
@Override
public final L2DoorInstance getActiveChar()
{
return (L2DoorInstance) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
if (object instanceof L2DefenderInstance)
{
return 800;
}
else if (!object.isPlayer())
{
return 0;
}
return 4000;
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
if (object instanceof L2DefenderInstance)
{
return 600;
}
else if (!object.isPlayer())
{
return 0;
}
return 3500;
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.ai.CtrlEvent;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2FriendlyMobInstance;
public class FriendlyMobKnownList extends AttackableKnownList
{
public FriendlyMobKnownList(L2FriendlyMobInstance activeChar)
{
super(activeChar);
}
@Override
public boolean addKnownObject(L2Object object)
{
if (!super.addKnownObject(object))
{
return false;
}
if (object.isPlayer() && (getActiveChar().getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE))
{
getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null);
}
return true;
}
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (!super.removeKnownObject(object, forget))
{
return false;
}
if (!(object instanceof L2Character))
{
return true;
}
if (getActiveChar().hasAI())
{
getActiveChar().getAI().notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
if (getActiveChar().getTarget() == object)
{
getActiveChar().setTarget(null);
}
}
if (getActiveChar().isVisible() && getKnownPlayers().isEmpty() && getKnownSummons().isEmpty())
{
getActiveChar().clearAggroList();
if (getActiveChar().hasAI())
{
getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null);
}
}
return true;
}
@Override
public final L2FriendlyMobInstance getActiveChar()
{
return (L2FriendlyMobInstance) super.getActiveChar();
}
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import java.util.logging.Logger;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2GuardInstance;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
public class GuardKnownList extends AttackableKnownList
{
private static final Logger _log = Logger.getLogger(GuardKnownList.class.getName());
public GuardKnownList(L2GuardInstance activeChar)
{
super(activeChar);
}
@Override
public boolean addKnownObject(L2Object object)
{
if (!super.addKnownObject(object))
{
return false;
}
if (object.isPlayer())
{
// Check if the object added is a L2PcInstance that owns Karma
if (object.getActingPlayer().getKarma() > 0)
{
if (Config.DEBUG)
{
_log.fine(getActiveChar().getObjectId() + ": PK " + object.getObjectId() + " entered scan range");
}
// Set the L2GuardInstance Intention to AI_INTENTION_ACTIVE
if (getActiveChar().getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE)
{
getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null);
}
}
}
else if ((Config.GUARD_ATTACK_AGGRO_MOB && getActiveChar().isInActiveRegion()) && object.isMonster())
{
// Check if the object added is an aggressive L2MonsterInstance
if (((L2MonsterInstance) object).isAggressive())
{
if (Config.DEBUG)
{
_log.fine(getActiveChar().getObjectId() + ": Aggressive mob " + object.getObjectId() + " entered scan range");
}
// Set the L2GuardInstance Intention to AI_INTENTION_ACTIVE
if (getActiveChar().getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE)
{
getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null);
}
}
}
return true;
}
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (!super.removeKnownObject(object, forget))
{
return false;
}
// Check if the aggression list of this guard is empty.
if (getActiveChar().getAggroList().isEmpty())
{
// Set the L2GuardInstance to AI_INTENTION_IDLE
if (getActiveChar().hasAI() && !getActiveChar().isWalker())
{
getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null);
}
}
return true;
}
@Override
public final L2GuardInstance getActiveChar()
{
return (L2GuardInstance) super.getActiveChar();
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.ai.CtrlEvent;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.ai.L2CharacterAI;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
public class MonsterKnownList extends AttackableKnownList
{
public MonsterKnownList(L2MonsterInstance activeChar)
{
super(activeChar);
}
@Override
public boolean addKnownObject(L2Object object)
{
if (!super.addKnownObject(object))
{
return false;
}
final L2CharacterAI ai = getActiveChar().getAI(); // force AI creation
// Set the L2MonsterInstance Intention to AI_INTENTION_ACTIVE if the state was AI_INTENTION_IDLE
if ((object instanceof L2PcInstance) && (ai != null) && (ai.getIntention() == CtrlIntention.AI_INTENTION_IDLE))
{
ai.setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null);
}
return true;
}
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (!super.removeKnownObject(object, forget))
{
return false;
}
if (!(object instanceof L2Character))
{
return true;
}
if (getActiveChar().hasAI())
{
// Notify the L2MonsterInstance AI with EVT_FORGET_OBJECT
getActiveChar().getAI().notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
}
if (getActiveChar().isVisible() && getKnownPlayers().isEmpty() && getKnownSummons().isEmpty())
{
// Clear the _aggroList of the L2MonsterInstance
getActiveChar().clearAggroList();
}
return true;
}
@Override
public final L2MonsterInstance getActiveChar()
{
return (L2MonsterInstance) super.getActiveChar();
}
}

View File

@ -0,0 +1,148 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import java.util.Collection;
import java.util.concurrent.ScheduledFuture;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.instancemanager.WalkingManager;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcCreatureSee;
public class NpcKnownList extends CharKnownList
{
private ScheduledFuture<?> _trackingTask = null;
public NpcKnownList(L2Npc activeChar)
{
super(activeChar);
}
@Override
public boolean addKnownObject(L2Object object)
{
if (!super.addKnownObject(object))
{
return false;
}
if (getActiveObject().isNpc() && (object instanceof L2Character))
{
final L2Npc npc = (L2Npc) getActiveObject();
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnNpcCreatureSee(npc, (L2Character) object, object.isSummon()), npc);
}
return true;
}
@Override
public L2Npc getActiveChar()
{
return (L2Npc) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
return 2 * getDistanceToWatchObject(object);
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
if (!(object instanceof L2Character))
{
return 0;
}
if (object.isPlayable())
{
return 1500;
}
return 500;
}
// Support for Walking monsters aggro
public void startTrackingTask()
{
if ((_trackingTask == null) && (getActiveChar().getAggroRange() > 0))
{
_trackingTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new TrackingTask(), 2000, 2000);
}
}
// Support for Walking monsters aggro
public void stopTrackingTask()
{
if (_trackingTask != null)
{
_trackingTask.cancel(true);
_trackingTask = null;
}
}
// Support for Walking monsters aggro
protected class TrackingTask implements Runnable
{
@Override
public void run()
{
if (getActiveChar() instanceof L2Attackable)
{
final L2Attackable monster = (L2Attackable) getActiveChar();
if (monster.getAI().getIntention() == CtrlIntention.AI_INTENTION_MOVE_TO)
{
final Collection<L2PcInstance> players = getKnownPlayers().values();
if (players != null)
{
for (L2PcInstance pl : players)
{
if (!pl.isDead() && !pl.isInvul() && pl.isInsideRadius(monster, monster.getAggroRange(), true, false) && (monster.isMonster() || (monster.isInstanceTypes(InstanceType.L2GuardInstance) && (pl.getKarma() > 0))))
{
// Send aggroRangeEnter
if (monster.getHating(pl) == 0)
{
monster.addDamageHate(pl, 0, 0);
}
// Skip attack for other targets, if one is already chosen for attack
if ((monster.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK) && !monster.isCoreAIDisabled())
{
WalkingManager.getInstance().stopMoving(getActiveChar(), false, true);
monster.addDamageHate(pl, 0, 100);
monster.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, pl, null);
}
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.L2Object;
public class NullKnownList extends ObjectKnownList
{
public NullKnownList(L2Object activeObject)
{
super(activeObject);
}
@Override
public boolean addKnownObject(L2Object object)
{
return false;
}
@Override
public L2Object getActiveObject()
{
return super.getActiveObject();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
return 0;
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
return 0;
}
@Override
public void removeAllKnownObjects()
{
}
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
return false;
}
}

View File

@ -0,0 +1,221 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2WorldRegion;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.util.Util;
public class ObjectKnownList
{
private final L2Object _activeObject;
private Map<Integer, L2Object> _knownObjects;
public ObjectKnownList(L2Object activeObject)
{
_activeObject = activeObject;
}
public boolean addKnownObject(L2Object object)
{
if (object == null)
{
return false;
}
// Instance -1 is for GMs that can see everything on all instances
if ((getActiveObject().getInstanceId() != -1) && (object.getInstanceId() != getActiveObject().getInstanceId()))
{
return false;
}
// Check if the object is an L2PcInstance in ghost mode
if (object.isPlayer() && object.getActingPlayer().getAppearance().isGhost())
{
return false;
}
// Check if already know object
if (knowsObject(object))
{
return false;
}
// Check if object is not inside distance to watch object
if (!Util.checkIfInShortRadius(getDistanceToWatchObject(object), getActiveObject(), object, true))
{
return false;
}
return (getKnownObjects().put(object.getObjectId(), object) == null);
}
public final boolean knowsObject(L2Object object)
{
if (object == null)
{
return false;
}
return (getActiveObject() == object) || getKnownObjects().containsKey(object.getObjectId());
}
/**
* Remove all L2Object from _knownObjects
*/
public void removeAllKnownObjects()
{
getKnownObjects().clear();
}
public final boolean removeKnownObject(L2Object object)
{
return removeKnownObject(object, false);
}
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (object == null)
{
return false;
}
if (forget)
{
return true;
}
return getKnownObjects().remove(object.getObjectId()) != null;
}
/**
* Used only in Config.MOVE_BASED_KNOWNLIST and does not support guards seeing moving monsters
*/
public final void findObjects()
{
final L2WorldRegion region = getActiveObject().getWorldRegion();
if (region == null)
{
return;
}
if (getActiveObject().isPlayable())
{
for (L2WorldRegion regi : region.getSurroundingRegions()) // offer members of this and surrounding regions
{
Collection<L2Object> vObj = regi.getVisibleObjects().values();
for (L2Object object : vObj)
{
if (object != getActiveObject())
{
addKnownObject(object);
if (object instanceof L2Character)
{
object.getKnownList().addKnownObject(getActiveObject());
}
}
}
}
}
else if (getActiveObject() instanceof L2Character)
{
for (L2WorldRegion regi : region.getSurroundingRegions()) // offer members of this and surrounding regions
{
if (regi.isActive())
{
Collection<L2Playable> vPls = regi.getVisiblePlayable().values();
for (L2Object object : vPls)
{
if (object != getActiveObject())
{
addKnownObject(object);
}
}
}
}
}
}
/**
* Remove invisible and too far L2Object from _knowObject and if necessary from _knownPlayers of the L2Character
* @param fullCheck
*/
public void forgetObjects(boolean fullCheck)
{
// Go through knownObjects
final Collection<L2Object> objs = getKnownObjects().values();
final Iterator<L2Object> oIter = objs.iterator();
L2Object object;
while (oIter.hasNext())
{
object = oIter.next();
if (object == null)
{
oIter.remove();
continue;
}
if (!fullCheck && !object.isPlayable())
{
continue;
}
// Remove all objects invisible or too far
if (!object.isVisible() || !Util.checkIfInShortRadius(getDistanceToForgetObject(object), getActiveObject(), object, true))
{
oIter.remove();
removeKnownObject(object, true);
}
}
}
public L2Object getActiveObject()
{
return _activeObject;
}
public int getDistanceToForgetObject(L2Object object)
{
return 0;
}
public int getDistanceToWatchObject(L2Object object)
{
return 0;
}
/**
* @return the _knownObjects containing all L2Object known by the L2Character.
*/
public final Map<Integer, L2Object> getKnownObjects()
{
if (_knownObjects == null)
{
_knownObjects = new ConcurrentHashMap<>();
}
return _knownObjects;
}
}

View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2AirShipInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.DeleteObject;
import com.l2jserver.gameserver.network.serverpackets.SpawnItem;
public class PcKnownList extends PlayableKnownList
{
public PcKnownList(L2PcInstance activeChar)
{
super(activeChar);
}
/**
* Add a visible L2Object to L2PcInstance _knownObjects and _knownPlayer (if necessary) and send Server-Client Packets needed to inform the L2PcInstance of its state and actions in progress.<BR>
* <BR>
* <B><U> object is a L2ItemInstance </U> :</B><BR>
* <BR>
* <li>Send Server-Client Packet DropItem/SpawnItem to the L2PcInstance</li><BR>
* <BR>
* <B><U> object is a L2DoorInstance </U> :</B><BR>
* <BR>
* <li>Send Server-Client Packets DoorInfo and DoorStatusUpdate to the L2PcInstance</li> <li>Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance</li><BR>
* <BR>
* <B><U> object is a L2NpcInstance </U> :</B><BR>
* <BR>
* <li>Send Server-Client Packet NpcInfo to the L2PcInstance</li> <li>Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance</li><BR>
* <BR>
* <B><U> object is a L2Summon </U> :</B><BR>
* <BR>
* <li>Send Server-Client Packet NpcInfo/PetItemList (if the L2PcInstance is the owner) to the L2PcInstance</li> <li>Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance</li><BR>
* <BR>
* <B><U> object is a L2PcInstance </U> :</B><BR>
* <BR>
* <li>Send Server-Client Packet CharInfo to the L2PcInstance</li> <li>If the object has a private store, Send Server-Client Packet PrivateStoreMsgSell to the L2PcInstance</li> <li>Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance</li><BR>
* <BR>
* @param object The L2Object to add to _knownObjects and _knownPlayer
*/
@Override
public boolean addKnownObject(L2Object object)
{
if (!super.addKnownObject(object))
{
return false;
}
if (object.getPoly().isMorphed() && object.getPoly().getPolyType().equals("item"))
{
// if (object.getPolytype().equals("item"))
getActiveChar().sendPacket(new SpawnItem(object));
// else if (object.getPolytype().equals("npc"))
// sendPacket(new NpcInfoPoly(object, this));
}
else
{
if (object.isVisibleFor(getActiveChar()))
{
object.sendInfo(getActiveChar());
if (object instanceof L2Character)
{
// Update the state of the L2Character object client side by sending Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance
final L2Character obj = (L2Character) object;
if (obj.hasAI())
{
obj.getAI().describeStateToPlayer(getActiveChar());
}
}
}
}
return true;
}
/**
* Remove a L2Object from L2PcInstance _knownObjects and _knownPlayer (if necessary) and send Server-Client Packet DeleteObject to the L2PcInstance.<BR>
* <BR>
* @param object The L2Object to remove from _knownObjects and _knownPlayer
*/
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (!super.removeKnownObject(object, forget))
{
return false;
}
if (object instanceof L2AirShipInstance)
{
if ((((L2AirShipInstance) object).getCaptainId() != 0) && (((L2AirShipInstance) object).getCaptainId() != getActiveChar().getObjectId()))
{
getActiveChar().sendPacket(new DeleteObject(((L2AirShipInstance) object).getCaptainId()));
}
if (((L2AirShipInstance) object).getHelmObjectId() != 0)
{
getActiveChar().sendPacket(new DeleteObject(((L2AirShipInstance) object).getHelmObjectId()));
}
}
// Send Server-Client Packet DeleteObject to the L2PcInstance
getActiveChar().sendPacket(new DeleteObject(object));
if (Config.CHECK_KNOWN && (object instanceof L2Npc) && getActiveChar().isGM())
{
getActiveChar().sendMessage("Removed NPC: " + object.getName());
}
return true;
}
@Override
public final L2PcInstance getActiveChar()
{
return (L2PcInstance) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
if (object.isVehicle())
{
return 10000;
}
// when knownlist grows, the distance to forget should be at least
// the same as the previous watch range, or it becomes possible that
// extra charinfo packets are being sent (watch-forget-watch-forget)
final int knownlistSize = getKnownObjects().size();
if (knownlistSize <= 25)
{
return 4000;
}
if (knownlistSize <= 35)
{
return 3500;
}
if (knownlistSize <= 70)
{
return 2910;
}
return 2310;
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
if (object.isVehicle())
{
return 9000;
}
final int knownlistSize = getKnownObjects().size();
if (knownlistSize <= 25)
{
return 3400; // empty field
}
if (knownlistSize <= 35)
{
return 2900;
}
if (knownlistSize <= 70)
{
return 2300;
}
return 1700; // Siege, TOI, city
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.actor.L2Playable;
public class PlayableKnownList extends CharKnownList
{
public PlayableKnownList(L2Playable activeChar)
{
super(activeChar);
}
@Override
public L2Playable getActiveChar()
{
return (L2Playable) super.getActiveChar();
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.MonsterRace;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2RaceManagerInstance;
import com.l2jserver.gameserver.network.serverpackets.DeleteObject;
public class RaceManagerKnownList extends NpcKnownList
{
public RaceManagerKnownList(L2RaceManagerInstance activeChar)
{
super(activeChar);
}
@Override
protected boolean removeKnownObject(L2Object object, boolean forget)
{
if (!super.removeKnownObject(object, forget))
{
return false;
}
if (object.isPlayer())
{
for (int i = 0; i < 8; i++)
{
object.sendPacket(new DeleteObject(MonsterRace.getInstance().getMonsters()[i]));
}
}
return true;
}
@Override
public L2RaceManagerInstance getActiveChar()
{
return (L2RaceManagerInstance) super.getActiveChar();
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jserver.gameserver.model.actor.instance.L2StaticObjectInstance;
public class StaticObjectKnownList extends CharKnownList
{
public StaticObjectKnownList(L2StaticObjectInstance activeChar)
{
super(activeChar);
}
@Override
public final L2StaticObjectInstance getActiveChar()
{
return (L2StaticObjectInstance) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
if (object instanceof L2DefenderInstance)
{
return 800;
}
if (!object.isPlayer())
{
return 0;
}
return 4000;
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
if (object instanceof L2DefenderInstance)
{
return 600;
}
if (!object.isPlayer())
{
return 0;
}
return 2000;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Summon;
public class SummonKnownList extends PlayableKnownList
{
public SummonKnownList(L2Summon activeChar)
{
super(activeChar);
}
@Override
public final L2Summon getActiveChar()
{
return (L2Summon) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
if ((object == getActiveChar().getOwner()) || (object == getActiveChar().getTarget()))
{
return 6000;
}
return 3000;
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
return 1500;
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2TrapInstance;
public class TrapKnownList extends NpcKnownList
{
public TrapKnownList(L2TrapInstance activeChar)
{
super(activeChar);
}
@Override
public final L2TrapInstance getActiveChar()
{
return (L2TrapInstance) super.getActiveChar();
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
if ((object == getActiveChar().getActingPlayer()) || (object == getActiveChar().getTarget()))
{
return 6000;
}
return 3000;
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
return 1500;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2004-2014 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.knownlist;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
public class VehicleKnownList extends CharKnownList
{
public VehicleKnownList(L2Character activeChar)
{
super(activeChar);
}
@Override
public int getDistanceToForgetObject(L2Object object)
{
if (!object.isPlayer())
{
return 0;
}
return object.getKnownList().getDistanceToForgetObject(getActiveObject());
}
@Override
public int getDistanceToWatchObject(L2Object object)
{
if (!object.isPlayer())
{
return 0;
}
return object.getKnownList().getDistanceToWatchObject(getActiveObject());
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2004-2014 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.poly;
import com.l2jserver.gameserver.model.L2Object;
public class ObjectPoly
{
private final L2Object _activeObject;
private int _polyId;
private String _polyType;
public ObjectPoly(L2Object activeObject)
{
_activeObject = activeObject;
}
public void setPolyInfo(String polyType, String polyId)
{
setPolyId(Integer.parseInt(polyId));
setPolyType(polyType);
}
public final L2Object getActiveObject()
{
return _activeObject;
}
public final boolean isMorphed()
{
return getPolyType() != null;
}
public final int getPolyId()
{
return _polyId;
}
public final void setPolyId(int value)
{
_polyId = value;
}
public final String getPolyType()
{
return _polyType;
}
public final void setPolyType(String value)
{
_polyType = value;
}
}

View File

@ -0,0 +1,853 @@
/*
* Copyright (C) 2004-2014 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.stat;
import java.util.Arrays;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.Elementals;
import com.l2jserver.gameserver.model.PcCondOverride;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.items.L2Weapon;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.stats.Calculator;
import com.l2jserver.gameserver.model.stats.MoveType;
import com.l2jserver.gameserver.model.stats.Stats;
import com.l2jserver.gameserver.model.stats.TraitType;
import com.l2jserver.gameserver.model.zone.ZoneId;
public class CharStat
{
private final L2Character _activeChar;
private long _exp = 0;
private long _sp = 0;
private byte _level = 1;
private final float[] _attackTraits = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length];
private final float[] _defenceTraits = new float[TraitType.values().length];
private final int[] _defenceTraitsCount = new int[TraitType.values().length];
private final int[] _traitsInvul = new int[TraitType.values().length];
/** Creature's maximum buff count. */
private int _maxBuffCount = Config.BUFFS_MAX_AMOUNT;
public CharStat(L2Character activeChar)
{
_activeChar = activeChar;
Arrays.fill(_attackTraits, 1.0f);
Arrays.fill(_defenceTraits, 1.0f);
}
public final double calcStat(Stats stat, double init)
{
return calcStat(stat, init, null, null);
}
/**
* Calculate the new value of the state with modifiers that will be applied on the targeted L2Character.<BR>
* <B><U> Concept</U> :</B><BR
* A L2Character owns a table of Calculators called <B>_calculators</B>. Each Calculator (a calculator per state) own a table of Func object. A Func object is a mathematic function that permit to calculate the modifier of a state (ex : REGENERATE_HP_RATE...) : <BR>
* FuncAtkAccuracy -> Math.sqrt(_player.getDEX())*6+_player.getLevel()<BR>
* When the calc method of a calculator is launched, each mathematical function is called according to its priority <B>_order</B>.<br>
* Indeed, Func with lowest priority order is executed firsta and Funcs with the same order are executed in unspecified order.<br>
* The result of the calculation is stored in the value property of an Env class instance.<br>
* @param stat The stat to calculate the new value with modifiers
* @param initVal The initial value of the stat before applying modifiers
* @param target The L2Charcater whose properties will be used in the calculation (ex : CON, INT...)
* @param skill The L2Skill whose properties will be used in the calculation (ex : Level...)
* @return
*/
public final double calcStat(Stats stat, double initVal, L2Character target, Skill skill)
{
double value = initVal;
if (stat == null)
{
return value;
}
final int id = stat.ordinal();
final Calculator c = _activeChar.getCalculators()[id];
// If no Func object found, no modifier is applied
if ((c == null) || (c.size() == 0))
{
return value;
}
// Apply transformation stats.
if (getActiveChar().isPlayer() && getActiveChar().isTransformed())
{
double val = getActiveChar().getTransformation().getStat(getActiveChar().getActingPlayer(), stat);
if (val > 0)
{
value = val;
}
}
// Launch the calculation
value = c.calc(_activeChar, target, skill, value);
// avoid some troubles with negative stats (some stats should never be negative)
if (value <= 0)
{
switch (stat)
{
case MAX_HP:
case MAX_MP:
case MAX_CP:
case MAGIC_DEFENCE:
case POWER_DEFENCE:
case POWER_ATTACK:
case MAGIC_ATTACK:
case POWER_ATTACK_SPEED:
case MAGIC_ATTACK_SPEED:
case SHIELD_DEFENCE:
case STAT_CON:
case STAT_DEX:
case STAT_INT:
case STAT_MEN:
case STAT_STR:
case STAT_WIT:
case STAT_LUC:
case STAT_CHA:
{
value = 1.0;
break;
}
}
}
return value;
}
/**
* @return the Accuracy (base+modifier) of the L2Character in function of the Weapon Expertise Penalty.
*/
public int getAccuracy()
{
return (int) Math.round(calcStat(Stats.ACCURACY_COMBAT, 0, null, null));
}
/**
* @return the Magic Accuracy (base+modifier) of the L2Character
*/
public int getMagicAccuracy()
{
return (int) Math.round(calcStat(Stats.ACCURACY_MAGIC, 0, null, null));
}
public L2Character getActiveChar()
{
return _activeChar;
}
/**
* @return the Attack Speed multiplier (base+modifier) of the L2Character to get proper animations.
*/
public final float getAttackSpeedMultiplier()
{
return (float) (((1.1) * getPAtkSpd()) / _activeChar.getTemplate().getBasePAtkSpd());
}
/**
* @return the CON of the L2Character (base+modifier).
*/
public final int getCON()
{
return (int) calcStat(Stats.STAT_CON, _activeChar.getTemplate().getBaseCON());
}
/**
* @param target
* @param init
* @return the Critical Damage rate (base+modifier) of the L2Character.
*/
public final double getCriticalDmg(L2Character target, double init)
{
return calcStat(Stats.CRITICAL_DAMAGE, init, target, null);
}
/**
* @param target
* @param skill
* @return the Critical Hit rate (base+modifier) of the L2Character.
*/
public int getCriticalHit(L2Character target, Skill skill)
{
int val = (int) calcStat(Stats.CRITICAL_RATE, _activeChar.getTemplate().getBaseCritRate(), target, skill);
if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
val = Math.min(val, Config.MAX_PCRIT_RATE);
}
return val;
}
/**
* @return the DEX of the L2Character (base+modifier).
*/
public final int getDEX()
{
return (int) calcStat(Stats.STAT_DEX, _activeChar.getTemplate().getBaseDEX());
}
/**
* @param target
* @return the Attack Evasion rate (base+modifier) of the L2Character.
*/
public int getEvasionRate(L2Character target)
{
int val = (int) Math.round(calcStat(Stats.EVASION_RATE, 0, target, null));
if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
val = Math.min(val, Config.MAX_EVASION);
}
return val;
}
/**
* @param target
* @return the Attack Evasion rate (base+modifier) of the L2Character.
*/
public int getMagicEvasionRate(L2Character target)
{
int val = (int) Math.round(calcStat(Stats.MAGIC_EVASION_RATE, 0, target, null));
if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
val = Math.min(val, Config.MAX_EVASION);
}
return val;
}
public long getExp()
{
return _exp;
}
public void setExp(long value)
{
_exp = value;
}
/**
* @return the INT of the L2Character (base+modifier).
*/
public int getINT()
{
return (int) calcStat(Stats.STAT_INT, _activeChar.getTemplate().getBaseINT());
}
public byte getLevel()
{
return _level;
}
public void setLevel(byte value)
{
_level = value;
}
/**
* @param skill
* @return the Magical Attack range (base+modifier) of the L2Character.
*/
public final int getMagicalAttackRange(Skill skill)
{
if (skill != null)
{
return (int) calcStat(Stats.MAGIC_ATTACK_RANGE, skill.getCastRange(), null, skill);
}
return _activeChar.getTemplate().getBaseAttackRange();
}
public int getMaxCp()
{
return (int) calcStat(Stats.MAX_CP, _activeChar.getTemplate().getBaseCpMax());
}
public int getMaxRecoverableCp()
{
return (int) calcStat(Stats.MAX_RECOVERABLE_CP, getMaxCp());
}
public int getMaxHp()
{
return (int) calcStat(Stats.MAX_HP, _activeChar.getTemplate().getBaseHpMax());
}
public int getMaxRecoverableHp()
{
return (int) calcStat(Stats.MAX_RECOVERABLE_HP, getMaxHp());
}
public int getMaxMp()
{
return (int) calcStat(Stats.MAX_MP, _activeChar.getTemplate().getBaseMpMax());
}
public int getMaxRecoverableMp()
{
return (int) calcStat(Stats.MAX_RECOVERABLE_MP, getMaxMp());
}
/**
* Return the MAtk (base+modifier) of the L2Character.<br>
* <B><U>Example of use</U>: Calculate Magic damage
* @param target The L2Character targeted by the skill
* @param skill The L2Skill used against the target
* @return
*/
public int getMAtk(L2Character target, Skill skill)
{
float bonusAtk = 1;
if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
{
bonusAtk = Config.L2JMOD_CHAMPION_ATK;
}
if (_activeChar.isRaid())
{
bonusAtk *= Config.RAID_MATTACK_MULTIPLIER;
}
// Calculate modifiers Magic Attack
return (int) calcStat(Stats.MAGIC_ATTACK, _activeChar.getTemplate().getBaseMAtk() * bonusAtk, target, skill);
}
/**
* @return the MAtk Speed (base+modifier) of the L2Character in function of the Armour Expertise Penalty.
*/
public int getMAtkSpd()
{
float bonusSpdAtk = 1;
if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
{
bonusSpdAtk = Config.L2JMOD_CHAMPION_SPD_ATK;
}
double val = calcStat(Stats.MAGIC_ATTACK_SPEED, _activeChar.getTemplate().getBaseMAtkSpd() * bonusSpdAtk);
if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
val = Math.min(val, Config.MAX_MATK_SPEED);
}
return (int) val;
}
/**
* @param target
* @param skill
* @return the Magic Critical Hit rate (base+modifier) of the L2Character.
*/
public final int getMCriticalHit(L2Character target, Skill skill)
{
int val = (int) calcStat(Stats.MCRITICAL_RATE, getActiveChar().getTemplate().getBaseMCritRate(), target, skill);
if (!_activeChar.canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
val = Math.min(val, Config.MAX_MCRIT_RATE);
}
return val;
}
/**
* <B><U>Example of use </U>: Calculate Magic damage.
* @param target The L2Character targeted by the skill
* @param skill The L2Skill used against the target
* @return the MDef (base+modifier) of the L2Character against a skill in function of abnormal effects in progress.
*/
public int getMDef(L2Character target, Skill skill)
{
// Get the base MDef of the L2Character
double defence = _activeChar.getTemplate().getBaseMDef();
// Calculate modifier for Raid Bosses
if (_activeChar.isRaid())
{
defence *= Config.RAID_MDEFENCE_MULTIPLIER;
}
// Calculate modifiers Magic Attack
return (int) calcStat(Stats.MAGIC_DEFENCE, defence, target, skill);
}
/**
* @return the MEN of the L2Character (base+modifier).
*/
public final int getMEN()
{
return (int) calcStat(Stats.STAT_MEN, _activeChar.getTemplate().getBaseMEN());
}
public final int getLUC()
{
return (int) calcStat(Stats.STAT_LUC, _activeChar.getTemplate().getBaseLUC());
}
public final int getCHA()
{
return (int) calcStat(Stats.STAT_CHA, _activeChar.getTemplate().getBaseCHA());
}
public double getMovementSpeedMultiplier()
{
double baseSpeed;
if (_activeChar.isInsideZone(ZoneId.WATER))
{
baseSpeed = getBaseMoveSpeed(_activeChar.isRunning() ? MoveType.FAST_SWIM : MoveType.SLOW_SWIM);
}
else
{
baseSpeed = getBaseMoveSpeed(_activeChar.isRunning() ? MoveType.RUN : MoveType.WALK);
}
return getMoveSpeed() * (1. / baseSpeed);
}
/**
* @return the RunSpeed (base+modifier) of the L2Character in function of the Armour Expertise Penalty.
*/
public double getRunSpeed()
{
final double baseRunSpd = _activeChar.isInsideZone(ZoneId.WATER) ? getSwimRunSpeed() : getBaseMoveSpeed(MoveType.RUN);
if (baseRunSpd <= 0)
{
return 0;
}
return calcStat(Stats.MOVE_SPEED, baseRunSpd, null, null);
}
/**
* @return the WalkSpeed (base+modifier) of the L2Character.
*/
public double getWalkSpeed()
{
final double baseWalkSpd = _activeChar.isInsideZone(ZoneId.WATER) ? getSwimWalkSpeed() : getBaseMoveSpeed(MoveType.WALK);
if (baseWalkSpd <= 0)
{
return 0;
}
return calcStat(Stats.MOVE_SPEED, baseWalkSpd);
}
/**
* @return the SwimRunSpeed (base+modifier) of the L2Character.
*/
public double getSwimRunSpeed()
{
final double baseRunSpd = getBaseMoveSpeed(MoveType.FAST_SWIM);
if (baseRunSpd <= 0)
{
return 0;
}
return calcStat(Stats.MOVE_SPEED, baseRunSpd, null, null);
}
/**
* @return the SwimWalkSpeed (base+modifier) of the L2Character.
*/
public double getSwimWalkSpeed()
{
final double baseWalkSpd = getBaseMoveSpeed(MoveType.SLOW_SWIM);
if (baseWalkSpd <= 0)
{
return 0;
}
return calcStat(Stats.MOVE_SPEED, baseWalkSpd);
}
/**
* @param type movement type
* @return the base move speed of given movement type.
*/
public double getBaseMoveSpeed(MoveType type)
{
return _activeChar.getTemplate().getBaseMoveSpeed(type);
}
/**
* @return the RunSpeed (base+modifier) or WalkSpeed (base+modifier) of the L2Character in function of the movement type.
*/
public double getMoveSpeed()
{
if (_activeChar.isInsideZone(ZoneId.WATER))
{
return _activeChar.isRunning() ? getSwimRunSpeed() : getSwimWalkSpeed();
}
return _activeChar.isRunning() ? getRunSpeed() : getWalkSpeed();
}
/**
* @param skill
* @return the MReuse rate (base+modifier) of the L2Character.
*/
public final double getMReuseRate(Skill skill)
{
return calcStat(Stats.MAGIC_REUSE_RATE, 1, null, skill);
}
/**
* @param target
* @return the PAtk (base+modifier) of the L2Character.
*/
public int getPAtk(L2Character target)
{
float bonusAtk = 1;
if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
{
bonusAtk = Config.L2JMOD_CHAMPION_ATK;
}
if (_activeChar.isRaid())
{
bonusAtk *= Config.RAID_PATTACK_MULTIPLIER;
}
return (int) calcStat(Stats.POWER_ATTACK, _activeChar.getTemplate().getBasePAtk() * bonusAtk, target, null);
}
/**
* @return the PAtk Speed (base+modifier) of the L2Character in function of the Armour Expertise Penalty.
*/
public int getPAtkSpd()
{
float bonusAtk = 1;
if (Config.L2JMOD_CHAMPION_ENABLE && _activeChar.isChampion())
{
bonusAtk = Config.L2JMOD_CHAMPION_SPD_ATK;
}
int val = (int) Math.round(calcStat(Stats.POWER_ATTACK_SPEED, _activeChar.getTemplate().getBasePAtkSpd() * bonusAtk, null, null));
return val;
}
/**
* @param target
* @return the PDef (base+modifier) of the L2Character.
*/
public int getPDef(L2Character target)
{
return (int) calcStat(Stats.POWER_DEFENCE, (_activeChar.isRaid()) ? _activeChar.getTemplate().getBasePDef() * Config.RAID_PDEFENCE_MULTIPLIER : _activeChar.getTemplate().getBasePDef(), target, null);
}
/**
* @return the Physical Attack range (base+modifier) of the L2Character.
*/
public final int getPhysicalAttackRange()
{
final L2Weapon weapon = _activeChar.getActiveWeaponItem();
int baseAttackRange;
if (_activeChar.isTransformed() && _activeChar.isPlayer())
{
baseAttackRange = _activeChar.getTransformation().getBaseAttackRange(_activeChar.getActingPlayer());
}
else if (weapon != null)
{
baseAttackRange = weapon.getBaseAttackRange();
}
else
{
baseAttackRange = _activeChar.getTemplate().getBaseAttackRange();
}
return (int) calcStat(Stats.POWER_ATTACK_RANGE, baseAttackRange, null, null);
}
public int getPhysicalAttackAngle()
{
final L2Weapon weapon = _activeChar.getActiveWeaponItem();
final int baseAttackAngle;
if (weapon != null)
{
baseAttackAngle = weapon.getBaseAttackAngle();
}
else
{
baseAttackAngle = 120;
}
return baseAttackAngle;
}
/**
* @param target
* @return the weapon reuse modifier.
*/
public final double getWeaponReuseModifier(L2Character target)
{
return calcStat(Stats.ATK_REUSE, 1, target, null);
}
/**
* @return the ShieldDef rate (base+modifier) of the L2Character.
*/
public final int getShldDef()
{
return (int) calcStat(Stats.SHIELD_DEFENCE, 0);
}
public long getSp()
{
return _sp;
}
public void setSp(long value)
{
_sp = value;
}
/**
* @return the STR of the L2Character (base+modifier).
*/
public final int getSTR()
{
return (int) calcStat(Stats.STAT_STR, _activeChar.getTemplate().getBaseSTR());
}
/**
* @return the WIT of the L2Character (base+modifier).
*/
public final int getWIT()
{
return (int) calcStat(Stats.STAT_WIT, _activeChar.getTemplate().getBaseWIT());
}
/**
* @param skill
* @return the mpConsume.
*/
public final int getMpConsume(Skill skill)
{
if (skill == null)
{
return 1;
}
double mpConsume = skill.getMpConsume();
double nextDanceMpCost = Math.ceil(skill.getMpConsume() / 2.);
if (skill.isDance())
{
if (Config.DANCE_CONSUME_ADDITIONAL_MP && (_activeChar != null) && (_activeChar.getDanceCount() > 0))
{
mpConsume += _activeChar.getDanceCount() * nextDanceMpCost;
}
}
mpConsume = calcStat(Stats.MP_CONSUME, mpConsume, null, skill);
if (skill.isDance())
{
return (int) calcStat(Stats.DANCE_MP_CONSUME_RATE, mpConsume);
}
else if (skill.isMagic())
{
return (int) calcStat(Stats.MAGICAL_MP_CONSUME_RATE, mpConsume);
}
else
{
return (int) calcStat(Stats.PHYSICAL_MP_CONSUME_RATE, mpConsume);
}
}
/**
* @param skill
* @return the mpInitialConsume.
*/
public final int getMpInitialConsume(Skill skill)
{
if (skill == null)
{
return 1;
}
double mpConsume = calcStat(Stats.MP_CONSUME, skill.getMpInitialConsume(), null, skill);
if (skill.isDance())
{
return (int) calcStat(Stats.DANCE_MP_CONSUME_RATE, mpConsume);
}
else if (skill.isMagic())
{
return (int) calcStat(Stats.MAGICAL_MP_CONSUME_RATE, mpConsume);
}
else
{
return (int) calcStat(Stats.PHYSICAL_MP_CONSUME_RATE, mpConsume);
}
}
public byte getAttackElement()
{
L2ItemInstance weaponInstance = _activeChar.getActiveWeaponInstance();
// 1st order - weapon element
if ((weaponInstance != null) && (weaponInstance.getAttackElementType() >= 0))
{
return weaponInstance.getAttackElementType();
}
// temp fix starts
int tempVal = 0, stats[] =
{
0,
0,
0,
0,
0,
0
};
byte returnVal = -2;
stats[0] = (int) calcStat(Stats.FIRE_POWER, _activeChar.getTemplate().getBaseFire());
stats[1] = (int) calcStat(Stats.WATER_POWER, _activeChar.getTemplate().getBaseWater());
stats[2] = (int) calcStat(Stats.WIND_POWER, _activeChar.getTemplate().getBaseWind());
stats[3] = (int) calcStat(Stats.EARTH_POWER, _activeChar.getTemplate().getBaseEarth());
stats[4] = (int) calcStat(Stats.HOLY_POWER, _activeChar.getTemplate().getBaseHoly());
stats[5] = (int) calcStat(Stats.DARK_POWER, _activeChar.getTemplate().getBaseDark());
for (byte x = 0; x < 6; x++)
{
if (stats[x] > tempVal)
{
returnVal = x;
tempVal = stats[x];
}
}
return returnVal;
// temp fix ends
/*
* uncomment me once deadlocks in getAllEffects() fixed return _activeChar.getElementIdFromEffects();
*/
}
public int getAttackElementValue(byte attackAttribute)
{
switch (attackAttribute)
{
case Elementals.FIRE:
return (int) calcStat(Stats.FIRE_POWER, _activeChar.getTemplate().getBaseFire());
case Elementals.WATER:
return (int) calcStat(Stats.WATER_POWER, _activeChar.getTemplate().getBaseWater());
case Elementals.WIND:
return (int) calcStat(Stats.WIND_POWER, _activeChar.getTemplate().getBaseWind());
case Elementals.EARTH:
return (int) calcStat(Stats.EARTH_POWER, _activeChar.getTemplate().getBaseEarth());
case Elementals.HOLY:
return (int) calcStat(Stats.HOLY_POWER, _activeChar.getTemplate().getBaseHoly());
case Elementals.DARK:
return (int) calcStat(Stats.DARK_POWER, _activeChar.getTemplate().getBaseDark());
default:
return 0;
}
}
public int getDefenseElementValue(byte defenseAttribute)
{
switch (defenseAttribute)
{
case Elementals.FIRE:
return (int) calcStat(Stats.FIRE_RES, _activeChar.getTemplate().getBaseFireRes());
case Elementals.WATER:
return (int) calcStat(Stats.WATER_RES, _activeChar.getTemplate().getBaseWaterRes());
case Elementals.WIND:
return (int) calcStat(Stats.WIND_RES, _activeChar.getTemplate().getBaseWindRes());
case Elementals.EARTH:
return (int) calcStat(Stats.EARTH_RES, _activeChar.getTemplate().getBaseEarthRes());
case Elementals.HOLY:
return (int) calcStat(Stats.HOLY_RES, _activeChar.getTemplate().getBaseHolyRes());
case Elementals.DARK:
return (int) calcStat(Stats.DARK_RES, _activeChar.getTemplate().getBaseDarkRes());
default:
return (int) _activeChar.getTemplate().getBaseElementRes();
}
}
public float getAttackTrait(TraitType traitType)
{
return _attackTraits[traitType.getId()];
}
public float[] getAttackTraits()
{
return _attackTraits;
}
public boolean hasAttackTrait(TraitType traitType)
{
return _attackTraitsCount[traitType.getId()] > 0;
}
public int[] getAttackTraitsCount()
{
return _attackTraitsCount;
}
public float getDefenceTrait(TraitType traitType)
{
return _defenceTraits[traitType.getId()];
}
public float[] getDefenceTraits()
{
return _defenceTraits;
}
public boolean hasDefenceTrait(TraitType traitType)
{
return _defenceTraitsCount[traitType.getId()] > 0;
}
public int[] getDefenceTraitsCount()
{
return _defenceTraitsCount;
}
public boolean isTraitInvul(TraitType traitType)
{
return _traitsInvul[traitType.getId()] > 0;
}
public int[] getTraitsInvul()
{
return _traitsInvul;
}
/**
* Gets the maximum buff count.
* @return the maximum buff count
*/
public int getMaxBuffCount()
{
return _maxBuffCount;
}
/**
* Sets the maximum buff count.
* @param buffCount the buff count
*/
public void setMaxBuffCount(int buffCount)
{
_maxBuffCount = buffCount;
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2004-2014 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.stat;
import com.l2jserver.gameserver.model.actor.instance.L2ControllableAirShipInstance;
public class ControllableAirShipStat extends VehicleStat
{
public ControllableAirShipStat(L2ControllableAirShipInstance activeChar)
{
super(activeChar);
}
@Override
public L2ControllableAirShipInstance getActiveChar()
{
return (L2ControllableAirShipInstance) super.getActiveChar();
}
@Override
public double getMoveSpeed()
{
if (getActiveChar().isInDock() || (getActiveChar().getFuel() > 0))
{
return super.getMoveSpeed();
}
return super.getMoveSpeed() * 0.05f;
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2004-2014 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.stat;
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
/**
* @author malyelfik
*/
public class DoorStat extends CharStat
{
private int _upgradeHpRatio = 1;
public DoorStat(L2DoorInstance activeChar)
{
super(activeChar);
}
@Override
public L2DoorInstance getActiveChar()
{
return (L2DoorInstance) super.getActiveChar();
}
@Override
public int getMaxHp()
{
return super.getMaxHp() * _upgradeHpRatio;
}
public void setUpgradeHpRatio(int ratio)
{
_upgradeHpRatio = ratio;
}
public int getUpgradeHpRatio()
{
return _upgradeHpRatio;
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2004-2014 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.stat;
import com.l2jserver.gameserver.model.actor.L2Npc;
public class NpcStat extends CharStat
{
public NpcStat(L2Npc activeChar)
{
super(activeChar);
}
@Override
public byte getLevel()
{
return getActiveChar().getTemplate().getLevel();
}
@Override
public L2Npc getActiveChar()
{
return (L2Npc) super.getActiveChar();
}
}

View File

@ -0,0 +1,916 @@
/*
* Copyright (C) 2004-2014 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.stat;
import java.util.concurrent.atomic.AtomicInteger;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.ExperienceTable;
import com.l2jserver.gameserver.datatables.PetDataTable;
import com.l2jserver.gameserver.enums.PartySmallWindowUpdateType;
import com.l2jserver.gameserver.enums.UserInfoType;
import com.l2jserver.gameserver.model.L2PetLevelData;
import com.l2jserver.gameserver.model.PcCondOverride;
import com.l2jserver.gameserver.model.actor.instance.L2ClassMasterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
import com.l2jserver.gameserver.model.actor.transform.TransformTemplate;
import com.l2jserver.gameserver.model.entity.RecoBonus;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerLevelChanged;
import com.l2jserver.gameserver.model.stats.Formulas;
import com.l2jserver.gameserver.model.stats.MoveType;
import com.l2jserver.gameserver.model.stats.Stats;
import com.l2jserver.gameserver.model.zone.ZoneId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.AcquireSkillList;
import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
import com.l2jserver.gameserver.network.serverpackets.ExVitalityPointInfo;
import com.l2jserver.gameserver.network.serverpackets.ExVoteSystemInfo;
import com.l2jserver.gameserver.network.serverpackets.PartySmallWindowUpdate;
import com.l2jserver.gameserver.network.serverpackets.PledgeShowMemberListUpdate;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.StatusUpdate;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.network.serverpackets.UserInfo;
import com.l2jserver.gameserver.network.serverpackets.friend.L2FriendStatus;
import com.l2jserver.gameserver.util.Util;
public class PcStat extends PlayableStat
{
private int _oldMaxHp; // stats watch
private int _oldMaxMp; // stats watch
private int _oldMaxCp; // stats watch
private float _vitalityPoints = 1;
private byte _vitalityLevel = 0;
private long _startingXp;
/** Player's maximum cubic count. */
private int _maxCubicCount = 1;
/** Player's maximum talisman count. */
private final AtomicInteger _talismanSlots = new AtomicInteger();
private boolean _cloakSlot = false;
public static final int VITALITY_LEVELS[] =
{
240,
2000,
13000,
17000,
20000
};
public static final int MAX_VITALITY_POINTS = VITALITY_LEVELS[4];
public static final int MIN_VITALITY_POINTS = 1;
public PcStat(L2PcInstance activeChar)
{
super(activeChar);
}
@Override
public boolean addExp(long value)
{
L2PcInstance activeChar = getActiveChar();
// Allowed to gain exp?
if (!getActiveChar().getAccessLevel().canGainExp())
{
return false;
}
if (!super.addExp(value))
{
return false;
}
// Set new karma
if (!activeChar.isCursedWeaponEquipped() && (activeChar.getKarma() > 0) && (activeChar.isGM() || !activeChar.isInsideZone(ZoneId.PVP)))
{
int karmaLost = Formulas.calculateKarmaLost(activeChar, value);
if (karmaLost > 0)
{
activeChar.setKarma(activeChar.getKarma() - karmaLost);
final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOUR_REPUTATION_HAS_BEEN_CHANGED_TO_S1);
msg.addInt(activeChar.getKarma());
activeChar.sendPacket(msg);
}
}
// EXP status update currently not used in retail
activeChar.sendPacket(new UserInfo(activeChar));
activeChar.sendPacket(new ExBrExtraUserInfo(activeChar));
return true;
}
public boolean addExpAndSp(long addToExp, long addToSp, boolean useBonuses)
{
L2PcInstance activeChar = getActiveChar();
// Allowed to gain exp/sp?
if (!activeChar.getAccessLevel().canGainExp())
{
return false;
}
long baseExp = addToExp;
long baseSp = addToSp;
double bonusExp = 1.;
double bonusSp = 1.;
if (useBonuses)
{
bonusExp = getExpBonusMultiplier();
bonusSp = getSpBonusMultiplier();
}
addToExp *= bonusExp;
addToSp *= bonusSp;
float ratioTakenByPlayer = 0;
// if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now
if (activeChar.hasPet() && Util.checkIfInShortRadius(Config.ALT_PARTY_RANGE, activeChar, activeChar.getSummon(), false))
{
L2PetInstance pet = (L2PetInstance) activeChar.getSummon();
ratioTakenByPlayer = pet.getPetLevelData().getOwnerExpTaken() / 100f;
// only give exp/sp to the pet by taking from the owner if the pet has a non-zero, positive ratio
// allow possible customizations that would have the pet earning more than 100% of the owner's exp/sp
if (ratioTakenByPlayer > 1)
{
ratioTakenByPlayer = 1;
}
if (!pet.isDead())
{
pet.addExpAndSp((long) (addToExp * (1 - ratioTakenByPlayer)), (int) (addToSp * (1 - ratioTakenByPlayer)));
}
// now adjust the max ratio to avoid the owner earning negative exp/sp
addToExp = (long) (addToExp * ratioTakenByPlayer);
addToSp = (int) (addToSp * ratioTakenByPlayer);
}
if (!addExp(addToExp))
{
addToExp = 0;
}
if (!addSp(addToSp))
{
addToSp = 0;
}
if ((addToExp == 0) && (addToSp == 0))
{
return false;
}
SystemMessage sm = null;
if ((addToExp == 0) && (addToSp != 0))
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP);
sm.addLong(addToSp);
}
else if ((addToSp == 0) && (addToExp != 0))
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP);
sm.addLong(addToExp);
}
else
{
if ((addToExp - baseExp) > 0)
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4);
sm.addLong(addToExp);
sm.addLong(addToExp - baseExp);
sm.addLong(addToSp);
sm.addLong(addToSp - baseSp);
}
else
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP_AND_S2_SP);
sm.addLong(addToExp);
sm.addLong(addToSp);
}
}
activeChar.sendPacket(sm);
return true;
}
@Override
public boolean removeExpAndSp(long addToExp, long addToSp)
{
return removeExpAndSp(addToExp, addToSp, true);
}
public boolean removeExpAndSp(long addToExp, long addToSp, boolean sendMessage)
{
int level = getLevel();
if (!super.removeExpAndSp(addToExp, addToSp))
{
return false;
}
if (sendMessage)
{
// Send a Server->Client System Message to the L2PcInstance
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_XP_HAS_DECREASED_BY_S1);
sm.addLong(addToExp);
getActiveChar().sendPacket(sm);
sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_SP_HAS_DECREASED_BY_S1);
sm.addLong(addToSp);
getActiveChar().sendPacket(sm);
if (getLevel() < level)
{
getActiveChar().broadcastStatusUpdate();
}
}
return true;
}
@Override
public final boolean addLevel(byte value)
{
if ((getLevel() + value) > (ExperienceTable.getInstance().getMaxLevel() - 1))
{
return false;
}
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLevelChanged(getActiveChar(), getLevel(), getLevel() + value), getActiveChar());
boolean levelIncreased = super.addLevel(value);
if (levelIncreased)
{
getActiveChar().setCurrentCp(getMaxCp());
getActiveChar().broadcastPacket(new SocialAction(getActiveChar().getObjectId(), SocialAction.LEVEL_UP));
getActiveChar().sendPacket(SystemMessageId.YOUR_LEVEL_HAS_INCREASED);
getActiveChar().notifyFriends(L2FriendStatus.MODE_LEVEL);
L2ClassMasterInstance.showQuestionMark(getActiveChar());
}
// Give AutoGet skills and all normal skills if Auto-Learn is activated.
getActiveChar().rewardSkills();
if (getActiveChar().getClan() != null)
{
getActiveChar().getClan().updateClanMember(getActiveChar());
getActiveChar().getClan().broadcastToOnlineMembers(new PledgeShowMemberListUpdate(getActiveChar()));
}
if (getActiveChar().isInParty())
{
getActiveChar().getParty().recalculatePartyLevel(); // Recalculate the party level
}
if (getActiveChar().isTransformed() || getActiveChar().isInStance())
{
getActiveChar().getTransformation().onLevelUp(getActiveChar());
}
// Synchronize level with pet if possible.
if (getActiveChar().hasPet())
{
final L2PetInstance pet = (L2PetInstance) getActiveChar().getSummon();
if (pet.getPetData().isSynchLevel() && (pet.getLevel() != getLevel()))
{
pet.getStat().setLevel(getLevel());
pet.getStat().getExpForLevel(getActiveChar().getLevel());
pet.setCurrentHp(pet.getMaxHp());
pet.setCurrentMp(pet.getMaxMp());
pet.broadcastPacket(new SocialAction(getActiveChar().getObjectId(), SocialAction.LEVEL_UP));
pet.updateAndBroadcastStatus(1);
}
}
StatusUpdate su = new StatusUpdate(getActiveChar());
su.addAttribute(StatusUpdate.LEVEL, getLevel());
su.addAttribute(StatusUpdate.MAX_CP, getMaxCp());
su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());
su.addAttribute(StatusUpdate.MAX_MP, getMaxMp());
getActiveChar().sendPacket(su);
// Update the overloaded status of the L2PcInstance
getActiveChar().refreshOverloaded();
// Update the expertise status of the L2PcInstance
getActiveChar().refreshExpertisePenalty();
// Send a Server->Client packet UserInfo to the L2PcInstance
getActiveChar().sendPacket(new UserInfo(getActiveChar()));
// Send acquirable skill list
getActiveChar().sendPacket(new AcquireSkillList(getActiveChar()));
getActiveChar().sendPacket(new ExBrExtraUserInfo(getActiveChar()));
getActiveChar().sendPacket(new ExVoteSystemInfo(getActiveChar()));
if (getActiveChar().isInParty())
{
final PartySmallWindowUpdate partyWindow = new PartySmallWindowUpdate(getActiveChar(), false);
partyWindow.addUpdateType(PartySmallWindowUpdateType.LEVEL);
getActiveChar().getParty().broadcastToPartyMembers(getActiveChar(), partyWindow);
}
return levelIncreased;
}
@Override
public boolean addSp(long value)
{
if (!super.addSp(value))
{
return false;
}
UserInfo ui = new UserInfo(getActiveChar(), false);
ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP);
getActiveChar().sendPacket(ui);
return true;
}
@Override
public final long getExpForLevel(int level)
{
return ExperienceTable.getInstance().getExpForLevel(level);
}
@Override
public final L2PcInstance getActiveChar()
{
return (L2PcInstance) super.getActiveChar();
}
@Override
public final long getExp()
{
if (getActiveChar().isSubClassActive())
{
return getActiveChar().getSubClasses().get(getActiveChar().getClassIndex()).getExp();
}
return super.getExp();
}
public final long getBaseExp()
{
return super.getExp();
}
@Override
public final void setExp(long value)
{
if (getActiveChar().isSubClassActive())
{
getActiveChar().getSubClasses().get(getActiveChar().getClassIndex()).setExp(value);
}
else
{
super.setExp(value);
}
}
public void setStartingExp(long value)
{
if (Config.BOTREPORT_ENABLE)
{
_startingXp = value;
}
}
public long getStartingExp()
{
return _startingXp;
}
/**
* Gets the maximum cubic count.
* @return the maximum cubic count
*/
public int getMaxCubicCount()
{
return _maxCubicCount;
}
/**
* Sets the maximum cubic count.
* @param cubicCount the maximum cubic count
*/
public void setMaxCubicCount(int cubicCount)
{
_maxCubicCount = cubicCount;
}
/**
* Gets the maximum talisman count.
* @return the maximum talisman count
*/
public int getTalismanSlots()
{
return _talismanSlots.get();
}
public void addTalismanSlots(int count)
{
_talismanSlots.addAndGet(count);
}
public boolean canEquipCloak()
{
return _cloakSlot;
}
public void setCloakSlotStatus(boolean cloakSlot)
{
_cloakSlot = cloakSlot;
}
@Override
public final byte getLevel()
{
if (getActiveChar().isSubClassActive())
{
return getActiveChar().getSubClasses().get(getActiveChar().getClassIndex()).getLevel();
}
return super.getLevel();
}
public final byte getBaseLevel()
{
return super.getLevel();
}
@Override
public final void setLevel(byte value)
{
if (value > (ExperienceTable.getInstance().getMaxLevel() - 1))
{
value = (byte) (ExperienceTable.getInstance().getMaxLevel() - 1);
}
if (getActiveChar().isSubClassActive())
{
getActiveChar().getSubClasses().get(getActiveChar().getClassIndex()).setLevel(value);
}
else
{
super.setLevel(value);
}
}
@Override
public final int getMaxCp()
{
// Get the Max CP (base+modifier) of the L2PcInstance
int val = (getActiveChar() == null) ? 1 : (int) calcStat(Stats.MAX_CP, getActiveChar().getTemplate().getBaseCpMax(getActiveChar().getLevel()));
if (val != _oldMaxCp)
{
_oldMaxCp = val;
// Launch a regen task if the new Max CP is higher than the old one
if (getActiveChar().getStatus().getCurrentCp() != val)
{
getActiveChar().getStatus().setCurrentCp(getActiveChar().getStatus().getCurrentCp()); // trigger start of regeneration
}
}
return val;
}
@Override
public final int getMaxHp()
{
// Get the Max HP (base+modifier) of the L2PcInstance
int val = (getActiveChar() == null) ? 1 : (int) calcStat(Stats.MAX_HP, getActiveChar().getTemplate().getBaseHpMax(getActiveChar().getLevel()));
if (val != _oldMaxHp)
{
_oldMaxHp = val;
// Launch a regen task if the new Max HP is higher than the old one
if (getActiveChar().getStatus().getCurrentHp() != val)
{
getActiveChar().getStatus().setCurrentHp(getActiveChar().getStatus().getCurrentHp()); // trigger start of regeneration
}
}
return val;
}
@Override
public final int getMaxMp()
{
// Get the Max MP (base+modifier) of the L2PcInstance
int val = (getActiveChar() == null) ? 1 : (int) calcStat(Stats.MAX_MP, getActiveChar().getTemplate().getBaseMpMax(getActiveChar().getLevel()));
if (val != _oldMaxMp)
{
_oldMaxMp = val;
// Launch a regen task if the new Max MP is higher than the old one
if (getActiveChar().getStatus().getCurrentMp() != val)
{
getActiveChar().getStatus().setCurrentMp(getActiveChar().getStatus().getCurrentMp()); // trigger start of regeneration
}
}
return val;
}
@Override
public final long getSp()
{
if (getActiveChar().isSubClassActive())
{
return getActiveChar().getSubClasses().get(getActiveChar().getClassIndex()).getSp();
}
return super.getSp();
}
public final long getBaseSp()
{
return super.getSp();
}
@Override
public final void setSp(long value)
{
if (getActiveChar().isSubClassActive())
{
getActiveChar().getSubClasses().get(getActiveChar().getClassIndex()).setSp(value);
}
else
{
super.setSp(value);
}
}
/**
* @param type movement type
* @return the base move speed of given movement type.
*/
@Override
public double getBaseMoveSpeed(MoveType type)
{
final L2PcInstance player = getActiveChar();
if (player.isTransformed())
{
final TransformTemplate template = player.getTransformation().getTemplate(player);
if (template != null)
{
return template.getBaseMoveSpeed(type);
}
}
else if (player.isMounted())
{
final L2PetLevelData data = PetDataTable.getInstance().getPetLevelData(player.getMountNpcId(), player.getMountLevel());
if (data != null)
{
return data.getSpeedOnRide(type);
}
}
return super.getBaseMoveSpeed(type);
}
@Override
public double getRunSpeed()
{
double val = super.getRunSpeed() + Config.RUN_SPD_BOOST;
// Apply max run speed cap.
if ((val > Config.MAX_RUN_SPEED) && !getActiveChar().canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
return Config.MAX_RUN_SPEED;
}
// Check for mount penalties
if (getActiveChar().isMounted())
{
// if level diff with mount >= 10, it decreases move speed by 50%
if ((getActiveChar().getMountLevel() - getActiveChar().getLevel()) >= 10)
{
val /= 2;
}
// if mount is hungry, it decreases move speed by 50%
if (getActiveChar().isHungry())
{
val /= 2;
}
}
return val;
}
@Override
public double getWalkSpeed()
{
double val = super.getWalkSpeed() + Config.RUN_SPD_BOOST;
// Apply max run speed cap.
if ((val > Config.MAX_RUN_SPEED) && !getActiveChar().canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
return Config.MAX_RUN_SPEED;
}
if (getActiveChar().isMounted())
{
// if level diff with mount >= 10, it decreases move speed by 50%
if ((getActiveChar().getMountLevel() - getActiveChar().getLevel()) >= 10)
{
val /= 2;
}
// if mount is hungry, it decreases move speed by 50%
if (getActiveChar().isHungry())
{
val /= 2;
}
}
return val;
}
@Override
public int getPAtkSpd()
{
int val = super.getPAtkSpd();
if ((val > Config.MAX_PATK_SPEED) && !getActiveChar().canOverrideCond(PcCondOverride.MAX_STATS_VALUE))
{
return Config.MAX_PATK_SPEED;
}
return val;
}
private void updateVitalityLevel(boolean quiet)
{
final byte level;
if (_vitalityPoints <= VITALITY_LEVELS[0])
{
level = 0;
}
else if (_vitalityPoints <= VITALITY_LEVELS[1])
{
level = 1;
}
else if (_vitalityPoints <= VITALITY_LEVELS[2])
{
level = 2;
}
else if (_vitalityPoints <= VITALITY_LEVELS[3])
{
level = 3;
}
else
{
level = 4;
}
if (!quiet && (level != _vitalityLevel))
{
if (level < _vitalityLevel)
{
getActiveChar().sendPacket(SystemMessageId.YOUR_VITALITY_HAS_DECREASED);
}
else
{
getActiveChar().sendPacket(SystemMessageId.YOUR_VITALITY_HAS_INCREASED);
}
if (level == 0)
{
getActiveChar().sendPacket(SystemMessageId.YOUR_VITALITY_IS_FULLY_EXHAUSTED);
}
else if (level == 4)
{
getActiveChar().sendPacket(SystemMessageId.YOUR_VITALITY_IS_AT_MAXIMUM);
}
}
_vitalityLevel = level;
}
/*
* Return current vitality points in integer format
*/
public int getVitalityPoints()
{
return (int) _vitalityPoints;
}
/*
* Set current vitality points to this value if quiet = true - does not send system messages
*/
public void setVitalityPoints(int points, boolean quiet)
{
points = Math.min(Math.max(points, MIN_VITALITY_POINTS), MAX_VITALITY_POINTS);
if (points == _vitalityPoints)
{
return;
}
_vitalityPoints = points;
updateVitalityLevel(quiet);
final L2PcInstance player = getActiveChar();
player.sendPacket(new ExVitalityPointInfo(getVitalityPoints()));
if (player.isInParty())
{
final PartySmallWindowUpdate partyWindow = new PartySmallWindowUpdate(player, false);
partyWindow.addUpdateType(PartySmallWindowUpdateType.VITALITY_POINTS);
player.getParty().broadcastToPartyMembers(player, partyWindow);
}
}
public synchronized void updateVitalityPoints(float points, boolean useRates, boolean quiet)
{
if ((points == 0) || !Config.ENABLE_VITALITY)
{
return;
}
if (useRates)
{
if (getActiveChar().isLucky())
{
return;
}
if (points < 0) // vitality consumed
{
int stat = (int) calcStat(Stats.VITALITY_CONSUME_RATE, 1, getActiveChar(), null);
if (stat == 0)
{
return;
}
if (stat < 0)
{
points = -points;
}
}
if (points > 0)
{
// vitality increased
points *= Config.RATE_VITALITY_GAIN;
}
else
{
// vitality decreased
points *= Config.RATE_VITALITY_LOST;
}
}
if (points > 0)
{
points = Math.min(_vitalityPoints + points, MAX_VITALITY_POINTS);
}
else
{
points = Math.max(_vitalityPoints + points, MIN_VITALITY_POINTS);
}
if (Math.abs(points - _vitalityPoints) <= 1e-6)
{
return;
}
_vitalityPoints = points;
updateVitalityLevel(quiet);
}
public double getVitalityMultiplier()
{
double vitality = 1.0;
if (Config.ENABLE_VITALITY)
{
switch (getVitalityLevel())
{
case 1:
vitality = Config.RATE_VITALITY_LEVEL_1;
break;
case 2:
vitality = Config.RATE_VITALITY_LEVEL_2;
break;
case 3:
vitality = Config.RATE_VITALITY_LEVEL_3;
break;
case 4:
vitality = Config.RATE_VITALITY_LEVEL_4;
break;
}
}
return vitality;
}
/**
* @return the _vitalityLevel
*/
public byte getVitalityLevel()
{
return _vitalityLevel;
}
public double getExpBonusMultiplier()
{
double bonus = 1.0;
double vitality = 1.0;
double nevits = 1.0;
double hunting = 1.0;
double bonusExp = 1.0;
// Bonus from Vitality System
vitality = getVitalityMultiplier();
// Bonus from Nevit's Blessing
nevits = RecoBonus.getRecoMultiplier(getActiveChar());
// Bonus from Nevit's Hunting
// TODO: Nevit's hunting bonus
// Bonus exp from skills
bonusExp = 1 + (calcStat(Stats.BONUS_EXP, 0, null, null) / 100);
if (vitality > 1.0)
{
bonus += (vitality - 1);
}
if (nevits > 1.0)
{
bonus += (nevits - 1);
}
if (hunting > 1.0)
{
bonus += (hunting - 1);
}
if (bonusExp > 1)
{
bonus += (bonusExp - 1);
}
// Check for abnormal bonuses
bonus = Math.max(bonus, 1);
bonus = Math.min(bonus, Config.MAX_BONUS_EXP);
return bonus;
}
public double getSpBonusMultiplier()
{
double bonus = 1.0;
double vitality = 1.0;
double nevits = 1.0;
double hunting = 1.0;
double bonusSp = 1.0;
// Bonus from Vitality System
vitality = getVitalityMultiplier();
// Bonus from Nevit's Blessing
nevits = RecoBonus.getRecoMultiplier(getActiveChar());
// Bonus from Nevit's Hunting
// TODO: Nevit's hunting bonus
// Bonus sp from skills
bonusSp = 1 + (calcStat(Stats.BONUS_SP, 0, null, null) / 100);
if (vitality > 1.0)
{
bonus += (vitality - 1);
}
if (nevits > 1.0)
{
bonus += (nevits - 1);
}
if (hunting > 1.0)
{
bonus += (hunting - 1);
}
if (bonusSp > 1)
{
bonus += (bonusSp - 1);
}
// Check for abnormal bonuses
bonus = Math.max(bonus, 1);
bonus = Math.min(bonus, Config.MAX_BONUS_SP);
return bonus;
}
}

Some files were not shown because too many files have changed in this diff Show More