questname обозначение

STALIN

Генералиссимус
VIP
Победитель в номинации 2022
Любитель реакций
Старожил I степени
Стальной Визионер
Победитель в номинации 2021
Участник Новогоднего Фонда 2021
Сообщения
249
Розыгрыши
0
Репутация
354
Реакции
559
Баллы
1 743
подскажите обозначение параметра для выполнения квеста, (необходимо убить к примеру 10 мобов определенных ID нужно в счетчик добавить квеста) или же подскажите для примера какой квест можно взять из готовых корейцами?* Shot00002.jpg
 
или же подскажите для примера какой квест можно взять из готовых корейцами?*
Признаки восстания? Он у тебя на скриншоте, если что.

А вообще честно говоря я может ерунду сморожу, но разве аларм требует какой то параметр? Чёто не припомню такого, вроде он просто любой квест прожрёт, где есть каунт чего либо. Но вот тут могу наврать.
 
  • Мне нравится
Реакции: Rolo
Признаки восстания? Он у тебя на скриншоте, если что.

А вообще честно говоря я может ерунду сморожу, но разве аларм требует какой то параметр? Чёто не припомню такого, вроде он просто любой квест прожрёт, где есть каунт чего либо. Но вот тут могу наврать.
я этот квест показал как пример что вот с права есть счетчик итемов, но мне нужно что бы счетчик работал не на итемы а на мобов (сколько мобов осталось убить и убил уже) п датник не принимает дополнительный параметр я так понял нужно уже ковырять сам клиент) то сообветственно того что я неумею)

ну или серверную часть) хотя мне кодер говорит все осталось в клиенте)
 
ну или серверную часть) хотя мне кодер говорит все осталось в клиенте)
ну он регистрирует какой то пачет
registerEvent( EV_ExpandQuestAlarmKillMonster );

и делает там вот это:
1642009730266.png

собсна так это и работает
 
Решение
я этот квест показал как пример что вот с права есть счетчик итемов, но мне нужно что бы счетчик работал не на итемы а на мобов (сколько мобов осталось убить и убил уже) п датник не принимает дополнительный параметр я так понял нужно уже ковырять сам клиент) то сообветственно того что я неумею)

ну или серверную часть) хотя мне кодер говорит все осталось в клиенте)
количество убиваемых мобов указывается в тех же самых полях QuestName, что и количество собираемых предметов

т.е. если к примеру для предметов это будет выглядеть так:
Код:
goal_id={36551;36556}    goal_type={0;0}    goal_num={70;145}

то для мобов надо указывать в goal_id ид моба, но не просто так, а прибавив к нему 1000000, т.е. к примеру так
Код:
goal_id={1022746;1022747}    goal_type={0;0}    goal_num={15;15}
в данном случае тогда будет показывать имена мобов с ид 22746 и 22747

так же в goal_type вместо 0 можно указывать 1 и тогда в goal_id необходимо указывать ид строки из NpcString, как к примеру так
Код:
goal_id={75021}    goal_type={1}    goal_num={1}
в данном случае в качестве пункта покажет строку с ид 75021 из NpcString

разные типы в goal_type можно комбинировать, например
Код:
goal_id={539354;36054}    goal_type={1;0}    goal_num={5;30}

ну а на стороне сервера пакет ExQuestNpcLogList требует доработки только если там не сделана поддержка goal_type равного 1, но это вряд ли.
 
Последнее редактирование:
Если что вот корректный пакет
Java:
package l2p.gameserver.network.s2c;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import l2p.gameserver.model.quest.QuestNpcLogInfo;
import l2p.gameserver.model.quest.QuestState;
import l2p.gameserver.network.components.Opcode;

public class ExQuestNpcLogList extends L2GameServerPacket
{
    private int _questId;
    private List<int[]> _list = Collections.emptyList();

    public ExQuestNpcLogList(QuestState state)
    {
        _questId = state.getQuest().getId();
        List<QuestNpcLogInfo> list = state.getQuest().getNpcLogList(state.getCond());

        if (list == null)
            return;

        _list = new ArrayList<int[]>(list.size());
        list.stream().forEach(info -> _list.add(info.getActionId() == 0 ? info.getNpcInfo(state) : info.getActionInfo(state)));
    }

    @Override
    protected void writeImpl()
    {
        writeEx(Opcode.ExQuestNpcLogList);
        writeD(_questId);
        writeC(_list.size());

        for (int[] info : _list)
        {
            writeD(info[0]); // ид npc с прибавкой к нему 1000000 или ид строки из NpcString
            writeC(info[1]); // тип данных: 0 - имя нпс, 1 - строка из NpcString
            writeD(info[2]); // значение счетчика
        }
    }
}
и используемый класс QuestNpcLogInfo в нем
Java:
package l2p.gameserver.model.quest;

public class QuestNpcLogInfo
{
    private final int[] _npcIds;
    private final int _actionId;
    private final int _add;
    private final int _max;
    private final String _varName;

    public QuestNpcLogInfo(int[] npcIds, int actionId, String varName, int add, int max)
    {
        _npcIds = npcIds;
        _actionId = actionId;
        _varName = varName;
        _add = add;
        _max = max;
    }

    public int[] getNpcIds()
    {
        return _npcIds;
    }

    public int getActionId()
    {
        return _actionId;
    }

    public String getVarName()
    {
        return _varName;
    }

    public int getAdd()
    {
        return _add;
    }

    public int getMax()
    {
        return _max;
    }
    
    public int[] getNpcInfo(QuestState st)
    {
        return new int[] { _npcIds[0] + 1000000, 0, st.getInt(_varName) };
    }
    
    public int[] getActionInfo(QuestState st)
    {
        return new int[] { _actionId, 1, st.getInt(_varName) };
    }
}
 
  • Мне нравится
Реакции: Rolo
Код:
tag_?    quest_id    quest_prog    main_name    prog_name    description    cnt1    items[0-13]    cnt2    num_items[0]    quest_x    quest_y    quest_z    lvl_min    lvl_max    quest_type    entity_name    get_item_in_quest    UNK_1    UNK_2    contact_npc_id    contact_npc_x    contact_npc_y    contact_npc_z    restricions    short_description    cnt3    req_class[0-68]   req_cl    cnt4    req_item[0-4]      clan_pet_quest    req_quest_complete    UNK_3    area_id    UNK_4    cnt5    tab5[0]    cnt6    tab6[0]
вот все мои колонки по квест нейм

Если что вот корректный пакет
Java:
package l2p.gameserver.network.s2c;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import l2p.gameserver.model.quest.QuestNpcLogInfo;
import l2p.gameserver.model.quest.QuestState;
import l2p.gameserver.network.components.Opcode;

public class ExQuestNpcLogList extends L2GameServerPacket
{
    private int _questId;
    private List<int[]> _list = Collections.emptyList();

    public ExQuestNpcLogList(QuestState state)
    {
        _questId = state.getQuest().getId();
        List<QuestNpcLogInfo> list = state.getQuest().getNpcLogList(state.getCond());

        if (list == null)
            return;

        _list = new ArrayList<int[]>(list.size());
        list.stream().forEach(info -> _list.add(info.getActionId() == 0 ? info.getNpcInfo(state) : info.getActionInfo(state)));
    }

    @Override
    protected void writeImpl()
    {
        writeEx(Opcode.ExQuestNpcLogList);
        writeD(_questId);
        writeC(_list.size());

        for (int[] info : _list)
        {
            writeD(info[0]); // ид npc с прибавкой к нему 1000000 или ид строки из NpcString
            writeC(info[1]); // тип данных: 0 - имя нпс, 1 - строка из NpcString
            writeD(info[2]); // значение счетчика
        }
    }
}
и используемый класс QuestNpcLogInfo в нем
Java:
package l2p.gameserver.model.quest;

public class QuestNpcLogInfo
{
    private final int[] _npcIds;
    private final int _actionId;
    private final int _add;
    private final int _max;
    private final String _varName;

    public QuestNpcLogInfo(int[] npcIds, int actionId, String varName, int add, int max)
    {
        _npcIds = npcIds;
        _actionId = actionId;
        _varName = varName;
        _add = add;
        _max = max;
    }

    public int[] getNpcIds()
    {
        return _npcIds;
    }

    public int getActionId()
    {
        return _actionId;
    }

    public String getVarName()
    {
        return _varName;
    }

    public int getAdd()
    {
        return _add;
    }

    public int getMax()
    {
        return _max;
    }
   
    public int[] getNpcInfo(QuestState st)
    {
        return new int[] { _npcIds[0] + 1000000, 0, st.getInt(_varName) };
    }
   
    public int[] getActionInfo(QuestState st)
    {
        return new int[] { _actionId, 1, st.getInt(_varName) };
    }
}
Java:
public class ExQuestNpcLogList extends L2GameServerPacket {
    private int _questId;
    private List<int[]> _logList = Collections.emptyList();

    public ExQuestNpcLogList(QuestState state) {
        _questId = state.getQuest().getId();
        int cond = state.getCond();
        List<QuestNpcLogInfo> vars = state.getQuest().getNpcLogList(cond);
        if (vars == null)
            return;

        _logList = new ArrayList<int[]>(vars.size());
        for (QuestNpcLogInfo entry : vars) {
            int[] i = new int[2];
            i[0] = entry.getNpcIds()[0] + 1000000;
            i[1] = state.getInt(entry.getVarName());
            _logList.add(i);
        }
    }

    @Override
    protected void writeImpl() {
        writeEx(0xC5);
        writeD(_questId);
        writeC(_logList.size());
        for (int i = 0; i < _logList.size(); i++) {
            int[] values = _logList.get(i);
            writeD(values[0]);
            writeC(0);      // npc index?
            writeD(values[1]);
        }
    }
}
 
Последнее редактирование:
Код:
tag_?    quest_id    quest_prog    main_name    prog_name    description    cnt1    items[0-13]    cnt2    num_items[0]    quest_x    quest_y    quest_z    lvl_min    lvl_max    quest_type    entity_name    get_item_in_quest    UNK_1    UNK_2    contact_npc_id    contact_npc_x    contact_npc_y    contact_npc_z    restricions    short_description    cnt3    req_class[0-68]   req_cl    cnt4    req_item[0-4]      clan_pet_quest    req_quest_complete    UNK_3    area_id    UNK_4    cnt5    tab5[0]    cnt6    tab6[0]
вот все мои колонки по квест нейм
ну у тебя это вот эти
Код:
cnt1    items[0-13]    cnt2    num_items[0]
непонятно только куда потерялся тип показываемого, видимо по недопониманию его запихали в "items[0-13]", т.е. половина данных идут ид предметов/нпс/строк, а другая половина - тип данных
 
был бы кодером понимал бы про что речь идет
Java:
 vars.add(new QuestNpcLogInfo(killIds, varName, max));
уперлись ошибки сюда, просто про серверную часть как то понятно но про клиент это ппц) примера просто нету квеста))
 
ну мой фрагмент кода из Quest.java, отвечающий за все это
Java:
    private Map<Integer, List<QuestNpcLogInfo>> _npcLogList = Collections.emptyMap();

    public List<QuestNpcLogInfo> getNpcLogList(int cond)
    {
        return _npcLogList.get(cond);
    }

    public void addKillNpcWithLog(int cond, int add, int max, String varName, int... killIds)
    {
        if (killIds.length == 0)
            throw new IllegalArgumentException("Npc list cant be empty!");

        addKillId(killIds);

        if (_npcLogList.isEmpty())
            _npcLogList = new HashMap<Integer, List<QuestNpcLogInfo>>(5);

        List<QuestNpcLogInfo> vars = _npcLogList.get(cond);

        if (vars == null)
            _npcLogList.put(cond, (vars = new ArrayList<QuestNpcLogInfo>(5)));

        vars.add(new QuestNpcLogInfo(killIds, 0, varName, add, max));
    }

    public void addKillNpcWithLog(int cond, int max, String varName, int... killIds)
    {
        addKillNpcWithLog(cond, 1, max, varName, killIds);
    }

    public void addKillNpcWithLog(int cond, int max, int... killIds)
    {
        addKillNpcWithLog(cond, 1, max, VAR_COUNTER, killIds);
    }

    public void addActionWithLog(int cond, int add, int max, String varName, int actionId)
    {
        if (_npcLogList.isEmpty())
            _npcLogList = new HashMap<Integer, List<QuestNpcLogInfo>>(5);

        List<QuestNpcLogInfo> vars = _npcLogList.get(cond);

        if (vars == null)
            _npcLogList.put(cond, (vars = new ArrayList<QuestNpcLogInfo>(5)));

        vars.add(new QuestNpcLogInfo(new int[0], actionId, varName, add, max));
    }

    public void addActionWithLog(int cond, int max, String varName, int actionId)
    {
        addActionWithLog(cond, 1, max, varName, actionId);
    }

    public void addActionWithLog(int cond, int max, int actionId)
    {
        addActionWithLog(cond, max, VAR_COUNTER, actionId);
    }

    public boolean updateKill(NpcInstance npc, QuestState st)
    {
        return updateKill(npc.getId(), st);
    }

    public boolean updateKill(int npcId, QuestState st)
    {
        Player player = st.getPlayer();

        if (player == null)
            return false;

        List<QuestNpcLogInfo> vars = getNpcLogList(st.getCond());

        if (vars == null)
            return false;

        boolean done = true;
        boolean find = false;

        for (QuestNpcLogInfo info : vars)
        {
            int count = st.getInt(info.getVarName());

            if (!find && ArrayUtils.contains(info.getNpcIds(), npcId))
            {
                find = true;

                if (count < info.getMax())
                {
                    count = Math.min(count + info.getAdd(), info.getMax());
                    st.set(info.getVarName(), count);
                    player.sendPacket(new ExQuestNpcLogList(st));
                }
            }

            if (count < info.getMax())
                done = false;
        }

        return done;
    }

    public boolean updateAction(int actionId, QuestState st)
    {
        Player player = st.getPlayer();

        if (player == null)
            return false;

        List<QuestNpcLogInfo> vars = getNpcLogList(st.getCond());

        if (vars == null)
            return false;

        boolean done = true;
        boolean find = false;

        for (QuestNpcLogInfo info : vars)
        {
            int count = st.getInt(info.getVarName());

            if (!find && info.getActionId() == actionId)
            {
                find = true;

                if (count < info.getMax())
                {
                    count = Math.min(count + info.getAdd(), info.getMax());
                    st.set(info.getVarName(), count);
                    player.sendPacket(new ExQuestNpcLogList(st));
                }
            }

            if (count < info.getMax())
                done = false;
        }

        return done;
    }
и пример квеста в котором задействовано и убийство мобов с показом количества и выполнение определенных действий
Java:
package quests;

import org.apache.commons.lang3.ArrayUtils;

import l2p.gameserver.data.holder.QuestRewardHolder;
import l2p.gameserver.enums.Race;
import l2p.gameserver.model.instances.NpcInstance;
import l2p.gameserver.model.quest.Quest;
import l2p.gameserver.model.quest.QuestState;

/**
 * @author Gaikotsu
 * @version 4.4
 */
public class _10417_DaimonTheWhiteEyed extends Quest
{
    private static final int EyeOfArgos = 31683;
    private static final int Janitt = 33851;

    private static final int[] Mobs = { 21294, 21295, 21296, 21297, 21299, 21304, 23311, 23312 };
    private static final int DaimonTheWhiteEyed = 27499;

    private static final int ActionId = 541711;

    public _10417_DaimonTheWhiteEyed()
    {
        super(PARTY_NONE);

        addLevelCheck(70);
        addRaceCheck(Race.HUMAN, Race.ELF, Race.DARK_ELF, Race.ORC, Race.DWARF, Race.KAMAEL);
        addQuestCompletedCheck(_10416_InSearchOfTheEyeOfArgos.class);
        addStartNpc(EyeOfArgos);
        addTalkId(Janitt);
        addKillId(Mobs);
        addActionWithLog(1, 100, VAR_COUNTER_1, ActionId);
        addKillNpcWithLog(2, 1, VAR_COUNTER_2, DaimonTheWhiteEyed);
    }

    @Override
    public String onEvent(String event, QuestState st, NpcInstance npc)
    {
        String htmltext = event;

        if (event.equalsIgnoreCase("31683-04.htm"))
        {
            st.setState(STARTED);
            st.setCond(1);
            st.playSound(SOUND_ACCEPT);
        }
        else if (event.equalsIgnoreCase("31683-08.htm"))
        {
            st.setCond(4);
            st.playSound(SOUND_MIDDLE);
        }
        else if (event.equalsIgnoreCase("33851-02.htm"))
        {
            QuestRewardHolder.getInstance().giveRewards(st);
            st.exitCurrentQuest(false);
        }

        return htmltext;
    }

    @Override
    public String onTalk(NpcInstance npc, QuestState st)
    {
        String htmltext = NO_QUEST;
        int cond = st.getCond();
        int npcId = npc.getId();

        if (npcId == EyeOfArgos)
        {
            if (cond == 0)
            {
                if (!isAvailableFor(st.getPlayer()))
                    return "31683-00.htm";
                else
                    return "31683-01.htm";
            }
            else if (cond == 1)
                return "31683-05.htm";
            else if (cond == 2)
                return "31683-06.htm";
            else if (cond == 3)
                return "31683-07.htm";
        }
        else if (npcId == Janitt)
        {
            if (cond == 4)
                return "33851-01.htm";
        }

        return htmltext;
    }

    @Override
    public String onKill(NpcInstance npc, QuestState st)
    {
        int cond = st.getCond();

        if (cond == 1)
        {
            if (ArrayUtils.contains(Mobs, npc.getId()) && updateAction(ActionId, st))
            {
                st.setCond(2);
                st.playSound(SOUND_MIDDLE);
            }
        }
        else if (cond == 2)
        {
            if (updateKill(npc, st))
            {
                st.setCond(3);
                st.playSound(SOUND_MIDDLE);
            }
        }

        return null;
    }
}
 
  • Мне нравится
Реакции: Rolo
Немного не по теме, но неблагодарное это дело писать квесты... Сидишь выдумываешь идею квеста, придумываешь мифологию, пилишь скрипт, html и датки, пилишь своих мобов иногда даже с уник ai, пилишь npc, потом еще все тестишь, тратишь на все это уйму времени, а по итогу игроки тупо пишут: "ой, можно было бы просто в alt+b итемчик запилить с обменом и все... кто это ценит в 22 году?)
 
вот и кореяки видимо так же подумали и выпилили из игры почти все квесты...
 
Немного не по теме, но неблагодарное это дело писать квесты... Сидишь выдумываешь идею квеста, придумываешь мифологию, пилишь скрипт, html и датки, пилишь своих мобов иногда даже с уник ai, пилишь npc, потом еще все тестишь, тратишь на все это уйму времени, а по итогу игроки тупо пишут: "ой, можно было бы просто в alt+b итемчик запилить с обменом и все... кто это ценит в 22 году?)
Потому что в л2 квесты это кал полный, надо которым никто не думал в реальности. Всё делится на 2 примитивных варианта:
1) Сходи в город к нпц
2) Иди убей %число% мобов и принеси %шкура\клык\коготь%"

Единственные квесты, которые постарались сделать интересно - цепь 7 печатей.
 
Потому что в л2 квесты это кал полный, надо которым никто не думал в реальности. Всё делится на 2 примитивных варианта:
1) Сходи в город к нпц
2) Иди убей %число% мобов и принеси %шкура\клык\коготь%"

Единственные квесты, которые постарались сделать интересно - цепь 7 печатей.
ты говоришь о корейских квестах. А я тебе о кастомных, насколько крутой ты бы квест не написал - никто его даже читать не будет.
А будут по дефолту все скипать (ну бывает пару исключений игроков конечно но это редкость в 99% скипают). Смысл пытался донести такой - что никто не будет ценить потерянное время на этот квест, ведь ты один знаешь сколько времени ты на это убил - а остальным по сути пофигу - что итем добывается через обменник или через круто навороченный квест - для игроков это будет едино.
У меня есть как и обычные квесты так и навороченные квесты, и обменники - так вот в большинстве случаев для игрока 0 разницы.
По итогу человек получает только убитое время на процесс создание этого квеста.
 
  • Мне нравится
Реакции: Rolo
ты говоришь о корейских квестах. А я тебе о кастомных, насколько крутой ты бы квест не написал - никто его даже читать не будет.
А будут по дефолту все скипать (ну бывает пару исключений игроков конечно но это редкость в 99% скипают). Смысл пытался донести такой - что никто не будет ценить потерянное время на этот квест, ведь ты один знаешь сколько времени ты на это убил - а остальным по сути пофигу - что итем добывается через обменник или через круто навороченный квест - для игроков это будет едино.
Ну так одно из другого - квесты в л2 изначально были скучным калом и никто не будет их воспринимать как нечто большее, чем просто получение чего-то там после их выполнения.

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

"Интересные квесты" это в принципе немного в другой раздел рпг - синглплеерных. А в этой игре квесты как максимум можно строить на херовом движке, используя ЛОР или окружение, из серии: "на мужика напало 4 гоблина иди помоги ему получишь 200 сосок".
 
  • Мне нравится
Реакции: kick
Единственные квесты, которые постарались сделать интересно - цепь 7 печатей.
С квестами таверны еще вроде попытались что-то неплохое сделать в принципе.
Хотя один фиг игроки их тупо побыстрее пробегают ради результата и все.
 
С квестами таверны еще вроде попытались что-то неплохое сделать в принципе.
Хотя один фиг игроки их тупо побыстрее пробегают ради результата и все.
ну не просто так же подарить им это)
Скрытое содержимое могут видеть только пользователи групп(ы): Модератор
 
Назад
Сверху Снизу