diff --git a/src/Episode3/DataIndexes.cc b/src/Episode3/DataIndexes.cc index 28da6d4a..2a91009d 100644 --- a/src/Episode3/DataIndexes.cc +++ b/src/Episode3/DataIndexes.cc @@ -1240,69 +1240,124 @@ void Rules::clear() { string Rules::str() const { vector tokens; - tokens.emplace_back(string_printf("char_hp=%hhu", this->char_hp)); + if (this->char_hp == 0xFF) { + tokens.emplace_back("char_hp=(open)"); + } else { + tokens.emplace_back(string_printf("char_hp=%hhu", this->char_hp)); + } + switch (this->hp_type) { case HPType::DEFEAT_PLAYER: - tokens.emplace_back("hp_type=DEFEAT_PLAYER"); + tokens.emplace_back("hp_type=defeat-player"); break; case HPType::DEFEAT_TEAM: - tokens.emplace_back("hp_type=DEFEAT_TEAM"); + tokens.emplace_back("hp_type=defeat-team"); break; case HPType::COMMON_HP: - tokens.emplace_back("hp_type=COMMON_HP"); + tokens.emplace_back("hp_type=common-hp"); break; default: - tokens.emplace_back(string_printf("hp_type=(%02hhX)", - static_cast(this->hp_type))); + if (static_cast(this->hp_type) == 0xFF) { + tokens.emplace_back("hp_type=(open)"); + } else { + tokens.emplace_back(string_printf("hp_type=(%02hhX)", + static_cast(this->hp_type))); + } break; } - tokens.emplace_back(string_printf("min_dice=%hhu", this->min_dice)); - tokens.emplace_back(string_printf("max_dice=%hhu", this->max_dice)); + if (this->min_dice == 0xFF) { + tokens.emplace_back("min_dice=(open)"); + } else if (this->min_dice == 0x00) { + tokens.emplace_back("min_dice=1 (default)"); + } else { + tokens.emplace_back(string_printf("min_dice=%hhu", this->min_dice)); + } + if (this->max_dice == 0xFF) { + tokens.emplace_back("max_dice=(open)"); + } else if (this->max_dice == 0x00) { + tokens.emplace_back("max_dice=6 (default)"); + } else { + tokens.emplace_back(string_printf("max_dice=%hhu", this->max_dice)); + } + switch (this->dice_exchange_mode) { case DiceExchangeMode::HIGH_ATK: - tokens.emplace_back("dice_exchange=HIGH_ATK"); + tokens.emplace_back("dice_exchange=high-atk"); break; case DiceExchangeMode::HIGH_DEF: - tokens.emplace_back("dice_exchange=HIGH_DEF"); + tokens.emplace_back("dice_exchange=high-def"); break; case DiceExchangeMode::NONE: - tokens.emplace_back("dice_exchange=NONE"); + tokens.emplace_back("dice_exchange=none"); break; default: - tokens.emplace_back(string_printf("dice_exchange=(%02hhX)", - static_cast(this->dice_exchange_mode))); + if (static_cast(this->dice_exchange_mode) == 0xFF) { + tokens.emplace_back("dice_exchange=(open)"); + } else { + tokens.emplace_back(string_printf("dice_exchange=(%02hhX)", + static_cast(this->dice_exchange_mode))); + } break; } - tokens.emplace_back(string_printf("dice_boost=%s", this->disable_dice_boost ? "DISABLED" : "ENABLED")); - tokens.emplace_back(string_printf("deck_shuffle=%s", this->disable_deck_shuffle ? "DISABLED" : "ENABLED")); - tokens.emplace_back(string_printf("deck_loop=%s", this->disable_deck_loop ? "DISABLED" : "ENABLED")); + auto str_for_disable_bool = +[](uint8_t v) -> string { + switch (v) { + case 0x00: + return "on"; + case 0x01: + return "off"; + case 0xFF: + return "(open)"; + default: + return string_printf("(%02hhX)", v); + } + }; + + tokens.emplace_back("dice_boost=" + str_for_disable_bool(this->disable_dice_boost)); + tokens.emplace_back("deck_shuffle=" + str_for_disable_bool(this->disable_deck_shuffle)); + tokens.emplace_back("deck_loop=" + str_for_disable_bool(this->disable_deck_loop)); switch (this->allowed_cards) { case AllowedCards::ALL: - tokens.emplace_back("allowed_cards=ALL"); + tokens.emplace_back("allowed_cards=all"); break; case AllowedCards::N_ONLY: - tokens.emplace_back("allowed_cards=N_ONLY"); + tokens.emplace_back("allowed_cards=n-only"); break; case AllowedCards::N_R_ONLY: - tokens.emplace_back("allowed_cards=N_R_ONLY"); + tokens.emplace_back("allowed_cards=n-r-only"); break; case AllowedCards::N_R_S_ONLY: - tokens.emplace_back("allowed_cards=N_R_S_ONLY"); + tokens.emplace_back("allowed_cards=n-r-s-only"); break; default: - tokens.emplace_back(string_printf("allowed_cards=(%02hhX)", - static_cast(this->allowed_cards))); + if (static_cast(this->allowed_cards) == 0xFF) { + tokens.emplace_back("allowed_cards=(open)"); + } else { + tokens.emplace_back(string_printf("allowed_cards=(%02hhX)", + static_cast(this->allowed_cards))); + } break; } - tokens.emplace_back(string_printf("assist_cards=%s", this->no_assist_cards ? "DISALLOWED" : "ALLOWED")); + tokens.emplace_back("allow_assist_cards=" + str_for_disable_bool(this->no_assist_cards)); - tokens.emplace_back(string_printf("time_limit=%zumin", static_cast(this->overall_time_limit * 5))); - tokens.emplace_back(string_printf("phase_time_limit=%hhusec", this->phase_time_limit)); + if (this->overall_time_limit == 0xFF) { + tokens.emplace_back("overall_time_limit=(open)"); + } else if (this->overall_time_limit) { + tokens.emplace_back(string_printf("overall_time_limit=%zumin", static_cast(this->overall_time_limit * 5))); + } else { + tokens.emplace_back("overall_time_limit=(infinite)"); + } + if (this->phase_time_limit == 0xFF) { + tokens.emplace_back("phase_time_limit=(open)"); + } else if (this->phase_time_limit) { + tokens.emplace_back(string_printf("phase_time_limit=%hhusec", this->phase_time_limit)); + } else { + tokens.emplace_back("phase_time_limit=(infinite)"); + } - tokens.emplace_back(string_printf("dialogue=%s", this->disable_dialogue ? "DISABLED" : "ENABLED")); + tokens.emplace_back("dialogue=" + str_for_disable_bool(this->disable_dialogue)); return "Rules[" + join(tokens, ", ") + "]"; } diff --git a/src/Episode3/DataIndexes.hh b/src/Episode3/DataIndexes.hh index 4972ca08..b50ae687 100644 --- a/src/Episode3/DataIndexes.hh +++ b/src/Episode3/DataIndexes.hh @@ -1019,12 +1019,12 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests } __attribute__((packed)); /* 20F0 */ parray npc_ai_params; // Unused if name[0] == 0 - /* 242C */ parray unknown_a7; // Always FF? + /* 242C */ parray unknown_a7; - // This array specifies which set of AI parameters to use from aiprm.dat. If - // it's -1, then the corresponding NPC's AI parameters are defined in the - // AIParams structure above. The names of the AI parameter sets defined in - // aiprm.dat are: + // This array specifies which set of predefined AI parameters (in aiprm.dat) + // to use for each NPC. If a value in this array is -1 (FFFFFFFF), then the + // corresponding NPC's AI parameters are defined in the AIParams structure + // above. The names of the AI parameter sets defined in aiprm.dat are: // 00 => Sample_Hunter 10 => Endu // 01 => Glustar 11 => Heiz // 02 => Guykild 12 => KC @@ -1041,6 +1041,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests // 0D => Sample_Dark 1D => Sample_Dark // 0E => Break // 0F => Creinu + // Presumably 0A is meant to be Stella, and they forgot to change the name. /* 2434 */ parray npc_ai_params_entry_index; // In story mode, before_message appears before the battle if it's not blank;