Посмотрите видео ниже, чтобы узнать, как установить наш сайт в виде веб-приложения на главном экране.
Примечание: Эта функция может быть недоступна в некоторых браузерах.
Признаки восстания? Он у тебя на скриншоте, если что.или же подскажите для примера какой квест можно взять из готовых корейцами?*
я этот квест показал как пример что вот с права есть счетчик итемов, но мне нужно что бы счетчик работал не на итемы а на мобов (сколько мобов осталось убить и убил уже) п датник не принимает дополнительный параметр я так понял нужно уже ковырять сам клиент) то сообветственно того что я неумею)Признаки восстания? Он у тебя на скриншоте, если что.
А вообще честно говоря я может ерунду сморожу, но разве аларм требует какой то параметр? Чёто не припомню такого, вроде он просто любой квест прожрёт, где есть каунт чего либо. Но вот тут могу наврать.
количество убиваемых мобов указывается в тех же самых полях QuestName, что и количество собираемых предметовя этот квест показал как пример что вот с права есть счетчик итемов, но мне нужно что бы счетчик работал не на итемы а на мобов (сколько мобов осталось убить и убил уже) п датник не принимает дополнительный параметр я так понял нужно уже ковырять сам клиент) то сообветственно того что я неумею)
ну или серверную часть) хотя мне кодер говорит все осталось в клиенте)
goal_id={36551;36556} goal_type={0;0} goal_num={70;145}
goal_id={1022746;1022747} goal_type={0;0} goal_num={15;15}
goal_id={75021} goal_type={1} goal_num={1}
goal_id={539354;36054} goal_type={1;0} goal_num={5;30}
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]); // значение счетчика
}
}
}
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) };
}
}
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]
Если что вот корректный пакет
и используемый класс QuestNpcLogInfo в нем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]); // значение счетчика } } }
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) }; } }
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]
vars.add(new QuestNpcLogInfo(killIds, varName, max));
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;
}
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;
}
}
Потому что в л2 квесты это кал полный, надо которым никто не думал в реальности. Всё делится на 2 примитивных варианта:Немного не по теме, но неблагодарное это дело писать квесты... Сидишь выдумываешь идею квеста, придумываешь мифологию, пилишь скрипт, html и датки, пилишь своих мобов иногда даже с уник ai, пилишь npc, потом еще все тестишь, тратишь на все это уйму времени, а по итогу игроки тупо пишут: "ой, можно было бы просто в alt+b итемчик запилить с обменом и все... кто это ценит в 22 году?)
ты говоришь о корейских квестах. А я тебе о кастомных, насколько крутой ты бы квест не написал - никто его даже читать не будет.Потому что в л2 квесты это кал полный, надо которым никто не думал в реальности. Всё делится на 2 примитивных варианта:
1) Сходи в город к нпц
2) Иди убей %число% мобов и принеси %шкура\клык\коготь%"
Единственные квесты, которые постарались сделать интересно - цепь 7 печатей.
Ну так одно из другого - квесты в л2 изначально были скучным калом и никто не будет их воспринимать как нечто большее, чем просто получение чего-то там после их выполнения.ты говоришь о корейских квестах. А я тебе о кастомных, насколько крутой ты бы квест не написал - никто его даже читать не будет.
А будут по дефолту все скипать (ну бывает пару исключений игроков конечно но это редкость в 99% скипают). Смысл пытался донести такой - что никто не будет ценить потерянное время на этот квест, ведь ты один знаешь сколько времени ты на это убил - а остальным по сути пофигу - что итем добывается через обменник или через круто навороченный квест - для игроков это будет едино.
С квестами таверны еще вроде попытались что-то неплохое сделать в принципе.Единственные квесты, которые постарались сделать интересно - цепь 7 печатей.
ну не просто так же подарить им это)С квестами таверны еще вроде попытались что-то неплохое сделать в принципе.
Хотя один фиг игроки их тупо побыстрее пробегают ради результата и все.