[?] Исчезают Quarry Slave

Psycho

Просветленный
Модератор
Орден Золотого Заката
Победитель в номинации 2023
Победитель в номинации 2022
Победитель в номинации 2021
Участник Новогоднего Фонда 2021
Неукротимое пламя
Старожил II степени
Победитель в номинации 2020
Победитель в номинации 2019
Знаток великого письма
Знаток письма
Веселый флудер
Мастер реакций
Любитель реакций
Знаток Lineage2
Старожил I степени
Победитель в номинации 2017
Победитель в номинации 2016
Медаль за активность на Форуме
За веру и верность форуму
Сообщения
4 456
Розыгрыши
1
Решения
3
Репутация
4 331
Реакции
2 805
Баллы
2 438
Quarry Slave после диалога тупо исчезают, вместо того чтобы следовать за персом до Dolmen'а.
Из-за отсутствия гео может быть, или же дело в другом?
Предыдущие стадии работают корректно.
Shot00000.jpg
 

Оффтоп:
Привет, Псих
 
Тут вроде лечащих проблемы по видео нет :)

Код их смотри - что отрабатывает при нажатии соответствующих байпасов в их диалогах.
 
Последнее редактирование модератором:
Тут вроде лечащих проблемы по видео нет :)

Код их смотри - что отрабатывает при нажатии соответствующих байпасов в их диалогах.
Ага, походу нашел...
Код:
//TODO: following
//getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player, Config.FOLLOW_RANGE);
Всё весьма печальненько. Даже если эту функу из TODO заюзать, они всё равно исчезают.

В яве я инвалид, самостоятельно не зафикшу. В какой нибудь сборке есть фикс?)
 
Последнее редактирование:

    KateKate7912

    Баллов: 0
    Даже если в другой сборке есть фикс, ты его перенесешь?
ღ Kate ღ
Даже если в другой сборке есть фикс, ты его перенесешь?
Остальное же переношу. :D
 
Думаю в квесте надо посмотреть метод FirstTalk c этим мобом (или в байпасе HTML псомотреть действсе после нажатия линка) по видео видно что ты его в место того чтоб дать команду следовать за сабой, просто убиваеш, из за этого они и исчезают
 
Думаю в квесте надо посмотреть метод FirstTalk c этим мобом (или в байпасе HTML псомотреть действсе после нажатия линка) по видео видно что ты его в место того чтоб дать команду следовать за сабой, просто убиваеш, из за этого они и исчезают
Ну да, тупо умирают, и быстро исчезают. Пробовал убивать через //kill, исчезают дольше.
Спасибо, посмотрю.
 
Почему дохнет нашел:
Код:
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 не реализован, то сначала реализовать его надо.
 
У него аи то какое? Если CtrlIntention.AI_INTENTION_FOLLOW не реализован, то сначала реализовать его надо.
В аи его вообще нет. Мб с кого-то содрать можно?
Я конечно хз, но мб это к нему можно прикрутить?
DefaultAI
Код:
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. по сути излишне - без такой конкретики можно обойтись.

или вот тебе пример универсального класса типа квестового нпс, который бежит за игроком до определенной зоны
Код:
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();
        }
    }
}
и пример его использования в квесте 457
Код:
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. по сути излишне - без такой конкретики можно обойтись.

или вот тебе пример универсального класса типа квестового нпс, который бежит за игроком до определенной зоны
Код:
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();
        }
    }
}
и пример его использования в квесте 457
Код:
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;
    }
}
Спасибо, попробую)
 
Gaikotsu, кстати, а у хб вообще квесты есть (ну кроме квеста на вход), или они по аи работают?
 
У l2jserver вот такое нарыл)
Код:
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);
    }
}
 
Назад
Сверху Снизу