Ошибка при взятии ежедневного квеста

Металлург1985

Путник
Пользователь
Сообщения
28
Розыгрыши
0
Репутация
0
Реакции
2
Баллы
75
Хроники
  1. Grand Cursade
Исходники
Присутствуют
Сборка
Mobius
Всем доброго дня.

Столкнулся с интересной проблемой в квесте "Поддержка сил сопротивления".
Если персонаж берет квест впервые (т.е. в БД отсутствует запись об этом квесте в статусе Completed) - то квест берется и проходится корректно.
По завершении в БД прописывается статус квеста Completed и время до отката в UNIX-формате.
Проходит время отката, пытаюсь взять квест повторно - и игра не активирует счетчик квестовых мобов для убийства и квест вообще не появляется у персонажа как активный.
По коду квеста (строки 105-109) вижу, что для квеста в статусе Completed не заложена проверка на истечение времени отката для повторного взятия, а просто должно выводиться уведомление, что квест можно повторить на следующий день в 6:30
Но реально даже не это уведомление выводится, а система судя по всему заходит в участок кода, где инициализируется количество убитых мобов (строки 67-74), т.к. видно, что в БД прописывается по нулям количество квестовых мобов.
При этом квест не активируется, хотя в строке 69 как будто указано - активировать квест.
Для наглядности прикладываю архив с листингом скрипта и диалоговые xml. Помогите плиз разобраться, в чем причина такого поведения квеста.
 

Вложения

Для квестов выполняемых раз в сутки по идее должен выставляться другой стейт при завершении, условное "Delayed", по которому квестдвижок понимает что квест надо сбросить в определенное время. По крайней мере для сборок на базе овера и т.п. так и не думаю что в мобиусе с этим по другому.
 
Запрещено публиковать исходный код без BB-кода — CODE
Для квестов выполняемых раз в сутки по идее должен выставляться другой стейт при завершении, условное "Delayed", по которому квестдвижок понимает что квест надо сбросить в определенное время. По крайней мере для сборок на базе овера и т.п. так и не думаю что в мобиусе с этим по другому.
Нашел в другом квесте, который нормально перезапускается по откату, вот такое подусловие:

else if (qs.isCompleted())
{
if (!qs.isNowAvailable())
{
htmltext = "33044-08.html";
}
else
{
qs.setState(State.CREATED);
htmltext = "33044-01.htm";
}
}

Вероятно это и есть вложенная проверка на доступность квеста по откату при статусе Completed.
Попробовал применить к текущему сбойному квесту. Завтра с утреца узнаю - помогло или нет :)
 
должно помочь. но соглашусь с Гайкотцу, по кодерской эстетике лучше делать разные статусы квеста после окончания для одиночных и повторяемых квестов. даже 3 разных- Completed, CompletedRepeatable, CompletedRepeatableWithDelay
 
Последнее редактирование:
ну обычный повторяемый обычно вобще после завершения не сохраняется, вместо этого чистятся все данные о нем, как будто квест и не выполнялся еще.
 
ну обычный повторяемый обычно вобще после завершения не сохраняется, вместо этого чистятся все данные о нем, как будто квест и не выполнялся еще.
странная логика сборки... а куда тогда сохраняется пометка, чтобы повторно не брался? чел вроде про запись итоговую в БД говорит, а не промежуточный переменный статус
 
я говорю про обычные повторяемые, которые можно сразу же повторно взять после выполнения.
Java:
    /**
     * Используется для однодневных квестов<br>
     * Завершает квест и даляет все предметы и переменные, связанные с ним<br>
     * Если необходимо оставить какую-то переменную в квесте, то необходимо выставить ее значение заново после вызова этого метода
     *
     * @param quest - завершаемый квест
     */
    public void exitQuest(Quest quest)
    {
        exitQuest(quest, Quest.SOUND_FINISH, CommonSkill.QUEST_DONE.getSkill());
    }

    /**
     * Используется для однодневных квестов<br>
     * Завершает квест и даляет все предметы и переменные, связанные с ним<br>
     * Если необходимо оставить какую-то переменную в квесте, то необходимо выставить ее значение заново после вызова этого метода
     *
     * @param quest - завершаемый квест
     * @param sound - звук, который необходимо воспроизвести
     * @param skill - скилл, анимацию каста которого необходимо показать
     */
    public void exitQuest(Quest quest, String sound, Skill skill)
    {
        Player player = getPlayer();
        exitQuest(true, sound, skill, false);
        QuestState qs = quest.newQuestStateAndNotSave(player, QuestStateType.DELAYED);
        qs.setResetTime();
        QuestDAO.getInstance().updateQuest(qs);
    }

    /**
     * Завершает квест и даляет все предметы и переменные, связанные с ним<br>
     * Если необходимо оставить какую-то переменную в квесте, то необходимо выставить ее значение заново после вызова этого метода
     *
     * @param repeatable - повторяемый или нет квест
     */
    public QuestState exitQuest(boolean repeatable)
    {
        return exitQuest(repeatable, Quest.SOUND_FINISH, CommonSkill.QUEST_DONE.getSkill(), false);
    }

    /**
     * Завершает квест и даляет все предметы и переменные, связанные с ним<br>
     * Если необходимо оставить какую-то переменную в квесте, то необходимо выставить ее значение заново после вызова этого метода
     *
     * @param repeatable - повторяемый или нет квест
     * @param sound - звук, который необходимо воспроизвести
     * @param skill - скилл, анимацию каста которого необходимо показать
     */
    public QuestState exitQuest(boolean repeatable, String sound, Skill skill)
    {
        return exitQuest(repeatable, sound, skill, false);
    }

    /**
     * Завершает квест и даляет все предметы и переменные, связанные с ним<br>
     * Если необходимо оставить какую-то переменную в квесте, то необходимо выставить ее значение заново после вызова этого метода
     *
     * @param repeatable - повторяемый или нет квест
     * @param sound - звук, который необходимо воспроизвести
     * @param skill - скилл, анимацию каста которого необходимо показать
     * @param aborted - если true, то квест был завершен через запрос его отмены
     */
    public QuestState exitQuest(boolean repeatable, String sound, Skill skill, boolean aborted)
    {
        Player player = getPlayer();

        if (player == null)
            return this;

        ItemInstance item = null;

        for (int itemId : _quest.getQuestItems())
        {
            if (itemId == CommonItem.ADENA.getId())
                continue;

            item = player.getInventory().getItemById(itemId);

            if (item == null)
                continue;

            player.getInventory().destroyItemById(itemId, item.getCount());
        }

        if (repeatable)
        {
            player.getQuests().removeState(_questId);
            QuestDAO.getInstance().deleteQuest(this);
            _vars.clear();
        }
        else
        {
            _vars.keySet().stream().filter(var -> var != null).forEach(var -> unset(var));
            setState(QuestStateType.COMPLETED);
            QuestDAO.getInstance().updateQuest(this); // FIXME: оно вроде не нужно?
        }

        player.getListeners().onEndQuest(_quest, repeatable, aborted);
        player.sendPacket(new QuestList(player));

        if (sound != null)
            Quest.playSound(player, sound);

        if (skill != null)
            player.broadcastPacket(new MagicSkillUse(player, skill));

        return this;
    }

    public void abortQuest(Player player)
    {
        _quest.onAbort(player, this);
        exitQuest(true, null, null, true);
    }
 
Последнее редактирование:
ну обычный повторяемый обычно вобще после завершения не сохраняется, вместо этого чистятся все данные о нем, как будто квест и не выполнялся еще.
Сохраняется в БД со статусом completed и временем отката в unix-формате.
Если бы не сохранялся - можно было бы его брать повторно множество раз в день, а не раз в сутки. Что уже неинтересно.
 
Назад
Сверху Снизу