From b7bc148e094d8250e9dce812fe8bc230c730674f Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Fri, 8 Dec 2023 17:01:11 -0800 Subject: [PATCH] implement solo quest progression flags --- CMakeLists.txt | 1 + src/Client.cc | 29 +- src/Client.hh | 3 +- src/CommandFormats.hh | 21 +- src/Lobby.cc | 12 +- src/Menu.hh | 4 +- src/Quest.cc | 58 ++-- src/Quest.hh | 22 +- src/QuestAvailabilityExpression.cc | 248 ++++++++++++++++++ src/QuestAvailabilityExpression.hh | 125 +++++++++ src/ReceiveCommands.cc | 4 +- src/SendCommands.cc | 40 ++- src/SendCommands.hh | 2 +- system/config.example.json | 3 +- system/quests/battle/b88001.json | 20 +- system/quests/government-ep1/q402-bb.json | 2 +- system/quests/government-ep1/q403-bb.json | 2 +- system/quests/government-ep1/q404-bb.json | 2 +- system/quests/government-ep1/q405-bb.json | 2 +- system/quests/government-ep1/q406-bb.json | 2 +- system/quests/government-ep1/q407-bb.json | 2 +- system/quests/government-ep1/q408-bb.json | 2 +- system/quests/government-ep1/q409-bb.json | 2 +- system/quests/government-ep1/q410-bb.json | 2 +- system/quests/government-ep1/q411-bb.json | 2 +- system/quests/government-ep1/q412-bb.json | 2 +- system/quests/government-ep1/q413-bb.json | 2 +- system/quests/government-ep1/q414-bb.json | 2 +- system/quests/government-ep1/q415-bb.json | 2 +- system/quests/government-ep2/q452-bb.json | 2 +- system/quests/government-ep2/q453-bb.json | 2 +- system/quests/government-ep2/q454-bb.json | 2 +- system/quests/government-ep2/q455-bb.json | 2 +- system/quests/government-ep2/q456-bb.json | 2 +- system/quests/government-ep2/q457-bb.json | 2 +- system/quests/government-ep2/q458-bb.json | 2 +- system/quests/government-ep2/q459-bb.json | 2 +- system/quests/government-ep2/q460-bb.json | 2 +- system/quests/government-ep2/q461-bb.json | 2 +- system/quests/government-ep2/q462-bb.json | 2 +- system/quests/government-ep2/q463-bb.json | 2 +- system/quests/government-ep2/q464-bb.json | 2 +- system/quests/government-ep2/q465-bb.json | 2 +- system/quests/government-ep2/q466-bb.json | 2 +- system/quests/government-ep2/q467-bb.json | 2 +- system/quests/government-ep2/q468-bb.json | 2 +- system/quests/government-ep4/q702-bb.json | 2 +- system/quests/government-ep4/q703-bb.json | 2 +- system/quests/government-ep4/q704-bb.json | 2 +- system/quests/government-ep4/q705-bb.json | 2 +- system/quests/government-ep4/q706-bb.json | 2 +- system/quests/government-ep4/q707-bb.json | 2 +- system/quests/government-ep4/q708-bb.json | 2 +- .../quests/{solo => solo-extra}/q035-bb-e.bin | Bin .../quests/{solo => solo-extra}/q035-bb-j.bin | Bin .../quests/{solo => solo-extra}/q035-bb.dat | Bin .../quests/{solo => solo-extra}/q036-bb-j.bin | Bin .../quests/{solo => solo-extra}/q036-bb.dat | Bin .../quests/{solo => solo-extra}/q126-bb-e.bin | Bin .../quests/{solo => solo-extra}/q126-bb-j.bin | Bin .../quests/{solo => solo-extra}/q126-bb.dat | Bin .../quests/{solo => solo-extra}/q143-bb-e.bin | Bin .../quests/{solo => solo-extra}/q143-bb-j.bin | Bin .../quests/{solo => solo-extra}/q143-bb.dat | Bin .../quests/{solo => solo-story}/q001-bb-e.bin | Bin .../quests/{solo => solo-story}/q001-bb-j.bin | Bin .../quests/{solo => solo-story}/q001-bb.dat | Bin system/quests/solo-story/q001.json | 3 + .../quests/{solo => solo-story}/q002-bb-e.bin | Bin .../quests/{solo => solo-story}/q002-bb-j.bin | Bin .../quests/{solo => solo-story}/q002-bb.dat | Bin system/quests/solo-story/q002.json | 3 + .../quests/{solo => solo-story}/q003-bb-e.bin | Bin .../quests/{solo => solo-story}/q003-bb-j.bin | Bin .../quests/{solo => solo-story}/q003-bb.dat | Bin system/quests/solo-story/q003.json | 4 + .../quests/{solo => solo-story}/q004-bb-e.bin | Bin .../quests/{solo => solo-story}/q004-bb-j.bin | Bin .../quests/{solo => solo-story}/q004-bb.dat | Bin system/quests/solo-story/q004.json | 3 + .../quests/{solo => solo-story}/q005-bb-e.bin | Bin .../quests/{solo => solo-story}/q005-bb-j.bin | Bin .../quests/{solo => solo-story}/q005-bb.dat | Bin system/quests/solo-story/q005.json | 4 + .../quests/{solo => solo-story}/q006-bb-e.bin | Bin .../quests/{solo => solo-story}/q006-bb-j.bin | Bin .../quests/{solo => solo-story}/q006-bb.dat | Bin system/quests/solo-story/q006.json | 4 + .../quests/{solo => solo-story}/q007-bb-e.bin | Bin .../quests/{solo => solo-story}/q007-bb-j.bin | Bin .../quests/{solo => solo-story}/q007-bb.dat | Bin system/quests/solo-story/q007.json | 4 + .../quests/{solo => solo-story}/q008-bb-e.bin | Bin .../quests/{solo => solo-story}/q008-bb-j.bin | Bin .../quests/{solo => solo-story}/q008-bb.dat | Bin system/quests/solo-story/q008.json | 4 + .../quests/{solo => solo-story}/q009-bb-e.bin | Bin .../quests/{solo => solo-story}/q009-bb-j.bin | Bin .../quests/{solo => solo-story}/q009-bb.dat | Bin system/quests/solo-story/q009.json | 4 + .../quests/{solo => solo-story}/q010-bb-e.bin | Bin .../quests/{solo => solo-story}/q010-bb-j.bin | Bin .../quests/{solo => solo-story}/q010-bb.dat | Bin system/quests/solo-story/q010.json | 4 + .../quests/{solo => solo-story}/q011-bb-e.bin | Bin .../quests/{solo => solo-story}/q011-bb-j.bin | Bin .../quests/{solo => solo-story}/q011-bb.dat | Bin system/quests/solo-story/q011.json | 4 + .../quests/{solo => solo-story}/q012-bb-e.bin | Bin .../quests/{solo => solo-story}/q012-bb-j.bin | Bin .../quests/{solo => solo-story}/q012-bb.dat | Bin system/quests/solo-story/q012.json | 4 + .../quests/{solo => solo-story}/q013-bb-e.bin | Bin .../quests/{solo => solo-story}/q013-bb-j.bin | Bin .../quests/{solo => solo-story}/q013-bb.dat | Bin system/quests/solo-story/q013.json | 4 + .../quests/{solo => solo-story}/q014-bb-e.bin | Bin .../quests/{solo => solo-story}/q014-bb-j.bin | Bin .../quests/{solo => solo-story}/q014-bb.dat | Bin system/quests/solo-story/q014.json | 4 + .../quests/{solo => solo-story}/q015-bb-e.bin | Bin .../quests/{solo => solo-story}/q015-bb-j.bin | Bin .../quests/{solo => solo-story}/q015-bb.dat | Bin system/quests/solo-story/q015.json | 4 + .../quests/{solo => solo-story}/q016-bb-e.bin | Bin .../quests/{solo => solo-story}/q016-bb-j.bin | Bin .../quests/{solo => solo-story}/q016-bb.dat | Bin system/quests/solo-story/q016.json | 4 + .../quests/{solo => solo-story}/q017-bb-e.bin | Bin .../quests/{solo => solo-story}/q017-bb-j.bin | Bin .../quests/{solo => solo-story}/q017-bb.dat | Bin system/quests/solo-story/q017.json | 4 + .../quests/{solo => solo-story}/q018-bb-e.bin | Bin .../quests/{solo => solo-story}/q018-bb-j.bin | Bin .../quests/{solo => solo-story}/q018-bb.dat | Bin system/quests/solo-story/q018.json | 4 + .../quests/{solo => solo-story}/q019-bb-e.bin | Bin .../quests/{solo => solo-story}/q019-bb-j.bin | Bin .../quests/{solo => solo-story}/q019-bb.dat | Bin system/quests/solo-story/q019.json | 4 + .../quests/{solo => solo-story}/q020-bb-e.bin | Bin .../quests/{solo => solo-story}/q020-bb-j.bin | Bin .../quests/{solo => solo-story}/q020-bb.dat | Bin system/quests/solo-story/q020.json | 4 + .../quests/{solo => solo-story}/q021-bb-e.bin | Bin .../quests/{solo => solo-story}/q021-bb-j.bin | Bin .../quests/{solo => solo-story}/q021-bb.dat | Bin system/quests/solo-story/q021.json | 4 + .../quests/{solo => solo-story}/q022-bb-e.bin | Bin .../quests/{solo => solo-story}/q022-bb-j.bin | Bin .../quests/{solo => solo-story}/q022-bb.dat | Bin system/quests/solo-story/q022.json | 4 + .../quests/{solo => solo-story}/q023-bb-e.bin | Bin .../quests/{solo => solo-story}/q023-bb-j.bin | Bin .../quests/{solo => solo-story}/q023-bb.dat | Bin system/quests/solo-story/q023.json | 4 + .../quests/{solo => solo-story}/q024-bb-e.bin | Bin .../quests/{solo => solo-story}/q024-bb-j.bin | Bin .../quests/{solo => solo-story}/q024-bb.dat | Bin system/quests/solo-story/q024.json | 4 + .../quests/{solo => solo-story}/q025-bb-e.bin | Bin .../quests/{solo => solo-story}/q025-bb-j.bin | Bin .../quests/{solo => solo-story}/q025-bb.dat | Bin system/quests/solo-story/q025.json | 4 + .../quests/{solo => solo-story}/q026-bb-e.bin | Bin .../quests/{solo => solo-story}/q026-bb-j.bin | Bin .../quests/{solo => solo-story}/q026-bb.dat | Bin system/quests/solo-story/q026.json | 3 + .../quests/{solo => solo-story}/q027-bb-e.bin | Bin .../quests/{solo => solo-story}/q027-bb-j.bin | Bin .../quests/{solo => solo-story}/q027-bb.dat | Bin .../quests/{solo => solo-story}/q030-bb-e.bin | Bin .../quests/{solo => solo-story}/q030-bb-j.bin | Bin .../quests/{solo => solo-story}/q030-bb.dat | Bin .../quests/{solo => solo-story}/q031-bb-e.bin | Bin .../quests/{solo => solo-story}/q031-bb-j.bin | Bin .../quests/{solo => solo-story}/q031-bb.dat | Bin .../quests/{solo => solo-story}/q032-bb-e.bin | Bin .../quests/{solo => solo-story}/q032-bb-j.bin | Bin .../quests/{solo => solo-story}/q032-bb.dat | Bin .../quests/{solo => solo-story}/q033-bb-e.bin | Bin .../quests/{solo => solo-story}/q033-bb-j.bin | Bin .../quests/{solo => solo-story}/q033-bb.dat | Bin .../quests/{solo => solo-story}/q034-bb-e.bin | Bin .../quests/{solo => solo-story}/q034-bb-j.bin | Bin .../quests/{solo => solo-story}/q034-bb.dat | Bin tests/config.json | 3 +- 187 files changed, 663 insertions(+), 108 deletions(-) create mode 100644 src/QuestAvailabilityExpression.cc create mode 100644 src/QuestAvailabilityExpression.hh rename system/quests/{solo => solo-extra}/q035-bb-e.bin (100%) rename system/quests/{solo => solo-extra}/q035-bb-j.bin (100%) rename system/quests/{solo => solo-extra}/q035-bb.dat (100%) rename system/quests/{solo => solo-extra}/q036-bb-j.bin (100%) rename system/quests/{solo => solo-extra}/q036-bb.dat (100%) rename system/quests/{solo => solo-extra}/q126-bb-e.bin (100%) rename system/quests/{solo => solo-extra}/q126-bb-j.bin (100%) rename system/quests/{solo => solo-extra}/q126-bb.dat (100%) rename system/quests/{solo => solo-extra}/q143-bb-e.bin (100%) rename system/quests/{solo => solo-extra}/q143-bb-j.bin (100%) rename system/quests/{solo => solo-extra}/q143-bb.dat (100%) rename system/quests/{solo => solo-story}/q001-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q001-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q001-bb.dat (100%) create mode 100644 system/quests/solo-story/q001.json rename system/quests/{solo => solo-story}/q002-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q002-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q002-bb.dat (100%) create mode 100644 system/quests/solo-story/q002.json rename system/quests/{solo => solo-story}/q003-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q003-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q003-bb.dat (100%) create mode 100644 system/quests/solo-story/q003.json rename system/quests/{solo => solo-story}/q004-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q004-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q004-bb.dat (100%) create mode 100644 system/quests/solo-story/q004.json rename system/quests/{solo => solo-story}/q005-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q005-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q005-bb.dat (100%) create mode 100644 system/quests/solo-story/q005.json rename system/quests/{solo => solo-story}/q006-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q006-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q006-bb.dat (100%) create mode 100644 system/quests/solo-story/q006.json rename system/quests/{solo => solo-story}/q007-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q007-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q007-bb.dat (100%) create mode 100644 system/quests/solo-story/q007.json rename system/quests/{solo => solo-story}/q008-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q008-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q008-bb.dat (100%) create mode 100644 system/quests/solo-story/q008.json rename system/quests/{solo => solo-story}/q009-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q009-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q009-bb.dat (100%) create mode 100644 system/quests/solo-story/q009.json rename system/quests/{solo => solo-story}/q010-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q010-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q010-bb.dat (100%) create mode 100644 system/quests/solo-story/q010.json rename system/quests/{solo => solo-story}/q011-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q011-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q011-bb.dat (100%) create mode 100644 system/quests/solo-story/q011.json rename system/quests/{solo => solo-story}/q012-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q012-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q012-bb.dat (100%) create mode 100644 system/quests/solo-story/q012.json rename system/quests/{solo => solo-story}/q013-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q013-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q013-bb.dat (100%) create mode 100644 system/quests/solo-story/q013.json rename system/quests/{solo => solo-story}/q014-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q014-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q014-bb.dat (100%) create mode 100644 system/quests/solo-story/q014.json rename system/quests/{solo => solo-story}/q015-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q015-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q015-bb.dat (100%) create mode 100644 system/quests/solo-story/q015.json rename system/quests/{solo => solo-story}/q016-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q016-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q016-bb.dat (100%) create mode 100644 system/quests/solo-story/q016.json rename system/quests/{solo => solo-story}/q017-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q017-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q017-bb.dat (100%) create mode 100644 system/quests/solo-story/q017.json rename system/quests/{solo => solo-story}/q018-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q018-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q018-bb.dat (100%) create mode 100644 system/quests/solo-story/q018.json rename system/quests/{solo => solo-story}/q019-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q019-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q019-bb.dat (100%) create mode 100644 system/quests/solo-story/q019.json rename system/quests/{solo => solo-story}/q020-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q020-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q020-bb.dat (100%) create mode 100644 system/quests/solo-story/q020.json rename system/quests/{solo => solo-story}/q021-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q021-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q021-bb.dat (100%) create mode 100644 system/quests/solo-story/q021.json rename system/quests/{solo => solo-story}/q022-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q022-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q022-bb.dat (100%) create mode 100644 system/quests/solo-story/q022.json rename system/quests/{solo => solo-story}/q023-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q023-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q023-bb.dat (100%) create mode 100644 system/quests/solo-story/q023.json rename system/quests/{solo => solo-story}/q024-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q024-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q024-bb.dat (100%) create mode 100644 system/quests/solo-story/q024.json rename system/quests/{solo => solo-story}/q025-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q025-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q025-bb.dat (100%) create mode 100644 system/quests/solo-story/q025.json rename system/quests/{solo => solo-story}/q026-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q026-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q026-bb.dat (100%) create mode 100644 system/quests/solo-story/q026.json rename system/quests/{solo => solo-story}/q027-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q027-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q027-bb.dat (100%) rename system/quests/{solo => solo-story}/q030-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q030-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q030-bb.dat (100%) rename system/quests/{solo => solo-story}/q031-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q031-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q031-bb.dat (100%) rename system/quests/{solo => solo-story}/q032-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q032-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q032-bb.dat (100%) rename system/quests/{solo => solo-story}/q033-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q033-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q033-bb.dat (100%) rename system/quests/{solo => solo-story}/q034-bb-e.bin (100%) rename system/quests/{solo => solo-story}/q034-bb-j.bin (100%) rename system/quests/{solo => solo-story}/q034-bb.dat (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c627bbb..a6a80165 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ set(SOURCES src/PSOGCObjectGraph.cc src/PSOProtocol.cc src/Quest.cc + src/QuestAvailabilityExpression.cc src/QuestScript.cc src/RareItemSet.cc src/ReceiveCommands.cc diff --git a/src/Client.cc b/src/Client.cc index 8f007015..b7f3cfaf 100644 --- a/src/Client.cc +++ b/src/Client.cc @@ -295,21 +295,30 @@ shared_ptr Client::team() const { return team; } -bool Client::can_access_quest(shared_ptr q, uint8_t difficulty) const { +bool Client::can_see_quest(shared_ptr q, uint8_t difficulty) const { if (this->license && (this->license->flags & License::Flag::DISABLE_QUEST_REQUIREMENTS)) { return true; } - if ((q->require_flag >= 0) && - !this->character()->quest_flags.get(difficulty, q->require_flag)) { - return false; + if (!q->available_expression) { + return true; } - if (!q->require_team_reward_key.empty()) { - auto team = this->team(); - if (!team || !team->has_reward(q->require_team_reward_key)) { - return false; - } + string expr = q->available_expression->str(); + bool ret = q->available_expression->evaluate(this->character()->quest_flags.data.at(difficulty), this->team()); + this->log.info("Evaluating quest availability expression %s => %s", expr.c_str(), ret ? "TRUE" : "FALSE"); + return ret; +} + +bool Client::can_play_quest(shared_ptr q, uint8_t difficulty) const { + if (this->license && (this->license->flags & License::Flag::DISABLE_QUEST_REQUIREMENTS)) { + return true; } - return true; + if (!q->enabled_expression) { + return true; + } + string expr = q->enabled_expression->str(); + bool ret = q->enabled_expression->evaluate(this->character()->quest_flags.data.at(difficulty), this->team()); + this->log.info("Evaluating quest enabled expression %s => %s", expr.c_str(), ret ? "TRUE" : "FALSE"); + return ret; } void Client::dispatch_save_game_data(evutil_socket_t, short, void* ctx) { diff --git a/src/Client.hh b/src/Client.hh index 0dc2259b..0fe25343 100644 --- a/src/Client.hh +++ b/src/Client.hh @@ -260,7 +260,8 @@ public: std::shared_ptr team() const; - bool can_access_quest(std::shared_ptr q, uint8_t difficulty) const; + bool can_see_quest(std::shared_ptr q, uint8_t difficulty) const; + bool can_play_quest(std::shared_ptr q, uint8_t difficulty) const; static void dispatch_save_game_data(evutil_socket_t, short, void* ctx); void save_game_data(); diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index da861b84..a10167fb 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -1996,6 +1996,15 @@ struct C_ChangeShipOrBlock_A0_A1 { template struct S_QuestMenuEntry { + // Note: The game treats menu_id as two 8-bit fields followed by a 16-bit + // field. In most situations, this is opaque to the server, so we treat it as + // a single 32-bit field, but in the case of the quest menu, the second byte + // is used to determine the icon that appears to the left of the quest name. + // Specifically: + // 0 = online quest icon (green diamond) + // 1 = download quest icon (green square with outlined diamond) + // 2 = completed download quest icon (orange square with outlined diamond) + // Anything else = same as 1 le_uint32_t menu_id = 0; le_uint32_t item_id = 0; pstring name; @@ -2007,7 +2016,17 @@ struct S_QuestMenuEntry_DC_GC_A2_A4 : S_QuestMenuEntry { } __packed__; -struct S_QuestMenuEntry_BB_A2_A4 : S_QuestMenuEntry { + +struct S_QuestMenuEntry_BB_A2_A4 { + le_uint32_t menu_id = 0; + le_uint32_t item_id = 0; + pstring name; + pstring short_description; + // If this field is set, a yellow hex icon is displayed instead of the green + // or orange diamond icon, and the quest is grayed out and cannot be selected. + // This field is ignored if the icon type (see S_QuestMenuEntry) isn't 1 or 2. + uint8_t disabled = 0; + parray unused; } __packed__; // A3 (S->C): Quest information diff --git a/src/Lobby.cc b/src/Lobby.cc index df6fe404..0fc8cf50 100644 --- a/src/Lobby.cc +++ b/src/Lobby.cc @@ -410,12 +410,16 @@ unordered_map> Lobby::clients_by_serial_number() co } QuestIndex::IncludeCondition Lobby::quest_include_condition() const { - return [this](shared_ptr q) -> bool { + return [this](shared_ptr q) -> QuestIndex::IncludeState { + bool is_enabled = true; for (const auto& lc : this->clients) { - if (lc && !lc->can_access_quest(q, this->difficulty)) { - return false; + if (lc && !lc->can_see_quest(q, this->difficulty)) { + return QuestIndex::IncludeState::HIDDEN; + } + if (lc && !lc->can_play_quest(q, this->difficulty)) { + is_enabled = false; } } - return true; + return is_enabled ? QuestIndex::IncludeState::AVAILABLE : QuestIndex::IncludeState::DISABLED; }; } diff --git a/src/Menu.hh b/src/Menu.hh index 589dc685..889041bf 100644 --- a/src/Menu.hh +++ b/src/Menu.hh @@ -17,8 +17,8 @@ constexpr uint32_t MAIN = 0x11000011; constexpr uint32_t INFORMATION = 0x22000022; constexpr uint32_t LOBBY = 0x33000033; constexpr uint32_t GAME = 0x44000044; -constexpr uint32_t QUEST = 0x55000055; -constexpr uint32_t QUEST_CATEGORIES = 0x66000066; +constexpr uint32_t QUEST = 0x55010155; +constexpr uint32_t QUEST_CATEGORIES = 0x66010166; constexpr uint32_t PROXY_DESTINATIONS = 0x77000077; constexpr uint32_t PROGRAMS = 0x88000088; constexpr uint32_t PATCHES = 0x99000099; diff --git a/src/Quest.cc b/src/Quest.cc index 56421dd1..9202a851 100644 --- a/src/Quest.cc +++ b/src/Quest.cc @@ -205,8 +205,8 @@ VersionedQuest::VersionedQuest( std::shared_ptr pvr_contents, std::shared_ptr battle_rules, ssize_t challenge_template_index, - int16_t require_flag, - const string& require_team_reward_key) + std::shared_ptr available_expression, + std::shared_ptr enabled_expression) : quest_number(quest_number), category_id(category_id), episode(Episode::NONE), @@ -219,8 +219,8 @@ VersionedQuest::VersionedQuest( pvr_contents(pvr_contents), battle_rules(battle_rules), challenge_template_index(challenge_template_index), - require_flag(require_flag), - require_team_reward_key(require_team_reward_key) { + available_expression(available_expression), + enabled_expression(enabled_expression) { auto bin_decompressed = prs_decompress(*this->bin_contents); @@ -378,8 +378,8 @@ Quest::Quest(shared_ptr initial_version) name(initial_version->name), battle_rules(initial_version->battle_rules), challenge_template_index(initial_version->challenge_template_index), - require_flag(initial_version->require_flag), - require_team_reward_key(initial_version->require_team_reward_key) { + available_expression(initial_version->available_expression), + enabled_expression(initial_version->enabled_expression) { this->versions.emplace(this->versions_key(initial_version->version, initial_version->language), initial_version); } @@ -409,11 +409,17 @@ void Quest::add_version(shared_ptr vq) { if (this->challenge_template_index != vq->challenge_template_index) { throw runtime_error("quest version has different challenge template index"); } - if (this->require_flag != vq->require_flag) { - throw runtime_error("quest version has different required flag"); + if (!this->available_expression != !vq->available_expression) { + throw runtime_error("quest version has available expression but root quest does not, or vice versa"); } - if (this->require_team_reward_key != vq->require_team_reward_key) { - throw runtime_error("quest version has different required team reward key"); + if (this->available_expression && *this->available_expression != *vq->available_expression) { + throw runtime_error("quest version has a different available expression"); + } + if (!this->enabled_expression != !vq->enabled_expression) { + throw runtime_error("quest version has enabled expression but root quest does not, or vice versa"); + } + if (this->enabled_expression && *this->enabled_expression != *vq->enabled_expression) { + throw runtime_error("quest version has a different enabled expression"); } this->versions.emplace(this->versions_key(vq->version, vq->language), vq); @@ -639,8 +645,8 @@ QuestIndex::QuestIndex( JSON metadata_json = nullptr; shared_ptr battle_rules; ssize_t challenge_template_index = -1; - int16_t require_flag = -1; - string require_team_reward_key; + shared_ptr available_expression; + shared_ptr enabled_expression; try { json_filename = basename; metadata_json = JSON::parse(*json_files.at(json_filename)); @@ -665,9 +671,12 @@ QuestIndex::QuestIndex( challenge_template_index = metadata_json.at("ChallengeTemplateIndex").as_int(); } catch (const out_of_range&) { } - require_flag = metadata_json.get_int("RequireFlag", -1); try { - require_team_reward_key = metadata_json.get_string("RequireTeamRewardKey"); + available_expression = make_shared(metadata_json.get_string("AvailableIf")); + } catch (const out_of_range&) { + } + try { + enabled_expression = make_shared(metadata_json.get_string("EnabledIf")); } catch (const out_of_range&) { } } @@ -682,8 +691,8 @@ QuestIndex::QuestIndex( pvr_contents, battle_rules, challenge_template_index, - require_flag, - require_team_reward_key); + available_expression, + enabled_expression); auto category_name = this->category_index->at(vq->category_id)->name; string dat_str = dat_filename.empty() ? "" : (" with layout from " + dat_filename + ".dat"); @@ -737,7 +746,7 @@ vector> QuestIndex::categories( QuestMenuType menu_type, Episode episode, Version version, - function)> include_condition) const { + IncludeCondition include_condition) const { // The episode filter should apply in normal or solo mode if ((menu_type != QuestMenuType::NORMAL) && (menu_type != QuestMenuType::SOLO)) { episode = Episode::NONE; @@ -752,27 +761,30 @@ vector> QuestIndex::categories( return ret; } -vector> QuestIndex::filter( +vector>> QuestIndex::filter( QuestMenuType menu_type, Episode episode, Version version, uint32_t category_id, - function)> include_condition, + IncludeCondition include_condition, size_t limit) const { if ((menu_type != QuestMenuType::NORMAL) && (menu_type != QuestMenuType::SOLO)) { episode = Episode::NONE; } - vector> ret; + vector>> ret; auto category_it = this->quests_by_category_id_and_number.find(category_id); if (category_it == this->quests_by_category_id_and_number.end()) { return ret; } for (auto it : category_it->second) { if (((episode == Episode::NONE) || (it.second->episode == episode)) && - it.second->has_version_any_language(version) && - (!include_condition || include_condition(it.second))) { - ret.emplace_back(it.second); + it.second->has_version_any_language(version)) { + IncludeState state = include_condition ? include_condition(it.second) : IncludeState::AVAILABLE; + if (state == IncludeState::HIDDEN) { + continue; + } + ret.emplace_back(make_pair(state, it.second)); if (limit && (ret.size() >= limit)) { break; } diff --git a/src/Quest.hh b/src/Quest.hh index a989bdc6..da5931c1 100644 --- a/src/Quest.hh +++ b/src/Quest.hh @@ -9,6 +9,7 @@ #include #include "PlayerSubordinates.hh" +#include "QuestAvailabilityExpression.hh" #include "QuestScript.hh" #include "StaticGameData.hh" #include "TeamIndex.hh" @@ -70,8 +71,8 @@ struct VersionedQuest { std::shared_ptr pvr_contents; std::shared_ptr battle_rules; ssize_t challenge_template_index; - int16_t require_flag; // <0 = none - std::string require_team_reward_key; + std::shared_ptr available_expression; + std::shared_ptr enabled_expression; VersionedQuest( uint32_t quest_number, @@ -83,8 +84,8 @@ struct VersionedQuest { std::shared_ptr pvr_contents, std::shared_ptr battle_rules = nullptr, ssize_t challenge_template_index = -1, - int16_t require_flag = -1, - const std::string& require_team_reward_key = ""); + std::shared_ptr available_expression = nullptr, + std::shared_ptr enabled_expression = nullptr); std::string bin_filename() const; std::string dat_filename() const; @@ -117,13 +118,18 @@ public: std::string name; std::shared_ptr battle_rules; ssize_t challenge_template_index; - int16_t require_flag; - std::string require_team_reward_key; + std::shared_ptr available_expression; + std::shared_ptr enabled_expression; std::map> versions; }; struct QuestIndex { - using IncludeCondition = std::function)>; + enum class IncludeState { + HIDDEN = 0, + AVAILABLE, + DISABLED, + }; + using IncludeCondition = std::function)>; std::string directory; std::shared_ptr category_index; @@ -140,7 +146,7 @@ struct QuestIndex { Episode episode, Version version, IncludeCondition include_condition = nullptr) const; - std::vector> filter( + std::vector>> filter( QuestMenuType menu_type, Episode episode, Version version, diff --git a/src/QuestAvailabilityExpression.cc b/src/QuestAvailabilityExpression.cc new file mode 100644 index 00000000..1d6305fb --- /dev/null +++ b/src/QuestAvailabilityExpression.cc @@ -0,0 +1,248 @@ +#include "QuestAvailabilityExpression.hh" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CommandFormats.hh" +#include "Compression.hh" +#include "Loggers.hh" +#include "PSOEncryption.hh" +#include "QuestScript.hh" +#include "SaveFileFormats.hh" +#include "Text.hh" + +using namespace std; + +QuestAvailabilityExpression::QuestAvailabilityExpression(const string& text) + : root(this->parse_expr(text)) {} + +QuestAvailabilityExpression::OrNode::OrNode(unique_ptr&& left, unique_ptr&& right) + : left(std::move(left)), + right(std::move(right)) {} + +bool QuestAvailabilityExpression::OrNode::operator==(const Node& other) const { + try { + const OrNode& other_or = dynamic_cast(other); + return *other_or.left == *this->left && *other_or.right == *this->right; + } catch (const bad_cast&) { + return false; + } +} + +bool QuestAvailabilityExpression::OrNode::evaluate( + const QuestFlagsForDifficulty& flags, shared_ptr team) const { + return this->left->evaluate(flags, team) || this->right->evaluate(flags, team); +} + +string QuestAvailabilityExpression::OrNode::str() const { + return "(" + this->left->str() + ") || (" + this->right->str() + ")"; +} + +QuestAvailabilityExpression::AndNode::AndNode(unique_ptr&& left, unique_ptr&& right) + : left(std::move(left)), + right(std::move(right)) {} + +bool QuestAvailabilityExpression::AndNode::operator==(const Node& other) const { + try { + const AndNode& other_and = dynamic_cast(other); + return *other_and.left == *this->left && *other_and.right == *this->right; + } catch (const bad_cast&) { + return false; + } +} + +bool QuestAvailabilityExpression::AndNode::evaluate( + const QuestFlagsForDifficulty& flags, shared_ptr team) const { + return this->left->evaluate(flags, team) && this->right->evaluate(flags, team); +} + +string QuestAvailabilityExpression::AndNode::str() const { + return "(" + this->left->str() + ") && (" + this->right->str() + ")"; +} + +QuestAvailabilityExpression::NotNode::NotNode(unique_ptr&& sub) + : sub(std::move(sub)) {} + +bool QuestAvailabilityExpression::NotNode::operator==(const Node& other) const { + try { + const NotNode& other_not = dynamic_cast(other); + return *other_not.sub == *this->sub; + } catch (const bad_cast&) { + return false; + } +} + +bool QuestAvailabilityExpression::NotNode::evaluate( + const QuestFlagsForDifficulty& flags, shared_ptr team) const { + return !this->sub->evaluate(flags, team); +} + +string QuestAvailabilityExpression::NotNode::str() const { + return "!(" + this->sub->str() + ")"; +} + +QuestAvailabilityExpression::FlagLookupNode::FlagLookupNode(uint16_t flag_index) + : flag_index(flag_index) {} + +bool QuestAvailabilityExpression::FlagLookupNode::operator==(const Node& other) const { + try { + const FlagLookupNode& other_flag = dynamic_cast(other); + return other_flag.flag_index == this->flag_index; + } catch (const bad_cast&) { + return false; + } +} + +bool QuestAvailabilityExpression::FlagLookupNode::evaluate( + const QuestFlagsForDifficulty& flags, shared_ptr) const { + return flags.get(this->flag_index); +} + +string QuestAvailabilityExpression::FlagLookupNode::str() const { + return string_printf("F_%04hX", this->flag_index); +} + +QuestAvailabilityExpression::TeamRewardLookupNode::TeamRewardLookupNode(const string& reward_name) + : reward_name(reward_name) {} + +bool QuestAvailabilityExpression::TeamRewardLookupNode::operator==(const Node& other) const { + try { + const TeamRewardLookupNode& other_team_reward = dynamic_cast(other); + return other_team_reward.reward_name == this->reward_name; + } catch (const bad_cast&) { + return false; + } +} + +bool QuestAvailabilityExpression::TeamRewardLookupNode::evaluate( + const QuestFlagsForDifficulty&, shared_ptr team) const { + return team && team->has_reward(this->reward_name); +} + +string QuestAvailabilityExpression::TeamRewardLookupNode::str() const { + return "T_" + this->reward_name; +} + +QuestAvailabilityExpression::ConstantNode::ConstantNode(bool value) + : value(value) {} + +bool QuestAvailabilityExpression::ConstantNode::operator==(const Node& other) const { + try { + const ConstantNode& other_const = dynamic_cast(other); + return other_const.value == this->value; + } catch (const bad_cast&) { + return false; + } +} + +bool QuestAvailabilityExpression::ConstantNode::evaluate( + const QuestFlagsForDifficulty&, shared_ptr) const { + return this->value; +} + +string QuestAvailabilityExpression::ConstantNode::str() const { + return this->value ? "true" : "false"; +} + +unique_ptr QuestAvailabilityExpression::parse_expr(string_view text) { + // Strip off spaces and fully-enclosing parentheses + for (;;) { + size_t starting_size = text.size(); + while (text.at(0) == ' ') { + text = text.substr(1); + } + while (text.at(text.size() - 1) == ' ') { + text = text.substr(0, text.size() - 1); + } + if (text.at(0) == '(' && text.at(text.size() - 1) == ')') { + // It doesn't suffice to just check the first ant last characters, since + // text could be like "(a) && (b)". Instead, we ignore the first and last + // characters, and don't strip anything if the internal parentheses are + // unbalanced. + size_t paren_level = 1; + for (size_t z = 1; z < text.size() - 1; z++) { + if (text[z] == '(') { + paren_level++; + } else if (text[z] == ')') { + paren_level--; + if (paren_level == 0) { + break; + } + } + } + if (paren_level > 0) { + text = text.substr(1, text.size() - 2); + } + } + if (text.size() == starting_size) { + break; + } + } + + // Check for binary operators at the root level + size_t paren_level = 0; + size_t and_pos = 0; + size_t or_pos = 0; + for (size_t z = 0; z < text.size() - 1; z++) { + if (text[z] == '(') { + paren_level++; + } else if (text[z] == ')') { + paren_level--; + } else if ((text[z] == '&') && (text[z + 1] == '&') && !paren_level) { + and_pos = z; + } else if ((text[z] == '|') && (text[z + 1] == '|') && !paren_level) { + or_pos = z; + } + } + if ((or_pos && (!and_pos || (and_pos > or_pos)))) { + auto left = QuestAvailabilityExpression::parse_expr(text.substr(0, or_pos)); + auto right = QuestAvailabilityExpression::parse_expr(text.substr(or_pos + 2)); + return make_unique(std::move(left), std::move(right)); + } + if ((and_pos && (!or_pos || (or_pos > and_pos)))) { + auto left = QuestAvailabilityExpression::parse_expr(text.substr(0, and_pos)); + auto right = QuestAvailabilityExpression::parse_expr(text.substr(and_pos + 2)); + return make_unique(std::move(left), std::move(right)); + } + + // Check for not operator + if (text.at(0) == '!') { + auto sub = QuestAvailabilityExpression::parse_expr(text.substr(1)); + return make_unique(std::move(sub)); + } + + // Check for constants + if (text == "true") { + return make_unique(true); + } + if (text == "false") { + return make_unique(false); + } + + // Check for flag lookups + if (text.starts_with("F_")) { + char* endptr = nullptr; + uint64_t flag = strtoul(text.data() + 2, &endptr, 16); + if (endptr != text.data() + text.size()) { + throw runtime_error("invalid flag lookup token"); + } + if (flag >= 0x400) { + throw runtime_error("invalid flag index"); + } + return make_unique(flag); + } + + if (text.starts_with("T_")) { + return make_unique(string(text.substr(2))); + } + + throw runtime_error("unparseable expression"); +} diff --git a/src/QuestAvailabilityExpression.hh b/src/QuestAvailabilityExpression.hh new file mode 100644 index 00000000..7f604532 --- /dev/null +++ b/src/QuestAvailabilityExpression.hh @@ -0,0 +1,125 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "PlayerSubordinates.hh" +#include "QuestScript.hh" +#include "StaticGameData.hh" +#include "TeamIndex.hh" + +class QuestAvailabilityExpression { +public: + QuestAvailabilityExpression(const std::string& text); + ~QuestAvailabilityExpression() = default; + inline bool operator==(const QuestAvailabilityExpression& other) const { + return this->root->operator==(*other.root); + } + inline bool operator!=(const QuestAvailabilityExpression& other) const { + return !this->operator==(other); + } + inline bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const { + return this->root->evaluate(flags, team); + } + inline std::string str() const { + return this->root->str(); + } + +protected: + class Node { + public: + virtual ~Node() = default; + virtual bool operator==(const Node& other) const = 0; + inline bool operator!=(const Node& other) const { + return !this->operator==(other); + } + virtual bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const = 0; + virtual std::string str() const = 0; + + protected: + Node() = default; + }; + + class OrNode : public Node { + public: + OrNode(std::unique_ptr&& left, std::unique_ptr&& right); + virtual ~OrNode() = default; + virtual bool operator==(const Node& other) const; + virtual bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const; + virtual std::string str() const; + + protected: + std::unique_ptr left; + std::unique_ptr right; + }; + + class AndNode : public Node { + public: + AndNode(std::unique_ptr&& left, std::unique_ptr&& right); + virtual ~AndNode() = default; + virtual bool operator==(const Node& other) const; + virtual bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const; + virtual std::string str() const; + + protected: + std::unique_ptr left; + std::unique_ptr right; + }; + + class NotNode : public Node { + public: + NotNode(std::unique_ptr&& sub); + virtual ~NotNode() = default; + virtual bool operator==(const Node& other) const; + virtual bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const; + virtual std::string str() const; + + protected: + std::unique_ptr sub; + }; + + class FlagLookupNode : public Node { + public: + FlagLookupNode(uint16_t flag_index); + virtual ~FlagLookupNode() = default; + virtual bool operator==(const Node& other) const; + virtual bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const; + virtual std::string str() const; + + protected: + uint16_t flag_index; + }; + + class TeamRewardLookupNode : public Node { + public: + TeamRewardLookupNode(const std::string& reward_name); + virtual ~TeamRewardLookupNode() = default; + virtual bool operator==(const Node& other) const; + virtual bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const; + virtual std::string str() const; + + protected: + std::string reward_name; + }; + + class ConstantNode : public Node { + public: + ConstantNode(bool value); + virtual ~ConstantNode() = default; + virtual bool operator==(const Node& other) const; + virtual bool evaluate(const QuestFlagsForDifficulty& flags, std::shared_ptr team) const; + virtual std::string str() const; + + protected: + bool value; + }; + + std::unique_ptr parse_expr(std::string_view text); + + std::unique_ptr root; +}; diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 13de380d..3d9d5ef1 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -2287,7 +2287,7 @@ static void on_10(shared_ptr c, uint16_t, uint32_t, string& data) { send_lobby_message_box(c, "$C6Your level is too\nhigh to join this\ngame."); break; } - if (game->quest && !c->can_access_quest(game->quest, game->difficulty)) { + if (game->quest && !c->can_play_quest(game->quest, game->difficulty)) { send_lobby_message_box(c, "$C6You don't have access\nto the quest in progress\nin this game."); break; } @@ -2370,7 +2370,7 @@ static void on_10(shared_ptr c, uint16_t, uint32_t, string& data) { send_lobby_message_box(c, "$C6A quest is already\nin progress."); break; } - if (!l->quest_include_condition()(q)) { + if (l->quest_include_condition()(q) != QuestIndex::IncludeState::AVAILABLE) { send_lobby_message_box(c, "$C6This quest has not\nbeen unlocked for\nall players in this\ngame."); break; } diff --git a/src/SendCommands.cc b/src/SendCommands.cc index ad63d5b8..2440b338 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -1414,25 +1414,48 @@ template void send_quest_menu_t( shared_ptr c, uint32_t menu_id, - const vector>& quests, + const vector>>& quests, bool is_download_menu) { auto v = c->version(); vector entries; - for (const auto& quest : quests) { - auto vq = quest->version(v, c->language()); + for (const auto& it : quests) { + auto vq = it.second->version(v, c->language()); if (!vq) { continue; } auto& e = entries.emplace_back(); e.menu_id = menu_id; - e.item_id = quest->quest_number; + e.item_id = it.second->quest_number; e.name.encode(vq->name, c->language()); e.short_description.encode(add_color(vq->short_description), c->language()); } send_command_vt(c, is_download_menu ? 0xA4 : 0xA2, entries.size(), entries); } +void send_quest_menu_bb( + shared_ptr c, + uint32_t menu_id, + const vector>>& quests, + bool is_download_menu) { + auto v = c->version(); + vector entries; + for (const auto& it : quests) { + auto vq = it.second->version(v, c->language()); + if (!vq) { + continue; + } + + auto& e = entries.emplace_back(); + e.menu_id = menu_id; + e.item_id = it.second->quest_number; + e.name.encode(vq->name, c->language()); + e.short_description.encode(add_color(vq->short_description), c->language()); + e.disabled = (it.first == QuestIndex::IncludeState::DISABLED) ? 1 : 0; + } + send_command_vt(c, is_download_menu ? 0xA4 : 0xA2, entries.size(), entries); +} + template void send_quest_categories_menu_t( shared_ptr c, @@ -1459,8 +1482,11 @@ void send_quest_categories_menu_t( send_command_vt(c, is_download_menu ? 0xA4 : 0xA2, entries.size(), entries); } -void send_quest_menu(shared_ptr c, uint32_t menu_id, - const vector>& quests, bool is_download_menu) { +void send_quest_menu( + shared_ptr c, + uint32_t menu_id, + const vector>>& quests, + bool is_download_menu) { switch (c->version()) { case Version::PC_V2: send_quest_menu_t(c, menu_id, quests, is_download_menu); @@ -1479,7 +1505,7 @@ void send_quest_menu(shared_ptr c, uint32_t menu_id, send_quest_menu_t(c, menu_id, quests, is_download_menu); break; case Version::BB_V4: - send_quest_menu_t(c, menu_id, quests, is_download_menu); + send_quest_menu_bb(c, menu_id, quests, is_download_menu); break; default: throw logic_error("unimplemented versioned command"); diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 7ece4ed4..f240d440 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -258,7 +258,7 @@ void send_game_menu( void send_quest_menu( std::shared_ptr c, uint32_t menu_id, - const std::vector>& quests, + const std::vector>>& quests, bool is_download_menu); void send_quest_categories_menu( std::shared_ptr c, diff --git a/system/config.example.json b/system/config.example.json index 7cafc77b..59efd96b 100644 --- a/system/config.example.json +++ b/system/config.example.json @@ -501,7 +501,8 @@ [0x02, "battle", "Battle", "$E$C6Battle mode rule\nsets"], [0x04, "challenge-ep1", "Challenge (Episode 1)", "$E$C6Challenge mode\nquests in Episode 1"], [0x84, "challenge-ep2", "Challenge (Episode 2)", "$E$C6Challenge mode\nquests in Episode 2"], - [0x08, "solo", "Solo", "$E$C6Quests that require\na single player"], + [0x08, "solo-story", "Story", "$E$C6Quests that follow\nthe Episode 1 story"], + [0x08, "solo-extra", "Solo", "$E$C6Quests that require\na single player"], [0x10, "government-ep1", "Hero in Red", "$E$CG-Red Ring Rico-\n$C6Quests that follow\nthe Episode 1\nstoryline"], [0x10, "government-ep2", "The Military's Hero", "$E$CG-Heathcliff Flowen-\n$C6Quests that follow\nthe Episode 2\nstoryline"], [0x10, "government-ep4", "The Meteor Impact Incident", "$E$C6Quests that follow\nthe Episode 4\nstoryline"], diff --git a/system/quests/battle/b88001.json b/system/quests/battle/b88001.json index a6bcaf73..89913b08 100644 --- a/system/quests/battle/b88001.json +++ b/system/quests/battle/b88001.json @@ -35,14 +35,16 @@ // "ChallengeTemplateIndex": 0, // Quests may be set to be unavailable until a preceding quest has been - // cleared. To enable this feature, set a value for RequireFlag in the quest's - // JSON file. This field is ignored if the player has the - // DISABLE_QUEST_REQUIREMENTS flag in their license. - // "RequireFlag": 0x01F5, + // cleared or a team reward has been purchased. To enable this feature, set a + // value for AvailableIf in the quest's JSON file. This field's value should + // be a boolean expression that tests one or more flags or team rewards. An + // example with random values is shown below. This field is ignored if the + // player has the DISABLE_QUEST_REQUIREMENTS flag in their license. + // "AvailableIf": "(F_016D || F_0171 || T_EpicCustomQuest) && !F_0173", - // Quests on BB may be set to be available only through a team reward. To - // enable this feature, set a value for RequireTeamRewardKey in the quest's - // JSON file. This field is ignored if the player has the - // DISABLE_QUEST_REQUIREMENTS flag in their license. - // "RequireTeamRewardKey": "PointOfDisasterQuest", + // On BB, quests may be disabled but still visible to the player. This + // expression controls when that should be the case. If AvailableIf evaluates + // to false, this is ignored. This field is also ignored if the player has + // the DISABLE_QUEST_REQUIREMENTS flag in their license. + // "EnabledIf": "!F_0169", } diff --git a/system/quests/government-ep1/q402-bb.json b/system/quests/government-ep1/q402-bb.json index b848b5dc..f1df27e5 100644 --- a/system/quests/government-ep1/q402-bb.json +++ b/system/quests/government-ep1/q402-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x01F5, + "AvailableIf": "F_01F5", } diff --git a/system/quests/government-ep1/q403-bb.json b/system/quests/government-ep1/q403-bb.json index b874455a..a937ec1a 100644 --- a/system/quests/government-ep1/q403-bb.json +++ b/system/quests/government-ep1/q403-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x01F7, + "AvailableIf": "F_01F7", } diff --git a/system/quests/government-ep1/q404-bb.json b/system/quests/government-ep1/q404-bb.json index 6f9fcceb..7a86cddd 100644 --- a/system/quests/government-ep1/q404-bb.json +++ b/system/quests/government-ep1/q404-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x01F9, + "AvailableIf": "F_01F9", } diff --git a/system/quests/government-ep1/q405-bb.json b/system/quests/government-ep1/q405-bb.json index e4771e85..566f4f27 100644 --- a/system/quests/government-ep1/q405-bb.json +++ b/system/quests/government-ep1/q405-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x01FB, + "AvailableIf": "F_01FB", } diff --git a/system/quests/government-ep1/q406-bb.json b/system/quests/government-ep1/q406-bb.json index 60c10f94..ff1dbaf0 100644 --- a/system/quests/government-ep1/q406-bb.json +++ b/system/quests/government-ep1/q406-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x01FD, + "AvailableIf": "F_01FD", } diff --git a/system/quests/government-ep1/q407-bb.json b/system/quests/government-ep1/q407-bb.json index d9fbd98a..44b9d795 100644 --- a/system/quests/government-ep1/q407-bb.json +++ b/system/quests/government-ep1/q407-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x01FF, + "AvailableIf": "F_01FF", } diff --git a/system/quests/government-ep1/q408-bb.json b/system/quests/government-ep1/q408-bb.json index 369e31d5..dfc28034 100644 --- a/system/quests/government-ep1/q408-bb.json +++ b/system/quests/government-ep1/q408-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0201, + "AvailableIf": "F_0201", } diff --git a/system/quests/government-ep1/q409-bb.json b/system/quests/government-ep1/q409-bb.json index cd64b00a..f94fdbc2 100644 --- a/system/quests/government-ep1/q409-bb.json +++ b/system/quests/government-ep1/q409-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0203, + "AvailableIf": "F_0203", } diff --git a/system/quests/government-ep1/q410-bb.json b/system/quests/government-ep1/q410-bb.json index 4c85c9dc..a154a066 100644 --- a/system/quests/government-ep1/q410-bb.json +++ b/system/quests/government-ep1/q410-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0205, + "AvailableIf": "F_0205", } diff --git a/system/quests/government-ep1/q411-bb.json b/system/quests/government-ep1/q411-bb.json index 94ced7db..6e6391f9 100644 --- a/system/quests/government-ep1/q411-bb.json +++ b/system/quests/government-ep1/q411-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0207, + "AvailableIf": "F_0207", } diff --git a/system/quests/government-ep1/q412-bb.json b/system/quests/government-ep1/q412-bb.json index d17ccce3..9be11262 100644 --- a/system/quests/government-ep1/q412-bb.json +++ b/system/quests/government-ep1/q412-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0209, + "AvailableIf": "F_0209", } diff --git a/system/quests/government-ep1/q413-bb.json b/system/quests/government-ep1/q413-bb.json index 00acf966..c612dbe5 100644 --- a/system/quests/government-ep1/q413-bb.json +++ b/system/quests/government-ep1/q413-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x020B, + "AvailableIf": "F_020B", } diff --git a/system/quests/government-ep1/q414-bb.json b/system/quests/government-ep1/q414-bb.json index 2e4bb7c5..08f8d837 100644 --- a/system/quests/government-ep1/q414-bb.json +++ b/system/quests/government-ep1/q414-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x020D, + "AvailableIf": "F_020D", } diff --git a/system/quests/government-ep1/q415-bb.json b/system/quests/government-ep1/q415-bb.json index 69f27b95..769d66ad 100644 --- a/system/quests/government-ep1/q415-bb.json +++ b/system/quests/government-ep1/q415-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x020F, + "AvailableIf": "F_020F", } diff --git a/system/quests/government-ep2/q452-bb.json b/system/quests/government-ep2/q452-bb.json index 168385dd..4f0ae36e 100644 --- a/system/quests/government-ep2/q452-bb.json +++ b/system/quests/government-ep2/q452-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0213, + "AvailableIf": "F_0213", } diff --git a/system/quests/government-ep2/q453-bb.json b/system/quests/government-ep2/q453-bb.json index ee889e48..cdc2fe53 100644 --- a/system/quests/government-ep2/q453-bb.json +++ b/system/quests/government-ep2/q453-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0215, + "AvailableIf": "F_0215", } diff --git a/system/quests/government-ep2/q454-bb.json b/system/quests/government-ep2/q454-bb.json index 91c74c87..11ddb07b 100644 --- a/system/quests/government-ep2/q454-bb.json +++ b/system/quests/government-ep2/q454-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0217, + "AvailableIf": "F_0217", } diff --git a/system/quests/government-ep2/q455-bb.json b/system/quests/government-ep2/q455-bb.json index 51f3357e..50c98bf0 100644 --- a/system/quests/government-ep2/q455-bb.json +++ b/system/quests/government-ep2/q455-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0219, + "AvailableIf": "F_0219", } diff --git a/system/quests/government-ep2/q456-bb.json b/system/quests/government-ep2/q456-bb.json index eaa90b9e..02bf786a 100644 --- a/system/quests/government-ep2/q456-bb.json +++ b/system/quests/government-ep2/q456-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x021B, + "AvailableIf": "F_021B", } diff --git a/system/quests/government-ep2/q457-bb.json b/system/quests/government-ep2/q457-bb.json index 1ad36d36..a3f41e19 100644 --- a/system/quests/government-ep2/q457-bb.json +++ b/system/quests/government-ep2/q457-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x021D, + "AvailableIf": "F_021D", } diff --git a/system/quests/government-ep2/q458-bb.json b/system/quests/government-ep2/q458-bb.json index 14a797af..8a425b96 100644 --- a/system/quests/government-ep2/q458-bb.json +++ b/system/quests/government-ep2/q458-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x021F, + "AvailableIf": "F_021F", } diff --git a/system/quests/government-ep2/q459-bb.json b/system/quests/government-ep2/q459-bb.json index d6f43d31..61dcdde4 100644 --- a/system/quests/government-ep2/q459-bb.json +++ b/system/quests/government-ep2/q459-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0221, + "AvailableIf": "F_0221", } diff --git a/system/quests/government-ep2/q460-bb.json b/system/quests/government-ep2/q460-bb.json index f3316531..e9980bc4 100644 --- a/system/quests/government-ep2/q460-bb.json +++ b/system/quests/government-ep2/q460-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0223, + "AvailableIf": "F_0223", } diff --git a/system/quests/government-ep2/q461-bb.json b/system/quests/government-ep2/q461-bb.json index 260c270c..983701c4 100644 --- a/system/quests/government-ep2/q461-bb.json +++ b/system/quests/government-ep2/q461-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0225, + "AvailableIf": "F_0225", } diff --git a/system/quests/government-ep2/q462-bb.json b/system/quests/government-ep2/q462-bb.json index df994729..0c4ad229 100644 --- a/system/quests/government-ep2/q462-bb.json +++ b/system/quests/government-ep2/q462-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0227, + "AvailableIf": "F_0227", } diff --git a/system/quests/government-ep2/q463-bb.json b/system/quests/government-ep2/q463-bb.json index 1342cb90..62218384 100644 --- a/system/quests/government-ep2/q463-bb.json +++ b/system/quests/government-ep2/q463-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0229, + "AvailableIf": "F_0229", } diff --git a/system/quests/government-ep2/q464-bb.json b/system/quests/government-ep2/q464-bb.json index 0e67aa65..40a91399 100644 --- a/system/quests/government-ep2/q464-bb.json +++ b/system/quests/government-ep2/q464-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x022B, + "AvailableIf": "F_022B", } diff --git a/system/quests/government-ep2/q465-bb.json b/system/quests/government-ep2/q465-bb.json index 32c79778..434b1b9b 100644 --- a/system/quests/government-ep2/q465-bb.json +++ b/system/quests/government-ep2/q465-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x022D, + "AvailableIf": "F_022D", } diff --git a/system/quests/government-ep2/q466-bb.json b/system/quests/government-ep2/q466-bb.json index 80674aaf..72af0390 100644 --- a/system/quests/government-ep2/q466-bb.json +++ b/system/quests/government-ep2/q466-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x022F, + "AvailableIf": "F_022F", } diff --git a/system/quests/government-ep2/q467-bb.json b/system/quests/government-ep2/q467-bb.json index e36165ec..b9c84f47 100644 --- a/system/quests/government-ep2/q467-bb.json +++ b/system/quests/government-ep2/q467-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0231, + "AvailableIf": "F_0231", } diff --git a/system/quests/government-ep2/q468-bb.json b/system/quests/government-ep2/q468-bb.json index b3a3a217..5499d9a0 100644 --- a/system/quests/government-ep2/q468-bb.json +++ b/system/quests/government-ep2/q468-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x0233, + "AvailableIf": "F_0233", } diff --git a/system/quests/government-ep4/q702-bb.json b/system/quests/government-ep4/q702-bb.json index 6a2c4e06..06357eb2 100644 --- a/system/quests/government-ep4/q702-bb.json +++ b/system/quests/government-ep4/q702-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x02BD, + "AvailableIf": "F_02BD", } diff --git a/system/quests/government-ep4/q703-bb.json b/system/quests/government-ep4/q703-bb.json index 69f1bc5b..ab3043ad 100644 --- a/system/quests/government-ep4/q703-bb.json +++ b/system/quests/government-ep4/q703-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x02BE, + "AvailableIf": "F_02BE", } diff --git a/system/quests/government-ep4/q704-bb.json b/system/quests/government-ep4/q704-bb.json index fa5b0652..47b7bce8 100644 --- a/system/quests/government-ep4/q704-bb.json +++ b/system/quests/government-ep4/q704-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x02BF, + "AvailableIf": "F_02BF", } diff --git a/system/quests/government-ep4/q705-bb.json b/system/quests/government-ep4/q705-bb.json index ec0157f0..c27781da 100644 --- a/system/quests/government-ep4/q705-bb.json +++ b/system/quests/government-ep4/q705-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x02C0, + "AvailableIf": "F_02C0", } diff --git a/system/quests/government-ep4/q706-bb.json b/system/quests/government-ep4/q706-bb.json index b3758669..6db7409f 100644 --- a/system/quests/government-ep4/q706-bb.json +++ b/system/quests/government-ep4/q706-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x02C1, + "AvailableIf": "F_02C1", } diff --git a/system/quests/government-ep4/q707-bb.json b/system/quests/government-ep4/q707-bb.json index 8cccbc50..0bfbc030 100644 --- a/system/quests/government-ep4/q707-bb.json +++ b/system/quests/government-ep4/q707-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x02C2, + "AvailableIf": "F_02C2", } diff --git a/system/quests/government-ep4/q708-bb.json b/system/quests/government-ep4/q708-bb.json index a887c33f..703688e6 100644 --- a/system/quests/government-ep4/q708-bb.json +++ b/system/quests/government-ep4/q708-bb.json @@ -1,3 +1,3 @@ { - "RequireFlag": 0x02C3, + "AvailableIf": "F_02C3", } diff --git a/system/quests/solo/q035-bb-e.bin b/system/quests/solo-extra/q035-bb-e.bin similarity index 100% rename from system/quests/solo/q035-bb-e.bin rename to system/quests/solo-extra/q035-bb-e.bin diff --git a/system/quests/solo/q035-bb-j.bin b/system/quests/solo-extra/q035-bb-j.bin similarity index 100% rename from system/quests/solo/q035-bb-j.bin rename to system/quests/solo-extra/q035-bb-j.bin diff --git a/system/quests/solo/q035-bb.dat b/system/quests/solo-extra/q035-bb.dat similarity index 100% rename from system/quests/solo/q035-bb.dat rename to system/quests/solo-extra/q035-bb.dat diff --git a/system/quests/solo/q036-bb-j.bin b/system/quests/solo-extra/q036-bb-j.bin similarity index 100% rename from system/quests/solo/q036-bb-j.bin rename to system/quests/solo-extra/q036-bb-j.bin diff --git a/system/quests/solo/q036-bb.dat b/system/quests/solo-extra/q036-bb.dat similarity index 100% rename from system/quests/solo/q036-bb.dat rename to system/quests/solo-extra/q036-bb.dat diff --git a/system/quests/solo/q126-bb-e.bin b/system/quests/solo-extra/q126-bb-e.bin similarity index 100% rename from system/quests/solo/q126-bb-e.bin rename to system/quests/solo-extra/q126-bb-e.bin diff --git a/system/quests/solo/q126-bb-j.bin b/system/quests/solo-extra/q126-bb-j.bin similarity index 100% rename from system/quests/solo/q126-bb-j.bin rename to system/quests/solo-extra/q126-bb-j.bin diff --git a/system/quests/solo/q126-bb.dat b/system/quests/solo-extra/q126-bb.dat similarity index 100% rename from system/quests/solo/q126-bb.dat rename to system/quests/solo-extra/q126-bb.dat diff --git a/system/quests/solo/q143-bb-e.bin b/system/quests/solo-extra/q143-bb-e.bin similarity index 100% rename from system/quests/solo/q143-bb-e.bin rename to system/quests/solo-extra/q143-bb-e.bin diff --git a/system/quests/solo/q143-bb-j.bin b/system/quests/solo-extra/q143-bb-j.bin similarity index 100% rename from system/quests/solo/q143-bb-j.bin rename to system/quests/solo-extra/q143-bb-j.bin diff --git a/system/quests/solo/q143-bb.dat b/system/quests/solo-extra/q143-bb.dat similarity index 100% rename from system/quests/solo/q143-bb.dat rename to system/quests/solo-extra/q143-bb.dat diff --git a/system/quests/solo/q001-bb-e.bin b/system/quests/solo-story/q001-bb-e.bin similarity index 100% rename from system/quests/solo/q001-bb-e.bin rename to system/quests/solo-story/q001-bb-e.bin diff --git a/system/quests/solo/q001-bb-j.bin b/system/quests/solo-story/q001-bb-j.bin similarity index 100% rename from system/quests/solo/q001-bb-j.bin rename to system/quests/solo-story/q001-bb-j.bin diff --git a/system/quests/solo/q001-bb.dat b/system/quests/solo-story/q001-bb.dat similarity index 100% rename from system/quests/solo/q001-bb.dat rename to system/quests/solo-story/q001-bb.dat diff --git a/system/quests/solo-story/q001.json b/system/quests/solo-story/q001.json new file mode 100644 index 00000000..5c2a07f4 --- /dev/null +++ b/system/quests/solo-story/q001.json @@ -0,0 +1,3 @@ +{ + "EnabledIf": "!F_0065 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q002-bb-e.bin b/system/quests/solo-story/q002-bb-e.bin similarity index 100% rename from system/quests/solo/q002-bb-e.bin rename to system/quests/solo-story/q002-bb-e.bin diff --git a/system/quests/solo/q002-bb-j.bin b/system/quests/solo-story/q002-bb-j.bin similarity index 100% rename from system/quests/solo/q002-bb-j.bin rename to system/quests/solo-story/q002-bb-j.bin diff --git a/system/quests/solo/q002-bb.dat b/system/quests/solo-story/q002-bb.dat similarity index 100% rename from system/quests/solo/q002-bb.dat rename to system/quests/solo-story/q002-bb.dat diff --git a/system/quests/solo-story/q002.json b/system/quests/solo-story/q002.json new file mode 100644 index 00000000..6842f452 --- /dev/null +++ b/system/quests/solo-story/q002.json @@ -0,0 +1,3 @@ +{ + "EnabledIf": "!F_0067 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q003-bb-e.bin b/system/quests/solo-story/q003-bb-e.bin similarity index 100% rename from system/quests/solo/q003-bb-e.bin rename to system/quests/solo-story/q003-bb-e.bin diff --git a/system/quests/solo/q003-bb-j.bin b/system/quests/solo-story/q003-bb-j.bin similarity index 100% rename from system/quests/solo/q003-bb-j.bin rename to system/quests/solo-story/q003-bb-j.bin diff --git a/system/quests/solo/q003-bb.dat b/system/quests/solo-story/q003-bb.dat similarity index 100% rename from system/quests/solo/q003-bb.dat rename to system/quests/solo-story/q003-bb.dat diff --git a/system/quests/solo-story/q003.json b/system/quests/solo-story/q003.json new file mode 100644 index 00000000..35710c6d --- /dev/null +++ b/system/quests/solo-story/q003.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9", + "EnabledIf": "!F_0069 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q004-bb-e.bin b/system/quests/solo-story/q004-bb-e.bin similarity index 100% rename from system/quests/solo/q004-bb-e.bin rename to system/quests/solo-story/q004-bb-e.bin diff --git a/system/quests/solo/q004-bb-j.bin b/system/quests/solo-story/q004-bb-j.bin similarity index 100% rename from system/quests/solo/q004-bb-j.bin rename to system/quests/solo-story/q004-bb-j.bin diff --git a/system/quests/solo/q004-bb.dat b/system/quests/solo-story/q004-bb.dat similarity index 100% rename from system/quests/solo/q004-bb.dat rename to system/quests/solo-story/q004-bb.dat diff --git a/system/quests/solo-story/q004.json b/system/quests/solo-story/q004.json new file mode 100644 index 00000000..369516d6 --- /dev/null +++ b/system/quests/solo-story/q004.json @@ -0,0 +1,3 @@ +{ + "EnabledIf": "!F_006B || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q005-bb-e.bin b/system/quests/solo-story/q005-bb-e.bin similarity index 100% rename from system/quests/solo/q005-bb-e.bin rename to system/quests/solo-story/q005-bb-e.bin diff --git a/system/quests/solo/q005-bb-j.bin b/system/quests/solo-story/q005-bb-j.bin similarity index 100% rename from system/quests/solo/q005-bb-j.bin rename to system/quests/solo-story/q005-bb-j.bin diff --git a/system/quests/solo/q005-bb.dat b/system/quests/solo-story/q005-bb.dat similarity index 100% rename from system/quests/solo/q005-bb.dat rename to system/quests/solo-story/q005-bb.dat diff --git a/system/quests/solo-story/q005.json b/system/quests/solo-story/q005.json new file mode 100644 index 00000000..26c72a09 --- /dev/null +++ b/system/quests/solo-story/q005.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B", + "EnabledIf": "!F_006D || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q006-bb-e.bin b/system/quests/solo-story/q006-bb-e.bin similarity index 100% rename from system/quests/solo/q006-bb-e.bin rename to system/quests/solo-story/q006-bb-e.bin diff --git a/system/quests/solo/q006-bb-j.bin b/system/quests/solo-story/q006-bb-j.bin similarity index 100% rename from system/quests/solo/q006-bb-j.bin rename to system/quests/solo-story/q006-bb-j.bin diff --git a/system/quests/solo/q006-bb.dat b/system/quests/solo-story/q006-bb.dat similarity index 100% rename from system/quests/solo/q006-bb.dat rename to system/quests/solo-story/q006-bb.dat diff --git a/system/quests/solo-story/q006.json b/system/quests/solo-story/q006.json new file mode 100644 index 00000000..33b510e6 --- /dev/null +++ b/system/quests/solo-story/q006.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B", + "EnabledIf": "!F_006F || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q007-bb-e.bin b/system/quests/solo-story/q007-bb-e.bin similarity index 100% rename from system/quests/solo/q007-bb-e.bin rename to system/quests/solo-story/q007-bb-e.bin diff --git a/system/quests/solo/q007-bb-j.bin b/system/quests/solo-story/q007-bb-j.bin similarity index 100% rename from system/quests/solo/q007-bb-j.bin rename to system/quests/solo-story/q007-bb-j.bin diff --git a/system/quests/solo/q007-bb.dat b/system/quests/solo-story/q007-bb.dat similarity index 100% rename from system/quests/solo/q007-bb.dat rename to system/quests/solo-story/q007-bb.dat diff --git a/system/quests/solo-story/q007.json b/system/quests/solo-story/q007.json new file mode 100644 index 00000000..72a1c8f8 --- /dev/null +++ b/system/quests/solo-story/q007.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B", + "EnabledIf": "!F_0071 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q008-bb-e.bin b/system/quests/solo-story/q008-bb-e.bin similarity index 100% rename from system/quests/solo/q008-bb-e.bin rename to system/quests/solo-story/q008-bb-e.bin diff --git a/system/quests/solo/q008-bb-j.bin b/system/quests/solo-story/q008-bb-j.bin similarity index 100% rename from system/quests/solo/q008-bb-j.bin rename to system/quests/solo-story/q008-bb-j.bin diff --git a/system/quests/solo/q008-bb.dat b/system/quests/solo-story/q008-bb.dat similarity index 100% rename from system/quests/solo/q008-bb.dat rename to system/quests/solo-story/q008-bb.dat diff --git a/system/quests/solo-story/q008.json b/system/quests/solo-story/q008.json new file mode 100644 index 00000000..ecbb4f3c --- /dev/null +++ b/system/quests/solo-story/q008.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0071", + "EnabledIf": "!F_0073 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q009-bb-e.bin b/system/quests/solo-story/q009-bb-e.bin similarity index 100% rename from system/quests/solo/q009-bb-e.bin rename to system/quests/solo-story/q009-bb-e.bin diff --git a/system/quests/solo/q009-bb-j.bin b/system/quests/solo-story/q009-bb-j.bin similarity index 100% rename from system/quests/solo/q009-bb-j.bin rename to system/quests/solo-story/q009-bb-j.bin diff --git a/system/quests/solo/q009-bb.dat b/system/quests/solo-story/q009-bb.dat similarity index 100% rename from system/quests/solo/q009-bb.dat rename to system/quests/solo-story/q009-bb.dat diff --git a/system/quests/solo-story/q009.json b/system/quests/solo-story/q009.json new file mode 100644 index 00000000..3b0040c6 --- /dev/null +++ b/system/quests/solo-story/q009.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B", + "EnabledIf": "!F_0075 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q010-bb-e.bin b/system/quests/solo-story/q010-bb-e.bin similarity index 100% rename from system/quests/solo/q010-bb-e.bin rename to system/quests/solo-story/q010-bb-e.bin diff --git a/system/quests/solo/q010-bb-j.bin b/system/quests/solo-story/q010-bb-j.bin similarity index 100% rename from system/quests/solo/q010-bb-j.bin rename to system/quests/solo-story/q010-bb-j.bin diff --git a/system/quests/solo/q010-bb.dat b/system/quests/solo-story/q010-bb.dat similarity index 100% rename from system/quests/solo/q010-bb.dat rename to system/quests/solo-story/q010-bb.dat diff --git a/system/quests/solo-story/q010.json b/system/quests/solo-story/q010.json new file mode 100644 index 00000000..47c9a375 --- /dev/null +++ b/system/quests/solo-story/q010.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9", + "EnabledIf": "!F_0077 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q011-bb-e.bin b/system/quests/solo-story/q011-bb-e.bin similarity index 100% rename from system/quests/solo/q011-bb-e.bin rename to system/quests/solo-story/q011-bb-e.bin diff --git a/system/quests/solo/q011-bb-j.bin b/system/quests/solo-story/q011-bb-j.bin similarity index 100% rename from system/quests/solo/q011-bb-j.bin rename to system/quests/solo-story/q011-bb-j.bin diff --git a/system/quests/solo/q011-bb.dat b/system/quests/solo-story/q011-bb.dat similarity index 100% rename from system/quests/solo/q011-bb.dat rename to system/quests/solo-story/q011-bb.dat diff --git a/system/quests/solo-story/q011.json b/system/quests/solo-story/q011.json new file mode 100644 index 00000000..32ffc500 --- /dev/null +++ b/system/quests/solo-story/q011.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9", + "EnabledIf": "!F_0079 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q012-bb-e.bin b/system/quests/solo-story/q012-bb-e.bin similarity index 100% rename from system/quests/solo/q012-bb-e.bin rename to system/quests/solo-story/q012-bb-e.bin diff --git a/system/quests/solo/q012-bb-j.bin b/system/quests/solo-story/q012-bb-j.bin similarity index 100% rename from system/quests/solo/q012-bb-j.bin rename to system/quests/solo-story/q012-bb-j.bin diff --git a/system/quests/solo/q012-bb.dat b/system/quests/solo-story/q012-bb.dat similarity index 100% rename from system/quests/solo/q012-bb.dat rename to system/quests/solo-story/q012-bb.dat diff --git a/system/quests/solo-story/q012.json b/system/quests/solo-story/q012.json new file mode 100644 index 00000000..56c012e5 --- /dev/null +++ b/system/quests/solo-story/q012.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_0077 && F_0079 && F_007F && F_0085 && F_01F9", + "EnabledIf": "!F_007B || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q013-bb-e.bin b/system/quests/solo-story/q013-bb-e.bin similarity index 100% rename from system/quests/solo/q013-bb-e.bin rename to system/quests/solo-story/q013-bb-e.bin diff --git a/system/quests/solo/q013-bb-j.bin b/system/quests/solo-story/q013-bb-j.bin similarity index 100% rename from system/quests/solo/q013-bb-j.bin rename to system/quests/solo-story/q013-bb-j.bin diff --git a/system/quests/solo/q013-bb.dat b/system/quests/solo-story/q013-bb.dat similarity index 100% rename from system/quests/solo/q013-bb.dat rename to system/quests/solo-story/q013-bb.dat diff --git a/system/quests/solo-story/q013.json b/system/quests/solo-story/q013.json new file mode 100644 index 00000000..75ba25dc --- /dev/null +++ b/system/quests/solo-story/q013.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_007B && F_01F9", + "EnabledIf": "!F_007D || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q014-bb-e.bin b/system/quests/solo-story/q014-bb-e.bin similarity index 100% rename from system/quests/solo/q014-bb-e.bin rename to system/quests/solo-story/q014-bb-e.bin diff --git a/system/quests/solo/q014-bb-j.bin b/system/quests/solo-story/q014-bb-j.bin similarity index 100% rename from system/quests/solo/q014-bb-j.bin rename to system/quests/solo-story/q014-bb-j.bin diff --git a/system/quests/solo/q014-bb.dat b/system/quests/solo-story/q014-bb.dat similarity index 100% rename from system/quests/solo/q014-bb.dat rename to system/quests/solo-story/q014-bb.dat diff --git a/system/quests/solo-story/q014.json b/system/quests/solo-story/q014.json new file mode 100644 index 00000000..5742ee81 --- /dev/null +++ b/system/quests/solo-story/q014.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9", + "EnabledIf": "!F_007F || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q015-bb-e.bin b/system/quests/solo-story/q015-bb-e.bin similarity index 100% rename from system/quests/solo/q015-bb-e.bin rename to system/quests/solo-story/q015-bb-e.bin diff --git a/system/quests/solo/q015-bb-j.bin b/system/quests/solo-story/q015-bb-j.bin similarity index 100% rename from system/quests/solo/q015-bb-j.bin rename to system/quests/solo-story/q015-bb-j.bin diff --git a/system/quests/solo/q015-bb.dat b/system/quests/solo-story/q015-bb.dat similarity index 100% rename from system/quests/solo/q015-bb.dat rename to system/quests/solo-story/q015-bb.dat diff --git a/system/quests/solo-story/q015.json b/system/quests/solo-story/q015.json new file mode 100644 index 00000000..a37c2476 --- /dev/null +++ b/system/quests/solo-story/q015.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_0077 && F_0079 && F_007F && F_0085 && F_01F9", + "EnabledIf": "!F_0081 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q016-bb-e.bin b/system/quests/solo-story/q016-bb-e.bin similarity index 100% rename from system/quests/solo/q016-bb-e.bin rename to system/quests/solo-story/q016-bb-e.bin diff --git a/system/quests/solo/q016-bb-j.bin b/system/quests/solo-story/q016-bb-j.bin similarity index 100% rename from system/quests/solo/q016-bb-j.bin rename to system/quests/solo-story/q016-bb-j.bin diff --git a/system/quests/solo/q016-bb.dat b/system/quests/solo-story/q016-bb.dat similarity index 100% rename from system/quests/solo/q016-bb.dat rename to system/quests/solo-story/q016-bb.dat diff --git a/system/quests/solo-story/q016.json b/system/quests/solo-story/q016.json new file mode 100644 index 00000000..6ee06a9c --- /dev/null +++ b/system/quests/solo-story/q016.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01FF", + "EnabledIf": "!F_0083 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q017-bb-e.bin b/system/quests/solo-story/q017-bb-e.bin similarity index 100% rename from system/quests/solo/q017-bb-e.bin rename to system/quests/solo-story/q017-bb-e.bin diff --git a/system/quests/solo/q017-bb-j.bin b/system/quests/solo-story/q017-bb-j.bin similarity index 100% rename from system/quests/solo/q017-bb-j.bin rename to system/quests/solo-story/q017-bb-j.bin diff --git a/system/quests/solo/q017-bb.dat b/system/quests/solo-story/q017-bb.dat similarity index 100% rename from system/quests/solo/q017-bb.dat rename to system/quests/solo-story/q017-bb.dat diff --git a/system/quests/solo-story/q017.json b/system/quests/solo-story/q017.json new file mode 100644 index 00000000..c661338a --- /dev/null +++ b/system/quests/solo-story/q017.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9", + "EnabledIf": "!F_0085 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q018-bb-e.bin b/system/quests/solo-story/q018-bb-e.bin similarity index 100% rename from system/quests/solo/q018-bb-e.bin rename to system/quests/solo-story/q018-bb-e.bin diff --git a/system/quests/solo/q018-bb-j.bin b/system/quests/solo-story/q018-bb-j.bin similarity index 100% rename from system/quests/solo/q018-bb-j.bin rename to system/quests/solo-story/q018-bb-j.bin diff --git a/system/quests/solo/q018-bb.dat b/system/quests/solo-story/q018-bb.dat similarity index 100% rename from system/quests/solo/q018-bb.dat rename to system/quests/solo-story/q018-bb.dat diff --git a/system/quests/solo-story/q018.json b/system/quests/solo-story/q018.json new file mode 100644 index 00000000..269ef10a --- /dev/null +++ b/system/quests/solo-story/q018.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9", + "EnabledIf": "!F_0087 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q019-bb-e.bin b/system/quests/solo-story/q019-bb-e.bin similarity index 100% rename from system/quests/solo/q019-bb-e.bin rename to system/quests/solo-story/q019-bb-e.bin diff --git a/system/quests/solo/q019-bb-j.bin b/system/quests/solo-story/q019-bb-j.bin similarity index 100% rename from system/quests/solo/q019-bb-j.bin rename to system/quests/solo-story/q019-bb-j.bin diff --git a/system/quests/solo/q019-bb.dat b/system/quests/solo-story/q019-bb.dat similarity index 100% rename from system/quests/solo/q019-bb.dat rename to system/quests/solo-story/q019-bb.dat diff --git a/system/quests/solo-story/q019.json b/system/quests/solo-story/q019.json new file mode 100644 index 00000000..63ca72c1 --- /dev/null +++ b/system/quests/solo-story/q019.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_0207", + "EnabledIf": "!F_0089 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q020-bb-e.bin b/system/quests/solo-story/q020-bb-e.bin similarity index 100% rename from system/quests/solo/q020-bb-e.bin rename to system/quests/solo-story/q020-bb-e.bin diff --git a/system/quests/solo/q020-bb-j.bin b/system/quests/solo-story/q020-bb-j.bin similarity index 100% rename from system/quests/solo/q020-bb-j.bin rename to system/quests/solo-story/q020-bb-j.bin diff --git a/system/quests/solo/q020-bb.dat b/system/quests/solo-story/q020-bb.dat similarity index 100% rename from system/quests/solo/q020-bb.dat rename to system/quests/solo-story/q020-bb.dat diff --git a/system/quests/solo-story/q020.json b/system/quests/solo-story/q020.json new file mode 100644 index 00000000..e59ecb24 --- /dev/null +++ b/system/quests/solo-story/q020.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9", + "EnabledIf": "!F_008B || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q021-bb-e.bin b/system/quests/solo-story/q021-bb-e.bin similarity index 100% rename from system/quests/solo/q021-bb-e.bin rename to system/quests/solo-story/q021-bb-e.bin diff --git a/system/quests/solo/q021-bb-j.bin b/system/quests/solo-story/q021-bb-j.bin similarity index 100% rename from system/quests/solo/q021-bb-j.bin rename to system/quests/solo-story/q021-bb-j.bin diff --git a/system/quests/solo/q021-bb.dat b/system/quests/solo-story/q021-bb.dat similarity index 100% rename from system/quests/solo/q021-bb.dat rename to system/quests/solo-story/q021-bb.dat diff --git a/system/quests/solo-story/q021.json b/system/quests/solo-story/q021.json new file mode 100644 index 00000000..5b92895b --- /dev/null +++ b/system/quests/solo-story/q021.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_007F && F_008B && F_01F9", + "EnabledIf": "!F_008D || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q022-bb-e.bin b/system/quests/solo-story/q022-bb-e.bin similarity index 100% rename from system/quests/solo/q022-bb-e.bin rename to system/quests/solo-story/q022-bb-e.bin diff --git a/system/quests/solo/q022-bb-j.bin b/system/quests/solo-story/q022-bb-j.bin similarity index 100% rename from system/quests/solo/q022-bb-j.bin rename to system/quests/solo-story/q022-bb-j.bin diff --git a/system/quests/solo/q022-bb.dat b/system/quests/solo-story/q022-bb.dat similarity index 100% rename from system/quests/solo/q022-bb.dat rename to system/quests/solo-story/q022-bb.dat diff --git a/system/quests/solo-story/q022.json b/system/quests/solo-story/q022.json new file mode 100644 index 00000000..dea1b0fe --- /dev/null +++ b/system/quests/solo-story/q022.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_0091 && F_0207", + "EnabledIf": "!F_008F || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q023-bb-e.bin b/system/quests/solo-story/q023-bb-e.bin similarity index 100% rename from system/quests/solo/q023-bb-e.bin rename to system/quests/solo-story/q023-bb-e.bin diff --git a/system/quests/solo/q023-bb-j.bin b/system/quests/solo-story/q023-bb-j.bin similarity index 100% rename from system/quests/solo/q023-bb-j.bin rename to system/quests/solo-story/q023-bb-j.bin diff --git a/system/quests/solo/q023-bb.dat b/system/quests/solo-story/q023-bb.dat similarity index 100% rename from system/quests/solo/q023-bb.dat rename to system/quests/solo-story/q023-bb.dat diff --git a/system/quests/solo-story/q023.json b/system/quests/solo-story/q023.json new file mode 100644 index 00000000..0e5e6932 --- /dev/null +++ b/system/quests/solo-story/q023.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_007F && F_0207", + "EnabledIf": "!F_0091 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q024-bb-e.bin b/system/quests/solo-story/q024-bb-e.bin similarity index 100% rename from system/quests/solo/q024-bb-e.bin rename to system/quests/solo-story/q024-bb-e.bin diff --git a/system/quests/solo/q024-bb-j.bin b/system/quests/solo-story/q024-bb-j.bin similarity index 100% rename from system/quests/solo/q024-bb-j.bin rename to system/quests/solo-story/q024-bb-j.bin diff --git a/system/quests/solo/q024-bb.dat b/system/quests/solo-story/q024-bb.dat similarity index 100% rename from system/quests/solo/q024-bb.dat rename to system/quests/solo-story/q024-bb.dat diff --git a/system/quests/solo-story/q024.json b/system/quests/solo-story/q024.json new file mode 100644 index 00000000..e90ca2ff --- /dev/null +++ b/system/quests/solo-story/q024.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_0207", + "EnabledIf": "!F_0093 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q025-bb-e.bin b/system/quests/solo-story/q025-bb-e.bin similarity index 100% rename from system/quests/solo/q025-bb-e.bin rename to system/quests/solo-story/q025-bb-e.bin diff --git a/system/quests/solo/q025-bb-j.bin b/system/quests/solo-story/q025-bb-j.bin similarity index 100% rename from system/quests/solo/q025-bb-j.bin rename to system/quests/solo-story/q025-bb-j.bin diff --git a/system/quests/solo/q025-bb.dat b/system/quests/solo-story/q025-bb.dat similarity index 100% rename from system/quests/solo/q025-bb.dat rename to system/quests/solo-story/q025-bb.dat diff --git a/system/quests/solo-story/q025.json b/system/quests/solo-story/q025.json new file mode 100644 index 00000000..d37d3d11 --- /dev/null +++ b/system/quests/solo-story/q025.json @@ -0,0 +1,4 @@ +{ + "AvailableIf": "F_0065 && F_0067 && F_006B && F_0091 && F_0207", + "EnabledIf": "!F_0095 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)", +} diff --git a/system/quests/solo/q026-bb-e.bin b/system/quests/solo-story/q026-bb-e.bin similarity index 100% rename from system/quests/solo/q026-bb-e.bin rename to system/quests/solo-story/q026-bb-e.bin diff --git a/system/quests/solo/q026-bb-j.bin b/system/quests/solo-story/q026-bb-j.bin similarity index 100% rename from system/quests/solo/q026-bb-j.bin rename to system/quests/solo-story/q026-bb-j.bin diff --git a/system/quests/solo/q026-bb.dat b/system/quests/solo-story/q026-bb.dat similarity index 100% rename from system/quests/solo/q026-bb.dat rename to system/quests/solo-story/q026-bb.dat diff --git a/system/quests/solo-story/q026.json b/system/quests/solo-story/q026.json new file mode 100644 index 00000000..17390bd3 --- /dev/null +++ b/system/quests/solo-story/q026.json @@ -0,0 +1,3 @@ +{ + "AvailableIf": "F_0073", +} diff --git a/system/quests/solo/q027-bb-e.bin b/system/quests/solo-story/q027-bb-e.bin similarity index 100% rename from system/quests/solo/q027-bb-e.bin rename to system/quests/solo-story/q027-bb-e.bin diff --git a/system/quests/solo/q027-bb-j.bin b/system/quests/solo-story/q027-bb-j.bin similarity index 100% rename from system/quests/solo/q027-bb-j.bin rename to system/quests/solo-story/q027-bb-j.bin diff --git a/system/quests/solo/q027-bb.dat b/system/quests/solo-story/q027-bb.dat similarity index 100% rename from system/quests/solo/q027-bb.dat rename to system/quests/solo-story/q027-bb.dat diff --git a/system/quests/solo/q030-bb-e.bin b/system/quests/solo-story/q030-bb-e.bin similarity index 100% rename from system/quests/solo/q030-bb-e.bin rename to system/quests/solo-story/q030-bb-e.bin diff --git a/system/quests/solo/q030-bb-j.bin b/system/quests/solo-story/q030-bb-j.bin similarity index 100% rename from system/quests/solo/q030-bb-j.bin rename to system/quests/solo-story/q030-bb-j.bin diff --git a/system/quests/solo/q030-bb.dat b/system/quests/solo-story/q030-bb.dat similarity index 100% rename from system/quests/solo/q030-bb.dat rename to system/quests/solo-story/q030-bb.dat diff --git a/system/quests/solo/q031-bb-e.bin b/system/quests/solo-story/q031-bb-e.bin similarity index 100% rename from system/quests/solo/q031-bb-e.bin rename to system/quests/solo-story/q031-bb-e.bin diff --git a/system/quests/solo/q031-bb-j.bin b/system/quests/solo-story/q031-bb-j.bin similarity index 100% rename from system/quests/solo/q031-bb-j.bin rename to system/quests/solo-story/q031-bb-j.bin diff --git a/system/quests/solo/q031-bb.dat b/system/quests/solo-story/q031-bb.dat similarity index 100% rename from system/quests/solo/q031-bb.dat rename to system/quests/solo-story/q031-bb.dat diff --git a/system/quests/solo/q032-bb-e.bin b/system/quests/solo-story/q032-bb-e.bin similarity index 100% rename from system/quests/solo/q032-bb-e.bin rename to system/quests/solo-story/q032-bb-e.bin diff --git a/system/quests/solo/q032-bb-j.bin b/system/quests/solo-story/q032-bb-j.bin similarity index 100% rename from system/quests/solo/q032-bb-j.bin rename to system/quests/solo-story/q032-bb-j.bin diff --git a/system/quests/solo/q032-bb.dat b/system/quests/solo-story/q032-bb.dat similarity index 100% rename from system/quests/solo/q032-bb.dat rename to system/quests/solo-story/q032-bb.dat diff --git a/system/quests/solo/q033-bb-e.bin b/system/quests/solo-story/q033-bb-e.bin similarity index 100% rename from system/quests/solo/q033-bb-e.bin rename to system/quests/solo-story/q033-bb-e.bin diff --git a/system/quests/solo/q033-bb-j.bin b/system/quests/solo-story/q033-bb-j.bin similarity index 100% rename from system/quests/solo/q033-bb-j.bin rename to system/quests/solo-story/q033-bb-j.bin diff --git a/system/quests/solo/q033-bb.dat b/system/quests/solo-story/q033-bb.dat similarity index 100% rename from system/quests/solo/q033-bb.dat rename to system/quests/solo-story/q033-bb.dat diff --git a/system/quests/solo/q034-bb-e.bin b/system/quests/solo-story/q034-bb-e.bin similarity index 100% rename from system/quests/solo/q034-bb-e.bin rename to system/quests/solo-story/q034-bb-e.bin diff --git a/system/quests/solo/q034-bb-j.bin b/system/quests/solo-story/q034-bb-j.bin similarity index 100% rename from system/quests/solo/q034-bb-j.bin rename to system/quests/solo-story/q034-bb-j.bin diff --git a/system/quests/solo/q034-bb.dat b/system/quests/solo-story/q034-bb.dat similarity index 100% rename from system/quests/solo/q034-bb.dat rename to system/quests/solo-story/q034-bb.dat diff --git a/tests/config.json b/tests/config.json index 34ead5e7..66ff163a 100644 --- a/tests/config.json +++ b/tests/config.json @@ -138,7 +138,8 @@ [0x02, "battle", "Battle", "$E$C6Battle mode rule\nsets"], [0x04, "challenge-ep1", "Challenge (Episode 1)", "$E$C6Challenge mode\nquests in Episode 1"], [0x84, "challenge-ep2", "Challenge (Episode 2)", "$E$C6Challenge mode\nquests in Episode 2"], - [0x08, "solo", "Solo", "$E$C6Quests that require\na single player"], + [0x08, "solo-story", "Story", "$E$C6Quests that follow\nthe Episode 1 story"], + [0x08, "solo-extra", "Solo", "$E$C6Quests that require\na single player"], [0x10, "government-ep1", "Hero in Red", "$E$CG-Red Ring Rico-\n$C6Quests that follow\nthe Episode 1\nstoryline"], [0x10, "government-ep2", "The Military's Hero", "$E$CG-Heathcliff Flowen-\n$C6Quests that follow\nthe Episode 2\nstoryline"], [0x10, "government-ep4", "The Meteor Impact Incident", "$E$C6Quests that follow\nthe Episode 4\nstoryline"],