Перейти к содержанию
Авторизация  
MeRDox

Кто хорошо понимает в скриптах квестов?

Рекомендуемые сообщения

Делаю одну фишку, но что-то немного запутался.
Доходит до уровня start_2, нажимаю, выскакивает диалог что нужно сделать 50002-10.htm.

Когда выполняю требования до уровня sobral_2, прихожу отдать предметы, возвращает меня на start_2. Где тут что поправить чтобы при достаточном количестве предметов, перейти на следующий уровень.

PS: Без этих диалогов(объяснений) все работало, когда добавил их, то перестало переходить на следующий уровень. 

package quests.Master;

import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
import net.sf.l2j.gameserver.model.quest.QuestState;
import net.sf.l2j.gameserver.model.quest.State;
import net.sf.l2j.gameserver.model.quest.jython.QuestJython;
import net.sf.l2j.util.Rnd;

public class Master extends QuestJython
{
	//NPC
	private final static int npcId = 50002;
	private final static int[] MOBS = {439017};
    private final static int RaidBoss = 439059;
	//Farm
	private final static int HEAD_UNDEAD = 14060;
	//Master
	private final static int MASTER_1 = 14070;
    private final static int MASTER_2 = 14071;
	private final static int MASTER_3 = 14072;
    //Chance from mobs
    private final static int chance1 = 100;

    private int count;
	private int caunt;


    private int cond = 0;

	private State STARTED = new State("Started", this);

	public Master(int questId, String name, String descr)
	{
		super(questId, name, descr, 1);
		
		State st = new State("Start", this);
		this.setInitialState(st);
		
		addStartNpc(npcId);
		addTalkId(npcId);
        for (int mobs : MOBS)
            addKillId(mobs);
        addKillId(RaidBoss);
	}

	public String onEvent(String event, QuestState st)
	{
        L2PcInstance player = st.getPlayer();
        if (event.equalsIgnoreCase("start"))
        {
            st.set("cond","1");
            event = "50002-2.htm";
            st.setState(STARTED);
        }
        else if (event.equalsIgnoreCase("sobral"))
        {
            count = player.getInventory().getInventoryItemCount(HEAD_UNDEAD,0);
            if (count < 500)
                event = "50002-no.htm";
            else
            {
                st.takeItems(HEAD_UNDEAD,500);
				st.giveItems(MASTER_1,1);
                st.set("cond","2");
                event = "50002-4.htm";
            }
        }
		if (event.equalsIgnoreCase("start_2"))
        {
            st.set("cond","2");
            event = "50002-10.htm";
            st.setState(STARTED);
        }
        else if (event.equalsIgnoreCase("sobral_2"))
        {
            count = player.getInventory().getInventoryItemCount(HEAD_UNDEAD,0);
            caunt = player.getInventory().getInventoryItemCount(MASTER_1,0);
            if (count < 2000)
                event = "50002-no1.htm";
			if (caunt < 1)
                event = "50002-no1.htm";
            else
            {
                st.takeItems(HEAD_UNDEAD,2000);
				st.takeItems(MASTER_1,1);
                st.giveItems(MASTER_2,1);
                st.set("cond","3");
                event = "50002-6.htm";
            }
        }
		if (event.equalsIgnoreCase("start_3"))
        {
            st.set("cond","3");
            event = "50002-11.htm";
            st.setState(STARTED);
        }
		        else if (event.equalsIgnoreCase("sobral_3"))
        {
            count = player.getInventory().getInventoryItemCount(HEAD_UNDEAD,0);
            caunt = player.getInventory().getInventoryItemCount(MASTER_2,0);
            if (count < 5000)
                event = "50002-no1.htm";
			if (caunt < 1)
                event = "50002-no1.htm";
            else
            {
                st.takeItems(HEAD_UNDEAD,5000);
				st.takeItems(MASTER_2,1);
                st.giveItems(MASTER_3,1);
                st.set("cond","3");
                event = "50002-8.htm";
            }
        }
        else if (event.equalsIgnoreCase("otmena"))
        {
            event = "<html><body>kvest otmenen</body></html>";
            st.exitQuest(true);
        }
		return event;
	}

	public String onTalk(L2NpcInstance npc, L2PcInstance talker)
	{
		QuestState st = talker.getQuestState(getName());
		String htmltext = "<html><body>You are either not on a quest that involves this NPC, or you don't meet this NPC's minimum quest requirements.</body></html>";
		if(st == null) return htmltext;
		int npcId = npc.getNpcId();
        cond = st.getInt("cond");
		if(npcId == npcId)
		{
            if (cond == 0)
                htmltext = "50002-1.htm";
            else if (cond == 1)
                htmltext = "50002-3.htm";
            else if (cond == 2)
                htmltext = "50002-5.htm";
            else if (cond == 3)
                htmltext = "50002-7.htm";
            else if (cond == 4)
                htmltext = "50002-9.htm";
		}
		return htmltext;
	}

    public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
    {
        QuestState st = killer.getQuestState(getName());
        if(st == null) return null;
        int npcId = npc.getNpcId();
        int cond = st.getInt("cond");
		switch(cond)
		{
			case 1:
				for(int id : MOBS)
					if(npcId == id && Rnd.get(100) < chance1 && st.getPlayer().getInventory().getInventoryItemCount(HEAD_UNDEAD,0) < 500)
						st.giveItems(HEAD_UNDEAD,1);
				break;
			case 2:
				for(int id : MOBS)
					if(npcId == id && Rnd.get(100) < chance1 && st.getPlayer().getInventory().getInventoryItemCount(HEAD_UNDEAD,0) < 2000)
						st.giveItems(HEAD_UNDEAD,1);
				break;
			case 3:
				for(int id : MOBS)
					if(npcId == id && Rnd.get(100) < chance1 && st.getPlayer().getInventory().getInventoryItemCount(HEAD_UNDEAD,0) < 5000)
						st.giveItems(HEAD_UNDEAD,1);

				break;
		}
        return null;
    }

	public static void main(String[] args)
	{
		new Master(-1, "Master", "quests");
	}
}

Изменено пользователем MeRDox

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы в OnKill сделал бы вот так:

if(npcId == element[0])
  {
      st.rollAndGive(Rock, 1, element[1]);
  }
if(st.getQuestItemsCount(Rock) > 19)
  {
      st.set("cond", "2");
      st.playSound(SOUND_MIDDLE);
  } 

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

 

А при общении с нпц сделать так:

if(cond == 2 && st.getQuestItemsCount(Rock) > 19)
  {
      st.takeItems(HEAD_UNDEAD,2000);
      st.takeItems(MASTER_1,1);
      st.giveItems(MASTER_2,1);
      st.set("cond","3");
      htmltext = "50002-6.htm";
  }

Ну это пример

Изменено пользователем ItCry
  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, возможно сделаю так. Это пока саму механику путей пробую сделать, дальше буду совершенствовать, главное сейчас решить эту проблему. Одну проблему решу, другая выскакивает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, возможно сделаю так. Это пока саму механику путей пробую сделать, дальше буду совершенствовать, главное сейчас решить эту проблему. Одну проблему решу, другая выскакивает.

И еще, если у Вас квест одноразовый, то я бы вот это:

st.takeItems(HEAD_UNDEAD,2000);
st.takeItems(MASTER_1,1);

поменял бы на:

st.takeItems(HEAD_UNDEAD,-1);
st.takeItems(MASTER_1,-1);

Случаи разные бывают)

  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, а насчет моей главной проблемы есть какие-то догадки? а то я перепробовал и менять разные значения, и добавлять новые формулы, ничего не получается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ни у кого нету вариантов решения проблемы? а то всё также не получается исправить её.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ни у кого нету вариантов решения проблемы? а то всё также не получается исправить её.

тоесть, весь путь со start до start_2 проходит нормально?

 

А вообще, хоть реформат бы сделал. Ато из-за разброса открывающихся и закрывающихся скобок на разном уровне не классно ориентироваться. И белый фон тоже как-то не радует глаз.

Изменено пользователем Blueeyer
  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, первый путь идеально работает, а дальше получается каша.
Извиняюсь, так получилось.

Первый раз просто занимаюсь квестами, и разместил как было, а оно получилось как видите.
Эту проблему решил, теперь на втором уровне за набитие 2000 итемов, их может быть хоть 0, всеровно дает дает главный итем, так же и на 3 уровне. Бред)
Вроде бы прописал как и на первом уровне.

Изменено пользователем Merdox

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, первый путь идеально работает, а дальше получается каша.

Извиняюсь, так получилось.

Первый раз просто занимаюсь квестами, и разместил как было, а оно получилось как видите.

Эту проблему решил, теперь на втором уровне за набитие 2000 итемов, их может быть хоть 0, всеровно дает дает главный итем, так же и на 3 уровне. Бред)

Вроде бы прописал как и на первом уровне.

по поводу 2000 итемов - у вас тело if состоит более, чем из одной строки, поэтому его надо открыть и закрыть с помощью скобок, иначе в это условие попадает только первая строка, остальные же выполнятся в не зависимости от того, истинно ли оно или ложно:

if (count < 2000) {
    event = "50002-no1.htm";
    if (caunt < 1) // не знаю, зачем вам это условие, можно убрать
        event = "50002-no1.htm"; 
}
else {
    st.takeItems(HEAD_UNDEAD,2000);
    st.takeItems(MASTER_1,1);
    st.giveItems(MASTER_2,1);
    st.set("cond","3");
    event = "50002-6.htm";
}
Изменено пользователем Blueeyer
  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я немного не верно выразился. Вот что у вас происходило в данных строках:

если кол-во меньше 2000, то event = "50002-no1.htm"

затем проверяем, если кол-во меньше 1, то опять то же действие, хотя не знаю - зачем...

а если кол-во не меньше 1 (т.е. >= 1) то выдает призы :) вот и вся проблема

 

P.S. аналогичная проблема и с 3 уровнем

 

Финально я бы сделал так:

if (count < 2000) event = "50002-no1.htm";
else {
    st.takeItems(HEAD_UNDEAD,2000);
    st.takeItems(MASTER_1, 1);
    st.giveItems(MASTER_2, 1);
    st.set("cond", "3");
    event = "50002-6.htm";
}
Изменено пользователем Blueeyer
  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо большое, объяснили. А то я сутки сидел над этим всем)
Ну в том смысле если нету предмета с 1 уровня, то тоже не давать награду. По уровням все.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, не могу не подметить:

if(npcId == npcId) { //Зачем это условие? Равна ли переменная сама себе. Всегда будет возвращать true
    if (cond == 0)
        htmltext = "50002-1.htm";
    else if (cond == 1)
                htmltext = "50002-3.htm";
    else if (cond == 2)
                htmltext = "50002-5.htm";
    else if (cond == 3)
                htmltext = "50002-7.htm";
    else if (cond == 4)
                htmltext = "50002-9.htm";
}

И тут же, в вашем случае очень просто все это заменить в пару строк:

if(cond >= 0 && cond <= 4) { 
    htmltext = "50002-" + (cond*2 + 1) + ".htm";
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо большое, объяснили. А то я сутки сидел над этим всем)

Ну в том смысле если нету предмета с 1 уровня, то тоже не давать награду. По уровням все.

а, вижу, не заметил что у вас переменные с разным названием (count и caunt), на будущее рекомендую переменные называть соответствующим образом. К примеру кол-во предметов itemCount, уровень предмета itemLevel. И самому будет проще ориентироваться, если вдруг вернешься к этому, и другим, если кто-то вступит в ттвою команду или еще что :)

 

Тогда, скорее всего, это будет более верным вариантом:

if (count < 2000 || caunt < 1) event = "50002-no1.htm";
else {
    st.takeItems(HEAD_UNDEAD,2000);
    st.takeItems(MASTER_1,1);
    st.giveItems(MASTER_2,1);
    st.set("cond","3");
    event = "50002-6.htm";
} 

Желаю удачи, если будут проблемы - обращайтесь.

Изменено пользователем Blueeyer
  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Меня тоже смутило это, так как делал все по примеру, думал то так и нужно, хотя ругался гейм сервер.
Работаю первый раз над квестами, из-за этого и есть недочеты. Спасибо большое за помощь

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Меня тоже смутило это, так как делал все по примеру, думал то так и нужно, хотя ругался гейм сервер.

Работаю первый раз над квестами, из-за этого и есть недочеты. Спасибо большое за помощь

Не было возможности ранее просмотреть ваш код внимательно, сейчас пришел с работы и еще раз перечитал его. По поводу:

if(npcId == npcId) 

Тут потерялась одна очень важная вещь. У вас есть два разных объекта npcId, один принадлежит классу квеста (явлется общим для всех экземпляров класса), а второй достается из поля npc, которое передается как параметр в метод onTalk, onKill... Так вот, там с параметра npc достается свойство npcId, которое существует только в теле метода, а за его пределами (после того, как метод отработал) - сборщик мусора очищает память, уничтожая его).

public String onTalk(L2NpcInstance npc, L2PcInstance talker) {
    int npcId = npc.getNpcId(); // тут мы через геттер достаем значение поля объекта (экзампляра класса) L2NpcInstance. Тоесть, какого-то определенного нпц, который вызвал этот метод.
   
} 

Таким образом в вашем условии вы дважды обращались к полю метода, вам же надо сравзнить - совпадает ли поле метода с полем класса.

private static final int npcId = 50002; // это поле класса, оно у вас объявлено вверху

Действительно ли нпц, который обращается к вашему квесту имеет тот же айди, что и нпц, прописанный в квесте. Чтобы обратиться к полю npcId объекта надо использовать зарезервированное слово this.

 

Как видите, у вас появляется несколько вариантов:

1) убрать значение статик (что менее логично), тогда можно обращаться к полю экземпляра через this. Однако, смысл каждому экземпляру класса резервировать память под одно и то же значение? (что происходит без статики).

private final int npcId = 50002;

И сравниваем:

if (this.npcId == npcId) {
    // Put your logic here 
}

2) переименуйте переменную в методе (тогда можно оставить поле класса статическим):

public String onTalk(L2NpcInstance npc, L2PcInstance talker) {
    int currNpcId = npc.getNpcId(); 
    if (currNpcId == npcId) {
        // ......
    }
} 

Объяснение материала - не мой конек :D Но постарался разъяснить все максиально доступно.

Изменено пользователем Blueeyer
  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация  

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...