All pastes #811491 Raw Edit

Mine

public java v1 · immutable
·published 2007-12-10 23:45 UTC
rendered paste body
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * http://www.gnu.org/copyleft/gpl.html */package net.sf.l2j.gameserver.model.actor.instance;import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;import java.text.DateFormat;import java.util.List;import javolution.text.TextBuilder;import javolution.util.FastList;import net.sf.l2j.Config;import net.sf.l2j.gameserver.Olympiad;import net.sf.l2j.gameserver.SevenSigns;import net.sf.l2j.gameserver.SevenSignsFestival;import net.sf.l2j.gameserver.ThreadPoolManager;import net.sf.l2j.gameserver.ai.CtrlIntention;import net.sf.l2j.gameserver.cache.HtmCache;import net.sf.l2j.gameserver.datatables.BuffTemplateTable;import net.sf.l2j.gameserver.datatables.ClanTable;import net.sf.l2j.gameserver.datatables.HelperBuffTable;import net.sf.l2j.gameserver.datatables.ItemTable;import net.sf.l2j.gameserver.datatables.SkillTable;import net.sf.l2j.gameserver.datatables.SpawnTable;import net.sf.l2j.gameserver.idfactory.IdFactory;import net.sf.l2j.gameserver.instancemanager.CastleManager;import net.sf.l2j.gameserver.instancemanager.DimensionalRiftManager;import net.sf.l2j.gameserver.instancemanager.QuestManager;import net.sf.l2j.gameserver.instancemanager.TownManager;import net.sf.l2j.gameserver.instancemanager.games.Lottery;import net.sf.l2j.gameserver.model.L2Attackable;import net.sf.l2j.gameserver.model.L2Character;import net.sf.l2j.gameserver.model.L2Clan;import net.sf.l2j.gameserver.model.L2DropCategory;import net.sf.l2j.gameserver.model.L2DropData;import net.sf.l2j.gameserver.model.L2ItemInstance;import net.sf.l2j.gameserver.model.L2Multisell;import net.sf.l2j.gameserver.model.L2Object;import net.sf.l2j.gameserver.model.L2Skill;import net.sf.l2j.gameserver.model.L2Spawn;import net.sf.l2j.gameserver.model.L2Summon;import net.sf.l2j.gameserver.model.L2World;import net.sf.l2j.gameserver.model.MobGroupTable;import net.sf.l2j.gameserver.model.L2Skill.SkillType;import net.sf.l2j.gameserver.model.actor.knownlist.NpcKnownList;import net.sf.l2j.gameserver.model.actor.stat.NpcStat;import net.sf.l2j.gameserver.model.actor.status.NpcStatus;import net.sf.l2j.gameserver.model.entity.Castle;import net.sf.l2j.gameserver.model.entity.L2Event;import net.sf.l2j.gameserver.model.entity.L2JOneoEvents.CTF;import net.sf.l2j.gameserver.model.entity.L2JOneoEvents.VIP;import net.sf.l2j.gameserver.model.quest.Quest;import net.sf.l2j.gameserver.model.quest.QuestState;import net.sf.l2j.gameserver.model.zone.type.L2TownZone;import net.sf.l2j.gameserver.network.L2GameClient;import net.sf.l2j.gameserver.network.SystemMessageId;import net.sf.l2j.gameserver.serverpackets.ActionFailed;import net.sf.l2j.gameserver.serverpackets.ExShowVariationCancelWindow;import net.sf.l2j.gameserver.serverpackets.ExShowVariationMakeWindow;import net.sf.l2j.gameserver.serverpackets.InventoryUpdate;import net.sf.l2j.gameserver.serverpackets.MyTargetSelected;import net.sf.l2j.gameserver.serverpackets.NpcHtmlMessage;import net.sf.l2j.gameserver.serverpackets.NpcInfo;import net.sf.l2j.gameserver.serverpackets.RadarControl;import net.sf.l2j.gameserver.serverpackets.SocialAction;import net.sf.l2j.gameserver.serverpackets.StatusUpdate;import net.sf.l2j.gameserver.serverpackets.SystemMessage;import net.sf.l2j.gameserver.serverpackets.ValidateLocation;import net.sf.l2j.gameserver.skills.Stats;import net.sf.l2j.gameserver.taskmanager.DecayTaskManager;import net.sf.l2j.gameserver.templates.L2HelperBuff;import net.sf.l2j.gameserver.templates.L2Item;import net.sf.l2j.gameserver.templates.L2NpcTemplate;import net.sf.l2j.gameserver.templates.L2Weapon;import net.sf.l2j.util.Rnd;/** * This class represents a Non-Player-Character in the world. It can be a * monster or a friendly character. It also uses a template to fetch some static * values. The templates are hardcoded in the client, so we can rely on them.<BR> * <BR> * * L2Character :<BR> * <BR> * <li>L2Attackable</li> * <li>L2BoxInstance</li> * <li>L2FolkInstance</li> * * @version $Revision: 1.32.2.7.2.24 $ $Date: 2005/04/11 10:06:09 $ */public class L2NpcInstance extends L2Character{    // private static Logger _log =    // Logger.getLogger(L2NpcInstance.class.getName());    /**     * The interaction distance of the L2NpcInstance(is used as offset in     * MovetoLocation method)     */    public static final int INTERACTION_DISTANCE = 150;    /** The L2Spawn object that manage this L2NpcInstance */    private L2Spawn _spawn;    /** The flag to specify if this L2NpcInstance is busy */    private boolean _isBusy = false;    /** The busy message for this L2NpcInstance */    private String _busyMessage = "";    /** true if endDecayTask has already been called */    volatile boolean _isDecayed = false;    /** true if a Dwarf has used Spoil on this L2NpcInstance */    private boolean _isSpoil = false;    /**     * The castle index in the array of L2Castle this L2NpcInstance belongs     * to     */    private int _castleIndex = -2;    public boolean isEventMob = false, _isEventVIPNPC = false,	    _isEventVIPNPCEnd = false;    public boolean _isEventMobCTF = false;    public boolean isPrivateEventMob = false;    private boolean _isInTown = false;    private int _isSpoiledBy = 0;    protected RandomAnimationTask _rAniTask = null;    private int _currentLHandId;  // normally this shouldn't change from the template, but there exist exceptions 	private int _currentRHandId;  // normally this shouldn't change from the template, but there exist exceptions     /** Task launching the function onRandomAnimation() */    protected class RandomAnimationTask implements Runnable    {	public void run()	{	    try	    {		if (this != _rAniTask)		{		    return; // Shouldn't happen, but who knows... just to		    // make		    // sure every active npc has only one timer.		}		if (isMob())		{		    // Cancel further animation timers until intention is		    // changed to ACTIVE again.		    if (getAI().getIntention() != AI_INTENTION_ACTIVE)		    {			return;		    }		} else		{		    if (!isInActiveRegion())		    {			return;		    }		    // update knownlist to remove playable which aren't in		    // range		    // any more		    getKnownList().updateKnownObjects();		}		if (!(isDead() || isStunned() || isSleeping() || isParalyzed()))		{		    onRandomAnimation();		}		startRandomAnimationTimer();	    } catch (Throwable t)	    {	    }	}    }    /**     * Send a packet SocialAction to all L2PcInstance in the _KnownPlayers     * of the L2NpcInstance and create a new RandomAnimation Task.<BR>     * <BR>     */    public void onRandomAnimation()    {	// Send a packet SocialAction to all L2PcInstance in the _KnownPlayers	// of the L2NpcInstance	SocialAction sa = new SocialAction(getObjectId(), Rnd.get(2, 3));	broadcastPacket(sa);    }    /**     * Create a RandomAnimation Task that will be launched after the     * calculated delay.<BR>     * <BR>     */    public void startRandomAnimationTimer()    {	if (!hasRandomAnimation())	{	    return;	}	int minWait = isMob() ? Config.MIN_MONSTER_ANIMATION : Config.MIN_NPC_ANIMATION;	int maxWait = isMob() ? Config.MAX_MONSTER_ANIMATION : Config.MAX_NPC_ANIMATION;	// Calculate the delay before the next animation	int interval = Rnd.get(minWait, maxWait) * 1000;	// Create a RandomAnimation Task that will be launched after the	// calculated delay	_rAniTask = new RandomAnimationTask();	ThreadPoolManager.getInstance().scheduleGeneral(_rAniTask, interval);    }    /**     * Check if the server allows Random Animation.<BR>     * <BR>     */    public boolean hasRandomAnimation()    {	return Config.MAX_NPC_ANIMATION > 0;    }    public class destroyTemporalNPC implements Runnable    {	private L2Spawn _oldSpawn;	public destroyTemporalNPC(L2Spawn spawn)	{	    _oldSpawn = spawn;	}	public void run()	{	    try	    {		_oldSpawn.getLastSpawn().deleteMe();		_oldSpawn.stopRespawn();		SpawnTable.getInstance().deleteSpawn(_oldSpawn, false);	    } catch (Throwable t)	    {		t.printStackTrace();	    }	}    }    public class destroyTemporalSummon implements Runnable    {	L2Summon _summon;	L2PcInstance _player;	public destroyTemporalSummon(L2Summon summon, L2PcInstance player)	{	    _summon = summon;	    _player = player;	}	public void run()	{	    _summon.unSummon(_player);	}    }    /**     * Constructor of L2NpcInstance (use L2Character constructor).<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Call the L2Character constructor to set the _template of the     * L2Character (copy skills from template to object and link     * _calculators to NPC_STD_CALCULATOR) </li>     * <li>Set the name of the L2Character</li>     * <li>Create a RandomAnimation Task that will be launched after the     * calculated delay if the server allow it </li>     * <BR>     * <BR>     *     * @param objectId     *                Identifier of the object to initialized     * @param template     *                The L2NpcTemplate to apply to the NPC     *     */    public L2NpcInstance(int objectId, L2NpcTemplate template)    {	// Call the L2Character constructor to set the _template of the	// L2Character, copy skills from template to object	// and link _calculators to NPC_STD_CALCULATOR	super(objectId, template);	getKnownList(); // init knownlist	getStat(); // init stats	getStatus(); // init status	initCharStatusUpdateValues();    // initialize the "current" equipment 	_currentLHandId = getTemplate().lhand;	_currentRHandId = getTemplate().rhand;		if (template == null)	{	    _log.severe("No template for Npc. Please check your datapack is setup correctly.");	    return;	}	// Set the name of the L2Character	setName(template.name);    }    @Override    public NpcKnownList getKnownList()    {	if (super.getKnownList() == null || !(super.getKnownList() instanceof NpcKnownList))	{	    setKnownList(new NpcKnownList(this));	}	return (NpcKnownList) super.getKnownList();    }    @Override    public NpcStat getStat()    {	if (super.getStat() == null || !(super.getStat() instanceof NpcStat))	{	    setStat(new NpcStat(this));	}	return (NpcStat) super.getStat();    }    @Override    public NpcStatus getStatus()    {	if (super.getStatus() == null || !(super.getStatus() instanceof NpcStatus))	{	    setStatus(new NpcStatus(this));	}	return (NpcStatus) super.getStatus();    }    /** Return the L2NpcTemplate of the L2NpcInstance. */    @Override    public final L2NpcTemplate getTemplate()    {	return (L2NpcTemplate) super.getTemplate();    }    /**     * Return the generic Identifier of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    public int getNpcId()    {	return getTemplate().npcId;    }    @Override    public boolean isAttackable()    {	return false;    }    /**     * Return the faction Identifier of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     *     * <B><U> Concept</U> :</B><BR>     * <BR>     * If a NPC belows to a Faction, other NPC of the faction inside the     * Faction range will help it if it's attacked<BR>     * <BR>     *     */    public final String getFactionId()    {	return getTemplate().factionId;    }    /**     * Return the Level of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    @Override    public final int getLevel()    {	return getTemplate().level;    }    /**     * Return true if the L2NpcInstance is agressive (ex : L2MonsterInstance     * in function of aggroRange).<BR>     * <BR>     */    public boolean isAggressive()    {	return false;    }    /**     * Return the Aggro Range of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    public int getAggroRange()    {	return getTemplate().aggroRange;    }    /**     * Return the Faction Range of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    public int getFactionRange()    {	return getTemplate().factionRange;    }    /**     * Return true if this L2NpcInstance is undead in function of the     * L2NpcTemplate.<BR>     * <BR>     */    @Override    public boolean isUndead()    {	return getTemplate().isUndead;    }    /**     * Send a packet NpcInfo with state of abnormal effect to all     * L2PcInstance in the _KnownPlayers of the L2NpcInstance.<BR>     * <BR>     */    @Override    public void updateAbnormalEffect()    {	// NpcInfo info = new NpcInfo(this);	// broadcastPacket(info);	// Send a Server->Client packet NpcInfo with state of abnormal effect to	// all L2PcInstance in the _KnownPlayers of the L2NpcInstance	for (L2PcInstance player : getKnownList().getKnownPlayers().values())	{	    if (player != null)	    {		player.sendPacket(new NpcInfo(this, player));	    }	}    }    /**     * Return the distance under which the object must be add to     * _knownObject in function of the object type.<BR>     * <BR>     *     * <B><U> Values </U> :</B><BR>     * <BR>     * <li> object is a L2FolkInstance : 0 (don't remember it) </li>     * <li> object is a L2Character : 0 (don't remember it) </li>     * <li> object is a L2PlayableInstance : 1500 </li>     * <li> others : 500 </li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2Attackable</li>     * <BR>     * <BR>     *     * @param object     *                The Object to add to _knownObject     *     */    public int getDistanceToWatchObject(L2Object object)    {	if (object instanceof L2FestivalGuideInstance)	{	    return 10000;	}	if (object instanceof L2FolkInstance || !(object instanceof L2Character))	{	    return 0;	}	if (object instanceof L2PlayableInstance)	{	    return 1500;	}	return 500;    }    /**     * Return the distance after which the object must be remove from     * _knownObject in function of the object type.<BR>     * <BR>     *     * <B><U> Values </U> :</B><BR>     * <BR>     * <li> object is not a L2Character : 0 (don't remember it) </li>     * <li> object is a L2FolkInstance : 0 (don't remember it)</li>     * <li> object is a L2PlayableInstance : 3000 </li>     * <li> others : 1000 </li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2Attackable</li>     * <BR>     * <BR>     *     * @param object     *                The Object to remove from _knownObject     *     */    public int getDistanceToForgetObject(L2Object object)    {	return 2 * getDistanceToWatchObject(object);    }    /**     * Return false.<BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2MonsterInstance : Check if the attacker is not another     * L2MonsterInstance</li>     * <li> L2PcInstance</li>     * <BR>     * <BR>     */    @Override    public boolean isAutoAttackable(@SuppressWarnings("unused")    L2Character attacker)    {	return false;    }    /**     * Return the Identifier of the item in the left hand of this     * L2NpcInstance contained in the L2NpcTemplate.<BR>     * <BR>     */    public int getLeftHandItem()    {	return _currentLHandId;    }    /**     * Return the Identifier of the item in the right hand of this     * L2NpcInstance contained in the L2NpcTemplate.<BR>     * <BR>     */    public int getRightHandItem()    {	return _currentRHandId;    }    /**     * Return true if this L2NpcInstance has drops that can be sweeped.<BR>     * <BR>     */    public boolean isSpoil()    {	return _isSpoil;    }    /**     * Set the spoil state of this L2NpcInstance.<BR>     * <BR>     */    public void setSpoil(boolean isSpoil)    {	_isSpoil = isSpoil;    }    public final int getIsSpoiledBy()    {	return _isSpoiledBy;    }    public final void setIsSpoiledBy(int value)    {	_isSpoiledBy = value;    }    /**     * Return the busy status of this L2NpcInstance.<BR>     * <BR>     */    public final boolean isBusy()    {	return _isBusy;    }    /**     * Set the busy status of this L2NpcInstance.<BR>     * <BR>     */    public void setBusy(boolean isBusy)    {	_isBusy = isBusy;    }    /**     * Return the busy message of this L2NpcInstance.<BR>     * <BR>     */    public final String getBusyMessage()    {	return _busyMessage;    }    /**     * Set the busy message of this L2NpcInstance.<BR>     * <BR>     */    public void setBusyMessage(String message)    {	_busyMessage = message;    }    protected boolean canTarget(L2PcInstance player)  	{     	if (player.isOutOfControl())  	{  			player.sendPacket(new ActionFailed());  			return false;  	}  			// TODO: More checks...  		  			return true;  	}  	 			protected boolean canInteract(L2PcInstance player)  	{  			// TODO: NPC busy check etc...  	          			//if (!canTarget(player)) 			//return false;  	  			if (!isInsideRadius(player, INTERACTION_DISTANCE, false, false))  				return false;  	 			return true;  	}     /**     * Manage actions when a player click on the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions on first click on the L2NpcInstance (Select it)</U> :</B><BR>     * <BR>     * <li>Set the L2NpcInstance 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>If L2NpcInstance is autoAttackable, send a Server->Client packet     * StatusUpdate to the L2PcInstance in order to update L2NpcInstance HP     * bar </li>     * <li>Send a Server->Client packet ValidateLocation to correct the     * L2NpcInstance position and heading on the client </li>     * <BR>     * <BR>     *     * <B><U> Actions on second click on the L2NpcInstance (Attack     * it/Intercat with it)</U> :</B><BR>     * <BR>     * <li>Send a Server->Client packet MyTargetSelected to the     * L2PcInstance player (display the select window)</li>     * <li>If L2NpcInstance is autoAttackable, notify the L2PcInstance AI     * with AI_INTENTION_ATTACK (after a height verification)</li>     * <li>If L2NpcInstance is NOT autoAttackable, notify the L2PcInstance     * AI with AI_INTENTION_INTERACT (after a distance verification) and     * show message</li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Each group of     * Server->Client packet must be terminated by a ActionFailed packet in     * order to avoid that client wait an other packet</B></FONT><BR>     * <BR>     *     * <B><U> Example of use </U> :</B><BR>     * <BR>     * <li> Client packet : Action, AttackRequest</li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2ArtefactInstance : Manage only fisrt click to select Artefact</li>     * <BR>     * <BR>     * <li> L2GuardInstance : </li>     * <BR>     * <BR>     *     * @param player     *                The L2PcInstance that start an action on the     *                L2NpcInstance     *     */    @Override    public void onAction(L2PcInstance player)    {    if (!canTarget(player)) return;    	// Check if the L2PcInstance already target the L2NpcInstance	if (this != player.getTarget())	{	    if (Config.DEBUG)	    {		_log.fine("new target selected:" + getObjectId());	    }	    // Set the target of the L2PcInstance player	    player.setTarget(this);	    // Send a Server->Client packet MyTargetSelected to the L2PcInstance player The player.getLevel() - getLevel() permit to display the correct color in the select window	    MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());	    player.sendPacket(my);	    // Check if the player is attackable (without a forced attack)	    if (isAutoAttackable(player))	    {            // Send a Server->Client packet MyTargetSelected to the L2PcInstance playe The player.getLevel() - getLevel() permit to display the correct color in the select window 	     	MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel()); 	     	player.sendPacket(my); 	     		 	     	// Send a Server->Client packet StatusUpdate of the	     	// L2NpcInstance to the L2PcInstance to update its HP bar	     	StatusUpdate su = new StatusUpdate(getObjectId());	     	su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp());	     	su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());	     	player.sendPacket(su);	    }        else         {         		// Send a Server->Client packet MyTargetSelected to the L2PcInstance player         		MyTargetSelected my = new MyTargetSelected(getObjectId(), 0);         		player.sendPacket(my);         } 	    // Send a Server->Client packet ValidateLocation to correct the	    // L2NpcInstance position and heading on the client	    player.sendPacket(new ValidateLocation(this));	} else	{	    player.sendPacket(new ValidateLocation(this));	    // 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);		    // player.startAttack(this);		} else		{		    // Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet		    player.sendPacket(new ActionFailed());		}	    } else 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);		    // Open a chat window on client with the text of the L2NpcInstance		    if (isEventMob)		    {			L2Event.showEventHtml(player, String.valueOf(getObjectId()));		    } else if (_isEventVIPNPCEnd)		    {			VIP.showEndHTML(player, String.valueOf(getObjectId()));		    } else if (_isEventMobCTF)		    {			CTF.showEventHtml(player, String.valueOf(getObjectId()));		    } else		    {			Quest[] qlst = getTemplate().getEventQuests(Quest.QuestEventType.NPC_FIRST_TALK);			if (qlst != null && qlst.length == 1)			{			    qlst[0].notifyFirstTalk(this, player);			} else			{			    showChatWindow(player, 0);			}		    }		}	    } else		player.sendPacket(new ActionFailed());	}    }    /**     * Manage and Display the GM console to modify the L2NpcInstance (GM     * only).<BR>     * <BR>     *     * <B><U> Actions (If the L2PcInstance is a GM only)</U> :</B><BR>     * <BR>     * <li>Set the L2NpcInstance 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>If L2NpcInstance is autoAttackable, send a Server->Client packet     * StatusUpdate to the L2PcInstance in order to update L2NpcInstance HP     * bar </li>     * <li>Send a Server->Client NpcHtmlMessage() containing the GM console     * about this L2NpcInstance </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Each group of     * Server->Client packet must be terminated by a ActionFailed packet in     * order to avoid that client wait an other packet</B></FONT><BR>     * <BR>     *     * <B><U> Example of use </U> :</B><BR>     * <BR>     * <li> Client packet : Action</li>     * <BR>     * <BR>     *     * @param client     *                The thread that manage the player that pessed Shift     *                and click on the L2NpcInstance     *     */    @Override    public void onActionShift(L2GameClient client)    {	// Get the L2PcInstance corresponding to the thread	L2PcInstance player = client.getActiveChar();	if (player == null)	{	    return;	}	// Check if the L2PcInstance is a GM	if (player.getAccessLevel() >= Config.GM_ACCESSLEVEL)	{	    // Set the target of the L2PcInstance player	    player.setTarget(this);	    // Send a Server->Client packet MyTargetSelected to the	    // L2PcInstance	    // player	    // The player.getLevel() - getLevel() permit to display the	    // correct	    // color in the select window	    MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());	    player.sendPacket(my);	    // Check if the player is attackable (without a forced attack)	    if (isAutoAttackable(player))	    {		// Send a Server->Client packet StatusUpdate of the		// L2NpcInstance to the L2PcInstance to update its HP bar		StatusUpdate su = new StatusUpdate(getObjectId());		su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp());		su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());		player.sendPacket(su);	    }	    // Send a Server->Client NpcHtmlMessage() containing the GM	    // console	    // about this L2NpcInstance	    NpcHtmlMessage html = new NpcHtmlMessage(0);	    TextBuilder html1 = new TextBuilder("<html><body><center><font color=\"LEVEL\">NPC Information</font></center>");	    String className = getClass().getName().substring(43);	    html1.append("<br>");	    html1.append("Instance Type: " + className + "<br1>Faction: " + getFactionId() + "<br1>Location ID: " + (getSpawn() != null ? getSpawn().getLocation() : 0) + "<br1>");	    if (this instanceof L2ControllableMobInstance)	    {		html1.append("Mob Group: " + MobGroupTable.getInstance().getGroupForMob((L2ControllableMobInstance) this).getGroupId() + "<br>");	    } else	    {		html1.append("Respawn Time: " + (getSpawn() != null ? getSpawn().getRespawnDelay() / 1000 + "  Seconds<br>" : "?  Seconds<br>"));	    }	    html1.append("<table border=\"0\" width=\"100%\">");	    html1.append("<tr><td>Object ID</td><td>" + getObjectId() + "</td><td>NPC ID</td><td>" + getTemplate().npcId + "</td></tr>");	    html1.append("<tr><td>Castle</td><td>" + getCastle().getCastleId() + "</td><td>Coords</td><td>" + getX() + "," + getY() + "," + getZ() + "</td></tr>");	    html1.append("<tr><td>Level</td><td>" + getLevel() + "</td><td>Aggro</td><td>" + (this instanceof L2Attackable ? ((L2Attackable) this).getAggroRange() : 0) + "</td></tr>");	    html1.append("</table><br>");	    html1.append("<font color=\"LEVEL\">Combat</font>");	    html1.append("<table border=\"0\" width=\"100%\">");	    html1.append("<tr><td>Current HP</td><td>" + getCurrentHp() + "</td><td>Current MP</td><td>" + getCurrentMp() + "</td></tr>");	    html1.append("<tr><td>Max.HP</td><td>" + (int) (getMaxHp() / getStat().calcStat(Stats.MAX_HP, 1, this, null)) + "*" + getStat().calcStat(Stats.MAX_HP, 1, this, null) + "</td><td>Max.MP</td><td>" + getMaxMp() + "</td></tr>");	    html1.append("<tr><td>P.Atk.</td><td>" + getPAtk(null) + "</td><td>M.Atk.</td><td>" + getMAtk(null, null) + "</td></tr>");	    html1.append("<tr><td>P.Def.</td><td>" + getPDef(null) + "</td><td>M.Def.</td><td>" + getMDef(null, null) + "</td></tr>");	    html1.append("<tr><td>Accuracy</td><td>" + getAccuracy() + "</td><td>Evasion</td><td>" + getEvasionRate(null) + "</td></tr>");	    html1.append("<tr><td>Critical</td><td>" + getCriticalHit(null, null) + "</td><td>Speed</td><td>" + getRunSpeed() + "</td></tr>");	    html1.append("<tr><td>Atk.Speed</td><td>" + getPAtkSpd() + "</td><td>Cast.Speed</td><td>" + getMAtkSpd() + "</td></tr>");	    html1.append("</table><br>");	    html1.append("<font color=\"LEVEL\">Basic Stats</font>");	    html1.append("<table border=\"0\" width=\"100%\">");	    html1.append("<tr><td>STR</td><td>" + getSTR() + "</td><td>DEX</td><td>" + getDEX() + "</td><td>CON</td><td>" + getCON() + "</td></tr>");	    html1.append("<tr><td>INT</td><td>" + getINT() + "</td><td>WIT</td><td>" + getWIT() + "</td><td>MEN</td><td>" + getMEN() + "</td></tr>");	    html1.append("</table>");	    html1.append("<br><center><table><tr><td><button value=\"Edit NPC\" action=\"bypass -h admin_edit_npc " + getTemplate().npcId + "\" width=100 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"><br1></td>");	    html1.append("<td><button value=\"Kill\" action=\"bypass -h admin_kill\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td><br1></tr>");	    html1.append("<tr><td><button value=\"Show DropList\" action=\"bypass -h admin_show_droplist " + getTemplate().npcId + "\" width=100 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr>");	    html1.append("<td><button value=\"Delete\" action=\"bypass -h admin_delete\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr>");	    html1.append("</table></center><br>");	    html1.append("</body></html>");	    html.setHtml(html1.toString());	    player.sendPacket(html);	} else if (Config.GAME_VIEWNPC || Config.GAME_VIEWNPC_COMBAT || Config.GAME_VIEWNPC_BASIC || Config.GAME_VIEWNPC_DROP)	{	    // Set the target of the L2PcInstance player	    player.setTarget(this);	    // Send a Server->Client packet MyTargetSelected to the	    // L2PcInstance player	    // The player.getLevel() - getLevel() permit to display the	    // correct color in the select window	    MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());	    player.sendPacket(my);	    // Check if the player is attackable (without a forced attack)	    if (isAutoAttackable(player))	    {		// Send a Server->Client packet StatusUpdate of the		// L2NpcInstance to the L2PcInstance to update its HP bar		StatusUpdate su = new StatusUpdate(getObjectId());		su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp());		su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());		player.sendPacket(su);	    }	    NpcHtmlMessage html = new NpcHtmlMessage(0);	    TextBuilder html1 = new TextBuilder("<html><body>");	    // npc name	    html1.append("<center><font color=\"LEVEL\">[Npc]</font></center><br>");	    html1.append(getName());	    // shows npc combat stats	    if (Config.GAME_VIEWNPC_COMBAT)	    {		html1.append("<br><center><font color=\"LEVEL\">[Combat Stats]</font></center>");		html1.append("<table border=0 width=\"100%\">");		html1.append("<tr><td>Max.HP</td><td>" + (int) (getMaxHp() / getStat().calcStat(Stats.MAX_HP, 1, this, null)) + "*" + (int) getStat().calcStat(Stats.MAX_HP, 1, this, null) + "</td><td>Max.MP</td><td>" + getMaxMp() + "</td></tr>");		html1.append("<tr><td>P.Atk.</td><td>" + getPAtk(null) + "</td><td>M.Atk.</td><td>" + getMAtk(null, null) + "</td></tr>");		html1.append("<tr><td>P.Def.</td><td>" + getPDef(null) + "</td><td>M.Def.</td><td>" + getMDef(null, null) + "</td></tr>");		html1.append("<tr><td>Accuracy</td><td>" + getAccuracy() + "</td><td>Evasion</td><td>" + getEvasionRate(null) + "</td></tr>");		html1.append("<tr><td>Critical</td><td>" + getCriticalHit(null, null) + "</td><td>Speed</td><td>" + getRunSpeed() + "</td></tr>");		html1.append("<tr><td>Atk.Speed</td><td>" + getPAtkSpd() + "</td><td>Cast.Speed</td><td>" + getMAtkSpd() + "</td></tr>");		html1.append("<tr><td>Race</td><td>" + getTemplate().race + "</td><td></td><td></td></tr>");		html1.append("</table>");	    }	    // shows basic stats	    if (Config.GAME_VIEWNPC_BASIC)	    {		html1.append("<br><center><font color=\"LEVEL\">[Basic Stats]</font></center>");		html1.append("<table border=0 width=\"100%\">");		html1.append("<tr><td>STR</td><td>" + getSTR() + "</td><td>DEX</td><td>" + getDEX() + "</td><td>CON</td><td>" + getCON() + "</td></tr>");		html1.append("<tr><td>INT</td><td>" + getINT() + "</td><td>WIT</td><td>" + getWIT() + "</td><td>MEN</td><td>" + getMEN() + "</td></tr>");		html1.append("</table>");	    }	    // shows drop stats	    if (Config.GAME_VIEWNPC_DROP)	    {		html1.append("<br><center><font color=\"LEVEL\">[Drop Info]</font></center>");		html1.append("<br>");		for (L2DropCategory cat : getTemplate().getDropData())		{		    for (L2DropData drop : cat.getAllDrops())		    {			if (!Config.GAME_VIEWNPC_QUESTDROP)			{			    // default info about drop item			    String name = ItemTable.getInstance().getTemplate(drop.getItemId()).getName();			    int chance = drop.getChance(); // drop chance			    int min_qty = drop.getMinDrop(); // min. q-ty			    // of items			    int max_qty = drop.getMaxDrop(); // max. q-ty			    // of items			    // calculating stats using drop-config			    if (drop.getItemId() == 57)			    {				chance *= Config.RATE_DROP_ADENA;				min_qty *= Config.RATE_DROP_ADENA; // temporary				// calculation				max_qty *= Config.RATE_DROP_ADENA; // temporary				// calculation			    } else if (cat.isSweep())			    {				chance *= Config.RATE_DROP_SPOIL;			    } else			    {				chance *= Config.RATE_DROP_ITEMS;			    }			    // chance in percents			    if (chance > drop.MAX_CHANCE)			    {				chance = drop.getChance();			    }			    double percentChance = chance * 0.0001;			    // output line (if min. q-ty = max. q-ty shows			    // only min.)			    html1.append((drop.isQuestDrop() ? "Quest: " : cat.isSweep() ? "Spoil: " : "Drop: ") + name + "   " + percentChance + "%" + "   [" + min_qty + (min_qty == max_qty ? "" : " - " + max_qty) + "]<br1>");			}		    }		}		html1.append("</body></html>");	    }	    html.setHtml(html1.toString());	    player.sendPacket(html);	}	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /** Return the L2Castle this L2NpcInstance belongs to. */    public final Castle getCastle()    {	// Get castle this NPC belongs to (excluding L2Attackable)	if (_castleIndex < 0)	{	    L2TownZone town = TownManager.getInstance().getTown(getX(), getY(), getZ());	    if (town != null)	    {		_castleIndex = CastleManager.getInstance().getCastleIndex(town.getTaxById());	    }	    if (_castleIndex < 0)	    {		_castleIndex = CastleManager.getInstance().findNearestCastleIndex(this);	    } else	    {		_isInTown = true; // Npc was spawned in town	    }	}	if (_castleIndex < 0)	{	    return null;	}	return CastleManager.getInstance().getCastles().get(_castleIndex);    }    public final boolean getIsInTown()    {	if (_castleIndex < 0)	{	    getCastle();	}	return _isInTown;    }    /**     * Open a quest or chat window on client with the text of the     * L2NpcInstance in function of the command.<BR>     * <BR>     *     * <B><U> Example of use </U> :</B><BR>     * <BR>     * <li> Client packet : RequestBypassToServer</li>     * <BR>     * <BR>     *     * @param command     *                The command string received from client     *     */    public void onBypassFeedback(L2PcInstance player, String command)    {        //if (canInteract(player))	{	    if (isBusy() && getBusyMessage().length() > 0)	    {		player.sendPacket(new ActionFailed());		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		html.setFile("data/html/npcbusy.htm");		html.replace("%busymessage%", getBusyMessage());		html.replace("%npcname%", getName());		html.replace("%playername%", player.getName());		player.sendPacket(html);	    } else if (command.equalsIgnoreCase("TerritoryStatus"))	    {		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		{		    if (getCastle().getOwnerId() > 0)		    {			html.setFile("data/html/territorystatus.htm");			L2Clan clan = ClanTable.getInstance().getClan(getCastle().getOwnerId());			html.replace("%clanname%", clan.getName());			html.replace("%clanleadername%", clan.getLeaderName());		    } else		    {			html.setFile("data/html/territorynoclan.htm");		    }		}		html.replace("%castlename%", getCastle().getName());		html.replace("%taxpercent%", "" + getCastle().getTaxPercent());		html.replace("%objectId%", String.valueOf(getObjectId()));		{		    if (getCastle().getCastleId() > 6)		    {			html.replace("%territory%", "The Kingdom of Elmore");		    } else		    {			html.replace("%territory%", "The Kingdom of Aden");		    }		}		player.sendPacket(html);	    } else if (command.startsWith("Quest"))	    {		String quest = "";		try		{		    quest = command.substring(5).trim();		} catch (IndexOutOfBoundsException ioobe)		{		}		if (quest.length() == 0)		{		    showQuestWindow(player);		} else		{		    showQuestWindow(player, quest);		}	    } 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("Link"))	    {		String path = command.substring(5).trim();		if (path.indexOf("..") != -1)		{		    return;		}		String filename = "data/html/" + path;		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		html.setFile(filename);		html.replace("%objectId%", String.valueOf(getObjectId()));		player.sendPacket(html);	    } else if (command.startsWith("NobleTeleport"))	    {		if (!player.isNoble())		{		    String filename = "data/html/teleporter/nobleteleporter-no.htm";		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    html.setFile(filename);		    html.replace("%objectId%", String.valueOf(getObjectId()));		    html.replace("%npcname%", getName());		    player.sendPacket(html);		    return;		}		int val = 0;		try		{		    val = Integer.parseInt(command.substring(5));		} catch (IndexOutOfBoundsException ioobe)		{		} catch (NumberFormatException nfe)		{		}		showChatWindow(player, val);	    } else if (command.startsWith("Loto"))	    {		int val = 0;		try		{		    val = Integer.parseInt(command.substring(5));		} catch (IndexOutOfBoundsException ioobe)		{		} catch (NumberFormatException nfe)		{		}		if (val == 0)		{		    // new loto ticket		    for (int i = 0; i < 5; i++)		    {			player.setLoto(i, 0);		    }		}		showLotoWindow(player, val);	    } else if (command.startsWith("CPRecovery"))	    {		makeCPRecovery(player);	    } else if (command.startsWith("SupportMagic"))	    {		makeSupportMagic(player);	    } else if (command.startsWith("multisell"))	    {		L2Multisell.getInstance().SeparateAndSend(Integer.parseInt(command.substring(9).trim()), player, false, getCastle().getTaxRate());	    } else if (command.startsWith("exc_multisell"))	    {		L2Multisell.getInstance().SeparateAndSend(Integer.parseInt(command.substring(13).trim()), player, true, getCastle().getTaxRate());	    } else if (command.startsWith("Augment"))	    {		int cmdChoice = Integer.parseInt(command.substring(8, 9).trim());		switch (cmdChoice)		{		case 1:		    player.sendPacket(new SystemMessage(SystemMessageId.SELECT_THE_ITEM_TO_BE_AUGMENTED));		    player.sendPacket(new ExShowVariationMakeWindow());		    break;		case 2:		    player.sendPacket(new SystemMessage(SystemMessageId.SELECT_THE_ITEM_FROM_WHICH_YOU_WISH_TO_REMOVE_AUGMENTATION));		    player.sendPacket(new ExShowVariationCancelWindow());		    break;		}	    } else if (command.startsWith("MakeBuffs"))	    {		makeBuffs(player, command.substring(9).trim());	    } else if (command.startsWith("npcfind_byid"))	    {		try		{		    L2Spawn spawn = SpawnTable.getInstance().getTemplate(Integer.parseInt(command.substring(12).trim()));		    if (spawn != null)		    {			player.sendPacket(new RadarControl(0, 1, spawn.getLocx(), spawn.getLocy(), spawn.getLocz()));		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("newbie_give_coupon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getLevel() < 6 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-3.htm");			player.sendPacket(html);		    } else if (player.getCoupon(0))		    {			html.setFile("data/html/adventurers_guide/31760-1.htm");			player.sendPacket(html);		    } else		    {			player.getInventory().addItem("Weapon Coupon", 7832, 1, player, this);			player.addCoupon(1);			html.setFile("data/html/adventurers_guide/31760-2.htm");			player.sendPacket(html);		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("newbie_give_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getLevel() < 6 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-3.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(0)) {		     * html.setFile("data/html/adventurers_guide/31760-1.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10010, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("newbie_return_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getLevel() < 6 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-3.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(0) || !player.isNewbie()) {		     * html.setFile("data/html/adventurers_guide/31760-1.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10011, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("traveller_give_coupon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getClassId().level() != 1 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-6.htm");			player.sendPacket(html);		    } else if (player.getCoupon(1))		    {			html.setFile("data/html/adventurers_guide/31760-4.htm");			player.sendPacket(html);		    } else		    {			player.getInventory().addItem("Weapon Coupon", 7833, 1, player, this);			player.addCoupon(2);			html.setFile("data/html/adventurers_guide/31760-5.htm");			player.sendPacket(html);		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("traveller_give_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getClassId().level() != 1 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-6.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(1)) {		     * html.setFile("data/html/adventurers_guide/31760-4.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10012, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("traveller_return_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getClassId().level() != 1 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-6.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(1)) {		     * html.setFile("data/html/adventurers_guide/31760-4.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10013, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("EnterRift"))	    {		try		{		    Byte b1 = Byte.parseByte(command.substring(10)); // Selected		    // Area:		    // Recruit,		    // Soldier		    // etc		    DimensionalRiftManager.getInstance().start(player, b1, this);		} catch (Exception e)		{		}	    } else if (command.startsWith("ChangeRiftRoom"))	    {		if (player.isInParty() && player.getParty().isInDimensionalRift())		{		    player.getParty().getDimensionalRift().manualTeleport(player, this);		} else		{		    DimensionalRiftManager.getInstance().handleCheat(player, this);		}	    } else if (command.startsWith("ExitRift"))	    {		if (player.isInParty() && player.getParty().isInDimensionalRift())		{		    player.getParty().getDimensionalRift().manualExitRift(player, this);		} else		{		    DimensionalRiftManager.getInstance().handleCheat(player, this);		}	    }	}    }    /**     * Throws an action command to L2BufferInstance.<br>     *     * @param player     *                --> Target player     * @param buffTemplate     *                --> Name of the Buff Template to Add     */    public void makeBuffs(L2PcInstance player, String buffTemplate)    {	int _templateId = 0;	try	{	    _templateId = Integer.parseInt(buffTemplate);	} catch (NumberFormatException e)	{	    _templateId = BuffTemplateTable.getInstance().getTemplateIdByName(buffTemplate);	}	if (_templateId > 0)	{	    L2BufferInstance.makeBuffs(player, _templateId, this, true);	}    }    /**     * Return null (regular NPCs don't have weapons instancies).<BR>     * <BR>     */    @Override    public L2ItemInstance getActiveWeaponInstance()    {	// regular NPCs dont have weapons instancies	return null;    }    /**     * Return the weapon item equiped in the right hand of the L2NpcInstance     * or null.<BR>     * <BR>     */    @Override    public L2Weapon getActiveWeaponItem()    {	// Get the weapon identifier equiped in the right hand of the	// L2NpcInstance	int weaponId = getTemplate().rhand;	if (weaponId < 1)	{	    return null;	}	// Get the weapon item equiped in the right hand of the L2NpcInstance	L2Item item = ItemTable.getInstance().getTemplate(getTemplate().rhand);	if (!(item instanceof L2Weapon))	{	    return null;	}	return (L2Weapon) item;    }    /**     * Return null (regular NPCs don't have weapons instancies).<BR>     * <BR>     */    @Override    public L2ItemInstance getSecondaryWeaponInstance()    {	// regular NPCs dont have weapons instancies	return null;    }    /**     * Return the weapon item equiped in the left hand of the L2NpcInstance     * or null.<BR>     * <BR>     */    @Override    public L2Weapon getSecondaryWeaponItem()    {	// Get the weapon identifier equiped in the right hand of the	// L2NpcInstance	int weaponId = getTemplate().lhand;	if (weaponId < 1)	{	    return null;	}	// Get the weapon item equiped in the right hand of the L2NpcInstance	L2Item item = ItemTable.getInstance().getTemplate(getTemplate().lhand);	if (!(item instanceof L2Weapon))	{	    return null;	}	return (L2Weapon) item;    }    /**     * Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in     * order to display the message of the L2NpcInstance.<BR>     * <BR>     *     * @param player     *                The L2PcInstance who talks with the L2NpcInstance     * @param content     *                The text of the L2NpcMessage     *     */    public void insertObjectIdAndShowChatWindow(L2PcInstance player, String content)    {	// Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in	// order to display the message of the L2NpcInstance	content = content.replaceAll("%objectId%", String.valueOf(getObjectId()));	NpcHtmlMessage npcReply = new NpcHtmlMessage(getObjectId());	npcReply.setHtml(content);	player.sendPacket(npcReply);    }    /**     * Return the pathfile of the selected HTML file in function of the     * npcId and of the page number.<BR>     * <BR>     *     * <B><U> Format of the pathfile </U> :</B><BR>     * <BR>     * <li> if the file exists on the server (page number = 0) :     * <B>data/html/default/12006.htm</B> (npcId-page number)</li>     * <li> if the file exists on the server (page number > 0) :     * <B>data/html/default/12006-1.htm</B> (npcId-page number)</li>     * <li> if the file doesn't exist on the server :     * <B>data/html/npcdefault.htm</B> (message : "I have nothing to say to     * you")</li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2GuardInstance : Set the pathfile to     * data/html/guard/12006-1.htm (npcId-page number)</li>     * <BR>     * <BR>     *     * @param npcId     *                The Identifier of the L2NpcInstance whose text must be     *                display     * @param val     *                The number of the page to display     *     */    public String getHtmlPath(int npcId, int val)    {	String pom = "";	if (val == 0)	{	    pom = "" + npcId;	} else	{	    pom = npcId + "-" + val;	}	String temp = "data/html/default/" + pom + ".htm";	if (!Config.LAZY_CACHE)	{	    // If not running lazy cache the file must be in the cache or it	    // doesnt exist	    if (HtmCache.getInstance().contains(temp))	    {		return temp;	    }	} else	{	    if (HtmCache.getInstance().isLoadable(temp))	    {		return temp;	    }	}	// If the file is not found, the standard message "I have nothing to say	// to you" is returned	return "data/html/npcdefault.htm";    }    /**     * Open a choose quest window on client with all quests available of the     * L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param quests     *                The table containing quests of the L2NpcInstance     *     */    public void showQuestChooseWindow(L2PcInstance player, Quest[] quests)    {	TextBuilder sb = new TextBuilder();	sb.append("<html><body><title>Talk about:</title><br>");	for (Quest q : quests)	{	    sb.append("<a action=\"bypass -h npc_").append(getObjectId()).append("_Quest ").append(q.getName()).append("\">").append(q.getDescr()).append("</a><br>");	}	sb.append("</body></html>");	// Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in	// order to display the message of the L2NpcInstance	insertObjectIdAndShowChatWindow(player, sb.toString());    }    /**     * Open a quest window on client with the text of the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the text of the quest state in the folder     * data/jscript/quests/questId/stateId.htm </li>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <li>Send a Server->Client ActionFailed to the L2PcInstance in order     * to avoid that the client wait another packet </li>     * <BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param questId     *                The Identifier of the quest to display the message     *     */    public void showQuestWindow(L2PcInstance player, String questId)    {	String content;	if (player.getWeightPenalty() >= 3)	{	    player.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_LESS_THAN_80_PERCENT));	    return;	}	// FileInputStream fis = null;	// Get the state of the selected quest	QuestState qs = player.getQuestState(questId);	if (qs != null)	{	    // If the quest is alreday started, no need to show a window	    if (!qs.getQuest().notifyTalk(this, qs))	    {		return;	    }	} else	{	    Quest q = QuestManager.getInstance().getQuest(questId);	    if (q != null)	    {		// check for start point		Quest[] qlst = getTemplate().getEventQuests(Quest.QuestEventType.QUEST_START);		if (qlst != null && qlst.length > 0)		{		    for (int i = 0; i < qlst.length; i++)		    {			if (qlst[i] == q)			{			    qs = q.newQuestState(player);			    // disabled by mr. becouse quest dialog only			    // show on			    // second click.			    // if(qs.getState().getName().equalsIgnoreCase("completed"))			    // {			    if (!qs.getQuest().notifyTalk(this, qs))			    {				return; // no need to show a window			    }			    // }			    break;			}		    }		}	    }	}	if (qs == null)	{	    // no quests found	    content = "<html><body>You are either not carrying out your quest or don't meet the criteria.</body></html>";	} else	{	    questId = qs.getQuest().getName();	    String stateId = qs.getStateId();	    String path = "data/jscript/quests/" + questId + "/" + stateId + ".htm";	    content = HtmCache.getInstance().getHtm(path); // TODO path for	    // quests html	    if (Config.DEBUG)	    {		if (content != null)		{		    _log.fine("Showing quest window for quest " + questId + " html path: " + path);		} else		{		    _log.fine("File not exists for quest " + questId + " html path: " + path);		}	    }	}	// Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in	// order to display the message of the L2NpcInstance	if (content != null)	{	    insertObjectIdAndShowChatWindow(player, content);	}	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /**     * Collect awaiting quests/start points and display a QuestChooseWindow     * (if several available) or QuestWindow.<BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     *     */    public void showQuestWindow(L2PcInstance player)    {	// collect awaiting quests and start points	List<Quest> options = new FastList<Quest>();	QuestState[] awaits = player.getQuestsForTalk(getTemplate().npcId);	Quest[] starts = getTemplate().getEventQuests(Quest.QuestEventType.QUEST_START);	// Quests are limited between 1 and 999 because those are the quests	// that are supported by the client.	// By limitting them there, we are allowed to create custom quests at	// higher IDs without interfering	if (awaits != null)	{	    for (QuestState x : awaits)	    {		if (!options.contains(x))		{		    if (x.getQuest().getQuestIntId() > 0 && x.getQuest().getQuestIntId() < 1000)		    {			options.add(x.getQuest());		    }		}	    }	}	if (starts != null)	{	    for (Quest x : starts)	    {		if (!options.contains(x))		{		    if (x.getQuestIntId() > 0 && x.getQuestIntId() < 1000)		    {			options.add(x);		    }		}	    }	}	// Display a QuestChooseWindow (if several quests are available) or	// QuestWindow	if (options.size() > 1)	{	    showQuestChooseWindow(player, options.toArray(new Quest[options.size()]));	} else if (options.size() == 1)	{	    showQuestWindow(player, options.get(0).getName());	} else	{	    showQuestWindow(player, "");	}    }    /**     * Open a Loto window on client with the text of the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the text of the selected HTML file in function of the npcId     * and of the page number </li>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <li>Send a Server->Client ActionFailed to the L2PcInstance in order     * to avoid that the client wait another packet </li>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param val     *                The number of the page of the L2NpcInstance to display     *     */    // 0 - first buy lottery ticket window    // 1-20 - buttons    // 21 - second buy lottery ticket window    // 22 - selected ticket with 5 numbers    // 23 - current lottery jackpot    // 24 - Previous winning numbers/Prize claim    // >24 - check lottery ticket by item object id    public void showLotoWindow(L2PcInstance player, int val)    {	int npcId = getTemplate().npcId;	String filename;	SystemMessage sm;	NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());	if (val == 0) // 0 - first buy lottery ticket window	{	    filename = getHtmlPath(npcId, 1);	    html.setFile(filename);	} else if (val >= 1 && val <= 21) // 1-20 - buttons, 21 - second	// buy	// lottery ticket window	{	    if (!Lottery.getInstance().isStarted())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_CURRENT_SOLD));		return;	    }	    if (!Lottery.getInstance().isSellableTickets())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_AVAILABLE));		return;	    }	    filename = getHtmlPath(npcId, 5);	    html.setFile(filename);	    int count = 0;	    int found = 0;	    // counting buttons and unsetting button if found	    for (int i = 0; i < 5; i++)	    {		if (player.getLoto(i) == val)		{		    // unsetting button		    player.setLoto(i, 0);		    found = 1;		} else if (player.getLoto(i) > 0)		{		    count++;		}	    }	    // if not rearched limit 5 and not unseted value	    if (count < 5 && found == 0 && val <= 20)	    {		for (int i = 0; i < 5; i++)		{		    if (player.getLoto(i) == 0)		    {			player.setLoto(i, val);			break;		    }		}	    }	    // setting pusshed buttons	    count = 0;	    for (int i = 0; i < 5; i++)	    {		if (player.getLoto(i) > 0)		{		    count++;		    String button = String.valueOf(player.getLoto(i));		    if (player.getLoto(i) < 10)		    {			button = "0" + button;		    }		    String search = "fore=\"L2UI.lottoNum" + button + "\" back=\"L2UI.lottoNum" + button + "a_check\"";		    String replace = "fore=\"L2UI.lottoNum" + button + "a_check\" back=\"L2UI.lottoNum" + button + "\"";		    html.replace(search, replace);		}	    }	    if (count == 5)	    {		String search = "0\">Return";		String replace = "22\">The winner selected the numbers above.";		html.replace(search, replace);	    }	} else if (val == 22) // 22 - selected ticket with 5 numbers	{	    if (!Lottery.getInstance().isStarted())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_CURRENT_SOLD));		return;	    }	    if (!Lottery.getInstance().isSellableTickets())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_AVAILABLE));		return;	    }	    int price = Config.ALT_LOTTERY_TICKET_PRICE;	    int lotonumber = Lottery.getInstance().getId();	    int enchant = 0;	    int type2 = 0;	    for (int i = 0; i < 5; i++)	    {		if (player.getLoto(i) == 0)		{		    return;		}		if (player.getLoto(i) < 17)		{		    enchant += Math.pow(2, player.getLoto(i) - 1);		} else		{		    type2 += Math.pow(2, player.getLoto(i) - 17);		}	    }	    if (player.getAdena() < price)	    {		sm = new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA);		player.sendPacket(sm);		return;	    }	    if (!player.reduceAdena("Loto", price, this, true))	    {		return;	    }	    Lottery.getInstance().increasePrize(price);	    sm = new SystemMessage(SystemMessageId.ACQUIRED);	    sm.addNumber(lotonumber);	    sm.addItemName(4442);	    player.sendPacket(sm);	    L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), 4442);	    item.setCount(1);	    item.setCustomType1(lotonumber);	    item.setEnchantLevel(enchant);	    item.setCustomType2(type2);	    player.getInventory().addItem("Loto", item, player, this);	    InventoryUpdate iu = new InventoryUpdate();	    iu.addItem(item);	    L2ItemInstance adenaupdate = player.getInventory().getItemByItemId(57);	    iu.addModifiedItem(adenaupdate);	    player.sendPacket(iu);	    filename = getHtmlPath(npcId, 3);	    html.setFile(filename);	} else if (val == 23) // 23 - current lottery jackpot	{	    filename = getHtmlPath(npcId, 3);	    html.setFile(filename);	} else if (val == 24) // 24 - Previous winning numbers/Prize	// claim	{	    filename = getHtmlPath(npcId, 4);	    html.setFile(filename);	    int lotonumber = Lottery.getInstance().getId();	    String message = "";	    for (L2ItemInstance item : player.getInventory().getItems())	    {		if (item == null)		{		    continue;		}		if (item.getItemId() == 4442 && item.getCustomType1() < lotonumber)		{		    message = message + "<a action=\"bypass -h npc_%objectId%_Loto " + item.getObjectId() + "\">" + item.getCustomType1() + " Event Number ";		    int[] numbers = Lottery.getInstance().decodeNumbers(item.getEnchantLevel(), item.getCustomType2());		    for (int i = 0; i < 5; i++)		    {			message += numbers[i] + " ";		    }		    int[] check = Lottery.getInstance().checkTicket(item);		    if (check[0] > 0)		    {			switch (check[0])			{			case 1:			    message += "- 1st Prize";			    break;			case 2:			    message += "- 2nd Prize";			    break;			case 3:			    message += "- 3th Prize";			    break;			case 4:			    message += "- 4th Prize";			    break;			}			message += " " + check[1] + "a.";		    }		    message += "</a><br>";		}	    }	    if (message == "")	    {		message += "There is no winning lottery ticket...<br>";	    }	    html.replace("%result%", message);	} else if (val > 24) // >24 - check lottery ticket by	// item object id	{	    int lotonumber = Lottery.getInstance().getId();	    L2ItemInstance item = player.getInventory().getItemByObjectId(val);	    if (item == null || item.getItemId() != 4442 || item.getCustomType1() >= lotonumber)	    {		return;	    }	    int[] check = Lottery.getInstance().checkTicket(item);	    sm = new SystemMessage(SystemMessageId.DISSAPEARED_ITEM);	    sm.addItemName(4442);	    player.sendPacket(sm);	    int adena = check[1];	    if (adena > 0)	    {		player.addAdena("Loto", adena, this, true);	    }	    player.destroyItem("Loto", item, this, false);	    return;	}	html.replace("%objectId%", String.valueOf(getObjectId()));	html.replace("%race%", "" + Lottery.getInstance().getId());	html.replace("%adena%", "" + Lottery.getInstance().getPrize());	html.replace("%ticket_price%", "" + Config.ALT_LOTTERY_TICKET_PRICE);	html.replace("%prize5%", "" + Config.ALT_LOTTERY_5_NUMBER_RATE * 100);	html.replace("%prize4%", "" + Config.ALT_LOTTERY_4_NUMBER_RATE * 100);	html.replace("%prize3%", "" + Config.ALT_LOTTERY_3_NUMBER_RATE * 100);	html.replace("%prize2%", "" + Config.ALT_LOTTERY_2_AND_1_NUMBER_PRIZE);	html.replace("%enddate%", "" + DateFormat.getDateInstance().format(Lottery.getInstance().getEndDate()));	player.sendPacket(html);	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    public void makeCPRecovery(L2PcInstance player)    {	if (getNpcId() != 31225 && getNpcId() != 31226)	{	    return;	}	if (player.isCursedWeaponEquiped())	{	    player.sendMessage("Go away, you're not welcome here.");	    return;	}	int neededmoney = 100;	SystemMessage sm;	if (!player.reduceAdena("RestoreCP", neededmoney, player.getLastFolkNPC(), true))	{	    return;	}	player.setCurrentCp(getCurrentCp() + 5000);	// cp restored	sm = new SystemMessage(SystemMessageId.S1_CP_WILL_BE_RESTORED);	sm.addString(player.getName());	player.sendPacket(sm);    }    /**     * Add Newbie helper buffs to L2Player according to its level.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the range level in wich player must be to obtain buff </li>     * <li>If player level is out of range, display a message and return     * </li>     * <li>According to player level cast buff </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> Newbie Helper Buff list is define in sql     * table helper_buff_list</B></FONT><BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     *     */    public void makeSupportMagic(L2PcInstance player)    {	if (player == null)	{	    return;	}	// Prevent a cursed weapon weilder of being buffed	if (player.isCursedWeaponEquiped())	{	    return;	}	int player_level = player.getLevel();	int lowestLevel = 0;	int higestLevel = 0;	// Select the player	setTarget(player);	// Calculate the min and max level between wich the player must be to	// obtain buff	if (player.isMageClass())	{	    lowestLevel = HelperBuffTable.getInstance().getMagicClassLowestLevel();	    higestLevel = HelperBuffTable.getInstance().getMagicClassHighestLevel();	} else	{	    lowestLevel = HelperBuffTable.getInstance().getPhysicClassLowestLevel();	    higestLevel = HelperBuffTable.getInstance().getPhysicClassHighestLevel();	}	// If the player is too high level, display a message and return	if (player_level > higestLevel || !player.isNewbie())	{	    String content = "<html><body>Newbie Guide:<br>Only a <font color=\"LEVEL\">novice character of level " + higestLevel + " or less</font> can receive my support magic.<br>Your novice character is the first one that you created and raised in this world.</body></html>";	    insertObjectIdAndShowChatWindow(player, content);	    return;	}	// If the player is too low level, display a message and return	if (player_level < lowestLevel)	{	    String content = "<html><body>Come back here when you have reached level " + lowestLevel + ". I will give you support magic then.</body></html>";	    insertObjectIdAndShowChatWindow(player, content);	    return;	}	L2Skill skill = null;	// Go through the Helper Buff list define in sql table helper_buff_list	// and cast skill	for (L2HelperBuff helperBuffItem : HelperBuffTable.getInstance().getHelperBuffTable())	{	    if (helperBuffItem.isMagicClassBuff() == player.isMageClass())	    {		if (player_level >= helperBuffItem.getLowerLevel() && player_level <= helperBuffItem.getUpperLevel())		{		    skill = SkillTable.getInstance().getInfo(helperBuffItem.getSkillID(), helperBuffItem.getSkillLevel());		    if (skill.getSkillType() == SkillType.SUMMON)		    {			player.doCast(skill);		    } else		    {			doCast(skill);		    }		}	    }	}    }    public void showChatWindow(L2PcInstance player)    {	showChatWindow(player, 0);    }    /**     * Returns true if html exists     *     * @param player     * @param type     * @return boolean     */    private boolean showPkDenyChatWindow(L2PcInstance player, String type)    {	String html = HtmCache.getInstance().getHtm("data/html/" + type + "/" + getNpcId() + "-pk.htm");	if (html != null)	{	    NpcHtmlMessage pkDenyMsg = new NpcHtmlMessage(getObjectId());	    pkDenyMsg.setHtml(html);	    player.sendPacket(pkDenyMsg);	    player.sendPacket(new ActionFailed());	    return true;	}	return false;    }    /**     * Open a chat window on client with the text of the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the text of the selected HTML file in function of the npcId     * and of the page number </li>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <li>Send a Server->Client ActionFailed to the L2PcInstance in order     * to avoid that the client wait another packet </li>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param val     *                The number of the page of the L2NpcInstance to display     *     */    public void showChatWindow(L2PcInstance player, int val)    {	if (player.getKarma() > 0)	{	    if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && this instanceof L2MerchantInstance)	    {		if (showPkDenyChatWindow(player, "merchant"))		{		    return;		}	    } else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_GK && this instanceof L2TeleporterInstance)	    {		if (showPkDenyChatWindow(player, "teleporter"))		{		    return;		}	    } else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE && this instanceof L2WarehouseInstance)	    {		if (showPkDenyChatWindow(player, "warehouse"))		{		    return;		}	    } else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && this instanceof L2FishermanInstance)	    {		if (showPkDenyChatWindow(player, "fisherman"))		{		    return;		}	    }	}	if (getTemplate().type == "L2Auctioneer" && val == 0)	{	    return;	}	int npcId = getTemplate().npcId;	/* For use with Seven Signs implementation */	String filename = SevenSigns.SEVEN_SIGNS_HTML_PATH;	int sealAvariceOwner = SevenSigns.getInstance().getSealOwner(SevenSigns.SEAL_AVARICE);	int sealGnosisOwner = SevenSigns.getInstance().getSealOwner(SevenSigns.SEAL_GNOSIS);	int playerCabal = SevenSigns.getInstance().getPlayerCabal(player);	boolean isSealValidationPeriod = SevenSigns.getInstance().isSealValidationPeriod();	int compWinner = SevenSigns.getInstance().getCabalHighestScore();	switch (npcId)	{	case 31078:	case 31079:	case 31080:	case 31081:	case 31082: // Dawn Priests	case 31083:	case 31084:	case 31168:	case 31692:	case 31694:	case 31997:	    switch (playerCabal)	    {	    case SevenSigns.CABAL_DAWN:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DAWN)		    {			if (compWinner != sealGnosisOwner)			{			    filename += "dawn_priest_2c.htm";			} else			{			    filename += "dawn_priest_2a.htm";			}		    } else		    {			filename += "dawn_priest_2b.htm";		    }		} else		{		    filename += "dawn_priest_1b.htm";		}		break;	    case SevenSigns.CABAL_DUSK:		if (isSealValidationPeriod)		{		    filename += "dawn_priest_3b.htm";		} else		{		    filename += "dawn_priest_3a.htm";		}		break;	    default:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DAWN)		    {			filename += "dawn_priest_4.htm";		    } else		    {			filename += "dawn_priest_2b.htm";		    }		} else		{		    filename += "dawn_priest_1a.htm";		}		break;	    }	    break;	case 31085:	case 31086:	case 31087:	case 31088: // Dusk Priest	case 31089:	case 31090:	case 31091:	case 31169:	case 31693:	case 31695:	case 31998:	    switch (playerCabal)	    {	    case SevenSigns.CABAL_DUSK:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DUSK)		    {			if (compWinner != sealGnosisOwner)			{			    filename += "dusk_priest_2c.htm";			} else			{			    filename += "dusk_priest_2a.htm";			}		    } else		    {			filename += "dusk_priest_2b.htm";		    }		} else		{		    filename += "dusk_priest_1b.htm";		}		break;	    case SevenSigns.CABAL_DAWN:		if (isSealValidationPeriod)		{		    filename += "dusk_priest_3b.htm";		} else		{		    filename += "dusk_priest_3a.htm";		}		break;	    default:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DUSK)		    {			filename += "dusk_priest_4.htm";		    } else		    {			filename += "dusk_priest_2b.htm";		    }		} else		{		    filename += "dusk_priest_1a.htm";		}		break;	    }	    break;	case 31095: //	case 31096: //	case 31097: //	case 31098: // Enter Necropolises	case 31099: //	case 31100: //	case 31101: //	case 31102: //	    if (isSealValidationPeriod)	    {		if (playerCabal != compWinner || sealAvariceOwner != compWinner)		{		    switch (compWinner)		    {		    case SevenSigns.CABAL_DAWN:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));			filename += "necro_no.htm";			break;		    case SevenSigns.CABAL_DUSK:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));			filename += "necro_no.htm";			break;		    case SevenSigns.CABAL_NULL:			filename = getHtmlPath(npcId, val); // do			// the			// default!			break;		    }		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    } else	    {		if (playerCabal == SevenSigns.CABAL_NULL)		{		    filename += "necro_no.htm";		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    }	    break;	case 31114: //	case 31115: //	case 31116: // Enter Catacombs	case 31117: //	case 31118: //	case 31119: //	    if (isSealValidationPeriod)	    {		if (playerCabal != compWinner || sealGnosisOwner != compWinner)		{		    switch (compWinner)		    {		    case SevenSigns.CABAL_DAWN:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));			filename += "cata_no.htm";			break;		    case SevenSigns.CABAL_DUSK:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));			filename += "cata_no.htm";			break;		    case SevenSigns.CABAL_NULL:			filename = getHtmlPath(npcId, val); // do			// the			// default!			break;		    }		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    } else	    {		if (playerCabal == SevenSigns.CABAL_NULL)		{		    filename += "cata_no.htm";		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    }	    break;	case 31111: // Gatekeeper Spirit (Disciples)	    if (playerCabal == sealAvariceOwner && playerCabal == compWinner)	    {		switch (sealAvariceOwner)		{		case SevenSigns.CABAL_DAWN:		    filename += "spirit_dawn.htm";		    break;		case SevenSigns.CABAL_DUSK:		    filename += "spirit_dusk.htm";		    break;		case SevenSigns.CABAL_NULL:		    filename += "spirit_null.htm";		    break;		}	    } else	    {		filename += "spirit_null.htm";	    }	    break;	case 31112: // Gatekeeper Spirit (Disciples)	    filename += "spirit_exit.htm";	    break;	case 31127: //	case 31128: //	case 31129: // Dawn Festival Guides	case 31130: //	case 31131: //	    filename += "festival/dawn_guide.htm";	    break;	case 31137: //	case 31138: //	case 31139: // Dusk Festival Guides	case 31140: //	case 31141: //	    filename += "festival/dusk_guide.htm";	    break;	case 31092: // Black Marketeer of Mammon	    filename += "blkmrkt_1.htm";	    break;	case 31113: // Merchant of Mammon	    switch (compWinner)	    {	    case SevenSigns.CABAL_DAWN:		if (playerCabal != compWinner || playerCabal != sealAvariceOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));		    return;		}		break;	    case SevenSigns.CABAL_DUSK:		if (playerCabal != compWinner || playerCabal != sealAvariceOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));		    return;		}		break;	    }	    filename += "mammmerch_1.htm";	    break;	case 31126: // Blacksmith of Mammon	    switch (compWinner)	    {	    case SevenSigns.CABAL_DAWN:		if (playerCabal != compWinner || playerCabal != sealGnosisOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));		    return;		}		break;	    case SevenSigns.CABAL_DUSK:		if (playerCabal != compWinner || playerCabal != sealGnosisOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));		    return;		}		break;	    }	    filename += "mammblack_1.htm";	    break;	case 31132:	case 31133:	case 31134:	case 31135:	case 31136: // Festival Witches	case 31142:	case 31143:	case 31144:	case 31145:	case 31146:	    filename += "festival/festival_witch.htm";	    break;	case 31688:	    if (player.isNoble())	    {		filename = Olympiad.OLYMPIAD_HTML_FILE + "noble_main.htm";	    } else	    {		filename = getHtmlPath(npcId, val);	    }	    break;	case 31690:	case 31769:	case 31770:	case 31771:	case 31772:	    if (player.isHero())	    {		filename = Olympiad.OLYMPIAD_HTML_FILE + "hero_main.htm";	    } else	    {		filename = getHtmlPath(npcId, val);	    }	    break;	default:	    if (npcId >= 31865 && npcId <= 31918)	    {		filename += "rift/GuardianOfBorder.htm";		break;	    }	    if (npcId >= 31093 && npcId <= 31094 || npcId >= 31172 && npcId <= 31201 || npcId >= 31239 && npcId <= 31254)	    {		return;	    }	    // Get the text of the selected HTML file in function of the	    // npcId and of the page number	    filename = getHtmlPath(npcId, val);	    break;	}	// Send a Server->Client NpcHtmlMessage containing the text of the	// L2NpcInstance to the L2PcInstance	NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());	html.setFile(filename);	// String word = "npc-"+npcId+(val>0 ? "-"+val : "" )+"-dialog-append";	if (this instanceof L2MerchantInstance)	{	    if (Config.LIST_PET_RENT_NPC.contains(npcId))	    {		html.replace("_Quest", "_RentPet\">Rent Pet</a><br><a action=\"bypass -h npc_%objectId%_Quest");	    }	}	html.replace("%objectId%", String.valueOf(getObjectId()));	html.replace("%festivalMins%", SevenSignsFestival.getInstance().getTimeToNextFestivalStr());	player.sendPacket(html);	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /**     * Open a chat window on client with the text specified by the given     * file name and path,<BR>     * relative to the datapack root. <BR>     * <BR>     * Added by Tempy     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param filename     *                The filename that contains the text to send     *     */    public void showChatWindow(L2PcInstance player, String filename)    {	// Send a Server->Client NpcHtmlMessage containing the text of the	// L2NpcInstance to the L2PcInstance	NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());	html.setFile(filename);	html.replace("%objectId%", String.valueOf(getObjectId()));	player.sendPacket(html);	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /**     * Return the Exp Reward of this L2NpcInstance contained in the     * L2NpcTemplate (modified by RATE_XP).<BR>     * <BR>     */    public int getExpReward()    {	double rateXp = getStat().calcStat(Stats.MAX_HP, 1, this, null);	return (int) (getTemplate().rewardExp * rateXp * Config.RATE_XP);    }    /**     * Return the SP Reward of this L2NpcInstance contained in the     * L2NpcTemplate (modified by RATE_SP).<BR>     * <BR>     */    public int getSpReward()    {	double rateSp = getStat().calcStat(Stats.MAX_HP, 1, this, null);	return (int) (getTemplate().rewardSp * rateSp * Config.RATE_SP);    }    /**     * Kill the L2NpcInstance (the corpse disappeared after 7 seconds).<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Create a DecayTask to remove the corpse of the L2NpcInstance     * after 7 seconds </li>     * <li>Set target to null and cancel Attack or Cast </li>     * <li>Stop movement </li>     * <li>Stop HP/MP/CP Regeneration task </li>     * <li>Stop all active skills effects in progress on the L2Character     * </li>     * <li>Send the Server->Client packet StatusUpdate with current HP and     * MP to all other L2PcInstance to inform </li>     * <li>Notify L2Character AI </li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2Attackable </li>     * <BR>     * <BR>     *     * @param killer     *                The L2Character who killed it     *     */    @Override    public boolean doDie(L2Character killer)    {	if (!super.doDie(killer))	{	    return false;	}	    // normally this wouldn't really be needed, but for those few exceptions,    // we do need to reset the weapons back to the initial templated weapon.	_currentLHandId = getTemplate().lhand;	_currentRHandId = getTemplate().rhand;		DecayTaskManager.getInstance().addDecayTask(this);	return true;    }    /**     * Set the spawn of the L2NpcInstance.<BR>     * <BR>     *     * @param spawn     *                The L2Spawn that manage the L2NpcInstance     *     */    public void setSpawn(L2Spawn spawn)    {	_spawn = spawn;    }    @Override    public void onSpawn()    {	super.onSpawn();    }    /**     * Remove the L2NpcInstance from the world and update its spawn object     * (for a complete removal use the deleteMe method).<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Remove the L2NpcInstance from the world when the decay task is     * launched </li>     * <li>Decrease its spawn counter </li>     * <li>Manage Siege task (killFlag, killCT) </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T REMOVE     * the object from _allObjects of L2World </B></FONT><BR>     * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND     * Server->Client packets to players</B></FONT><BR>     * <BR>     *     */    @Override    public void onDecay()    {	if (isDecayed())	{	    return;	}	setDecayed(true);	// Manage Life Control Tower	if (this instanceof L2ControlTowerInstance)	{	    ((L2ControlTowerInstance) this).onDeath();	}	// Remove the L2NpcInstance from the world when the decay task is	// launched	super.onDecay();	// Decrease its spawn counter	if (_spawn != null)	{	    _spawn.decreaseCount(this);	}    }    /**     * Remove PROPERLY the L2NpcInstance from the world.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Remove the L2NpcInstance from the world and update its spawn     * object </li>     * <li>Remove all L2Object from _knownObjects and _knownPlayer of the     * L2NpcInstance then cancel Attak or Cast and notify AI </li>     * <li>Remove L2Object object from _allObjects of L2World </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND     * Server->Client packets to players</B></FONT><BR>     * <BR>     *     */    public void deleteMe()    {	if (getWorldRegion() != null)	{	    getWorldRegion().removeFromZones(this);	    // FIXME this is just a temp hack, we should find a better	    // solution	}	try	{	    decayMe();	} catch (Throwable t)	{	    _log.severe("deletedMe(): " + t);	}	// Remove all L2Object from _knownObjects and _knownPlayer of the	// L2Character then cancel Attak or Cast and notify AI	try	{	    getKnownList().removeAllKnownObjects();	} catch (Throwable t)	{	    _log.severe("deletedMe(): " + t);	}	// Remove L2Object object from _allObjects of L2World	L2World.getInstance().removeObject(this);    }    /**     * Return the L2Spawn object that manage this L2NpcInstance.<BR>     * <BR>     */    public L2Spawn getSpawn()    {	return _spawn;    }    @Override    public String toString()    {	return getTemplate().name;    }    public boolean isDecayed()    {	return _isDecayed;    }    public void setDecayed(boolean decayed)    {	_isDecayed = decayed;    }    public void endDecayTask()    {	if (!isDecayed())	{	    DecayTaskManager.getInstance().cancelDecayTask(this);	    onDecay();	}    }    public boolean isMob() // rather delete this check    {	return false; // This means we use MAX_NPC_ANIMATION instead of	// MAX_MONSTER_ANIMATION    }       	    // Two functions to change the appearance of the equipped weapons on the NPC 	    // This is only useful for a few NPCs and is most likely going to be called from AI 	    public void setLHandId(int newWeaponId) 	    { 	        _currentLHandId = newWeaponId; 	    } 	    public void setRHandId(int newWeaponId) 	    { 	        _currentRHandId = newWeaponId; 	    }     }/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * http://www.gnu.org/copyleft/gpl.html */package net.sf.l2j.gameserver.model.actor.instance;import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;import java.text.DateFormat;import java.util.List;import javolution.text.TextBuilder;import javolution.util.FastList;import net.sf.l2j.Config;import net.sf.l2j.gameserver.Olympiad;import net.sf.l2j.gameserver.SevenSigns;import net.sf.l2j.gameserver.SevenSignsFestival;import net.sf.l2j.gameserver.ThreadPoolManager;import net.sf.l2j.gameserver.ai.CtrlIntention;import net.sf.l2j.gameserver.cache.HtmCache;import net.sf.l2j.gameserver.datatables.BuffTemplateTable;import net.sf.l2j.gameserver.datatables.ClanTable;import net.sf.l2j.gameserver.datatables.HelperBuffTable;import net.sf.l2j.gameserver.datatables.ItemTable;import net.sf.l2j.gameserver.datatables.SkillTable;import net.sf.l2j.gameserver.datatables.SpawnTable;import net.sf.l2j.gameserver.idfactory.IdFactory;import net.sf.l2j.gameserver.instancemanager.CastleManager;import net.sf.l2j.gameserver.instancemanager.DimensionalRiftManager;import net.sf.l2j.gameserver.instancemanager.QuestManager;import net.sf.l2j.gameserver.instancemanager.TownManager;import net.sf.l2j.gameserver.instancemanager.games.Lottery;import net.sf.l2j.gameserver.model.L2Attackable;import net.sf.l2j.gameserver.model.L2Character;import net.sf.l2j.gameserver.model.L2Clan;import net.sf.l2j.gameserver.model.L2DropCategory;import net.sf.l2j.gameserver.model.L2DropData;import net.sf.l2j.gameserver.model.L2ItemInstance;import net.sf.l2j.gameserver.model.L2Multisell;import net.sf.l2j.gameserver.model.L2Object;import net.sf.l2j.gameserver.model.L2Skill;import net.sf.l2j.gameserver.model.L2Spawn;import net.sf.l2j.gameserver.model.L2Summon;import net.sf.l2j.gameserver.model.L2World;import net.sf.l2j.gameserver.model.MobGroupTable;import net.sf.l2j.gameserver.model.L2Skill.SkillType;import net.sf.l2j.gameserver.model.actor.knownlist.NpcKnownList;import net.sf.l2j.gameserver.model.actor.stat.NpcStat;import net.sf.l2j.gameserver.model.actor.status.NpcStatus;import net.sf.l2j.gameserver.model.entity.Castle;import net.sf.l2j.gameserver.model.entity.L2Event;import net.sf.l2j.gameserver.model.entity.L2JOneoEvents.CTF;import net.sf.l2j.gameserver.model.entity.L2JOneoEvents.VIP;import net.sf.l2j.gameserver.model.quest.Quest;import net.sf.l2j.gameserver.model.quest.QuestState;import net.sf.l2j.gameserver.model.zone.type.L2TownZone;import net.sf.l2j.gameserver.network.L2GameClient;import net.sf.l2j.gameserver.network.SystemMessageId;import net.sf.l2j.gameserver.serverpackets.ActionFailed;import net.sf.l2j.gameserver.serverpackets.ExShowVariationCancelWindow;import net.sf.l2j.gameserver.serverpackets.ExShowVariationMakeWindow;import net.sf.l2j.gameserver.serverpackets.InventoryUpdate;import net.sf.l2j.gameserver.serverpackets.MyTargetSelected;import net.sf.l2j.gameserver.serverpackets.NpcHtmlMessage;import net.sf.l2j.gameserver.serverpackets.NpcInfo;import net.sf.l2j.gameserver.serverpackets.RadarControl;import net.sf.l2j.gameserver.serverpackets.SocialAction;import net.sf.l2j.gameserver.serverpackets.StatusUpdate;import net.sf.l2j.gameserver.serverpackets.SystemMessage;import net.sf.l2j.gameserver.serverpackets.ValidateLocation;import net.sf.l2j.gameserver.skills.Stats;import net.sf.l2j.gameserver.taskmanager.DecayTaskManager;import net.sf.l2j.gameserver.templates.L2HelperBuff;import net.sf.l2j.gameserver.templates.L2Item;import net.sf.l2j.gameserver.templates.L2NpcTemplate;import net.sf.l2j.gameserver.templates.L2Weapon;import net.sf.l2j.util.Rnd;/** * This class represents a Non-Player-Character in the world. It can be a * monster or a friendly character. It also uses a template to fetch some static * values. The templates are hardcoded in the client, so we can rely on them.<BR> * <BR> * * L2Character :<BR> * <BR> * <li>L2Attackable</li> * <li>L2BoxInstance</li> * <li>L2FolkInstance</li> * * @version $Revision: 1.32.2.7.2.24 $ $Date: 2005/04/11 10:06:09 $ */public class L2NpcInstance extends L2Character{    // private static Logger _log =    // Logger.getLogger(L2NpcInstance.class.getName());    /**     * The interaction distance of the L2NpcInstance(is used as offset in     * MovetoLocation method)     */    public static final int INTERACTION_DISTANCE = 150;    /** The L2Spawn object that manage this L2NpcInstance */    private L2Spawn _spawn;    /** The flag to specify if this L2NpcInstance is busy */    private boolean _isBusy = false;    /** The busy message for this L2NpcInstance */    private String _busyMessage = "";    /** true if endDecayTask has already been called */    volatile boolean _isDecayed = false;    /** true if a Dwarf has used Spoil on this L2NpcInstance */    private boolean _isSpoil = false;    /**     * The castle index in the array of L2Castle this L2NpcInstance belongs     * to     */    private int _castleIndex = -2;    public boolean isEventMob = false, _isEventVIPNPC = false,	    _isEventVIPNPCEnd = false;    public boolean _isEventMobCTF = false;    public boolean isPrivateEventMob = false;    private boolean _isInTown = false;    private int _isSpoiledBy = 0;    protected RandomAnimationTask _rAniTask = null;    private int _currentLHandId;  // normally this shouldn't change from the template, but there exist exceptions 	private int _currentRHandId;  // normally this shouldn't change from the template, but there exist exceptions     /** Task launching the function onRandomAnimation() */    protected class RandomAnimationTask implements Runnable    {	public void run()	{	    try	    {		if (this != _rAniTask)		{		    return; // Shouldn't happen, but who knows... just to		    // make		    // sure every active npc has only one timer.		}		if (isMob())		{		    // Cancel further animation timers until intention is		    // changed to ACTIVE again.		    if (getAI().getIntention() != AI_INTENTION_ACTIVE)		    {			return;		    }		} else		{		    if (!isInActiveRegion())		    {			return;		    }		    // update knownlist to remove playable which aren't in		    // range		    // any more		    getKnownList().updateKnownObjects();		}		if (!(isDead() || isStunned() || isSleeping() || isParalyzed()))		{		    onRandomAnimation();		}		startRandomAnimationTimer();	    } catch (Throwable t)	    {	    }	}    }    /**     * Send a packet SocialAction to all L2PcInstance in the _KnownPlayers     * of the L2NpcInstance and create a new RandomAnimation Task.<BR>     * <BR>     */    public void onRandomAnimation()    {	// Send a packet SocialAction to all L2PcInstance in the _KnownPlayers	// of the L2NpcInstance	SocialAction sa = new SocialAction(getObjectId(), Rnd.get(2, 3));	broadcastPacket(sa);    }    /**     * Create a RandomAnimation Task that will be launched after the     * calculated delay.<BR>     * <BR>     */    public void startRandomAnimationTimer()    {	if (!hasRandomAnimation())	{	    return;	}	int minWait = isMob() ? Config.MIN_MONSTER_ANIMATION : Config.MIN_NPC_ANIMATION;	int maxWait = isMob() ? Config.MAX_MONSTER_ANIMATION : Config.MAX_NPC_ANIMATION;	// Calculate the delay before the next animation	int interval = Rnd.get(minWait, maxWait) * 1000;	// Create a RandomAnimation Task that will be launched after the	// calculated delay	_rAniTask = new RandomAnimationTask();	ThreadPoolManager.getInstance().scheduleGeneral(_rAniTask, interval);    }    /**     * Check if the server allows Random Animation.<BR>     * <BR>     */    public boolean hasRandomAnimation()    {	return Config.MAX_NPC_ANIMATION > 0;    }    public class destroyTemporalNPC implements Runnable    {	private L2Spawn _oldSpawn;	public destroyTemporalNPC(L2Spawn spawn)	{	    _oldSpawn = spawn;	}	public void run()	{	    try	    {		_oldSpawn.getLastSpawn().deleteMe();		_oldSpawn.stopRespawn();		SpawnTable.getInstance().deleteSpawn(_oldSpawn, false);	    } catch (Throwable t)	    {		t.printStackTrace();	    }	}    }    public class destroyTemporalSummon implements Runnable    {	L2Summon _summon;	L2PcInstance _player;	public destroyTemporalSummon(L2Summon summon, L2PcInstance player)	{	    _summon = summon;	    _player = player;	}	public void run()	{	    _summon.unSummon(_player);	}    }    /**     * Constructor of L2NpcInstance (use L2Character constructor).<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Call the L2Character constructor to set the _template of the     * L2Character (copy skills from template to object and link     * _calculators to NPC_STD_CALCULATOR) </li>     * <li>Set the name of the L2Character</li>     * <li>Create a RandomAnimation Task that will be launched after the     * calculated delay if the server allow it </li>     * <BR>     * <BR>     *     * @param objectId     *                Identifier of the object to initialized     * @param template     *                The L2NpcTemplate to apply to the NPC     *     */    public L2NpcInstance(int objectId, L2NpcTemplate template)    {	// Call the L2Character constructor to set the _template of the	// L2Character, copy skills from template to object	// and link _calculators to NPC_STD_CALCULATOR	super(objectId, template);	getKnownList(); // init knownlist	getStat(); // init stats	getStatus(); // init status	initCharStatusUpdateValues();    // initialize the "current" equipment 	_currentLHandId = getTemplate().lhand;	_currentRHandId = getTemplate().rhand;		if (template == null)	{	    _log.severe("No template for Npc. Please check your datapack is setup correctly.");	    return;	}	// Set the name of the L2Character	setName(template.name);    }    @Override    public NpcKnownList getKnownList()    {	if (super.getKnownList() == null || !(super.getKnownList() instanceof NpcKnownList))	{	    setKnownList(new NpcKnownList(this));	}	return (NpcKnownList) super.getKnownList();    }    @Override    public NpcStat getStat()    {	if (super.getStat() == null || !(super.getStat() instanceof NpcStat))	{	    setStat(new NpcStat(this));	}	return (NpcStat) super.getStat();    }    @Override    public NpcStatus getStatus()    {	if (super.getStatus() == null || !(super.getStatus() instanceof NpcStatus))	{	    setStatus(new NpcStatus(this));	}	return (NpcStatus) super.getStatus();    }    /** Return the L2NpcTemplate of the L2NpcInstance. */    @Override    public final L2NpcTemplate getTemplate()    {	return (L2NpcTemplate) super.getTemplate();    }    /**     * Return the generic Identifier of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    public int getNpcId()    {	return getTemplate().npcId;    }    @Override    public boolean isAttackable()    {	return false;    }    /**     * Return the faction Identifier of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     *     * <B><U> Concept</U> :</B><BR>     * <BR>     * If a NPC belows to a Faction, other NPC of the faction inside the     * Faction range will help it if it's attacked<BR>     * <BR>     *     */    public final String getFactionId()    {	return getTemplate().factionId;    }    /**     * Return the Level of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    @Override    public final int getLevel()    {	return getTemplate().level;    }    /**     * Return true if the L2NpcInstance is agressive (ex : L2MonsterInstance     * in function of aggroRange).<BR>     * <BR>     */    public boolean isAggressive()    {	return false;    }    /**     * Return the Aggro Range of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    public int getAggroRange()    {	return getTemplate().aggroRange;    }    /**     * Return the Faction Range of this L2NpcInstance contained in the     * L2NpcTemplate.<BR>     * <BR>     */    public int getFactionRange()    {	return getTemplate().factionRange;    }    /**     * Return true if this L2NpcInstance is undead in function of the     * L2NpcTemplate.<BR>     * <BR>     */    @Override    public boolean isUndead()    {	return getTemplate().isUndead;    }    /**     * Send a packet NpcInfo with state of abnormal effect to all     * L2PcInstance in the _KnownPlayers of the L2NpcInstance.<BR>     * <BR>     */    @Override    public void updateAbnormalEffect()    {	// NpcInfo info = new NpcInfo(this);	// broadcastPacket(info);	// Send a Server->Client packet NpcInfo with state of abnormal effect to	// all L2PcInstance in the _KnownPlayers of the L2NpcInstance	for (L2PcInstance player : getKnownList().getKnownPlayers().values())	{	    if (player != null)	    {		player.sendPacket(new NpcInfo(this, player));	    }	}    }    /**     * Return the distance under which the object must be add to     * _knownObject in function of the object type.<BR>     * <BR>     *     * <B><U> Values </U> :</B><BR>     * <BR>     * <li> object is a L2FolkInstance : 0 (don't remember it) </li>     * <li> object is a L2Character : 0 (don't remember it) </li>     * <li> object is a L2PlayableInstance : 1500 </li>     * <li> others : 500 </li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2Attackable</li>     * <BR>     * <BR>     *     * @param object     *                The Object to add to _knownObject     *     */    public int getDistanceToWatchObject(L2Object object)    {	if (object instanceof L2FestivalGuideInstance)	{	    return 10000;	}	if (object instanceof L2FolkInstance || !(object instanceof L2Character))	{	    return 0;	}	if (object instanceof L2PlayableInstance)	{	    return 1500;	}	return 500;    }    /**     * Return the distance after which the object must be remove from     * _knownObject in function of the object type.<BR>     * <BR>     *     * <B><U> Values </U> :</B><BR>     * <BR>     * <li> object is not a L2Character : 0 (don't remember it) </li>     * <li> object is a L2FolkInstance : 0 (don't remember it)</li>     * <li> object is a L2PlayableInstance : 3000 </li>     * <li> others : 1000 </li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2Attackable</li>     * <BR>     * <BR>     *     * @param object     *                The Object to remove from _knownObject     *     */    public int getDistanceToForgetObject(L2Object object)    {	return 2 * getDistanceToWatchObject(object);    }    /**     * Return false.<BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2MonsterInstance : Check if the attacker is not another     * L2MonsterInstance</li>     * <li> L2PcInstance</li>     * <BR>     * <BR>     */    @Override    public boolean isAutoAttackable(@SuppressWarnings("unused")    L2Character attacker)    {	return false;    }    /**     * Return the Identifier of the item in the left hand of this     * L2NpcInstance contained in the L2NpcTemplate.<BR>     * <BR>     */    public int getLeftHandItem()    {	return _currentLHandId;    }    /**     * Return the Identifier of the item in the right hand of this     * L2NpcInstance contained in the L2NpcTemplate.<BR>     * <BR>     */    public int getRightHandItem()    {	return _currentRHandId;    }    /**     * Return true if this L2NpcInstance has drops that can be sweeped.<BR>     * <BR>     */    public boolean isSpoil()    {	return _isSpoil;    }    /**     * Set the spoil state of this L2NpcInstance.<BR>     * <BR>     */    public void setSpoil(boolean isSpoil)    {	_isSpoil = isSpoil;    }    public final int getIsSpoiledBy()    {	return _isSpoiledBy;    }    public final void setIsSpoiledBy(int value)    {	_isSpoiledBy = value;    }    /**     * Return the busy status of this L2NpcInstance.<BR>     * <BR>     */    public final boolean isBusy()    {	return _isBusy;    }    /**     * Set the busy status of this L2NpcInstance.<BR>     * <BR>     */    public void setBusy(boolean isBusy)    {	_isBusy = isBusy;    }    /**     * Return the busy message of this L2NpcInstance.<BR>     * <BR>     */    public final String getBusyMessage()    {	return _busyMessage;    }    /**     * Set the busy message of this L2NpcInstance.<BR>     * <BR>     */    public void setBusyMessage(String message)    {	_busyMessage = message;    }    protected boolean canTarget(L2PcInstance player)  	{     	if (player.isOutOfControl())  	{  			player.sendPacket(new ActionFailed());  			return false;  	}  			// TODO: More checks...  		  			return true;  	}  	 			protected boolean canInteract(L2PcInstance player)  	{  			// TODO: NPC busy check etc...  	          			//if (!canTarget(player)) 			//return false;  	  			if (!isInsideRadius(player, INTERACTION_DISTANCE, false, false))  				return false;  	 			return true;  	}     /**     * Manage actions when a player click on the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions on first click on the L2NpcInstance (Select it)</U> :</B><BR>     * <BR>     * <li>Set the L2NpcInstance 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>If L2NpcInstance is autoAttackable, send a Server->Client packet     * StatusUpdate to the L2PcInstance in order to update L2NpcInstance HP     * bar </li>     * <li>Send a Server->Client packet ValidateLocation to correct the     * L2NpcInstance position and heading on the client </li>     * <BR>     * <BR>     *     * <B><U> Actions on second click on the L2NpcInstance (Attack     * it/Intercat with it)</U> :</B><BR>     * <BR>     * <li>Send a Server->Client packet MyTargetSelected to the     * L2PcInstance player (display the select window)</li>     * <li>If L2NpcInstance is autoAttackable, notify the L2PcInstance AI     * with AI_INTENTION_ATTACK (after a height verification)</li>     * <li>If L2NpcInstance is NOT autoAttackable, notify the L2PcInstance     * AI with AI_INTENTION_INTERACT (after a distance verification) and     * show message</li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Each group of     * Server->Client packet must be terminated by a ActionFailed packet in     * order to avoid that client wait an other packet</B></FONT><BR>     * <BR>     *     * <B><U> Example of use </U> :</B><BR>     * <BR>     * <li> Client packet : Action, AttackRequest</li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2ArtefactInstance : Manage only fisrt click to select Artefact</li>     * <BR>     * <BR>     * <li> L2GuardInstance : </li>     * <BR>     * <BR>     *     * @param player     *                The L2PcInstance that start an action on the     *                L2NpcInstance     *     */    @Override    public void onAction(L2PcInstance player)    {    if (!canTarget(player)) return;    	// Check if the L2PcInstance already target the L2NpcInstance	if (this != player.getTarget())	{	    if (Config.DEBUG)	    {		_log.fine("new target selected:" + getObjectId());	    }	    // Set the target of the L2PcInstance player	    player.setTarget(this);	    // Send a Server->Client packet MyTargetSelected to the L2PcInstance player The player.getLevel() - getLevel() permit to display the correct color in the select window	    MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());	    player.sendPacket(my);	    // Check if the player is attackable (without a forced attack)	    if (isAutoAttackable(player))	    {            // Send a Server->Client packet MyTargetSelected to the L2PcInstance playe The player.getLevel() - getLevel() permit to display the correct color in the select window 	     	MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel()); 	     	player.sendPacket(my); 	     		 	     	// Send a Server->Client packet StatusUpdate of the	     	// L2NpcInstance to the L2PcInstance to update its HP bar	     	StatusUpdate su = new StatusUpdate(getObjectId());	     	su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp());	     	su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());	     	player.sendPacket(su);	    }        else         {         		// Send a Server->Client packet MyTargetSelected to the L2PcInstance player         		MyTargetSelected my = new MyTargetSelected(getObjectId(), 0);         		player.sendPacket(my);         } 	    // Send a Server->Client packet ValidateLocation to correct the	    // L2NpcInstance position and heading on the client	    player.sendPacket(new ValidateLocation(this));	} else	{	    player.sendPacket(new ValidateLocation(this));	    // 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);		    // player.startAttack(this);		} else		{		    // Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet		    player.sendPacket(new ActionFailed());		}	    } else 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);		    // Open a chat window on client with the text of the L2NpcInstance		    if (isEventMob)		    {			L2Event.showEventHtml(player, String.valueOf(getObjectId()));		    } else if (_isEventVIPNPCEnd)		    {			VIP.showEndHTML(player, String.valueOf(getObjectId()));		    } else if (_isEventMobCTF)		    {			CTF.showEventHtml(player, String.valueOf(getObjectId()));		    } else		    {			Quest[] qlst = getTemplate().getEventQuests(Quest.QuestEventType.NPC_FIRST_TALK);			if (qlst != null && qlst.length == 1)			{			    qlst[0].notifyFirstTalk(this, player);			} else			{			    showChatWindow(player, 0);			}		    }		}	    } else		player.sendPacket(new ActionFailed());	}    }    /**     * Manage and Display the GM console to modify the L2NpcInstance (GM     * only).<BR>     * <BR>     *     * <B><U> Actions (If the L2PcInstance is a GM only)</U> :</B><BR>     * <BR>     * <li>Set the L2NpcInstance 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>If L2NpcInstance is autoAttackable, send a Server->Client packet     * StatusUpdate to the L2PcInstance in order to update L2NpcInstance HP     * bar </li>     * <li>Send a Server->Client NpcHtmlMessage() containing the GM console     * about this L2NpcInstance </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Each group of     * Server->Client packet must be terminated by a ActionFailed packet in     * order to avoid that client wait an other packet</B></FONT><BR>     * <BR>     *     * <B><U> Example of use </U> :</B><BR>     * <BR>     * <li> Client packet : Action</li>     * <BR>     * <BR>     *     * @param client     *                The thread that manage the player that pessed Shift     *                and click on the L2NpcInstance     *     */    @Override    public void onActionShift(L2GameClient client)    {	// Get the L2PcInstance corresponding to the thread	L2PcInstance player = client.getActiveChar();	if (player == null)	{	    return;	}	// Check if the L2PcInstance is a GM	if (player.getAccessLevel() >= Config.GM_ACCESSLEVEL)	{	    // Set the target of the L2PcInstance player	    player.setTarget(this);	    // Send a Server->Client packet MyTargetSelected to the	    // L2PcInstance	    // player	    // The player.getLevel() - getLevel() permit to display the	    // correct	    // color in the select window	    MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());	    player.sendPacket(my);	    // Check if the player is attackable (without a forced attack)	    if (isAutoAttackable(player))	    {		// Send a Server->Client packet StatusUpdate of the		// L2NpcInstance to the L2PcInstance to update its HP bar		StatusUpdate su = new StatusUpdate(getObjectId());		su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp());		su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());		player.sendPacket(su);	    }	    // Send a Server->Client NpcHtmlMessage() containing the GM	    // console	    // about this L2NpcInstance	    NpcHtmlMessage html = new NpcHtmlMessage(0);	    TextBuilder html1 = new TextBuilder("<html><body><center><font color=\"LEVEL\">NPC Information</font></center>");	    String className = getClass().getName().substring(43);	    html1.append("<br>");	    html1.append("Instance Type: " + className + "<br1>Faction: " + getFactionId() + "<br1>Location ID: " + (getSpawn() != null ? getSpawn().getLocation() : 0) + "<br1>");	    if (this instanceof L2ControllableMobInstance)	    {		html1.append("Mob Group: " + MobGroupTable.getInstance().getGroupForMob((L2ControllableMobInstance) this).getGroupId() + "<br>");	    } else	    {		html1.append("Respawn Time: " + (getSpawn() != null ? getSpawn().getRespawnDelay() / 1000 + "  Seconds<br>" : "?  Seconds<br>"));	    }	    html1.append("<table border=\"0\" width=\"100%\">");	    html1.append("<tr><td>Object ID</td><td>" + getObjectId() + "</td><td>NPC ID</td><td>" + getTemplate().npcId + "</td></tr>");	    html1.append("<tr><td>Castle</td><td>" + getCastle().getCastleId() + "</td><td>Coords</td><td>" + getX() + "," + getY() + "," + getZ() + "</td></tr>");	    html1.append("<tr><td>Level</td><td>" + getLevel() + "</td><td>Aggro</td><td>" + (this instanceof L2Attackable ? ((L2Attackable) this).getAggroRange() : 0) + "</td></tr>");	    html1.append("</table><br>");	    html1.append("<font color=\"LEVEL\">Combat</font>");	    html1.append("<table border=\"0\" width=\"100%\">");	    html1.append("<tr><td>Current HP</td><td>" + getCurrentHp() + "</td><td>Current MP</td><td>" + getCurrentMp() + "</td></tr>");	    html1.append("<tr><td>Max.HP</td><td>" + (int) (getMaxHp() / getStat().calcStat(Stats.MAX_HP, 1, this, null)) + "*" + getStat().calcStat(Stats.MAX_HP, 1, this, null) + "</td><td>Max.MP</td><td>" + getMaxMp() + "</td></tr>");	    html1.append("<tr><td>P.Atk.</td><td>" + getPAtk(null) + "</td><td>M.Atk.</td><td>" + getMAtk(null, null) + "</td></tr>");	    html1.append("<tr><td>P.Def.</td><td>" + getPDef(null) + "</td><td>M.Def.</td><td>" + getMDef(null, null) + "</td></tr>");	    html1.append("<tr><td>Accuracy</td><td>" + getAccuracy() + "</td><td>Evasion</td><td>" + getEvasionRate(null) + "</td></tr>");	    html1.append("<tr><td>Critical</td><td>" + getCriticalHit(null, null) + "</td><td>Speed</td><td>" + getRunSpeed() + "</td></tr>");	    html1.append("<tr><td>Atk.Speed</td><td>" + getPAtkSpd() + "</td><td>Cast.Speed</td><td>" + getMAtkSpd() + "</td></tr>");	    html1.append("</table><br>");	    html1.append("<font color=\"LEVEL\">Basic Stats</font>");	    html1.append("<table border=\"0\" width=\"100%\">");	    html1.append("<tr><td>STR</td><td>" + getSTR() + "</td><td>DEX</td><td>" + getDEX() + "</td><td>CON</td><td>" + getCON() + "</td></tr>");	    html1.append("<tr><td>INT</td><td>" + getINT() + "</td><td>WIT</td><td>" + getWIT() + "</td><td>MEN</td><td>" + getMEN() + "</td></tr>");	    html1.append("</table>");	    html1.append("<br><center><table><tr><td><button value=\"Edit NPC\" action=\"bypass -h admin_edit_npc " + getTemplate().npcId + "\" width=100 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"><br1></td>");	    html1.append("<td><button value=\"Kill\" action=\"bypass -h admin_kill\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td><br1></tr>");	    html1.append("<tr><td><button value=\"Show DropList\" action=\"bypass -h admin_show_droplist " + getTemplate().npcId + "\" width=100 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr>");	    html1.append("<td><button value=\"Delete\" action=\"bypass -h admin_delete\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr>");	    html1.append("</table></center><br>");	    html1.append("</body></html>");	    html.setHtml(html1.toString());	    player.sendPacket(html);	} else if (Config.GAME_VIEWNPC || Config.GAME_VIEWNPC_COMBAT || Config.GAME_VIEWNPC_BASIC || Config.GAME_VIEWNPC_DROP)	{	    // Set the target of the L2PcInstance player	    player.setTarget(this);	    // Send a Server->Client packet MyTargetSelected to the	    // L2PcInstance player	    // The player.getLevel() - getLevel() permit to display the	    // correct color in the select window	    MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());	    player.sendPacket(my);	    // Check if the player is attackable (without a forced attack)	    if (isAutoAttackable(player))	    {		// Send a Server->Client packet StatusUpdate of the		// L2NpcInstance to the L2PcInstance to update its HP bar		StatusUpdate su = new StatusUpdate(getObjectId());		su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp());		su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());		player.sendPacket(su);	    }	    NpcHtmlMessage html = new NpcHtmlMessage(0);	    TextBuilder html1 = new TextBuilder("<html><body>");	    // npc name	    html1.append("<center><font color=\"LEVEL\">[Npc]</font></center><br>");	    html1.append(getName());	    // shows npc combat stats	    if (Config.GAME_VIEWNPC_COMBAT)	    {		html1.append("<br><center><font color=\"LEVEL\">[Combat Stats]</font></center>");		html1.append("<table border=0 width=\"100%\">");		html1.append("<tr><td>Max.HP</td><td>" + (int) (getMaxHp() / getStat().calcStat(Stats.MAX_HP, 1, this, null)) + "*" + (int) getStat().calcStat(Stats.MAX_HP, 1, this, null) + "</td><td>Max.MP</td><td>" + getMaxMp() + "</td></tr>");		html1.append("<tr><td>P.Atk.</td><td>" + getPAtk(null) + "</td><td>M.Atk.</td><td>" + getMAtk(null, null) + "</td></tr>");		html1.append("<tr><td>P.Def.</td><td>" + getPDef(null) + "</td><td>M.Def.</td><td>" + getMDef(null, null) + "</td></tr>");		html1.append("<tr><td>Accuracy</td><td>" + getAccuracy() + "</td><td>Evasion</td><td>" + getEvasionRate(null) + "</td></tr>");		html1.append("<tr><td>Critical</td><td>" + getCriticalHit(null, null) + "</td><td>Speed</td><td>" + getRunSpeed() + "</td></tr>");		html1.append("<tr><td>Atk.Speed</td><td>" + getPAtkSpd() + "</td><td>Cast.Speed</td><td>" + getMAtkSpd() + "</td></tr>");		html1.append("<tr><td>Race</td><td>" + getTemplate().race + "</td><td></td><td></td></tr>");		html1.append("</table>");	    }	    // shows basic stats	    if (Config.GAME_VIEWNPC_BASIC)	    {		html1.append("<br><center><font color=\"LEVEL\">[Basic Stats]</font></center>");		html1.append("<table border=0 width=\"100%\">");		html1.append("<tr><td>STR</td><td>" + getSTR() + "</td><td>DEX</td><td>" + getDEX() + "</td><td>CON</td><td>" + getCON() + "</td></tr>");		html1.append("<tr><td>INT</td><td>" + getINT() + "</td><td>WIT</td><td>" + getWIT() + "</td><td>MEN</td><td>" + getMEN() + "</td></tr>");		html1.append("</table>");	    }	    // shows drop stats	    if (Config.GAME_VIEWNPC_DROP)	    {		html1.append("<br><center><font color=\"LEVEL\">[Drop Info]</font></center>");		html1.append("<br>");		for (L2DropCategory cat : getTemplate().getDropData())		{		    for (L2DropData drop : cat.getAllDrops())		    {			if (!Config.GAME_VIEWNPC_QUESTDROP)			{			    // default info about drop item			    String name = ItemTable.getInstance().getTemplate(drop.getItemId()).getName();			    int chance = drop.getChance(); // drop chance			    int min_qty = drop.getMinDrop(); // min. q-ty			    // of items			    int max_qty = drop.getMaxDrop(); // max. q-ty			    // of items			    // calculating stats using drop-config			    if (drop.getItemId() == 57)			    {				chance *= Config.RATE_DROP_ADENA;				min_qty *= Config.RATE_DROP_ADENA; // temporary				// calculation				max_qty *= Config.RATE_DROP_ADENA; // temporary				// calculation			    } else if (cat.isSweep())			    {				chance *= Config.RATE_DROP_SPOIL;			    } else			    {				chance *= Config.RATE_DROP_ITEMS;			    }			    // chance in percents			    if (chance > drop.MAX_CHANCE)			    {				chance = drop.getChance();			    }			    double percentChance = chance * 0.0001;			    // output line (if min. q-ty = max. q-ty shows			    // only min.)			    html1.append((drop.isQuestDrop() ? "Quest: " : cat.isSweep() ? "Spoil: " : "Drop: ") + name + "   " + percentChance + "%" + "   [" + min_qty + (min_qty == max_qty ? "" : " - " + max_qty) + "]<br1>");			}		    }		}		html1.append("</body></html>");	    }	    html.setHtml(html1.toString());	    player.sendPacket(html);	}	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /** Return the L2Castle this L2NpcInstance belongs to. */    public final Castle getCastle()    {	// Get castle this NPC belongs to (excluding L2Attackable)	if (_castleIndex < 0)	{	    L2TownZone town = TownManager.getInstance().getTown(getX(), getY(), getZ());	    if (town != null)	    {		_castleIndex = CastleManager.getInstance().getCastleIndex(town.getTaxById());	    }	    if (_castleIndex < 0)	    {		_castleIndex = CastleManager.getInstance().findNearestCastleIndex(this);	    } else	    {		_isInTown = true; // Npc was spawned in town	    }	}	if (_castleIndex < 0)	{	    return null;	}	return CastleManager.getInstance().getCastles().get(_castleIndex);    }    public final boolean getIsInTown()    {	if (_castleIndex < 0)	{	    getCastle();	}	return _isInTown;    }    /**     * Open a quest or chat window on client with the text of the     * L2NpcInstance in function of the command.<BR>     * <BR>     *     * <B><U> Example of use </U> :</B><BR>     * <BR>     * <li> Client packet : RequestBypassToServer</li>     * <BR>     * <BR>     *     * @param command     *                The command string received from client     *     */    public void onBypassFeedback(L2PcInstance player, String command)    {        //if (canInteract(player))	{	    if (isBusy() && getBusyMessage().length() > 0)	    {		player.sendPacket(new ActionFailed());		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		html.setFile("data/html/npcbusy.htm");		html.replace("%busymessage%", getBusyMessage());		html.replace("%npcname%", getName());		html.replace("%playername%", player.getName());		player.sendPacket(html);	    } else if (command.equalsIgnoreCase("TerritoryStatus"))	    {		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		{		    if (getCastle().getOwnerId() > 0)		    {			html.setFile("data/html/territorystatus.htm");			L2Clan clan = ClanTable.getInstance().getClan(getCastle().getOwnerId());			html.replace("%clanname%", clan.getName());			html.replace("%clanleadername%", clan.getLeaderName());		    } else		    {			html.setFile("data/html/territorynoclan.htm");		    }		}		html.replace("%castlename%", getCastle().getName());		html.replace("%taxpercent%", "" + getCastle().getTaxPercent());		html.replace("%objectId%", String.valueOf(getObjectId()));		{		    if (getCastle().getCastleId() > 6)		    {			html.replace("%territory%", "The Kingdom of Elmore");		    } else		    {			html.replace("%territory%", "The Kingdom of Aden");		    }		}		player.sendPacket(html);	    } else if (command.startsWith("Quest"))	    {		String quest = "";		try		{		    quest = command.substring(5).trim();		} catch (IndexOutOfBoundsException ioobe)		{		}		if (quest.length() == 0)		{		    showQuestWindow(player);		} else		{		    showQuestWindow(player, quest);		}	    } 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("Link"))	    {		String path = command.substring(5).trim();		if (path.indexOf("..") != -1)		{		    return;		}		String filename = "data/html/" + path;		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		html.setFile(filename);		html.replace("%objectId%", String.valueOf(getObjectId()));		player.sendPacket(html);	    } else if (command.startsWith("NobleTeleport"))	    {		if (!player.isNoble())		{		    String filename = "data/html/teleporter/nobleteleporter-no.htm";		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    html.setFile(filename);		    html.replace("%objectId%", String.valueOf(getObjectId()));		    html.replace("%npcname%", getName());		    player.sendPacket(html);		    return;		}		int val = 0;		try		{		    val = Integer.parseInt(command.substring(5));		} catch (IndexOutOfBoundsException ioobe)		{		} catch (NumberFormatException nfe)		{		}		showChatWindow(player, val);	    } else if (command.startsWith("Loto"))	    {		int val = 0;		try		{		    val = Integer.parseInt(command.substring(5));		} catch (IndexOutOfBoundsException ioobe)		{		} catch (NumberFormatException nfe)		{		}		if (val == 0)		{		    // new loto ticket		    for (int i = 0; i < 5; i++)		    {			player.setLoto(i, 0);		    }		}		showLotoWindow(player, val);	    } else if (command.startsWith("CPRecovery"))	    {		makeCPRecovery(player);	    } else if (command.startsWith("SupportMagic"))	    {		makeSupportMagic(player);	    } else if (command.startsWith("multisell"))	    {		L2Multisell.getInstance().SeparateAndSend(Integer.parseInt(command.substring(9).trim()), player, false, getCastle().getTaxRate());	    } else if (command.startsWith("exc_multisell"))	    {		L2Multisell.getInstance().SeparateAndSend(Integer.parseInt(command.substring(13).trim()), player, true, getCastle().getTaxRate());	    } else if (command.startsWith("Augment"))	    {		int cmdChoice = Integer.parseInt(command.substring(8, 9).trim());		switch (cmdChoice)		{		case 1:		    player.sendPacket(new SystemMessage(SystemMessageId.SELECT_THE_ITEM_TO_BE_AUGMENTED));		    player.sendPacket(new ExShowVariationMakeWindow());		    break;		case 2:		    player.sendPacket(new SystemMessage(SystemMessageId.SELECT_THE_ITEM_FROM_WHICH_YOU_WISH_TO_REMOVE_AUGMENTATION));		    player.sendPacket(new ExShowVariationCancelWindow());		    break;		}	    } else if (command.startsWith("MakeBuffs"))	    {		makeBuffs(player, command.substring(9).trim());	    } else if (command.startsWith("npcfind_byid"))	    {		try		{		    L2Spawn spawn = SpawnTable.getInstance().getTemplate(Integer.parseInt(command.substring(12).trim()));		    if (spawn != null)		    {			player.sendPacket(new RadarControl(0, 1, spawn.getLocx(), spawn.getLocy(), spawn.getLocz()));		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("newbie_give_coupon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getLevel() < 6 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-3.htm");			player.sendPacket(html);		    } else if (player.getCoupon(0))		    {			html.setFile("data/html/adventurers_guide/31760-1.htm");			player.sendPacket(html);		    } else		    {			player.getInventory().addItem("Weapon Coupon", 7832, 1, player, this);			player.addCoupon(1);			html.setFile("data/html/adventurers_guide/31760-2.htm");			player.sendPacket(html);		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("newbie_give_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getLevel() < 6 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-3.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(0)) {		     * html.setFile("data/html/adventurers_guide/31760-1.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10010, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("newbie_return_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getLevel() < 6 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-3.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(0) || !player.isNewbie()) {		     * html.setFile("data/html/adventurers_guide/31760-1.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10011, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("traveller_give_coupon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getClassId().level() != 1 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-6.htm");			player.sendPacket(html);		    } else if (player.getCoupon(1))		    {			html.setFile("data/html/adventurers_guide/31760-4.htm");			player.sendPacket(html);		    } else		    {			player.getInventory().addItem("Weapon Coupon", 7833, 1, player, this);			player.addCoupon(2);			html.setFile("data/html/adventurers_guide/31760-5.htm");			player.sendPacket(html);		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("traveller_give_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getClassId().level() != 1 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-6.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(1)) {		     * html.setFile("data/html/adventurers_guide/31760-4.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10012, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("traveller_return_weapon"))	    {		try		{		    NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());		    if (player.getLevel() > 25 || player.getClassId().level() != 1 || !player.isNewbie())		    {			html.setFile("data/html/adventurers_guide/31760-6.htm");			player.sendPacket(html);		    } else		    /*		     * if (player.getCoupon(1)) {		     * html.setFile("data/html/adventurers_guide/31760-4.htm");		     * player.sendPacket(html); } else		     */{			L2Multisell.getInstance().SeparateAndSend(10013, player, false, getCastle().getTaxRate());		    }		} catch (NumberFormatException nfe)		{		    player.sendMessage("Wrong command parameters");		}	    } else if (command.startsWith("EnterRift"))	    {		try		{		    Byte b1 = Byte.parseByte(command.substring(10)); // Selected		    // Area:		    // Recruit,		    // Soldier		    // etc		    DimensionalRiftManager.getInstance().start(player, b1, this);		} catch (Exception e)		{		}	    } else if (command.startsWith("ChangeRiftRoom"))	    {		if (player.isInParty() && player.getParty().isInDimensionalRift())		{		    player.getParty().getDimensionalRift().manualTeleport(player, this);		} else		{		    DimensionalRiftManager.getInstance().handleCheat(player, this);		}	    } else if (command.startsWith("ExitRift"))	    {		if (player.isInParty() && player.getParty().isInDimensionalRift())		{		    player.getParty().getDimensionalRift().manualExitRift(player, this);		} else		{		    DimensionalRiftManager.getInstance().handleCheat(player, this);		}	    }	}    }    /**     * Throws an action command to L2BufferInstance.<br>     *     * @param player     *                --> Target player     * @param buffTemplate     *                --> Name of the Buff Template to Add     */    public void makeBuffs(L2PcInstance player, String buffTemplate)    {	int _templateId = 0;	try	{	    _templateId = Integer.parseInt(buffTemplate);	} catch (NumberFormatException e)	{	    _templateId = BuffTemplateTable.getInstance().getTemplateIdByName(buffTemplate);	}	if (_templateId > 0)	{	    L2BufferInstance.makeBuffs(player, _templateId, this, true);	}    }    /**     * Return null (regular NPCs don't have weapons instancies).<BR>     * <BR>     */    @Override    public L2ItemInstance getActiveWeaponInstance()    {	// regular NPCs dont have weapons instancies	return null;    }    /**     * Return the weapon item equiped in the right hand of the L2NpcInstance     * or null.<BR>     * <BR>     */    @Override    public L2Weapon getActiveWeaponItem()    {	// Get the weapon identifier equiped in the right hand of the	// L2NpcInstance	int weaponId = getTemplate().rhand;	if (weaponId < 1)	{	    return null;	}	// Get the weapon item equiped in the right hand of the L2NpcInstance	L2Item item = ItemTable.getInstance().getTemplate(getTemplate().rhand);	if (!(item instanceof L2Weapon))	{	    return null;	}	return (L2Weapon) item;    }    /**     * Return null (regular NPCs don't have weapons instancies).<BR>     * <BR>     */    @Override    public L2ItemInstance getSecondaryWeaponInstance()    {	// regular NPCs dont have weapons instancies	return null;    }    /**     * Return the weapon item equiped in the left hand of the L2NpcInstance     * or null.<BR>     * <BR>     */    @Override    public L2Weapon getSecondaryWeaponItem()    {	// Get the weapon identifier equiped in the right hand of the	// L2NpcInstance	int weaponId = getTemplate().lhand;	if (weaponId < 1)	{	    return null;	}	// Get the weapon item equiped in the right hand of the L2NpcInstance	L2Item item = ItemTable.getInstance().getTemplate(getTemplate().lhand);	if (!(item instanceof L2Weapon))	{	    return null;	}	return (L2Weapon) item;    }    /**     * Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in     * order to display the message of the L2NpcInstance.<BR>     * <BR>     *     * @param player     *                The L2PcInstance who talks with the L2NpcInstance     * @param content     *                The text of the L2NpcMessage     *     */    public void insertObjectIdAndShowChatWindow(L2PcInstance player, String content)    {	// Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in	// order to display the message of the L2NpcInstance	content = content.replaceAll("%objectId%", String.valueOf(getObjectId()));	NpcHtmlMessage npcReply = new NpcHtmlMessage(getObjectId());	npcReply.setHtml(content);	player.sendPacket(npcReply);    }    /**     * Return the pathfile of the selected HTML file in function of the     * npcId and of the page number.<BR>     * <BR>     *     * <B><U> Format of the pathfile </U> :</B><BR>     * <BR>     * <li> if the file exists on the server (page number = 0) :     * <B>data/html/default/12006.htm</B> (npcId-page number)</li>     * <li> if the file exists on the server (page number > 0) :     * <B>data/html/default/12006-1.htm</B> (npcId-page number)</li>     * <li> if the file doesn't exist on the server :     * <B>data/html/npcdefault.htm</B> (message : "I have nothing to say to     * you")</li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2GuardInstance : Set the pathfile to     * data/html/guard/12006-1.htm (npcId-page number)</li>     * <BR>     * <BR>     *     * @param npcId     *                The Identifier of the L2NpcInstance whose text must be     *                display     * @param val     *                The number of the page to display     *     */    public String getHtmlPath(int npcId, int val)    {	String pom = "";	if (val == 0)	{	    pom = "" + npcId;	} else	{	    pom = npcId + "-" + val;	}	String temp = "data/html/default/" + pom + ".htm";	if (!Config.LAZY_CACHE)	{	    // If not running lazy cache the file must be in the cache or it	    // doesnt exist	    if (HtmCache.getInstance().contains(temp))	    {		return temp;	    }	} else	{	    if (HtmCache.getInstance().isLoadable(temp))	    {		return temp;	    }	}	// If the file is not found, the standard message "I have nothing to say	// to you" is returned	return "data/html/npcdefault.htm";    }    /**     * Open a choose quest window on client with all quests available of the     * L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param quests     *                The table containing quests of the L2NpcInstance     *     */    public void showQuestChooseWindow(L2PcInstance player, Quest[] quests)    {	TextBuilder sb = new TextBuilder();	sb.append("<html><body><title>Talk about:</title><br>");	for (Quest q : quests)	{	    sb.append("<a action=\"bypass -h npc_").append(getObjectId()).append("_Quest ").append(q.getName()).append("\">").append(q.getDescr()).append("</a><br>");	}	sb.append("</body></html>");	// Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in	// order to display the message of the L2NpcInstance	insertObjectIdAndShowChatWindow(player, sb.toString());    }    /**     * Open a quest window on client with the text of the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the text of the quest state in the folder     * data/jscript/quests/questId/stateId.htm </li>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <li>Send a Server->Client ActionFailed to the L2PcInstance in order     * to avoid that the client wait another packet </li>     * <BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param questId     *                The Identifier of the quest to display the message     *     */    public void showQuestWindow(L2PcInstance player, String questId)    {	String content;	if (player.getWeightPenalty() >= 3)	{	    player.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_LESS_THAN_80_PERCENT));	    return;	}	// FileInputStream fis = null;	// Get the state of the selected quest	QuestState qs = player.getQuestState(questId);	if (qs != null)	{	    // If the quest is alreday started, no need to show a window	    if (!qs.getQuest().notifyTalk(this, qs))	    {		return;	    }	} else	{	    Quest q = QuestManager.getInstance().getQuest(questId);	    if (q != null)	    {		// check for start point		Quest[] qlst = getTemplate().getEventQuests(Quest.QuestEventType.QUEST_START);		if (qlst != null && qlst.length > 0)		{		    for (int i = 0; i < qlst.length; i++)		    {			if (qlst[i] == q)			{			    qs = q.newQuestState(player);			    // disabled by mr. becouse quest dialog only			    // show on			    // second click.			    // if(qs.getState().getName().equalsIgnoreCase("completed"))			    // {			    if (!qs.getQuest().notifyTalk(this, qs))			    {				return; // no need to show a window			    }			    // }			    break;			}		    }		}	    }	}	if (qs == null)	{	    // no quests found	    content = "<html><body>You are either not carrying out your quest or don't meet the criteria.</body></html>";	} else	{	    questId = qs.getQuest().getName();	    String stateId = qs.getStateId();	    String path = "data/jscript/quests/" + questId + "/" + stateId + ".htm";	    content = HtmCache.getInstance().getHtm(path); // TODO path for	    // quests html	    if (Config.DEBUG)	    {		if (content != null)		{		    _log.fine("Showing quest window for quest " + questId + " html path: " + path);		} else		{		    _log.fine("File not exists for quest " + questId + " html path: " + path);		}	    }	}	// Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in	// order to display the message of the L2NpcInstance	if (content != null)	{	    insertObjectIdAndShowChatWindow(player, content);	}	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /**     * Collect awaiting quests/start points and display a QuestChooseWindow     * (if several available) or QuestWindow.<BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     *     */    public void showQuestWindow(L2PcInstance player)    {	// collect awaiting quests and start points	List<Quest> options = new FastList<Quest>();	QuestState[] awaits = player.getQuestsForTalk(getTemplate().npcId);	Quest[] starts = getTemplate().getEventQuests(Quest.QuestEventType.QUEST_START);	// Quests are limited between 1 and 999 because those are the quests	// that are supported by the client.	// By limitting them there, we are allowed to create custom quests at	// higher IDs without interfering	if (awaits != null)	{	    for (QuestState x : awaits)	    {		if (!options.contains(x))		{		    if (x.getQuest().getQuestIntId() > 0 && x.getQuest().getQuestIntId() < 1000)		    {			options.add(x.getQuest());		    }		}	    }	}	if (starts != null)	{	    for (Quest x : starts)	    {		if (!options.contains(x))		{		    if (x.getQuestIntId() > 0 && x.getQuestIntId() < 1000)		    {			options.add(x);		    }		}	    }	}	// Display a QuestChooseWindow (if several quests are available) or	// QuestWindow	if (options.size() > 1)	{	    showQuestChooseWindow(player, options.toArray(new Quest[options.size()]));	} else if (options.size() == 1)	{	    showQuestWindow(player, options.get(0).getName());	} else	{	    showQuestWindow(player, "");	}    }    /**     * Open a Loto window on client with the text of the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the text of the selected HTML file in function of the npcId     * and of the page number </li>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <li>Send a Server->Client ActionFailed to the L2PcInstance in order     * to avoid that the client wait another packet </li>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param val     *                The number of the page of the L2NpcInstance to display     *     */    // 0 - first buy lottery ticket window    // 1-20 - buttons    // 21 - second buy lottery ticket window    // 22 - selected ticket with 5 numbers    // 23 - current lottery jackpot    // 24 - Previous winning numbers/Prize claim    // >24 - check lottery ticket by item object id    public void showLotoWindow(L2PcInstance player, int val)    {	int npcId = getTemplate().npcId;	String filename;	SystemMessage sm;	NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());	if (val == 0) // 0 - first buy lottery ticket window	{	    filename = getHtmlPath(npcId, 1);	    html.setFile(filename);	} else if (val >= 1 && val <= 21) // 1-20 - buttons, 21 - second	// buy	// lottery ticket window	{	    if (!Lottery.getInstance().isStarted())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_CURRENT_SOLD));		return;	    }	    if (!Lottery.getInstance().isSellableTickets())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_AVAILABLE));		return;	    }	    filename = getHtmlPath(npcId, 5);	    html.setFile(filename);	    int count = 0;	    int found = 0;	    // counting buttons and unsetting button if found	    for (int i = 0; i < 5; i++)	    {		if (player.getLoto(i) == val)		{		    // unsetting button		    player.setLoto(i, 0);		    found = 1;		} else if (player.getLoto(i) > 0)		{		    count++;		}	    }	    // if not rearched limit 5 and not unseted value	    if (count < 5 && found == 0 && val <= 20)	    {		for (int i = 0; i < 5; i++)		{		    if (player.getLoto(i) == 0)		    {			player.setLoto(i, val);			break;		    }		}	    }	    // setting pusshed buttons	    count = 0;	    for (int i = 0; i < 5; i++)	    {		if (player.getLoto(i) > 0)		{		    count++;		    String button = String.valueOf(player.getLoto(i));		    if (player.getLoto(i) < 10)		    {			button = "0" + button;		    }		    String search = "fore=\"L2UI.lottoNum" + button + "\" back=\"L2UI.lottoNum" + button + "a_check\"";		    String replace = "fore=\"L2UI.lottoNum" + button + "a_check\" back=\"L2UI.lottoNum" + button + "\"";		    html.replace(search, replace);		}	    }	    if (count == 5)	    {		String search = "0\">Return";		String replace = "22\">The winner selected the numbers above.";		html.replace(search, replace);	    }	} else if (val == 22) // 22 - selected ticket with 5 numbers	{	    if (!Lottery.getInstance().isStarted())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_CURRENT_SOLD));		return;	    }	    if (!Lottery.getInstance().isSellableTickets())	    {		// tickets can't be sold		player.sendPacket(new SystemMessage(SystemMessageId.NO_LOTTERY_TICKETS_AVAILABLE));		return;	    }	    int price = Config.ALT_LOTTERY_TICKET_PRICE;	    int lotonumber = Lottery.getInstance().getId();	    int enchant = 0;	    int type2 = 0;	    for (int i = 0; i < 5; i++)	    {		if (player.getLoto(i) == 0)		{		    return;		}		if (player.getLoto(i) < 17)		{		    enchant += Math.pow(2, player.getLoto(i) - 1);		} else		{		    type2 += Math.pow(2, player.getLoto(i) - 17);		}	    }	    if (player.getAdena() < price)	    {		sm = new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA);		player.sendPacket(sm);		return;	    }	    if (!player.reduceAdena("Loto", price, this, true))	    {		return;	    }	    Lottery.getInstance().increasePrize(price);	    sm = new SystemMessage(SystemMessageId.ACQUIRED);	    sm.addNumber(lotonumber);	    sm.addItemName(4442);	    player.sendPacket(sm);	    L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), 4442);	    item.setCount(1);	    item.setCustomType1(lotonumber);	    item.setEnchantLevel(enchant);	    item.setCustomType2(type2);	    player.getInventory().addItem("Loto", item, player, this);	    InventoryUpdate iu = new InventoryUpdate();	    iu.addItem(item);	    L2ItemInstance adenaupdate = player.getInventory().getItemByItemId(57);	    iu.addModifiedItem(adenaupdate);	    player.sendPacket(iu);	    filename = getHtmlPath(npcId, 3);	    html.setFile(filename);	} else if (val == 23) // 23 - current lottery jackpot	{	    filename = getHtmlPath(npcId, 3);	    html.setFile(filename);	} else if (val == 24) // 24 - Previous winning numbers/Prize	// claim	{	    filename = getHtmlPath(npcId, 4);	    html.setFile(filename);	    int lotonumber = Lottery.getInstance().getId();	    String message = "";	    for (L2ItemInstance item : player.getInventory().getItems())	    {		if (item == null)		{		    continue;		}		if (item.getItemId() == 4442 && item.getCustomType1() < lotonumber)		{		    message = message + "<a action=\"bypass -h npc_%objectId%_Loto " + item.getObjectId() + "\">" + item.getCustomType1() + " Event Number ";		    int[] numbers = Lottery.getInstance().decodeNumbers(item.getEnchantLevel(), item.getCustomType2());		    for (int i = 0; i < 5; i++)		    {			message += numbers[i] + " ";		    }		    int[] check = Lottery.getInstance().checkTicket(item);		    if (check[0] > 0)		    {			switch (check[0])			{			case 1:			    message += "- 1st Prize";			    break;			case 2:			    message += "- 2nd Prize";			    break;			case 3:			    message += "- 3th Prize";			    break;			case 4:			    message += "- 4th Prize";			    break;			}			message += " " + check[1] + "a.";		    }		    message += "</a><br>";		}	    }	    if (message == "")	    {		message += "There is no winning lottery ticket...<br>";	    }	    html.replace("%result%", message);	} else if (val > 24) // >24 - check lottery ticket by	// item object id	{	    int lotonumber = Lottery.getInstance().getId();	    L2ItemInstance item = player.getInventory().getItemByObjectId(val);	    if (item == null || item.getItemId() != 4442 || item.getCustomType1() >= lotonumber)	    {		return;	    }	    int[] check = Lottery.getInstance().checkTicket(item);	    sm = new SystemMessage(SystemMessageId.DISSAPEARED_ITEM);	    sm.addItemName(4442);	    player.sendPacket(sm);	    int adena = check[1];	    if (adena > 0)	    {		player.addAdena("Loto", adena, this, true);	    }	    player.destroyItem("Loto", item, this, false);	    return;	}	html.replace("%objectId%", String.valueOf(getObjectId()));	html.replace("%race%", "" + Lottery.getInstance().getId());	html.replace("%adena%", "" + Lottery.getInstance().getPrize());	html.replace("%ticket_price%", "" + Config.ALT_LOTTERY_TICKET_PRICE);	html.replace("%prize5%", "" + Config.ALT_LOTTERY_5_NUMBER_RATE * 100);	html.replace("%prize4%", "" + Config.ALT_LOTTERY_4_NUMBER_RATE * 100);	html.replace("%prize3%", "" + Config.ALT_LOTTERY_3_NUMBER_RATE * 100);	html.replace("%prize2%", "" + Config.ALT_LOTTERY_2_AND_1_NUMBER_PRIZE);	html.replace("%enddate%", "" + DateFormat.getDateInstance().format(Lottery.getInstance().getEndDate()));	player.sendPacket(html);	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    public void makeCPRecovery(L2PcInstance player)    {	if (getNpcId() != 31225 && getNpcId() != 31226)	{	    return;	}	if (player.isCursedWeaponEquiped())	{	    player.sendMessage("Go away, you're not welcome here.");	    return;	}	int neededmoney = 100;	SystemMessage sm;	if (!player.reduceAdena("RestoreCP", neededmoney, player.getLastFolkNPC(), true))	{	    return;	}	player.setCurrentCp(getCurrentCp() + 5000);	// cp restored	sm = new SystemMessage(SystemMessageId.S1_CP_WILL_BE_RESTORED);	sm.addString(player.getName());	player.sendPacket(sm);    }    /**     * Add Newbie helper buffs to L2Player according to its level.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the range level in wich player must be to obtain buff </li>     * <li>If player level is out of range, display a message and return     * </li>     * <li>According to player level cast buff </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> Newbie Helper Buff list is define in sql     * table helper_buff_list</B></FONT><BR>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     *     */    public void makeSupportMagic(L2PcInstance player)    {	if (player == null)	{	    return;	}	// Prevent a cursed weapon weilder of being buffed	if (player.isCursedWeaponEquiped())	{	    return;	}	int player_level = player.getLevel();	int lowestLevel = 0;	int higestLevel = 0;	// Select the player	setTarget(player);	// Calculate the min and max level between wich the player must be to	// obtain buff	if (player.isMageClass())	{	    lowestLevel = HelperBuffTable.getInstance().getMagicClassLowestLevel();	    higestLevel = HelperBuffTable.getInstance().getMagicClassHighestLevel();	} else	{	    lowestLevel = HelperBuffTable.getInstance().getPhysicClassLowestLevel();	    higestLevel = HelperBuffTable.getInstance().getPhysicClassHighestLevel();	}	// If the player is too high level, display a message and return	if (player_level > higestLevel || !player.isNewbie())	{	    String content = "<html><body>Newbie Guide:<br>Only a <font color=\"LEVEL\">novice character of level " + higestLevel + " or less</font> can receive my support magic.<br>Your novice character is the first one that you created and raised in this world.</body></html>";	    insertObjectIdAndShowChatWindow(player, content);	    return;	}	// If the player is too low level, display a message and return	if (player_level < lowestLevel)	{	    String content = "<html><body>Come back here when you have reached level " + lowestLevel + ". I will give you support magic then.</body></html>";	    insertObjectIdAndShowChatWindow(player, content);	    return;	}	L2Skill skill = null;	// Go through the Helper Buff list define in sql table helper_buff_list	// and cast skill	for (L2HelperBuff helperBuffItem : HelperBuffTable.getInstance().getHelperBuffTable())	{	    if (helperBuffItem.isMagicClassBuff() == player.isMageClass())	    {		if (player_level >= helperBuffItem.getLowerLevel() && player_level <= helperBuffItem.getUpperLevel())		{		    skill = SkillTable.getInstance().getInfo(helperBuffItem.getSkillID(), helperBuffItem.getSkillLevel());		    if (skill.getSkillType() == SkillType.SUMMON)		    {			player.doCast(skill);		    } else		    {			doCast(skill);		    }		}	    }	}    }    public void showChatWindow(L2PcInstance player)    {	showChatWindow(player, 0);    }    /**     * Returns true if html exists     *     * @param player     * @param type     * @return boolean     */    private boolean showPkDenyChatWindow(L2PcInstance player, String type)    {	String html = HtmCache.getInstance().getHtm("data/html/" + type + "/" + getNpcId() + "-pk.htm");	if (html != null)	{	    NpcHtmlMessage pkDenyMsg = new NpcHtmlMessage(getObjectId());	    pkDenyMsg.setHtml(html);	    player.sendPacket(pkDenyMsg);	    player.sendPacket(new ActionFailed());	    return true;	}	return false;    }    /**     * Open a chat window on client with the text of the L2NpcInstance.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Get the text of the selected HTML file in function of the npcId     * and of the page number </li>     * <li>Send a Server->Client NpcHtmlMessage containing the text of the     * L2NpcInstance to the L2PcInstance </li>     * <li>Send a Server->Client ActionFailed to the L2PcInstance in order     * to avoid that the client wait another packet </li>     * <BR>     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param val     *                The number of the page of the L2NpcInstance to display     *     */    public void showChatWindow(L2PcInstance player, int val)    {	if (player.getKarma() > 0)	{	    if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && this instanceof L2MerchantInstance)	    {		if (showPkDenyChatWindow(player, "merchant"))		{		    return;		}	    } else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_GK && this instanceof L2TeleporterInstance)	    {		if (showPkDenyChatWindow(player, "teleporter"))		{		    return;		}	    } else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE && this instanceof L2WarehouseInstance)	    {		if (showPkDenyChatWindow(player, "warehouse"))		{		    return;		}	    } else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && this instanceof L2FishermanInstance)	    {		if (showPkDenyChatWindow(player, "fisherman"))		{		    return;		}	    }	}	if (getTemplate().type == "L2Auctioneer" && val == 0)	{	    return;	}	int npcId = getTemplate().npcId;	/* For use with Seven Signs implementation */	String filename = SevenSigns.SEVEN_SIGNS_HTML_PATH;	int sealAvariceOwner = SevenSigns.getInstance().getSealOwner(SevenSigns.SEAL_AVARICE);	int sealGnosisOwner = SevenSigns.getInstance().getSealOwner(SevenSigns.SEAL_GNOSIS);	int playerCabal = SevenSigns.getInstance().getPlayerCabal(player);	boolean isSealValidationPeriod = SevenSigns.getInstance().isSealValidationPeriod();	int compWinner = SevenSigns.getInstance().getCabalHighestScore();	switch (npcId)	{	case 31078:	case 31079:	case 31080:	case 31081:	case 31082: // Dawn Priests	case 31083:	case 31084:	case 31168:	case 31692:	case 31694:	case 31997:	    switch (playerCabal)	    {	    case SevenSigns.CABAL_DAWN:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DAWN)		    {			if (compWinner != sealGnosisOwner)			{			    filename += "dawn_priest_2c.htm";			} else			{			    filename += "dawn_priest_2a.htm";			}		    } else		    {			filename += "dawn_priest_2b.htm";		    }		} else		{		    filename += "dawn_priest_1b.htm";		}		break;	    case SevenSigns.CABAL_DUSK:		if (isSealValidationPeriod)		{		    filename += "dawn_priest_3b.htm";		} else		{		    filename += "dawn_priest_3a.htm";		}		break;	    default:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DAWN)		    {			filename += "dawn_priest_4.htm";		    } else		    {			filename += "dawn_priest_2b.htm";		    }		} else		{		    filename += "dawn_priest_1a.htm";		}		break;	    }	    break;	case 31085:	case 31086:	case 31087:	case 31088: // Dusk Priest	case 31089:	case 31090:	case 31091:	case 31169:	case 31693:	case 31695:	case 31998:	    switch (playerCabal)	    {	    case SevenSigns.CABAL_DUSK:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DUSK)		    {			if (compWinner != sealGnosisOwner)			{			    filename += "dusk_priest_2c.htm";			} else			{			    filename += "dusk_priest_2a.htm";			}		    } else		    {			filename += "dusk_priest_2b.htm";		    }		} else		{		    filename += "dusk_priest_1b.htm";		}		break;	    case SevenSigns.CABAL_DAWN:		if (isSealValidationPeriod)		{		    filename += "dusk_priest_3b.htm";		} else		{		    filename += "dusk_priest_3a.htm";		}		break;	    default:		if (isSealValidationPeriod)		{		    if (compWinner == SevenSigns.CABAL_DUSK)		    {			filename += "dusk_priest_4.htm";		    } else		    {			filename += "dusk_priest_2b.htm";		    }		} else		{		    filename += "dusk_priest_1a.htm";		}		break;	    }	    break;	case 31095: //	case 31096: //	case 31097: //	case 31098: // Enter Necropolises	case 31099: //	case 31100: //	case 31101: //	case 31102: //	    if (isSealValidationPeriod)	    {		if (playerCabal != compWinner || sealAvariceOwner != compWinner)		{		    switch (compWinner)		    {		    case SevenSigns.CABAL_DAWN:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));			filename += "necro_no.htm";			break;		    case SevenSigns.CABAL_DUSK:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));			filename += "necro_no.htm";			break;		    case SevenSigns.CABAL_NULL:			filename = getHtmlPath(npcId, val); // do			// the			// default!			break;		    }		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    } else	    {		if (playerCabal == SevenSigns.CABAL_NULL)		{		    filename += "necro_no.htm";		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    }	    break;	case 31114: //	case 31115: //	case 31116: // Enter Catacombs	case 31117: //	case 31118: //	case 31119: //	    if (isSealValidationPeriod)	    {		if (playerCabal != compWinner || sealGnosisOwner != compWinner)		{		    switch (compWinner)		    {		    case SevenSigns.CABAL_DAWN:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));			filename += "cata_no.htm";			break;		    case SevenSigns.CABAL_DUSK:			player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));			filename += "cata_no.htm";			break;		    case SevenSigns.CABAL_NULL:			filename = getHtmlPath(npcId, val); // do			// the			// default!			break;		    }		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    } else	    {		if (playerCabal == SevenSigns.CABAL_NULL)		{		    filename += "cata_no.htm";		} else		{		    filename = getHtmlPath(npcId, val); // do the		    // default!		}	    }	    break;	case 31111: // Gatekeeper Spirit (Disciples)	    if (playerCabal == sealAvariceOwner && playerCabal == compWinner)	    {		switch (sealAvariceOwner)		{		case SevenSigns.CABAL_DAWN:		    filename += "spirit_dawn.htm";		    break;		case SevenSigns.CABAL_DUSK:		    filename += "spirit_dusk.htm";		    break;		case SevenSigns.CABAL_NULL:		    filename += "spirit_null.htm";		    break;		}	    } else	    {		filename += "spirit_null.htm";	    }	    break;	case 31112: // Gatekeeper Spirit (Disciples)	    filename += "spirit_exit.htm";	    break;	case 31127: //	case 31128: //	case 31129: // Dawn Festival Guides	case 31130: //	case 31131: //	    filename += "festival/dawn_guide.htm";	    break;	case 31137: //	case 31138: //	case 31139: // Dusk Festival Guides	case 31140: //	case 31141: //	    filename += "festival/dusk_guide.htm";	    break;	case 31092: // Black Marketeer of Mammon	    filename += "blkmrkt_1.htm";	    break;	case 31113: // Merchant of Mammon	    switch (compWinner)	    {	    case SevenSigns.CABAL_DAWN:		if (playerCabal != compWinner || playerCabal != sealAvariceOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));		    return;		}		break;	    case SevenSigns.CABAL_DUSK:		if (playerCabal != compWinner || playerCabal != sealAvariceOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));		    return;		}		break;	    }	    filename += "mammmerch_1.htm";	    break;	case 31126: // Blacksmith of Mammon	    switch (compWinner)	    {	    case SevenSigns.CABAL_DAWN:		if (playerCabal != compWinner || playerCabal != sealGnosisOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));		    return;		}		break;	    case SevenSigns.CABAL_DUSK:		if (playerCabal != compWinner || playerCabal != sealGnosisOwner)		{		    player.sendPacket(new SystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));		    return;		}		break;	    }	    filename += "mammblack_1.htm";	    break;	case 31132:	case 31133:	case 31134:	case 31135:	case 31136: // Festival Witches	case 31142:	case 31143:	case 31144:	case 31145:	case 31146:	    filename += "festival/festival_witch.htm";	    break;	case 31688:	    if (player.isNoble())	    {		filename = Olympiad.OLYMPIAD_HTML_FILE + "noble_main.htm";	    } else	    {		filename = getHtmlPath(npcId, val);	    }	    break;	case 31690:	case 31769:	case 31770:	case 31771:	case 31772:	    if (player.isHero())	    {		filename = Olympiad.OLYMPIAD_HTML_FILE + "hero_main.htm";	    } else	    {		filename = getHtmlPath(npcId, val);	    }	    break;	default:	    if (npcId >= 31865 && npcId <= 31918)	    {		filename += "rift/GuardianOfBorder.htm";		break;	    }	    if (npcId >= 31093 && npcId <= 31094 || npcId >= 31172 && npcId <= 31201 || npcId >= 31239 && npcId <= 31254)	    {		return;	    }	    // Get the text of the selected HTML file in function of the	    // npcId and of the page number	    filename = getHtmlPath(npcId, val);	    break;	}	// Send a Server->Client NpcHtmlMessage containing the text of the	// L2NpcInstance to the L2PcInstance	NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());	html.setFile(filename);	// String word = "npc-"+npcId+(val>0 ? "-"+val : "" )+"-dialog-append";	if (this instanceof L2MerchantInstance)	{	    if (Config.LIST_PET_RENT_NPC.contains(npcId))	    {		html.replace("_Quest", "_RentPet\">Rent Pet</a><br><a action=\"bypass -h npc_%objectId%_Quest");	    }	}	html.replace("%objectId%", String.valueOf(getObjectId()));	html.replace("%festivalMins%", SevenSignsFestival.getInstance().getTimeToNextFestivalStr());	player.sendPacket(html);	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /**     * Open a chat window on client with the text specified by the given     * file name and path,<BR>     * relative to the datapack root. <BR>     * <BR>     * Added by Tempy     *     * @param player     *                The L2PcInstance that talk with the L2NpcInstance     * @param filename     *                The filename that contains the text to send     *     */    public void showChatWindow(L2PcInstance player, String filename)    {	// Send a Server->Client NpcHtmlMessage containing the text of the	// L2NpcInstance to the L2PcInstance	NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());	html.setFile(filename);	html.replace("%objectId%", String.valueOf(getObjectId()));	player.sendPacket(html);	// Send a Server->Client ActionFailed to the L2PcInstance in order to	// avoid that the client wait another packet	player.sendPacket(new ActionFailed());    }    /**     * Return the Exp Reward of this L2NpcInstance contained in the     * L2NpcTemplate (modified by RATE_XP).<BR>     * <BR>     */    public int getExpReward()    {	double rateXp = getStat().calcStat(Stats.MAX_HP, 1, this, null);	return (int) (getTemplate().rewardExp * rateXp * Config.RATE_XP);    }    /**     * Return the SP Reward of this L2NpcInstance contained in the     * L2NpcTemplate (modified by RATE_SP).<BR>     * <BR>     */    public int getSpReward()    {	double rateSp = getStat().calcStat(Stats.MAX_HP, 1, this, null);	return (int) (getTemplate().rewardSp * rateSp * Config.RATE_SP);    }    /**     * Kill the L2NpcInstance (the corpse disappeared after 7 seconds).<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Create a DecayTask to remove the corpse of the L2NpcInstance     * after 7 seconds </li>     * <li>Set target to null and cancel Attack or Cast </li>     * <li>Stop movement </li>     * <li>Stop HP/MP/CP Regeneration task </li>     * <li>Stop all active skills effects in progress on the L2Character     * </li>     * <li>Send the Server->Client packet StatusUpdate with current HP and     * MP to all other L2PcInstance to inform </li>     * <li>Notify L2Character AI </li>     * <BR>     * <BR>     *     * <B><U> Overriden in </U> :</B><BR>     * <BR>     * <li> L2Attackable </li>     * <BR>     * <BR>     *     * @param killer     *                The L2Character who killed it     *     */    @Override    public boolean doDie(L2Character killer)    {	if (!super.doDie(killer))	{	    return false;	}	    // normally this wouldn't really be needed, but for those few exceptions,    // we do need to reset the weapons back to the initial templated weapon.	_currentLHandId = getTemplate().lhand;	_currentRHandId = getTemplate().rhand;		DecayTaskManager.getInstance().addDecayTask(this);	return true;    }    /**     * Set the spawn of the L2NpcInstance.<BR>     * <BR>     *     * @param spawn     *                The L2Spawn that manage the L2NpcInstance     *     */    public void setSpawn(L2Spawn spawn)    {	_spawn = spawn;    }    @Override    public void onSpawn()    {	super.onSpawn();    }    /**     * Remove the L2NpcInstance from the world and update its spawn object     * (for a complete removal use the deleteMe method).<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Remove the L2NpcInstance from the world when the decay task is     * launched </li>     * <li>Decrease its spawn counter </li>     * <li>Manage Siege task (killFlag, killCT) </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T REMOVE     * the object from _allObjects of L2World </B></FONT><BR>     * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND     * Server->Client packets to players</B></FONT><BR>     * <BR>     *     */    @Override    public void onDecay()    {	if (isDecayed())	{	    return;	}	setDecayed(true);	// Manage Life Control Tower	if (this instanceof L2ControlTowerInstance)	{	    ((L2ControlTowerInstance) this).onDeath();	}	// Remove the L2NpcInstance from the world when the decay task is	// launched	super.onDecay();	// Decrease its spawn counter	if (_spawn != null)	{	    _spawn.decreaseCount(this);	}    }    /**     * Remove PROPERLY the L2NpcInstance from the world.<BR>     * <BR>     *     * <B><U> Actions</U> :</B><BR>     * <BR>     * <li>Remove the L2NpcInstance from the world and update its spawn     * object </li>     * <li>Remove all L2Object from _knownObjects and _knownPlayer of the     * L2NpcInstance then cancel Attak or Cast and notify AI </li>     * <li>Remove L2Object object from _allObjects of L2World </li>     * <BR>     * <BR>     *     * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND     * Server->Client packets to players</B></FONT><BR>     * <BR>     *     */    public void deleteMe()    {	if (getWorldRegion() != null)	{	    getWorldRegion().removeFromZones(this);	    // FIXME this is just a temp hack, we should find a better	    // solution	}	try	{	    decayMe();	} catch (Throwable t)	{	    _log.severe("deletedMe(): " + t);	}	// Remove all L2Object from _knownObjects and _knownPlayer of the	// L2Character then cancel Attak or Cast and notify AI	try	{	    getKnownList().removeAllKnownObjects();	} catch (Throwable t)	{	    _log.severe("deletedMe(): " + t);	}	// Remove L2Object object from _allObjects of L2World	L2World.getInstance().removeObject(this);    }    /**     * Return the L2Spawn object that manage this L2NpcInstance.<BR>     * <BR>     */    public L2Spawn getSpawn()    {	return _spawn;    }    @Override    public String toString()    {	return getTemplate().name;    }    public boolean isDecayed()    {	return _isDecayed;    }    public void setDecayed(boolean decayed)    {	_isDecayed = decayed;    }    public void endDecayTask()    {	if (!isDecayed())	{	    DecayTaskManager.getInstance().cancelDecayTask(this);	    onDecay();	}    }    public boolean isMob() // rather delete this check    {	return false; // This means we use MAX_NPC_ANIMATION instead of	// MAX_MONSTER_ANIMATION    }       	    // Two functions to change the appearance of the equipped weapons on the NPC 	    // This is only useful for a few NPCs and is most likely going to be called from AI 	    public void setLHandId(int newWeaponId) 	    { 	        _currentLHandId = newWeaponId; 	    } 	    public void setRHandId(int newWeaponId) 	    { 	        _currentRHandId = newWeaponId; 	    }     }