Как сделать нпц l2jmobius

la2bluff4

Свой человек
Участник
Сообщения
29
Розыгрыши
0
Репутация
58
Реакции
16
Баллы
548
Хроники
  1. Fafurion
Сборка
l2jmobius
Всем привет !! такой вопрос как сделать нпц которого надо сопроводить до определенной точке ( наподобие нпц в мосе *Искатель сокровищ Сумиэль* _)
cборка l2Jmobius fufarion
 
Посмотреть как сделан этот самый нпц в мосе?
 
Java:
/*
 * This file is part of the L2J Mobius project.
 *
 * 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
 */
package ai.areas.TalkingIsland.QuestRoutes;

import ai.AbstractNpcAI;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.WalkRoute;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.interfaces.IPositionable;
import org.l2jmobius.gameserver.model.quest.QuestState;
import org.l2jmobius.gameserver.model.variables.NpcVariables;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExRotation;
import org.l2jmobius.gameserver.util.Util;
import quests.Q10322_SearchingForTheMysteriousPower.Q10322_SearchingForTheMysteriousPower;
import quests.Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField;

/**
 * Training Camp Soldier route AI.
 * @author Index
 */
public class TrainingCampSoldier_01 extends AbstractNpcAI
{
    // NPCs
    private static final int CAMP_SOLDIER_01 = 33006;
    // Misc
    private static final String PLAYER_VAR = "OWNER";
    private static final String CURRENT_QUEST = "CURRENT_QUEST";
    private static final String CURRENT_ROUTE = "CURRENT_ROUTE";
    private static final String CURRENT_POINT = "CURRENT_POINT";
    private static final String AVOID_POINT = "AVOID_POINT";
    private static final WalkRoute _route01 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10322_SHANNON_TO_EVAIN");
    private static final WalkRoute _route02 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10323_EVAIN_TO_HOLDEN_01");
    private static final WalkRoute _route03 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10323_EVAIN_TO_HOLDEN_02");

    private TrainingCampSoldier_01()
    {
        addSpawnId(CAMP_SOLDIER_01);
        addMoveFinishedId(CAMP_SOLDIER_01);
    }

    @Override
    public String onAdvEvent(String event, Npc npc, Player player)
    {
        NpcVariables npcVar = npc.getVariables();
        if (event.equals("CHECK_CHARACTER"))
        {
            Player owner = npcVar.getPlayer(PLAYER_VAR) == null ? null : npcVar.getPlayer(PLAYER_VAR);
            WalkRoute _current_route = npcVar.getObject(CURRENT_ROUTE, WalkRoute.class);
            if (    owner == null ||
                    !owner.isOnline() ||
                    _current_route == null ||
                    owner.getQuestState(npcVar.getString(CURRENT_QUEST)) == null
                )
            {
                npcVar.remove(PLAYER_VAR);
                npcVar.remove(CURRENT_QUEST);
                npcVar.remove(CURRENT_ROUTE);
                npcVar.remove(CURRENT_POINT);
                npcVar.remove(AVOID_POINT);
                npc.deleteMe();
                cancelQuestTimer("CHECK_CHARACTER", npc, owner);
                return null;
            }
            QuestState questState = owner.getQuestState(npcVar.getString(CURRENT_QUEST));
            int _currentPoint = npcVar.getInt(CURRENT_POINT, -1);
            int _avoid = npcVar.getInt(AVOID_POINT, 0);
            if (npc.calculateDistance2D(player.getLocation()) < 200)
            {
                npcVar.set(AVOID_POINT, 0);
                if (_currentPoint < _current_route.getNodesCount())
                {
                    IPositionable l = _current_route.getNodeList().get(_currentPoint).getLocation();
                    addMoveToDesire(npc, new Location(l.getX(), l.getY(), l.getZ()), 0);
                }
                startQuestTimer("CHECK_CHARACTER", 500, npc, owner);
            }
            else if (npc.calculateDistance2D(player.getLocation()) >= 150)
            {
                npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, player.getAppearance().getVisibleName());
                npcVar.set(AVOID_POINT, _avoid + 1);
                npc.setHeading(Util.calculateHeadingFrom(npc, owner));
                npc.broadcastPacket(new ExRotation(npc.getObjectId(), npc.getHeading()));
                startQuestTimer("CHECK_CHARACTER", 3000, npc, owner);
            }
            if ((_currentPoint == _current_route.getNodesCount() && npc.calculateDistance2D(_current_route.getNodeList().get(0).getLocation()) < 10)
                    || npc.calculateDistance2D(_current_route.getLastNode().getLocation()) < 10
                    || questState.getCond() != 1)
            {
                npcVar.remove(PLAYER_VAR);
                npcVar.remove(CURRENT_QUEST);
                npcVar.remove(CURRENT_ROUTE);
                npcVar.remove(CURRENT_POINT);
                npcVar.remove(AVOID_POINT);
                npc.deleteMe();
                cancelQuestTimer("CHECK_CHARACTER", npc, owner);
                return null;
            }
        }
        else
        {
            npcVar.remove(PLAYER_VAR);
            npcVar.remove(CURRENT_QUEST);
            npcVar.remove(CURRENT_ROUTE);
            npcVar.remove(CURRENT_POINT);
            npcVar.remove(AVOID_POINT);
            npc.deleteMe();
            cancelQuestTimer("CHECK_CHARACTER", npc, player);
            return null;
        }
        return super.onAdvEvent(event, npc, player);
    }

    @Override
    public String onSpawn(Npc npc)
    {
        if (npc.getTarget() == null)
        {
            return null;
        }
        Player player = npc.getTarget().getActingPlayer();
        NpcVariables npcVar = npc.getVariables();
        npcVar.set(PLAYER_VAR, player);
        npcVar.set(CURRENT_POINT, 0);
        npcVar.set(AVOID_POINT, 0);
        if (player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()) != null &&
                !player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()).isCompleted() &&
                player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()).isCond(1))
        {
            npcVar.set(CURRENT_QUEST, Q10322_SearchingForTheMysteriousPower.class.getSimpleName());
            npcVar.set(CURRENT_ROUTE, _route01);
        }
        else if (player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()) != null &&
                !player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()).isCompleted() &&
                player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()).isCond(1))
        {
            npcVar.set(CURRENT_ROUTE, Rnd.get(0, 100) < 50 ? _route02 : _route03);
            npcVar.set(CURRENT_QUEST, Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName());
        }
        else
        {
            return null;
        }
        npc.setRunning();
        startQuestTimer("CHECK_CHARACTER", 500, npc, npc.getTarget().getActingPlayer());
        npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, player.getAppearance().getVisibleName());

        return super.onSpawn(npc);
    }

    @Override
    public void onMoveFinished(Npc npc)
    {
        final Player owner = npc.getVariables().getPlayer(PLAYER_VAR);
        if (owner != null)
        {
            npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, owner.getAppearance().getVisibleName());
            npc.getVariables().set(CURRENT_POINT, npc.getVariables().getInt(CURRENT_POINT, 0) + 1);
        }
    }

    public static void main(String[] args)
    {
        new TrainingCampSoldier_01();
    }
}
Вот я короче делал НПС-а, который водит чаров на ГОД и кричит "ей ты, беги сюда".
А это его маршрут.
XML:
<route name="TALKING_ISLAND_10322_SHANNON_TO_EVAIN" repeat="false" repeatStyle="none">
        <!-- <target id="33306" spawnX="-111392" spawnY="255781" spawnZ="-1447" /> -->
        <point X="-111392" Y="255781" Z="-1447" run="true" delay="0"/>
        <point X="-112039" Y="255331" Z="-1456" run="true" delay="0"/>
        <point X="-112603" Y="254820" Z="-1532" run="true" delay="0"/>
        <point X="-112284" Y="254249" Z="-1548" run="true" delay="0"/>
        <point X="-111699" Y="254038" Z="-1679" run="true" delay="0"/>
        <point X="-110780" Y="253714" Z="-1794" run="true" delay="0"/>
    </route>
 
Java:
/*
 * This file is part of the L2J Mobius project.
 *
 * 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
 */
package ai.areas.TalkingIsland.QuestRoutes;

import ai.AbstractNpcAI;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.WalkRoute;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.interfaces.IPositionable;
import org.l2jmobius.gameserver.model.quest.QuestState;
import org.l2jmobius.gameserver.model.variables.NpcVariables;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExRotation;
import org.l2jmobius.gameserver.util.Util;
import quests.Q10322_SearchingForTheMysteriousPower.Q10322_SearchingForTheMysteriousPower;
import quests.Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField;

/**
 * Training Camp Soldier route AI.
 * @author Index
 */
public class TrainingCampSoldier_01 extends AbstractNpcAI
{
    // NPCs
    private static final int CAMP_SOLDIER_01 = 33006;
    // Misc
    private static final String PLAYER_VAR = "OWNER";
    private static final String CURRENT_QUEST = "CURRENT_QUEST";
    private static final String CURRENT_ROUTE = "CURRENT_ROUTE";
    private static final String CURRENT_POINT = "CURRENT_POINT";
    private static final String AVOID_POINT = "AVOID_POINT";
    private static final WalkRoute _route01 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10322_SHANNON_TO_EVAIN");
    private static final WalkRoute _route02 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10323_EVAIN_TO_HOLDEN_01");
    private static final WalkRoute _route03 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10323_EVAIN_TO_HOLDEN_02");

    private TrainingCampSoldier_01()
    {
        addSpawnId(CAMP_SOLDIER_01);
        addMoveFinishedId(CAMP_SOLDIER_01);
    }

    @Override
    public String onAdvEvent(String event, Npc npc, Player player)
    {
        NpcVariables npcVar = npc.getVariables();
        if (event.equals("CHECK_CHARACTER"))
        {
            Player owner = npcVar.getPlayer(PLAYER_VAR) == null ? null : npcVar.getPlayer(PLAYER_VAR);
            WalkRoute _current_route = npcVar.getObject(CURRENT_ROUTE, WalkRoute.class);
            if (    owner == null ||
                    !owner.isOnline() ||
                    _current_route == null ||
                    owner.getQuestState(npcVar.getString(CURRENT_QUEST)) == null
                )
            {
                npcVar.remove(PLAYER_VAR);
                npcVar.remove(CURRENT_QUEST);
                npcVar.remove(CURRENT_ROUTE);
                npcVar.remove(CURRENT_POINT);
                npcVar.remove(AVOID_POINT);
                npc.deleteMe();
                cancelQuestTimer("CHECK_CHARACTER", npc, owner);
                return null;
            }
            QuestState questState = owner.getQuestState(npcVar.getString(CURRENT_QUEST));
            int _currentPoint = npcVar.getInt(CURRENT_POINT, -1);
            int _avoid = npcVar.getInt(AVOID_POINT, 0);
            if (npc.calculateDistance2D(player.getLocation()) < 200)
            {
                npcVar.set(AVOID_POINT, 0);
                if (_currentPoint < _current_route.getNodesCount())
                {
                    IPositionable l = _current_route.getNodeList().get(_currentPoint).getLocation();
                    addMoveToDesire(npc, new Location(l.getX(), l.getY(), l.getZ()), 0);
                }
                startQuestTimer("CHECK_CHARACTER", 500, npc, owner);
            }
            else if (npc.calculateDistance2D(player.getLocation()) >= 150)
            {
                npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, player.getAppearance().getVisibleName());
                npcVar.set(AVOID_POINT, _avoid + 1);
                npc.setHeading(Util.calculateHeadingFrom(npc, owner));
                npc.broadcastPacket(new ExRotation(npc.getObjectId(), npc.getHeading()));
                startQuestTimer("CHECK_CHARACTER", 3000, npc, owner);
            }
            if ((_currentPoint == _current_route.getNodesCount() && npc.calculateDistance2D(_current_route.getNodeList().get(0).getLocation()) < 10)
                    || npc.calculateDistance2D(_current_route.getLastNode().getLocation()) < 10
                    || questState.getCond() != 1)
            {
                npcVar.remove(PLAYER_VAR);
                npcVar.remove(CURRENT_QUEST);
                npcVar.remove(CURRENT_ROUTE);
                npcVar.remove(CURRENT_POINT);
                npcVar.remove(AVOID_POINT);
                npc.deleteMe();
                cancelQuestTimer("CHECK_CHARACTER", npc, owner);
                return null;
            }
        }
        else
        {
            npcVar.remove(PLAYER_VAR);
            npcVar.remove(CURRENT_QUEST);
            npcVar.remove(CURRENT_ROUTE);
            npcVar.remove(CURRENT_POINT);
            npcVar.remove(AVOID_POINT);
            npc.deleteMe();
            cancelQuestTimer("CHECK_CHARACTER", npc, player);
            return null;
        }
        return super.onAdvEvent(event, npc, player);
    }

    @Override
    public String onSpawn(Npc npc)
    {
        if (npc.getTarget() == null)
        {
            return null;
        }
        Player player = npc.getTarget().getActingPlayer();
        NpcVariables npcVar = npc.getVariables();
        npcVar.set(PLAYER_VAR, player);
        npcVar.set(CURRENT_POINT, 0);
        npcVar.set(AVOID_POINT, 0);
        if (player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()) != null &&
                !player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()).isCompleted() &&
                player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()).isCond(1))
        {
            npcVar.set(CURRENT_QUEST, Q10322_SearchingForTheMysteriousPower.class.getSimpleName());
            npcVar.set(CURRENT_ROUTE, _route01);
        }
        else if (player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()) != null &&
                !player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()).isCompleted() &&
                player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()).isCond(1))
        {
            npcVar.set(CURRENT_ROUTE, Rnd.get(0, 100) < 50 ? _route02 : _route03);
            npcVar.set(CURRENT_QUEST, Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName());
        }
        else
        {
            return null;
        }
        npc.setRunning();
        startQuestTimer("CHECK_CHARACTER", 500, npc, npc.getTarget().getActingPlayer());
        npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, player.getAppearance().getVisibleName());

        return super.onSpawn(npc);
    }

    @Override
    public void onMoveFinished(Npc npc)
    {
        final Player owner = npc.getVariables().getPlayer(PLAYER_VAR);
        if (owner != null)
        {
            npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, owner.getAppearance().getVisibleName());
            npc.getVariables().set(CURRENT_POINT, npc.getVariables().getInt(CURRENT_POINT, 0) + 1);
        }
    }

    public static void main(String[] args)
    {
        new TrainingCampSoldier_01();
    }
}
Вот я короче делал НПС-а, который водит чаров на ГОД и кричит "ей ты, беги сюда".
А это его маршрут.
XML:
<route name="TALKING_ISLAND_10322_SHANNON_TO_EVAIN" repeat="false" repeatStyle="none">
        <!-- <target id="33306" spawnX="-111392" spawnY="255781" spawnZ="-1447" /> -->
        <point X="-111392" Y="255781" Z="-1447" run="true" delay="0"/>
        <point X="-112039" Y="255331" Z="-1456" run="true" delay="0"/>
        <point X="-112603" Y="254820" Z="-1532" run="true" delay="0"/>
        <point X="-112284" Y="254249" Z="-1548" run="true" delay="0"/>
        <point X="-111699" Y="254038" Z="-1679" run="true" delay="0"/>
        <point X="-110780" Y="253714" Z="-1794" run="true" delay="0"/>
    </route>
а вот это создавать надо аи фаил да как напримере с мосом ?
 
давайте вместе составим мануал ! чтоб другим тоже понятно было а то я только учусь такому,
было бы полезно узнать у опытных форумчан

а можеш файлом в личку готового скинуть с html папкой в аи чтоб я смог прикрутить
 
При работе НПС через АИ нужно:
1. Придумать респ. Сам себя НПС не зареспит. Или делать его сразу в спавнах или делать через АИ или при каких-то условиях в скриптах (пример - временные зоны. Там сложнее ибо идет респ через группы, которые указываются в XML файле и потом вызываются через spawnGroup).
2. Создать АИ в папке с АИ (если в инстах каких-то учавствуют - в то там же (в скрипте инство) чаще всего и задают все... Но правильнее будет создать отдельный АИ скрипт);
3. Ну а дальше смотреть на примеры уже готовых АИ ? Не понимаю вопрос в чем смысл "в личку готового НПС".
НПС, которого я выше скинул - он у меня молчит как партизан в ближнем разговоре. Кричать любит издалека )
Есть 2 метода для работы с АИ.
1 - это через default - то-есть добавляем в html/default файлик с ИД нпс и там уже пишем что хотим сказать и кнопку (используется если не знаю, НПС на выход из инсты только и заделан). Там уже с помощью кнопок <a action="bypass -h Quest TalkingIslandUndergroundTrainingRoom 33021-01.html">"No, please tell me."</a> вызываем ивент у АИ.
2 - это полная работа через АИ. То-есть добавление его через onFirstTalk и onAdvEvent (к примеру кнопка выше будет обработана onAdvEvent и ивентом будет служить 33021-01.html, от вот этого можно и плясать:
Java:
    @Override
    public String onAdvEvent(String event, Npc npc, Player player)
    {
        switch (event)
        {
            case "33021-01.html":
            {
                player.sendPacket(new TutorialShowHtml(npc.getObjectId(), "..\\L2Text\\QT_003_bullet_01.htm", TutorialShowHtml.LARGE_WINDOW));
                return "33021-02w.html";
            }
        }
    }
, главное не забыть добавить обработку в АИ типо addFirstTalkId(TI_GUARD);)
Еще можно таймеры создавать и они будут обрабатываться по типу onAdvEvent(), где ивентом будет имя таймера
Java:
 @Override
 public String onAdvEvent(String event, Npc npc, Player player)
 {
     if (event.equals("ATTACK"))
    {
        startAttack(npc.getInstanceWorld());
    }
    return null;
}
 
 private void startAttack(Instance instance)
    {
        for (Npc npc : instance.getNpcs(GUARD))
        {
            if (npc.isDead() || npc.isInCombat())
            {
                continue;
            }
            for (Npc nearby : World.getInstance().getVisibleObjectsInRange(npc, Npc.class, 150))
            {
                if (nearby.getId() != CRAWLER)
                {
                    continue;
                }
                nearby.setRandomWalking(false);
                nearby.setRandomAnimation(false);
                npc.setRandomWalking(false);
                npc.setRandomAnimation(false);
                npc.setInvul(true);
                nearby.doAutoAttack(npc);
                npc.doAutoAttack(nearby);
                nearby.disableAllSkills();
                break;
            }
        }
        startQuestTimer("ATTACK", 1000, instance.getNpc(AYMEN), instance.getFirstPlayer());
    }
 
При работе НПС через АИ нужно:
1. Придумать респ. Сам себя НПС не зареспит. Или делать его сразу в спавнах или делать через АИ или при каких-то условиях в скриптах (пример - временные зоны. Там сложнее ибо идет респ через группы, которые указываются в XML файле и потом вызываются через spawnGroup).
2. Создать АИ в папке с АИ (если в инстах каких-то учавствуют - в то там же (в скрипте инство) чаще всего и задают все... Но правильнее будет создать отдельный АИ скрипт);
3. Ну а дальше смотреть на примеры уже готовых АИ ? Не понимаю вопрос в чем смысл "в личку готового НПС".
НПС, которого я выше скинул - он у меня молчит как партизан в ближнем разговоре. Кричать любит издалека )
Есть 2 метода для работы с АИ.
1 - это через default - то-есть добавляем в html/default файлик с ИД нпс и там уже пишем что хотим сказать и кнопку (используется если не знаю, НПС на выход из инсты только и заделан). Там уже с помощью кнопок <a action="bypass -h Quest TalkingIslandUndergroundTrainingRoom 33021-01.html">"No, please tell me."</a> вызываем ивент у АИ.
2 - это полная работа через АИ. То-есть добавление его через onFirstTalk и onAdvEvent (к примеру кнопка выше будет обработана onAdvEvent и ивентом будет служить 33021-01.html, от вот этого можно и плясать:
Java:
    @Override
    public String onAdvEvent(String event, Npc npc, Player player)
    {
        switch (event)
        {
            case "33021-01.html":
            {
                player.sendPacket(new TutorialShowHtml(npc.getObjectId(), "..\\L2Text\\QT_003_bullet_01.htm", TutorialShowHtml.LARGE_WINDOW));
                return "33021-02w.html";
            }
        }
    }
, главное не забыть добавить обработку в АИ типо addFirstTalkId(TI_GUARD);)
Еще можно таймеры создавать и они будут обрабатываться по типу onAdvEvent(), где ивентом будет имя таймера
Java:
 @Override
 public String onAdvEvent(String event, Npc npc, Player player)
 {
     if (event.equals("ATTACK"))
    {
        startAttack(npc.getInstanceWorld());
    }
    return null;
}
 
 private void startAttack(Instance instance)
    {
        for (Npc npc : instance.getNpcs(GUARD))
        {
            if (npc.isDead() || npc.isInCombat())
            {
                continue;
            }
            for (Npc nearby : World.getInstance().getVisibleObjectsInRange(npc, Npc.class, 150))
            {
                if (nearby.getId() != CRAWLER)
                {
                    continue;
                }
                nearby.setRandomWalking(false);
                nearby.setRandomAnimation(false);
                npc.setRandomWalking(false);
                npc.setRandomAnimation(false);
                npc.setInvul(true);
                nearby.doAutoAttack(npc);
                npc.doAutoAttack(nearby);
                nearby.disableAllSkills();
                break;
            }
        }
        startQuestTimer("ATTACK", 1000, instance.getNpc(AYMEN), instance.getFirstPlayer());
    }
cпасибо щас попробую разобраться !

кто нить может скинуть пример !
в дионе стоит нпц его нужно довести до церкви к примеру ! чтоб все было понятно а то что то я не могу его установить и все
 
Java:
/*
 * This file is part of the L2J Mobius project.
 *
 * 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
 */
package ai.areas.TalkingIsland.QuestRoutes;

import ai.AbstractNpcAI;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.WalkRoute;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.interfaces.IPositionable;
import org.l2jmobius.gameserver.model.quest.QuestState;
import org.l2jmobius.gameserver.model.variables.NpcVariables;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExRotation;
import org.l2jmobius.gameserver.util.Util;
import quests.Q10322_SearchingForTheMysteriousPower.Q10322_SearchingForTheMysteriousPower;
import quests.Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField;

/**
 * Training Camp Soldier route AI.
 * @author Index
 */
public class TrainingCampSoldier_01 extends AbstractNpcAI
{
    // NPCs
    private static final int CAMP_SOLDIER_01 = 33006;
    // Misc
    private static final String PLAYER_VAR = "OWNER";
    private static final String CURRENT_QUEST = "CURRENT_QUEST";
    private static final String CURRENT_ROUTE = "CURRENT_ROUTE";
    private static final String CURRENT_POINT = "CURRENT_POINT";
    private static final String AVOID_POINT = "AVOID_POINT";
    private static final WalkRoute _route01 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10322_SHANNON_TO_EVAIN");
    private static final WalkRoute _route02 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10323_EVAIN_TO_HOLDEN_01");
    private static final WalkRoute _route03 = WalkingManager.getInstance().getRoute("TALKING_ISLAND_10323_EVAIN_TO_HOLDEN_02");

    private TrainingCampSoldier_01()
    {
        addSpawnId(CAMP_SOLDIER_01);
        addMoveFinishedId(CAMP_SOLDIER_01);
    }

    @Override
    public String onAdvEvent(String event, Npc npc, Player player)
    {
        NpcVariables npcVar = npc.getVariables();
        if (event.equals("CHECK_CHARACTER"))
        {
            Player owner = npcVar.getPlayer(PLAYER_VAR) == null ? null : npcVar.getPlayer(PLAYER_VAR);
            WalkRoute _current_route = npcVar.getObject(CURRENT_ROUTE, WalkRoute.class);
            if (    owner == null ||
                    !owner.isOnline() ||
                    _current_route == null ||
                    owner.getQuestState(npcVar.getString(CURRENT_QUEST)) == null
                )
            {
                npcVar.remove(PLAYER_VAR);
                npcVar.remove(CURRENT_QUEST);
                npcVar.remove(CURRENT_ROUTE);
                npcVar.remove(CURRENT_POINT);
                npcVar.remove(AVOID_POINT);
                npc.deleteMe();
                cancelQuestTimer("CHECK_CHARACTER", npc, owner);
                return null;
            }
            QuestState questState = owner.getQuestState(npcVar.getString(CURRENT_QUEST));
            int _currentPoint = npcVar.getInt(CURRENT_POINT, -1);
            int _avoid = npcVar.getInt(AVOID_POINT, 0);
            if (npc.calculateDistance2D(player.getLocation()) < 200)
            {
                npcVar.set(AVOID_POINT, 0);
                if (_currentPoint < _current_route.getNodesCount())
                {
                    IPositionable l = _current_route.getNodeList().get(_currentPoint).getLocation();
                    addMoveToDesire(npc, new Location(l.getX(), l.getY(), l.getZ()), 0);
                }
                startQuestTimer("CHECK_CHARACTER", 500, npc, owner);
            }
            else if (npc.calculateDistance2D(player.getLocation()) >= 150)
            {
                npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, player.getAppearance().getVisibleName());
                npcVar.set(AVOID_POINT, _avoid + 1);
                npc.setHeading(Util.calculateHeadingFrom(npc, owner));
                npc.broadcastPacket(new ExRotation(npc.getObjectId(), npc.getHeading()));
                startQuestTimer("CHECK_CHARACTER", 3000, npc, owner);
            }
            if ((_currentPoint == _current_route.getNodesCount() && npc.calculateDistance2D(_current_route.getNodeList().get(0).getLocation()) < 10)
                    || npc.calculateDistance2D(_current_route.getLastNode().getLocation()) < 10
                    || questState.getCond() != 1)
            {
                npcVar.remove(PLAYER_VAR);
                npcVar.remove(CURRENT_QUEST);
                npcVar.remove(CURRENT_ROUTE);
                npcVar.remove(CURRENT_POINT);
                npcVar.remove(AVOID_POINT);
                npc.deleteMe();
                cancelQuestTimer("CHECK_CHARACTER", npc, owner);
                return null;
            }
        }
        else
        {
            npcVar.remove(PLAYER_VAR);
            npcVar.remove(CURRENT_QUEST);
            npcVar.remove(CURRENT_ROUTE);
            npcVar.remove(CURRENT_POINT);
            npcVar.remove(AVOID_POINT);
            npc.deleteMe();
            cancelQuestTimer("CHECK_CHARACTER", npc, player);
            return null;
        }
        return super.onAdvEvent(event, npc, player);
    }

    @Override
    public String onSpawn(Npc npc)
    {
        if (npc.getTarget() == null)
        {
            return null;
        }
        Player player = npc.getTarget().getActingPlayer();
        NpcVariables npcVar = npc.getVariables();
        npcVar.set(PLAYER_VAR, player);
        npcVar.set(CURRENT_POINT, 0);
        npcVar.set(AVOID_POINT, 0);
        if (player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()) != null &&
                !player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()).isCompleted() &&
                player.getQuestState(Q10322_SearchingForTheMysteriousPower.class.getSimpleName()).isCond(1))
        {
            npcVar.set(CURRENT_QUEST, Q10322_SearchingForTheMysteriousPower.class.getSimpleName());
            npcVar.set(CURRENT_ROUTE, _route01);
        }
        else if (player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()) != null &&
                !player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()).isCompleted() &&
                player.getQuestState(Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName()).isCond(1))
        {
            npcVar.set(CURRENT_ROUTE, Rnd.get(0, 100) < 50 ? _route02 : _route03);
            npcVar.set(CURRENT_QUEST, Q10323_GoingIntoARealWarLetsGoToTheUndergroundTrainingField.class.getSimpleName());
        }
        else
        {
            return null;
        }
        npc.setRunning();
        startQuestTimer("CHECK_CHARACTER", 500, npc, npc.getTarget().getActingPlayer());
        npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, player.getAppearance().getVisibleName());

        return super.onSpawn(npc);
    }

    @Override
    public void onMoveFinished(Npc npc)
    {
        final Player owner = npc.getVariables().getPlayer(PLAYER_VAR);
        if (owner != null)
        {
            npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_COME_FOLLOW_ME, owner.getAppearance().getVisibleName());
            npc.getVariables().set(CURRENT_POINT, npc.getVariables().getInt(CURRENT_POINT, 0) + 1);
        }
    }

    public static void main(String[] args)
    {
        new TrainingCampSoldier_01();
    }
}
Вот я короче делал НПС-а, который водит чаров на ГОД и кричит "ей ты, беги сюда".
А это его маршрут.
XML:
<route name="TALKING_ISLAND_10322_SHANNON_TO_EVAIN" repeat="false" repeatStyle="none">
        <!-- <target id="33306" spawnX="-111392" spawnY="255781" spawnZ="-1447" /> -->
        <point X="-111392" Y="255781" Z="-1447" run="true" delay="0"/>
        <point X="-112039" Y="255331" Z="-1456" run="true" delay="0"/>
        <point X="-112603" Y="254820" Z="-1532" run="true" delay="0"/>
        <point X="-112284" Y="254249" Z="-1548" run="true" delay="0"/>
        <point X="-111699" Y="254038" Z="-1679" run="true" delay="0"/>
        <point X="-110780" Y="253714" Z="-1794" run="true" delay="0"/>
    </route>
???????
ну и смертельный номер...
Ветка артея - файл - dist/game/data/scripts/quests/Q10326_RespectYourElders/Q10326_RespectYourElders.java
НПС, который ведет чара - private static final int HANDERMONKEY = 32971;
Код:
private static final Location HANDERMONKEY_SPAWN = new Location(-116617, 255497, -1432);
    private static final Location[] HANDERMONKEY_LOC =
    {
        new Location(-116560, 255951, -1457),
        new Location(-116688, 256597, -1472),
        new Location(-116518, 257309, -1512),
        new Location(-116418, 257746, -1512),
        new Location(-115907, 257780, -1312),
        new Location(-115449, 257782, -1136),
        new Location(-114946, 257760, -1316),
        new Location(-114637, 257349, -1142),
        new Location(-114414, 257318, -1136),
    };
Параметры квеста
Код:
addSpawnId(HANDERMONKEY);
        addMoveFinishedId(HANDERMONKEY);
АДВ ивент
Код:
@Override
    public String onAdvEvent(String event, Npc npc, Player player)
    {
        case "CHECK_PLAYER":
            {
                final Player owner = npc.getVariables().getObject("OWNER", Player.class);
                if (owner != null)
                {
                    if (npc.calculateDistance2D(owner) < 120)
                    {
                        npc.getVariables().set("FAIL_COUNT", 0);
                        final int loc_index = npc.getVariables().getInt("MOVE_INDEX", -1) + 1;
                        if (loc_index > 0)
                        {
                            if (loc_index == 9)
                            {
                                npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.GO_GO_GO_CREEK);
                                startQuestTimer("DELETE_NPC", 2000, npc, owner);
                                break;
                            }
                            npc.getVariables().set("MOVE_INDEX", loc_index);
                            addMoveToDesire(npc, HANDERMONKEY_LOC[loc_index], 0);
                        }
                    }
                    else
                    {
                        final int failCount = npc.getVariables().getInt("FAIL_COUNT", 0);
                        npc.getVariables().set("FAIL_COUNT", failCount + 1);
                        if (failCount >= 30)
                        {
                            npc.deleteMe();
                            break;
                        }
                        
                        startQuestTimer("CHECK_PLAYER", 2000, npc, owner);
                        if (getRandom(100) < 10)
                        {
                            npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.COME_ON_CREEK);
                        }
                    }
                }
                else
                {
                    npc.deleteMe();
                }
                break;
            }
            case "MOVE_DELAY":
            {
                npc.getVariables().set("OWNER", player);
                npc.setTitle(player.getName());
                npc.setRunning();
                npc.broadcastInfo();
                addMoveToDesire(npc, HANDERMONKEY_LOC[0], 0);
                npc.getVariables().set("MOVE_INDEX", 0);
                break;
            }
            case "DELETE_NPC":
            {
                npc.deleteMe();
                break;
            }
        }
        return htmltext;
    }
и проверка на достижение точки
Код:
@Override
    public void onMoveFinished(Npc npc)
    {
        npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.COME_ON_CREEK);
        final Player owner = npc.getVariables().getObject("OWNER", Player.class);
        if (owner != null)
        {
            startQuestTimer("CHECK_PLAYER", 2000, npc, owner);
            npc.setHeading(Util.calculateHeadingFrom(npc, owner));
            npc.broadcastPacket(new ExRotation(npc.getObjectId(), npc.getHeading()));
        }
    }

ЕЩЕ СМЕРТЕЛЬНЫЙ НОМЕР
хроники - где-то етина фейт думаю
файл -> dist/game/data/scripts/instances/MysticTavern/StoryOfTauti/StoryOfTauti.java
НПС - private static final int DETON = 34170;
и заставляем его следовать за лидером пати
Код:
case "check_status":
            {
                final Npc deton = world.getNpc(DETON);
                deton.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.ARE_YOU_THE_ONES_WHO_WILL_BE_HELPING_OUT_WELCOME_I_VE_BEEN_WAITING_FOR_YOU);
                World.getInstance().forEachVisibleObjectInRange(npc, Player.class, 1000, pl ->
                {
                    if ((pl != null) && ((pl.isInParty() && pl.getParty().isLeader(pl)) || pl.isGM()))
                    {
                        deton.setTarget(pl);
                        deton.setRunning();
                        deton.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, pl);
                    }
                });
                startQuestTimer("msg_1", 7000, deton, null);
                break;
            }
Ну и на последок:
 
это конечно все хорошо но мне бы ! помогло вот такое

целый код нпц квеста готового уже чтоб от точки а в точку б и штмл и куда это все правильно записывать или просто создать в папке с квестами папку например minigame1 туда что дальше та )) вообщем обьясните дураку а то куски кода я их не соединю не как мне как для 5 летних детей пожалуйста ((( обьясните очень хочу сделать но не могу понять вот как и все
 
это конечно все хорошо но мне бы ! помогло вот такое

целый код нпц квеста готового уже чтоб от точки а в точку б и штмл и куда это все правильно записывать или просто создать в папке с квестами папку например minigame1 туда что дальше та )) вообщем обьясните дураку а то куски кода я их не соединю не как мне как для 5 летних детей пожалуйста ((( обьясните очень хочу сделать но не могу понять вот как и все
Тебе по ходу в раздел рынок.
 
Рассказываю.
У мобиуса есть такая штука, как "битбакет".
Заходим - ищем ветку (артея, это )
Ветка артея - файл - dist/game/data/scripts/quests/Q10326_RespectYourElders/Q10326_RespectYourElders.java
ищем файл выше.
1657786772525.webp
1657786792743.webp
Повторяем с другой ссылкой.
Или же просто напишите как есть "спасибо всем, но мне влом в этом всем разбираться, напишите мне и дайте уже готовый скрипт что сразу и это и это и 10 ХТМЛок показывало";
 
я это нашел даже вставил в папку с квестами и что там же целый квест с другой цепочки квестов
 
Назад
Сверху Снизу