Посмотрите видео ниже, чтобы узнать, как установить наш сайт в виде веб-приложения на главном экране.
Примечание: Эта функция может быть недоступна в некоторых браузерах.

[OFF]Привет[/OFF][OFF]Привет, Псих[/OFF]
Ок, гляну. Пасиб)Тут вроде лечащих проблемы по видео нет
Код их смотри - что отрабатывает при нажатии соответствующих байпасов в их диалогах.
Ага, походу нашел...Тут вроде лечащих проблемы по видео нет
Код их смотри - что отрабатывает при нажатии соответствующих байпасов в их диалогах.
//TODO: following
//getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE);Ну да, тупо умирают, и быстро исчезают. Пробовал убивать через //kill, исчезают дольше.Думаю в квесте надо посмотреть метод FirstTalk c этим мобом (или в байпасе HTML псомотреть действсе после нажатия линка) по видео видно что ты его в место того чтоб дать команду следовать за сабой, просто убиваеш, из за этого они и исчезают
this.doDie(null);getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE);    @Override
    public void onBypassFeedback(Player player, String command)
    {
        if(!canBypassCheck(player, this) || isBusy())
            return;
        StringTokenizer st = new StringTokenizer(command);
        if(st.nextToken().equals("rescue") && HellboundManager.getHellboundLevel() == 5)
        {
            Functions.npcSay(this, "Только тихо! Охранники повсюду. Пойдем.");
            HellboundManager.addConfidence(10);
            //this.doDie(null);
            this.endDecayTask();
            //TODO fallowing
            getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE);
        }
        else
            super.onBypassFeedback(player, command);
    }Почему дохнет нашел:
Врубил:Код:this.doDie(null);
Теперь проблема в том, что он не идет за персом...Код:getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE);
Код:@Override public void onBypassFeedback(Player player, String command) { if(!canBypassCheck(player, this) || isBusy()) return; StringTokenizer st = new StringTokenizer(command); if(st.nextToken().equals("rescue") && HellboundManager.getHellboundLevel() == 5) { Functions.npcSay(this, "Только тихо! Охранники повсюду. Пойдем."); HellboundManager.addConfidence(10); //this.doDie(null); this.endDecayTask(); //TODO fallowing getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE); } else super.onBypassFeedback(player, command); }
В аи его вообще нет. Мб с кого-то содрать можно?У него аи то какое? Если CtrlIntention.AI_INTENTION_FOLLOW не реализован, то сначала реализовать его надо.
protected boolean tryMoveToTarget(Creature target, int range)
    {
        NpcInstance actor = getActor();
        if(!actor.followToCharacter(target, actor.getPhysicalAttackRange(), true))
            _pathfindFails++;
        if(_pathfindFails >= getMaxPathfindFails() && (System.currentTimeMillis() > getAttackTimeout() - getMaxAttackTimeout() + getTeleportTimeout()) && actor.isInRange(target, MAX_PURSUE_RANGE))
        {
            _pathfindFails = 0;
            if(target.isPlayable())
            {
                AggroInfo hate = actor.getAggroList().get(target);
                if(hate == null || hate.hate < 100)
                {
                    returnHome();
                    return false;
                }
            }
            Location loc = GeoEngine.moveCheckForAI(target.getLoc(), actor.getLoc(), actor.getGeoIndex());
            if(!GeoEngine.canMoveToCoord(actor.getX(), actor.getY(), actor.getZ(), loc.x, loc.y, loc.z, actor.getGeoIndex())) // Для подстраховки
                loc = target.getLoc();
            actor.teleToLocation(loc);
        }
        return true;
    }this.setRunning();
this.setFollowTarget(player);
this.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE);Тоже самое.Код:this.setRunning(); this.setFollowTarget(player); this.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE);
package npc.model;
import java.util.concurrent.Future;
import l2p.commons.threading.RunnableImpl;
import l2p.gameserver.ThreadPoolManager;
import l2p.gameserver.config.OtherConfig;
import l2p.gameserver.model.Creature;
import l2p.gameserver.model.Party;
import l2p.gameserver.model.Player;
import l2p.gameserver.model.Zone;
import l2p.gameserver.model.instances.NpcInstance;
import l2p.gameserver.model.quest.QuestState;
import l2p.gameserver.templates.npc.NpcTemplate;
import l2p.gameserver.utils.ChatUtils;
import l2p.gameserver.utils.ReflectionUtils;
public final class QuestFollowerNpcInstance extends NpcInstance
{
    // С какой периодичностью проверять зону в текущих координатах, а так же расстояние до игрока и заставлять нпс следовать за игроком при необходимости
    private static final int StateCheckInterval = 5 * 1000;
    // Через какое время после появления деспавнится, если с нпс никто не поговорил
    private static final int DespawnIfStartInterval = 120 * 1000;
    // Через какое время после завершения всех задач по квесту деспавнится
    private static final int DespawnIfFinalizedInterval = 60 * 1000;
    // Расстояние, на которое максимально игрок, за которым следует нпс, может отойти - при превышении этого расстояния нпс деспавнется
    private static final int MaxFollowRange = 5000;
    private Future<?> _stateCheckTask, _despawnTask = null;
    private State _state = State.START;
    private Player _leader = null;
    private Party _party = null;
    private int _questId, _questCond = 0;
    private String[] _arrivedZone = new String[0];
    private boolean _partyQuest = false;
    public enum State
    {
        START,
        WALK,
        ARRIVED,
        FINALIZED
    }
    public QuestFollowerNpcInstance(int objectId, NpcTemplate template)
    {
        super(objectId, template);
        _despawnTask = scheduleDespawnTask(_despawnTask, DespawnIfStartInterval);
        _questId = 0;
        _questCond = 0;
        _partyQuest = false;
    }
    public State getState()
    {
        return _state;
    }
    public void setState(State state)
    {
        if (_leader == null)
            return;
        if (state == State.WALK)
        {
            ChatUtils.npcSay(this, "Вперед, не будем терять время и быстрее доберемся до безопасного места.");
            setRunning();
            if (_stateCheckTask != null)
            {
                _stateCheckTask.cancel(true);
                _stateCheckTask = null;
            }
            _stateCheckTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new CheckState(this), StateCheckInterval, StateCheckInterval);
        }
        else if (state == State.ARRIVED)
        {
            ChatUtils.npcSay(this, "Все, мы добрались до безопасного места. Поговорите со мной для продолжения задания.");
            stopMove();
        }
        else if (state == State.FINALIZED)
        {
            if (_despawnTask != null)
            {
                _despawnTask.cancel(true);
                _despawnTask = null;
            }
            _despawnTask = scheduleDespawnTask(_despawnTask, DespawnIfFinalizedInterval);
        }
        _state = state;
    }
    public void setQuest(int questId, int questCond, boolean partyQuest, boolean startDespawnTask)
    {
        _questId = questId;
        _questCond = questCond;
        _partyQuest = partyQuest;
        if (startDespawnTask)
            _despawnTask = scheduleDespawnTask(_despawnTask, DespawnIfStartInterval);
    }
    public void setArrivedZone(String... zone)
    {
        _arrivedZone = zone;
    }
    public void setArrivedState()
    {
        if (_questId == 0 || _questCond == 0 || _leader == null)
            return;
        if (_partyQuest && _party != null && _leader.getParty() != null && _party == _leader.getParty())
        {
            for (Player member : _leader.getParty().getPartyMembers())
            {
                QuestState st = member.getQuests().getState(_questId);
                if (_leader.isInRange(member, 1000) && st != null && st.isStarted() && st.getCond() != _questCond)
                    st.setCond(_questCond);
            }
        }
        else
        {
            QuestState st = _leader.getQuests().getState(_questId);
            if (st != null && st.isStarted() && st.getCond() != _questCond)
                st.setCond(_questCond);
        }
        setState(State.ARRIVED);
    }
    public Player getLeader()
    {
        return _leader;
    }
    public void setLeader(Player leader)
    {
        if (leader != null)
        {
            if (_despawnTask != null)
            {
                _despawnTask.cancel(true);
                _despawnTask = null;
            }
            _leader = leader;
            if (_partyQuest && _leader.getParty() != null)
                setLeaderParty(_leader.getParty());
        }
        else
        {
            resetState();
            onDecay();
        }
    }
    public void setLeaderParty(Party party)
    {
        _party = party;
    }
    public Party getLeaderParty()
    {
        return _party;
    }
    public void resetState()
    {
        stopMove();
        if (_stateCheckTask != null)
        {
            _stateCheckTask.cancel(true);
            _stateCheckTask = null;
        }
        if (_despawnTask != null)
        {
            _despawnTask.cancel(true);
            _despawnTask = null;
        }
        _leader = null;
        _party = null;
        _questId = 0;
        _questCond = 0;
        _arrivedZone = new String[0];
        _partyQuest = false;
        setState(State.START);
    }
    private Future<?> scheduleDespawnTask(Future<?> task, int taskInterval)
    {
        if (task != null)
            task.cancel(false);
        return ThreadPoolManager.getInstance().schedule(new DespawnTask(), taskInterval);
    }
    @Override
    protected void onDeath(Creature killer)
    {
        super.onDeath(killer);
        resetState();
    }
    private class CheckState extends RunnableImpl
    {
        private final QuestFollowerNpcInstance _follower;
        CheckState(QuestFollowerNpcInstance follower)
        {
            _follower = follower;
        }
        @Override
        public void runImpl() throws Exception
        {
            Player leader = _follower.getLeader();
            if (leader == null || !leader.isOnline() || !_follower.isInRange(leader, MaxFollowRange))
            {
                resetState();
                onDecay();
                return;
            }
            if (leader.isDead())
                return;
            if (_follower.getState() == State.WALK)
            {
                boolean isArrived = false;
                for (String zoneName : _arrivedZone)
                {
                    Zone zone = ReflectionUtils.getZone(zoneName);
                    if (zone != null && zone.checkIfInZone(_follower))
                        isArrived = true;
                }
                if (isArrived)
                    _follower.setArrivedState();
                else
                    _follower.followToCharacter(leader, OtherConfig.FOLLOW_RANGE, false);
            }
            else
                _follower.stopMove();
        }
    }
    private class DespawnTask extends RunnableImpl
    {
        @Override
        public void runImpl() throws Exception
        {
            resetState();
            onDecay();
        }
    }
}package quests;
import npc.model.QuestFollowerNpcInstance;
import npc.model.QuestFollowerNpcInstance.State;
import l2p.gameserver.data.holder.QuestRewardHolder;
import l2p.gameserver.model.instances.NpcInstance;
import l2p.gameserver.model.quest.Quest;
import l2p.gameserver.model.quest.QuestState;
/**
 * @author Gaikotsu
 * @version 4.1
 * @url https://l2central.info/wiki/Конца_и_края_нет
 */
public class _457_LostAndFound extends Quest
{
	private static final int Gumiel = 32759;
	private static final String[] Zones = { "[MoS_arrived_zone_1]", "[MoS_arrived_zone_2]" };
	public _457_LostAndFound()
	{
		super(PARTY_NONE);
		addLevelCheck(82);
		addStartNpc(Gumiel);
	}
	@Override
	public String onEvent(String event, QuestState st, NpcInstance npc)
	{
		String htmltext = event;
		if (event.equalsIgnoreCase("32759-02.htm"))
		{
			QuestFollowerNpcInstance follower = (QuestFollowerNpcInstance) npc;
			if (follower.getState() != State.START)
				return null;
			st.setState(STARTED);
			st.setCond(1);
			st.playSound(SOUND_ACCEPT);
			follower.setLeader(st.getPlayer());
			follower.setArrivedZone(Zones);
			follower.setState(State.WALK);
		}
		return htmltext;
	}
	@Override
	public String onTalk(NpcInstance npc, QuestState st)
	{
		String htmltext = "noquest";
		int npcId = npc.getNpcId();
		int cond = st.getCond();
		if (npcId == Gumiel)
		{
			QuestFollowerNpcInstance follower = (QuestFollowerNpcInstance) npc;
			if (cond == 0)
			{
				if (!isAvailableFor(st.getPlayer()))
					return "32759-00.htm";
				else if (follower.getState() == State.START)
					return "32759-01.htm";
				else if (follower.getState() == State.FINALIZED)
					return "32759-05.htm";
				else
					return "32759-06.htm";
			}
			else if (cond == 1 && follower.getState() == State.WALK)
				return "32759-03.htm";
			else if (cond == 2 && follower.getState() == State.ARRIVED)
			{
				follower.setState(State.FINALIZED);
				QuestRewardHolder.getInstance().giveRewards(st);
				st.exitCurrentQuest(this);
				return "32759-04.htm";
			}
		}
		return htmltext;
	}
}Спасибо, попробую)а ты смотри как суммоны за хозяином следуют и реализуй по аналогии.
скорее всего запускается таск, который периодически проверяет расстояние до хозяина и если расстояние слишком большое - задает движение к хозяину.
вот и запили аналогичный таск для данного случая.
з.ы. вызов методов через this. по сути излишне - без такой конкретики можно обойтись.
или вот тебе пример универсального класса типа квестового нпс, который бежит за игроком до определенной зоны
и пример его использования в квесте 457Код:package npc.model; import java.util.concurrent.Future; import l2p.commons.threading.RunnableImpl; import l2p.gameserver.ThreadPoolManager; import l2p.gameserver.config.OtherConfig; import l2p.gameserver.model.Creature; import l2p.gameserver.model.Party; import l2p.gameserver.model.Player; import l2p.gameserver.model.Zone; import l2p.gameserver.model.instances.NpcInstance; import l2p.gameserver.model.quest.QuestState; import l2p.gameserver.templates.npc.NpcTemplate; import l2p.gameserver.utils.ChatUtils; import l2p.gameserver.utils.ReflectionUtils; public final class QuestFollowerNpcInstance extends NpcInstance { // С какой периодичностью проверять зону в текущих координатах, а так же расстояние до игрока и заставлять нпс следовать за игроком при необходимости private static final int StateCheckInterval = 5 * 1000; // Через какое время после появления деспавнится, если с нпс никто не поговорил private static final int DespawnIfStartInterval = 120 * 1000; // Через какое время после завершения всех задач по квесту деспавнится private static final int DespawnIfFinalizedInterval = 60 * 1000; // Расстояние, на которое максимально игрок, за которым следует нпс, может отойти - при превышении этого расстояния нпс деспавнется private static final int MaxFollowRange = 5000; private Future<?> _stateCheckTask, _despawnTask = null; private State _state = State.START; private Player _leader = null; private Party _party = null; private int _questId, _questCond = 0; private String[] _arrivedZone = new String[0]; private boolean _partyQuest = false; public enum State { START, WALK, ARRIVED, FINALIZED } public QuestFollowerNpcInstance(int objectId, NpcTemplate template) { super(objectId, template); _despawnTask = scheduleDespawnTask(_despawnTask, DespawnIfStartInterval); _questId = 0; _questCond = 0; _partyQuest = false; } public State getState() { return _state; } public void setState(State state) { if (_leader == null) return; if (state == State.WALK) { ChatUtils.npcSay(this, "Вперед, не будем терять время и быстрее доберемся до безопасного места."); setRunning(); if (_stateCheckTask != null) { _stateCheckTask.cancel(true); _stateCheckTask = null; } _stateCheckTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new CheckState(this), StateCheckInterval, StateCheckInterval); } else if (state == State.ARRIVED) { ChatUtils.npcSay(this, "Все, мы добрались до безопасного места. Поговорите со мной для продолжения задания."); stopMove(); } else if (state == State.FINALIZED) { if (_despawnTask != null) { _despawnTask.cancel(true); _despawnTask = null; } _despawnTask = scheduleDespawnTask(_despawnTask, DespawnIfFinalizedInterval); } _state = state; } public void setQuest(int questId, int questCond, boolean partyQuest, boolean startDespawnTask) { _questId = questId; _questCond = questCond; _partyQuest = partyQuest; if (startDespawnTask) _despawnTask = scheduleDespawnTask(_despawnTask, DespawnIfStartInterval); } public void setArrivedZone(String... zone) { _arrivedZone = zone; } public void setArrivedState() { if (_questId == 0 || _questCond == 0 || _leader == null) return; if (_partyQuest && _party != null && _leader.getParty() != null && _party == _leader.getParty()) { for (Player member : _leader.getParty().getPartyMembers()) { QuestState st = member.getQuests().getState(_questId); if (_leader.isInRange(member, 1000) && st != null && st.isStarted() && st.getCond() != _questCond) st.setCond(_questCond); } } else { QuestState st = _leader.getQuests().getState(_questId); if (st != null && st.isStarted() && st.getCond() != _questCond) st.setCond(_questCond); } setState(State.ARRIVED); } public Player getLeader() { return _leader; } public void setLeader(Player leader) { if (leader != null) { if (_despawnTask != null) { _despawnTask.cancel(true); _despawnTask = null; } _leader = leader; if (_partyQuest && _leader.getParty() != null) setLeaderParty(_leader.getParty()); } else { resetState(); onDecay(); } } public void setLeaderParty(Party party) { _party = party; } public Party getLeaderParty() { return _party; } public void resetState() { stopMove(); if (_stateCheckTask != null) { _stateCheckTask.cancel(true); _stateCheckTask = null; } if (_despawnTask != null) { _despawnTask.cancel(true); _despawnTask = null; } _leader = null; _party = null; _questId = 0; _questCond = 0; _arrivedZone = new String[0]; _partyQuest = false; setState(State.START); } private Future<?> scheduleDespawnTask(Future<?> task, int taskInterval) { if (task != null) task.cancel(false); return ThreadPoolManager.getInstance().schedule(new DespawnTask(), taskInterval); } @Override protected void onDeath(Creature killer) { super.onDeath(killer); resetState(); } private class CheckState extends RunnableImpl { private final QuestFollowerNpcInstance _follower; CheckState(QuestFollowerNpcInstance follower) { _follower = follower; } @Override public void runImpl() throws Exception { Player leader = _follower.getLeader(); if (leader == null || !leader.isOnline() || !_follower.isInRange(leader, MaxFollowRange)) { resetState(); onDecay(); return; } if (leader.isDead()) return; if (_follower.getState() == State.WALK) { boolean isArrived = false; for (String zoneName : _arrivedZone) { Zone zone = ReflectionUtils.getZone(zoneName); if (zone != null && zone.checkIfInZone(_follower)) isArrived = true; } if (isArrived) _follower.setArrivedState(); else _follower.followToCharacter(leader, OtherConfig.FOLLOW_RANGE, false); } else _follower.stopMove(); } } private class DespawnTask extends RunnableImpl { @Override public void runImpl() throws Exception { resetState(); onDecay(); } } }
Код:package quests; import npc.model.QuestFollowerNpcInstance; import npc.model.QuestFollowerNpcInstance.State; import l2p.gameserver.data.holder.QuestRewardHolder; import l2p.gameserver.model.instances.NpcInstance; import l2p.gameserver.model.quest.Quest; import l2p.gameserver.model.quest.QuestState; /** * @author Gaikotsu * @version 4.1 * @url https://l2central.info/wiki/Конца_и_края_нет */ public class _457_LostAndFound extends Quest { private static final int Gumiel = 32759; private static final String[] Zones = { "[MoS_arrived_zone_1]", "[MoS_arrived_zone_2]" }; public _457_LostAndFound() { super(PARTY_NONE); addLevelCheck(82); addStartNpc(Gumiel); } @Override public String onEvent(String event, QuestState st, NpcInstance npc) { String htmltext = event; if (event.equalsIgnoreCase("32759-02.htm")) { QuestFollowerNpcInstance follower = (QuestFollowerNpcInstance) npc; if (follower.getState() != State.START) return null; st.setState(STARTED); st.setCond(1); st.playSound(SOUND_ACCEPT); follower.setLeader(st.getPlayer()); follower.setArrivedZone(Zones); follower.setState(State.WALK); } return htmltext; } @Override public String onTalk(NpcInstance npc, QuestState st) { String htmltext = "noquest"; int npcId = npc.getNpcId(); int cond = st.getCond(); if (npcId == Gumiel) { QuestFollowerNpcInstance follower = (QuestFollowerNpcInstance) npc; if (cond == 0) { if (!isAvailableFor(st.getPlayer())) return "32759-00.htm"; else if (follower.getState() == State.START) return "32759-01.htm"; else if (follower.getState() == State.FINALIZED) return "32759-05.htm"; else return "32759-06.htm"; } else if (cond == 1 && follower.getState() == State.WALK) return "32759-03.htm"; else if (cond == 2 && follower.getState() == State.ARRIVED) { follower.setState(State.FINALIZED); QuestRewardHolder.getInstance().giveRewards(st); st.exitCurrentQuest(this); return "32759-04.htm"; } } return htmltext; } }
public final class Slaves extends AbstractNpcAI
{
    // NPCs
    private static final int[] MASTERS =
    {
        22320, // Junior Watchman
        22321, // Junior Summoner
    };
    // Locations
    private static final Location MOVE_TO = new Location(-25451, 252291, -3252, 3500);
    // Misc
    private static final int TRUST_REWARD = 10;
   
    public Slaves()
    {
        super(Slaves.class.getSimpleName(), "hellbound/AI");
        addSpawnId(MASTERS);
        addKillId(MASTERS);
    }
   
    @Override
    public final String onSpawn(L2Npc npc)
    {
        ((L2MonsterInstance) npc).enableMinions(HellboundEngine.getInstance().getLevel() < 5);
        ((L2MonsterInstance) npc).setOnKillDelay(1000);
        return super.onSpawn(npc);
    }
   
    @Override
    public final String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
    {
        if (((L2MonsterInstance) npc).getMinionList() != null)
        {
            final List<L2MonsterInstance> slaves = ((L2MonsterInstance) npc).getMinionList().getSpawnedMinions();
            if ((slaves != null) && !slaves.isEmpty())
            {
                for (L2MonsterInstance slave : slaves)
                {
                    if ((slave == null) || slave.isDead())
                    {
                        continue;
                    }
                    slave.clearAggroList();
                    slave.abortAttack();
                    slave.abortCast();
                    broadcastNpcSay(slave, Say2.NPC_ALL, NpcStringId.THANK_YOU_FOR_SAVING_ME_FROM_THE_CLUTCHES_OF_EVIL);
                   
                    if ((HellboundEngine.getInstance().getLevel() >= 1) && (HellboundEngine.getInstance().getLevel() <= 2))
                    {
                        HellboundEngine.getInstance().updateTrust(TRUST_REWARD, false);
                    }
                    slave.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, MOVE_TO);
                    DecayTaskManager.getInstance().add(slave);
                }
            }
        }
        return super.onKill(npc, killer, isSummon);
    }
}public final class Quarry extends AbstractNpcAI
{
    // NPCs
    private static final int SLAVE = 32299;
    // Items
    protected static final ItemChanceHolder[] DROP_LIST =
    {
        new ItemChanceHolder(9628, 261), // Leonard
        new ItemChanceHolder(9630, 175), // Orichalcum
        new ItemChanceHolder(9629, 145), // Adamantine
        new ItemChanceHolder(1876, 6667), // Mithril ore
        new ItemChanceHolder(1877, 1333), // Adamantine nugget
        new ItemChanceHolder(1874, 2222), // Oriharukon ore
    };
    // Zone
    private static final int ZONE = 40107;
    // Misc
    private static final int TRUST = 50;
    
    public Quarry()
    {
        super(Quarry.class.getSimpleName(), "hellbound/AI/NPC");
        addSpawnId(SLAVE);
        addFirstTalkId(SLAVE);
        addStartNpc(SLAVE);
        addTalkId(SLAVE);
        addKillId(SLAVE);
        addEnterZoneId(ZONE);
    }
    
    @Override
    public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
    {
        String htmltext = null;
        switch (event)
        {
            case "FollowMe":
            {
                npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
                npc.setTarget(player);
                npc.setAutoAttackable(true);
                npc.setRHandId(9136);
                npc.setWalking();
                
                if (getQuestTimer("TIME_LIMIT", npc, null) == null)
                {
                    startQuestTimer("TIME_LIMIT", 900000, npc, null); // 15 min limit for save
                }
                htmltext = "32299-02.htm";
                break;
            }
            case "TIME_LIMIT":
            {
                for (L2ZoneType zone : ZoneManager.getInstance().getZones(npc))
                {
                    if (zone.getId() == 40108)
                    {
                        npc.setTarget(null);
                        npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
                        npc.setAutoAttackable(false);
                        npc.setRHandId(0);
                        npc.teleToLocation(npc.getSpawn().getLocation());
                        return null;
                    }
                }
                broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.HUN_HUNGRY);
                npc.doDie(npc);
                break;
            }
            case "DECAY":
            {
                if ((npc != null) && !npc.isDead())
                {
                    if (npc.getTarget().isPlayer())
                    {
                        for (ItemChanceHolder item : DROP_LIST)
                        {
                            if (getRandom(10000) < item.getChance())
                            {
                                npc.dropItem((L2PcInstance) npc.getTarget(), item.getId(), (int) (item.getCount() * Config.RATE_QUEST_DROP));
                                break;
                            }
                        }
                    }
                    npc.setAutoAttackable(false);
                    npc.deleteMe();
                    npc.getSpawn().decreaseCount(npc);
                    HellboundEngine.getInstance().updateTrust(TRUST, true);
                }
            }
        }
        
        return htmltext;
    }
    
    @Override
    public final String onSpawn(L2Npc npc)
    {
        npc.setAutoAttackable(false);
        if (npc instanceof L2QuestGuardInstance)
        {
            ((L2QuestGuardInstance) npc).setPassive(true);
        }
        return super.onSpawn(npc);
    }
    
    @Override
    public final String onFirstTalk(L2Npc npc, L2PcInstance player)
    {
        if (HellboundEngine.getInstance().getLevel() != 5)
        {
            return "32299.htm";
        }
        return "32299-01.htm";
    }
    
    @Override
    public final String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
    {
        npc.setAutoAttackable(false);
        return super.onKill(npc, killer, isSummon);
    }
    
    @Override
    public final String onEnterZone(L2Character character, L2ZoneType zone)
    {
        if (character.isAttackable())
        {
            final L2Attackable npc = (L2Attackable) character;
            if (npc.getId() == SLAVE)
            {
                if (!npc.isDead() && !npc.isDecayed() && (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_FOLLOW))
                {
                    if (HellboundEngine.getInstance().getLevel() == 5)
                    {
                        startQuestTimer("DECAY", 1000, npc, null);
                        try
                        {
                            broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.THANK_YOU_FOR_THE_RESCUE_ITS_A_SMALL_GIFT);
                        }
                        catch (Exception e)
                        {
                            //
                        }
                    }
                }
            }
        }
        return super.onEnterZone(character, zone);
    }
}