Как НЕ надо писать квесты

Gaikotsu

яжпрограммист
Легенда
Победитель в номинации 2023
Победитель в номинации 2022
Победитель в номинации 2021
Участник Новогоднего Фонда 2021
Эксперт
Знаток
Просветитель
Магистр реакций
Знаток письма
Куратор Данных
Медаль Благодарности
Старожил II степени
Старожил I степени
Победитель в номинации 2020
Победитель в номинации 2019
Клиент разработчик
Преподаватель
За веру и верность форуму
Победитель в номинации 2018
Медаль за активность на Форуме
За заслуги перед форумом
Web разработчик
Разработчик
За знание датапака
За знание ядра
Сообщения
1 519
Розыгрыши
0
Решения
24
Репутация
6 004
Реакции
2 579
Баллы
2 188
Сидел сегодня, писал реализацию квеста
И чет черт попутал позырить, как же этот квест у L2Scripts реализован, в той шарной сборке Артеи.
Ну... вобщем самое цензурное что мне в голову пришло после того как я "это" увидел это слово "п...ц"...

Ну вобщем сами смотрите, как не стоит писать
Код:
package quests;

import java.util.List;

import l2s.commons.threading.RunnableImpl;
import l2s.commons.util.Rnd;
import l2s.gameserver.Config;
import l2s.gameserver.ThreadPoolManager;
import l2s.gameserver.ai.CtrlIntention;
import l2s.gameserver.model.GameObjectsStorage;
import l2s.gameserver.model.Player;
import l2s.gameserver.model.instances.NpcInstance;
import l2s.gameserver.model.quest.Quest;
import l2s.gameserver.model.quest.QuestState;
import l2s.gameserver.network.l2.s2c.ExSendUIEventPacket;
import l2s.gameserver.network.l2.s2c.ExShowScreenMessage;
import l2s.gameserver.network.l2.s2c.ExShowScreenMessage.ScreenMessageAlign;
import l2s.gameserver.network.l2.components.NpcString;
import l2s.gameserver.scripts.ScriptFile;
import l2s.gameserver.utils.Location;
import l2s.gameserver.utils.NpcUtils;

/**
* @author blacksmoke
*/
public class _10742_AFurryFriend extends Quest implements ScriptFile
{
    private static final int Leira = 33952;
    private static final int KikusCave = 33995;
    private static final int Ricky = 19552;
    private static final int Kiku = 23453;
  
    protected static Location[] POINTS =
    {
        new Location(-78152, 237352, -3569),
        new Location(-79176, 236792, -3440),
        new Location(-80072, 237064, -3311),
        new Location(-80440, 237320, -3313)
    };
  
    public _10742_AFurryFriend()
    {
        super(false);
        addStartNpc(Leira);
        addTalkId(Leira, KikusCave);
        addLevelCheck(11, 20);
        addClassIdCheck(182, 183);
    }
  
    @Override
    public String onEvent(String event, QuestState qs, NpcInstance npc)
    {
        NpcInstance ricky = GameObjectsStorage.getByNpcId(Ricky);
        String htmltext = event;
        switch(event)
        {
            case "quest_ac":
                qs.setState(STARTED);
                qs.setCond(1);
                qs.playSound(SOUND_ACCEPT);
                qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.FOLLOW_RICKY, 4500, ScreenMessageAlign.TOP_CENTER));
                ricky = NpcUtils.spawnSingle(Ricky, new Location(-78138, 237328, -3548));
                ricky.setRunning();
                ThreadPoolManager.getInstance().schedule(new RickyMoveTask(ricky), 1000L);
                htmltext = "33952-3.htm";
                break;
          
            case "quest_cont":
                qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.TAKE_RICKY_TO_LEIRA_IN_UNDER_2_MINUTES, 4500, ScreenMessageAlign.TOP_CENTER));
                ricky = NpcUtils.spawnSingle(Ricky, new Location(qs.getPlayer().getX(), qs.getPlayer().getY(), qs.getPlayer().getZ()));
              
                if(seeRicky(ricky, qs.getPlayer()) == null)
                {
                    // TODO: Ricky's title don't work
                    ricky.setTitle(qs.getPlayer().getName());
                    ricky.setRunning();
                    ricky.setFollowTarget(qs.getPlayer());
                    ricky.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, qs.getPlayer(), 50);
                }
              
                ThreadPoolManager.getInstance().schedule(new CheckRickyDistance(GameObjectsStorage.getByNpcId(Ricky), GameObjectsStorage.getByNpcId(Leira), qs), 500L);
                qs.getPlayer().sendPacket(new ExSendUIEventPacket(qs.getPlayer(), 0, 0, 120, 0, NpcString.REMAINING_TIME));
                qs.startQuestTimer("despawnRicky", 120 * 1000L, ricky);
                htmltext = "33995-3.htm";
                break;
          
            case "despawnRicky":
                if(ricky != null)
                {
                    ricky.deleteMe();
                }
                break;
        }
      
        return htmltext;
    }
  
    @Override
    public String onTalk(NpcInstance npc, QuestState qs)
    {
        if(qs.isCompleted())
        {
            return "completed";
        }
        String htmltext = "noquest";
        final int cond = qs.getCond();
      
        switch(npc.getNpcId())
        {
            case Leira:
                switch(cond)
                {
                    case 0:
                        if(checkStartCondition(qs.getPlayer()))
                        {
                            htmltext = "33952-1.htm";
                        }
                        break;
                  
                    case 2:
                        htmltext = "33952-4.htm";
                        qs.giveItems(57, 2500);
                        qs.addExpAndSp(52516, 5);
                        qs.exitCurrentQuest(false);
                        qs.playSound(SOUND_FINISH);
                        break;
                  
                    default:
                        htmltext = "noqu.htm";
                        break;
                }
                break;
          
            case KikusCave:
                if(cond == 1)
                {
                    final NpcInstance ricky = GameObjectsStorage.getByNpcId(Ricky);
                    if(ricky == null)
                    {
                        htmltext = "33995-1.htm";
                    }
                    else
                    {
                        final NpcInstance kiku = qs.addSpawn(Kiku, qs.getPlayer().getX() - Rnd.get(50), qs.getPlayer().getY() - Rnd.get(50), qs.getPlayer().getZ());
                        kiku.getAggroList().addDamageHate(qs.getPlayer(), 0, 10000);
                        kiku.setAggressionTarget(qs.getPlayer());
                        qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.RICKY_IS_NOT_HERENTRY_SEARCHING_ANOTHER_KIKUS_CAVE, 4500, ScreenMessageAlign.TOP_CENTER));
                        htmltext = "33995-2.htm";
                    }
                }
                break;
        }
        return htmltext;
    }
  
    class CheckRickyDistance implements Runnable
    {
        final NpcInstance ricky;
        final NpcInstance leira;
        final QuestState qs;
      
        public CheckRickyDistance(NpcInstance npcRicky, NpcInstance npcLeira, QuestState state)
        {
            ricky = npcRicky;
            leira = npcLeira;
            qs = state;
        }
      
        @Override
        public void run()
        {
            while (true)
            {
                if((ricky != null) && (leira != null) && (ricky.getDistance(leira) < 100))
                {
                    qs.setCond(2);
                    qs.getPlayer().sendPacket(new ExSendUIEventPacket(qs.getPlayer(), 0, 0, 0, 0, NpcString.REMAINING_TIME));
                    qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.RICKY_HAS_FOUND_LEIRA, 4500, ScreenMessageAlign.TOP_CENTER));

                    ThreadPoolManager.getInstance().schedule(new RunnableImpl(){
                        @Override
                        public void runImpl() throws Exception
                        {
                            ricky.deleteMe();
                        }
                    }, 3000);
                    return;
                }
              
                if(ricky == null)
                {
                    return;
                }
              
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
  
    class RickyMoveTask implements Runnable
    {
        final NpcInstance ricky;
        int _step = 0;
      
        RickyMoveTask(NpcInstance npc)
        {
            ricky = npc;
        }
      
        @Override
        public void run()
        {
            while (true)
            {
                if(_step < POINTS.length)
                {
                    if(ricky.isMoving)
                    {
                        try
                        {
                            Thread.sleep(500L);
                        }
                        catch (InterruptedException e)
                        {
                            e.printStackTrace();
                        }
                        continue;
                    }
                    ricky.moveToLocation(POINTS[_step], 0, true);
                    _step++;
                }
                else
                {
                    ricky.deleteMe();
                    return;
                }
            }
        }
    }
  
    private NpcInstance seeRicky(NpcInstance npc, Player player)
    {
        final List<NpcInstance> around = npc.getAroundNpc(Config.FOLLOW_RANGE * 2, 300);
      
        if((around != null) && !around.isEmpty())
        {
            for (NpcInstance n : around)
            {
                if(((n.getNpcId() == Ricky) && (n.getFollowTarget() != null)) && (n.getFollowTarget().getObjectId() == player.getObjectId()))
                {
                    return n;
                }
            }
        }
      
        return null;
    }
  
    @Override
    public void onLoad()
    {
        //
    }
  
    @Override
    public void onReload()
    {
        //
    }
  
    @Override
    public void onShutdown()
    {
        //
    }
}
Сразу видно как минимум 2 мега-косяка
1. вся работа с нпс, которого надо притащить к другому нпс идет через GameObjectsStorage.getByNpcId, т.е. всегда берется первый попавшися в хранилище объектов нпс с этим ид. к чему это приведет, если квест паралельно в одно время делают больше одного игрока, вы думаю уже осознали.
2. Таски CheckRickyDistance и RickyMoveTask - это "п...ц" в квадрате - while(true), слипание трида...

чисто ради примера, вот какая у меня реализация получилась - не скажу что тоже идеал, но все же мне думаю за нее краснеть не придется
 
Последнее редактирование модератором:

Однозначно +. Сейчас набегут чудо кОдиры чтобы квест захапать)
 
а толку :)
там есть вещи в других классах, на которые ссылается квест, которых нет в оригинальном овере, так что тому кто захочет заличить - поведение всего этого придется самому реализовывать.
вон к примеру за маленьким таким подключением AI WalkerAI лежат несколько десятков кб кода, которые отвечают за полную реализацию любых бродящих по заданным маршрутам мирных неписей и мобов.
 
Жесть, и их сборки берут по 20к. Жаль клиентов.
 
Немножко оффтопа по этому поводу
Жесть, и их сборки берут по 20к. Жаль клиентов.
[2:48:42] ADMIN Lineage-sib: поможешь )С ПЕРЕНОСАМ БД ЗАПЛАЧУ[2:49:17] smile10: Заплачешь? Ну лан[2:49:32] smile10: )00[2:49:53] Enmity: чё ему[2:49:57] Enmity: перенести надо[2:50:00] Enmity: куда откуда зачем[2:50:09] smile10: ХЗ ШОТА НА ИНТЕРЛЮДАХ Х1200 НАВЕРНА[2:50:16] Enmity: скажи[2:50:19] Enmity: фришки не чиним[2:51:05] smile10: руоффы чиним[2:51:06] smile10: изи[2:51:09] smile10: особенно корейские[2:51:12] Enmity: байдкоды[2:51:17] Enmity: от профессионалов[2:56:17] smile10: НПЕ в хтмлки и многое другое. Выбирая жопакоде девелопмент вы получаете полное отсутствие проблем по работе кода, максимально опциональную и гибкую настройку сервера, а так же многое другое, чего не описать словами. Выбирая Жопакоде - вы выбираете качество, гарантию, стабильность и уверенность в завтрашнем дне. Выбирай с умом.[2:56:31] Enmity: збс[2:56:34] Enmity: не купят[2:56:50] smile10: Ну бля[2:56:55] smile10: у скриптов же прокатило[2:56:58] Enmity: бля[2:57:00] Enmity: а правда ведь
 
Обратите внимание, что данный пользователь заблокирован! Не совершайте с ним никаких сделок! Перейдите в его профиль, чтобы узнать причину блокировки.
Код:
package quests;

import java.util.List;

import l2s.commons.threading.RunnableImpl;
import l2s.commons.util.Rnd;
import l2s.gameserver.Config;
import l2s.gameserver.ThreadPoolManager;
import l2s.gameserver.ai.CtrlIntention;
import l2s.gameserver.model.GameObjectsStorage;
import l2s.gameserver.model.Player;
import l2s.gameserver.model.instances.NpcInstance;
import l2s.gameserver.model.quest.Quest;
import l2s.gameserver.model.quest.QuestState;
import l2s.gameserver.network.l2.s2c.ExSendUIEventPacket;
import l2s.gameserver.network.l2.s2c.ExShowScreenMessage;
import l2s.gameserver.network.l2.s2c.ExShowScreenMessage.ScreenMessageAlign;
import l2s.gameserver.network.l2.components.NpcString;
import l2s.gameserver.scripts.ScriptFile;
import l2s.gameserver.utils.Location;
import l2s.gameserver.utils.NpcUtils;

/**
* @author blacksmoke
*/
public class _10742_AFurryFriend extends Quest implements ScriptFile
{
    private static final int Leira = 33952;
    private static final int KikusCave = 33995;
    private static int KikusCout;
    private static final int Ricky = 19552;
    private static final int Kiku = 23453;
   
    protected static Location[] POINTS =
    {
        new Location(-78152, 237352, -3569),
        new Location(-79176, 236792, -3440),
        new Location(-80072, 237064, -3311),
        new Location(-80440, 237320, -3313)
    };
   
    public _10742_AFurryFriend()
    {
        super(false);
        addStartNpc(Leira);
        addTalkId(Leira, KikusCave);
        addLevelCheck(11, 20);
        addClassIdCheck(182, 183);
    }
   
    @Override
    public String onEvent(String event, QuestState qs, NpcInstance npc)
    {
        NpcInstance ricky = GameObjectsStorage.getByNpcId(Ricky);
        String htmltext = event;
        switch(event)
        {
            case "quest_ac":
                qs.setState(STARTED);
                qs.setCond(1);
                qs.playSound(SOUND_ACCEPT);
                qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.FOLLOW_RICKY, 4500, ScreenMessageAlign.TOP_CENTER));
                ricky = NpcUtils.spawnSingle(Ricky, new Location(-78138, 237328, -3548));
                ricky.setRunning();
                ThreadPoolManager.getInstance().schedule(new RickyMoveTask(ricky), 1000L);
                htmltext = "33952-3.htm";
                KikusCout = 0;
                break;
           
            case "quest_cont":
                qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.TAKE_RICKY_TO_LEIRA_IN_UNDER_2_MINUTES, 4500, ScreenMessageAlign.TOP_CENTER));
                ricky = NpcUtils.spawnSingle(Ricky, new Location(qs.getPlayer().getX(), qs.getPlayer().getY(), qs.getPlayer().getZ()));
               
                if(seeRicky(ricky, qs.getPlayer()) == null)
                {
                    // TODO: Ricky's title don't work
                    ricky.setTitle(qs.getPlayer().getName());
                    ricky.setRunning();
                    ricky.setFollowTarget(qs.getPlayer());
                    ricky.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, qs.getPlayer(), 50);
                }
               
                ThreadPoolManager.getInstance().schedule(new CheckRickyDistance(GameObjectsStorage.getByNpcId(Ricky), GameObjectsStorage.getByNpcId(Leira), qs), 500L);
                qs.getPlayer().sendPacket(new ExSendUIEventPacket(qs.getPlayer(), 0, 0, 120, 0, NpcString.REMAINING_TIME));
                qs.startQuestTimer("despawnRicky", 120 * 1000L, ricky);
                htmltext = "33995-3.htm";
                break;
           
            case "despawnRicky":
                if(ricky != null)
                {
                    KikusCout = 0;
                    ricky.deleteMe();
                }
                break;
        }
       
        return htmltext;
    }
   
    @Override
    public String onTalk(NpcInstance npc, QuestState qs)
    {
        if(qs.isCompleted())
        {
            return "completed";
        }
        String htmltext = "noquest";
        final int cond = qs.getCond();
       
        switch(npc.getNpcId())
        {
            case Leira:
                switch(cond)
                {
                    case 0:
                        if(checkStartCondition(qs.getPlayer()))
                        {
                            htmltext = "33952-1.htm";
                        }
                        break;
                   
                    case 2:
                        htmltext = "33952-4.htm";
                        qs.giveItems(57, 2500);
                        qs.addExpAndSp(52516, 5);
                        qs.exitCurrentQuest(false);
                        qs.playSound(SOUND_FINISH);
                        break;
                   
                    default:
                        htmltext = "noqu.htm";
                        break;
                }
                break;
           
            case KikusCave:
                if(cond == 1)
                {
                    if (qs.get("RikkyCave") == null)
                        qs.set("RikkyCave", Rnd.get(0, 2));

                    final NpcInstance ricky = GameObjectsStorage.getByNpcId(Ricky);
                    if(ricky == null && KikusCout == Integer.valueOf(qs.get("RikkyCave")))
                    {
                        KikusCout = 0;
                        qs.unset("RikkyCave");
                        htmltext = "33995-1.htm";
                    }
                    else
                    {
                        if (ricky == null)
                        {
                            final NpcInstance kiku = qs.addSpawn(Kiku, qs.getPlayer().getX() - Rnd.get(50), qs.getPlayer().getY() - Rnd.get(50), qs.getPlayer().getZ());
                            kiku.getAggroList().addDamageHate(qs.getPlayer(), 0, 10000);
                            kiku.setAggressionTarget(qs.getPlayer());
                        }
                        qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.RICKY_IS_NOT_HERENTRY_SEARCHING_ANOTHER_KIKUS_CAVE, 4500, ScreenMessageAlign.TOP_CENTER));
                        htmltext = "33995-2.htm";
                        KikusCout++;
                    }
                }
                break;
        }
        return htmltext;
    }
   
    class CheckRickyDistance implements Runnable
    {
        final NpcInstance ricky;
        final NpcInstance leira;
        final QuestState qs;
       
        public CheckRickyDistance(NpcInstance npcRicky, NpcInstance npcLeira, QuestState state)
        {
            ricky = npcRicky;
            leira = npcLeira;
            qs = state;
        }
       
        @Override
        public void run()
        {
            while (true)
            {
                if((ricky != null) && (leira != null) && (ricky.getDistance(leira) < 100))
                {
                    qs.setCond(2);
                    qs.getPlayer().sendPacket(new ExSendUIEventPacket(qs.getPlayer(), 0, 0, 0, 0, NpcString.REMAINING_TIME));
                    qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.RICKY_HAS_FOUND_LEIRA, 4500, ScreenMessageAlign.TOP_CENTER));

                    ThreadPoolManager.getInstance().schedule(new RunnableImpl(){
                        @Override
                        public void runImpl() throws Exception
                        {
                            ricky.deleteMe();
                        }
                    }, 3000);
                    return;
                }
               
                if(ricky == null)
                {
                    return;
                }
               
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
   
    class RickyMoveTask implements Runnable
    {
        final NpcInstance ricky;
        int _step = 0;
       
        RickyMoveTask(NpcInstance npc)
        {
            ricky = npc;
        }
       
        @Override
        public void run()
        {
            while (true)
            {
                if(_step < POINTS.length)
                {
                    if(ricky.isMoving)
                    {
                        try
                        {
                            Thread.sleep(500L);
                        }
                        catch (InterruptedException e)
                        {
                            e.printStackTrace();
                        }
                        continue;
                    }
                    ricky.moveToLocation(POINTS[_step], 0, true);
                    _step++;
                }
                else
                {
                    ricky.deleteMe();
                    return;
                }
            }
        }
    }
   
    private NpcInstance seeRicky(NpcInstance npc, Player player)
    {
        final List<NpcInstance> around = npc.getAroundNpc(Config.FOLLOW_RANGE * 2, 300);
       
        if((around != null) && !around.isEmpty())
        {
            for (NpcInstance n : around)
            {
                if(((n.getNpcId() == Ricky) && (n.getFollowTarget() != null)) && (n.getFollowTarget().getObjectId() == player.getObjectId()))
                {
                    return n;
                }
            }
        }
       
        return null;
    }
   
    @Override
    public void onLoad()
    {
        //
    }
   
    @Override
    public void onReload()
    {
        //
    }
   
    @Override
    public void onShutdown()
    {
        //
    }
}
 
Код:
package quests;

import java.util.List;

import l2s.commons.threading.RunnableImpl;
import l2s.commons.util.Rnd;
import l2s.gameserver.Config;
import l2s.gameserver.ThreadPoolManager;
import l2s.gameserver.ai.CtrlIntention;
import l2s.gameserver.model.GameObjectsStorage;
import l2s.gameserver.model.Player;
import l2s.gameserver.model.instances.NpcInstance;
import l2s.gameserver.model.quest.Quest;
import l2s.gameserver.model.quest.QuestState;
import l2s.gameserver.network.l2.s2c.ExSendUIEventPacket;
import l2s.gameserver.network.l2.s2c.ExShowScreenMessage;
import l2s.gameserver.network.l2.s2c.ExShowScreenMessage.ScreenMessageAlign;
import l2s.gameserver.network.l2.components.NpcString;
import l2s.gameserver.scripts.ScriptFile;
import l2s.gameserver.utils.Location;
import l2s.gameserver.utils.NpcUtils;

/**
* @author blacksmoke
*/
public class _10742_AFurryFriend extends Quest implements ScriptFile
{
    private static final int Leira = 33952;
    private static final int KikusCave = 33995;
    private static int KikusCout;
    private static final int Ricky = 19552;
    private static final int Kiku = 23453;
  
    protected static Location[] POINTS =
    {
        new Location(-78152, 237352, -3569),
        new Location(-79176, 236792, -3440),
        new Location(-80072, 237064, -3311),
        new Location(-80440, 237320, -3313)
    };
  
    public _10742_AFurryFriend()
    {
        super(false);
        addStartNpc(Leira);
        addTalkId(Leira, KikusCave);
        addLevelCheck(11, 20);
        addClassIdCheck(182, 183);
    }
  
    @Override
    public String onEvent(String event, QuestState qs, NpcInstance npc)
    {
        NpcInstance ricky = GameObjectsStorage.getByNpcId(Ricky);
        String htmltext = event;
        switch(event)
        {
            case "quest_ac":
                qs.setState(STARTED);
                qs.setCond(1);
                qs.playSound(SOUND_ACCEPT);
                qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.FOLLOW_RICKY, 4500, ScreenMessageAlign.TOP_CENTER));
                ricky = NpcUtils.spawnSingle(Ricky, new Location(-78138, 237328, -3548));
                ricky.setRunning();
                ThreadPoolManager.getInstance().schedule(new RickyMoveTask(ricky), 1000L);
                htmltext = "33952-3.htm";
                KikusCout = 0;
                break;
          
            case "quest_cont":
                qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.TAKE_RICKY_TO_LEIRA_IN_UNDER_2_MINUTES, 4500, ScreenMessageAlign.TOP_CENTER));
                ricky = NpcUtils.spawnSingle(Ricky, new Location(qs.getPlayer().getX(), qs.getPlayer().getY(), qs.getPlayer().getZ()));
              
                if(seeRicky(ricky, qs.getPlayer()) == null)
                {
                    // TODO: Ricky's title don't work
                    ricky.setTitle(qs.getPlayer().getName());
                    ricky.setRunning();
                    ricky.setFollowTarget(qs.getPlayer());
                    ricky.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, qs.getPlayer(), 50);
                }
              
                ThreadPoolManager.getInstance().schedule(new CheckRickyDistance(GameObjectsStorage.getByNpcId(Ricky), GameObjectsStorage.getByNpcId(Leira), qs), 500L);
                qs.getPlayer().sendPacket(new ExSendUIEventPacket(qs.getPlayer(), 0, 0, 120, 0, NpcString.REMAINING_TIME));
                qs.startQuestTimer("despawnRicky", 120 * 1000L, ricky);
                htmltext = "33995-3.htm";
                break;
          
            case "despawnRicky":
                if(ricky != null)
                {
                    KikusCout = 0;
                    ricky.deleteMe();
                }
                break;
        }
      
        return htmltext;
    }
  
    @Override
    public String onTalk(NpcInstance npc, QuestState qs)
    {
        if(qs.isCompleted())
        {
            return "completed";
        }
        String htmltext = "noquest";
        final int cond = qs.getCond();
      
        switch(npc.getNpcId())
        {
            case Leira:
                switch(cond)
                {
                    case 0:
                        if(checkStartCondition(qs.getPlayer()))
                        {
                            htmltext = "33952-1.htm";
                        }
                        break;
                  
                    case 2:
                        htmltext = "33952-4.htm";
                        qs.giveItems(57, 2500);
                        qs.addExpAndSp(52516, 5);
                        qs.exitCurrentQuest(false);
                        qs.playSound(SOUND_FINISH);
                        break;
                  
                    default:
                        htmltext = "noqu.htm";
                        break;
                }
                break;
          
            case KikusCave:
                if(cond == 1)
                {
                    if (qs.get("RikkyCave") == null)
                        qs.set("RikkyCave", Rnd.get(0, 2));

                    final NpcInstance ricky = GameObjectsStorage.getByNpcId(Ricky);
                    if(ricky == null && KikusCout == Integer.valueOf(qs.get("RikkyCave")))
                    {
                        KikusCout = 0;
                        qs.unset("RikkyCave");
                        htmltext = "33995-1.htm";
                    }
                    else
                    {
                        if (ricky == null)
                        {
                            final NpcInstance kiku = qs.addSpawn(Kiku, qs.getPlayer().getX() - Rnd.get(50), qs.getPlayer().getY() - Rnd.get(50), qs.getPlayer().getZ());
                            kiku.getAggroList().addDamageHate(qs.getPlayer(), 0, 10000);
                            kiku.setAggressionTarget(qs.getPlayer());
                        }
                        qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.RICKY_IS_NOT_HERENTRY_SEARCHING_ANOTHER_KIKUS_CAVE, 4500, ScreenMessageAlign.TOP_CENTER));
                        htmltext = "33995-2.htm";
                        KikusCout++;
                    }
                }
                break;
        }
        return htmltext;
    }
  
    class CheckRickyDistance implements Runnable
    {
        final NpcInstance ricky;
        final NpcInstance leira;
        final QuestState qs;
      
        public CheckRickyDistance(NpcInstance npcRicky, NpcInstance npcLeira, QuestState state)
        {
            ricky = npcRicky;
            leira = npcLeira;
            qs = state;
        }
      
        @Override
        public void run()
        {
            while (true)
            {
                if((ricky != null) && (leira != null) && (ricky.getDistance(leira) < 100))
                {
                    qs.setCond(2);
                    qs.getPlayer().sendPacket(new ExSendUIEventPacket(qs.getPlayer(), 0, 0, 0, 0, NpcString.REMAINING_TIME));
                    qs.getPlayer().sendPacket(new ExShowScreenMessage(NpcString.RICKY_HAS_FOUND_LEIRA, 4500, ScreenMessageAlign.TOP_CENTER));

                    ThreadPoolManager.getInstance().schedule(new RunnableImpl(){
                        @Override
                        public void runImpl() throws Exception
                        {
                            ricky.deleteMe();
                        }
                    }, 3000);
                    return;
                }
              
                if(ricky == null)
                {
                    return;
                }
              
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
  
    class RickyMoveTask implements Runnable
    {
        final NpcInstance ricky;
        int _step = 0;
      
        RickyMoveTask(NpcInstance npc)
        {
            ricky = npc;
        }
      
        @Override
        public void run()
        {
            while (true)
            {
                if(_step < POINTS.length)
                {
                    if(ricky.isMoving)
                    {
                        try
                        {
                            Thread.sleep(500L);
                        }
                        catch (InterruptedException e)
                        {
                            e.printStackTrace();
                        }
                        continue;
                    }
                    ricky.moveToLocation(POINTS[_step], 0, true);
                    _step++;
                }
                else
                {
                    ricky.deleteMe();
                    return;
                }
            }
        }
    }
  
    private NpcInstance seeRicky(NpcInstance npc, Player player)
    {
        final List<NpcInstance> around = npc.getAroundNpc(Config.FOLLOW_RANGE * 2, 300);
      
        if((around != null) && !around.isEmpty())
        {
            for (NpcInstance n : around)
            {
                if(((n.getNpcId() == Ricky) && (n.getFollowTarget() != null)) && (n.getFollowTarget().getObjectId() == player.getObjectId()))
                {
                    return n;
                }
            }
        }
      
        return null;
    }
  
    @Override
    public void onLoad()
    {
        //
    }
  
    @Override
    public void onReload()
    {
        //
    }
  
    @Override
    public void onShutdown()
    {
        //
    }
}
Ага, новый трид запилили с while(true).
 
Назад
Сверху Снизу