diff --git a/README.md b/README.md index 4ed476ca..d42201b2 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,11 @@ At the time of its inception, Aeon was also called newserv, and you may find som Independently of this project, there are many other PSO servers out there. Those that I know of that are (or were) public are listed here in approximate chronological order: -* (Early 2000s) **[Schtserv](https://schtserv.com/)**: The first public-access PSO server; written in Delphi by Schthack. Still active and popular as of this writing (early 2024). Schtserv is also the only other unofficial server to support all versions of PSO, including Episode 3. +* (Early 2000s) **[Schtserv](https://schtserv.com/)**: The first public-access PSO server; written in Delphi by Schthack. Still active and popular as of early 2025. Schtserv is also the only other unofficial server to support all versions of PSO, including Episode 3. (Their implementation of Episode 3 is based on newserv's, which is itself based on Sega's.) * (2005) **Khyller**: An early attempt of mine to support PSO PC, GC, and BB. See above for more details. * (2006) **Aeon**: My second attempt. Better than Khyller, but still unreliable. * (2008) **Tethealla**: A fairly extensive implementation of PSOBB, written in C by Sodaboy. The public version of Tethealla has been [officially disowned](https://www.pioneer2.net/community/threads/tethealla-server-forums-removal.26365/) (as it is now more than 15 years old), but closed-source development continues. [Ephinea](https://ephinea.pioneer2.net/), currently the most popular PSOBB server, is the continuation of this project. Several other modern PSOBB servers are forks of the initial public version of Tethealla as well. -* (2008) **[Sylverant](https://sylverant.net/)** [(source)](https://sourceforge.net/projects/sylverant/): The second public-access PSO server; written in C by BlueCrab. Still active and popular as of this writing (early 2024). +* (2008) **[Sylverant](https://sylverant.net/)** [(source)](https://sourceforge.net/projects/sylverant/): The second public-access PSO server; written in C by BlueCrab. Still active and popular as of early 2025. * (2015) **[Archon](https://github.com/dcrodman/archon)**: A PSOBB server written in Go by Drew Rodman. * (2015) **[Idola](https://github.com/HybridEidolon/idolapsoserv)**: A PSOBB server written in Rust by HybridEidolon. Functionality status unknown; the project has been archived. * (2017) **[Aselia](https://github.com/Solybum/Aselia)**: A PSOBB server written written in C# by Soly. It seems this was planned to be open-source at some point, but that has not (yet) happened. @@ -71,12 +71,14 @@ Independently of this project, there are many other PSO servers out there. Those There is a lot of code in this project that could be useful as a reference. Some of the more notable files are: * **src/CommandFormats.hh**: Complete listing of all network commands used in all known versions of the game, and their formats +* **src/CommonItemSet.hh/cc**: Format of ItemPT files, shop definition files, and tekker adjustment tables * **src/DCSerialNumbers.hh/cc**: PSO DC serial number validation algorithm and serial number generator * **src/ItemData.hh**: Item format reference * **src/ItemCreator.hh/cc**: Reverse-engineered item generator from Episodes 1&2 (used for all versions) * **src/ItemParameterTable.hh**: Format of many structures in ItemPMT.prs * **src/Map.hh/cc**: Map file (.dat) structure and reverse-engineered Challenge Mode random enemy generation algorithm * **src/QuestScript.cc**: Complete listing of all quest opcodes on all versions, along with their arguments and behavior +* **src/RareItemSet.hh/cc**: Format of ItemRT files (rare item drop tables) * **src/SaveFileFormats.hh**: Definitions of save file structures for all versions * **src/Episode3/DataIndexes.hh**: Episode 3 file structures, including card definition format and map/quest format * **system/item-tables/names-v4.json**: Names of all items, indexed by the first 3 bytes of data1 @@ -291,12 +293,12 @@ Within the category directories, quest files should be named like `q###-VERSION- For .dat files, the `LANGUAGE` token may be omitted. If it's present, then that .dat file will only be used for that language of the quest; if omitted, then that .dat file will be used for all languages of the quest. -Some quests (mostly battle and challenge mode quests) have additional JSON metadata files that describe how the server should handle them. This includes flags that can be used to hide the quest unless a preceding quest has been cleared, or to hide the quest unless purchased as a team reward. These metadata files are generally named similarly to their .bin and .dat counterparts, except the `VERSION` token may also be omitted if the metadata applies to all languages of the quest on all PSO versions. See system/quests/battle/b88001.json for documentation on the exact format of the JSON file. +For example, the GameCube version of Lost HEAT SWORD is in two files named `q058-gc-e.bin` and `q058-gc.dat`. newserv knows these files are quests because they're in the system/quests/ directory, it knows they're for PSO GC because the filenames contain `-gc`, it knows this is the English version of the quest because the .bin filename ends with `-e` (even though the .dat filename does not), and it puts them in the Retrieval category because the files are within the retrieval/ directory within system/quests/. + +Some quests (mostly battle and challenge mode quests) have additional JSON metadata files that describe how the server should handle them. These files include flags that can be used to hide the quest unless a preceding quest has been cleared, or to hide the quest unless purchased as a BB team reward. These metadata files are generally named similarly to their .bin and .dat counterparts, except the `VERSION` token may also be omitted if the metadata applies to all languages of the quest on all PSO versions. See system/quests/battle/b88001.json for documentation on the exact format of the JSON file. Some quests may also include a .pvr file, which contains an image used in the quest. These files are named similarly to their .bin and .dat counterparts. -For example, the GameCube version of Lost HEAT SWORD is in two files named `q058-gc-e.bin` and `q058-gc.dat`. newserv knows these files are quests because they're in the system/quests/ directory, it knows they're for PSO GC because the filenames contain `-gc`, it knows this is the English version of the quest because the .bin filename ends with `-e` (even though the .dat filename does not), and it puts them in the Retrieval category because the files are within the retrieval/ directory within system/quests/. - The GameCube and Xbox quest formats are very similar, but newserv treats them as different. If you want to use the same quest file for GameCube and Xbox clients, you can make one a symbolic link to the other. There are multiple PSO quest formats out there; newserv supports all of them. It can also decode any known format to standard .bin/.dat format. Specifically: @@ -574,7 +576,7 @@ Some commands only work on the game server and not on the proxy server. The chat * Personal state commands * `$arrow `: Change your lobby arrow color. - * `$secid `: Set your override section ID. After running this command, any games you create will use your override section ID for rare drops instead of your character's actual section ID. If you're in a game and you are the leader of the game, this also immediately changes the item tables used by the server when creating items. To revert to your actual section id, run `$secid` with no name after it. On the proxy server, this will not work if the remote server controls item drops (e.g. on BB, or on Schtserv with server drops enabled). If the server does not allow cheat mode anywhere (that is, "CheatModeBehavior" is "Off" in config.json), this command does nothing. + * `$secid `: Set your override section ID. After running this command, any games you create will use your override section ID for rare drops instead of your character's actual section ID. If you're in a game and you are the leader of the game, this also immediately changes the item tables used by the server when creating items. To revert to your actual section id, run `$secid` with no name after it. On the proxy server, this will not work if the remote server controls item drops. If the server does not allow cheat mode anywhere (that is, "CheatModeBehavior" is "Off" in config.json), this command does nothing. * `$rand `: Set your override random seed (specified as a 32-bit hex value). This will make any games you create use the given seed for rare enemies. This also makes item drops deterministic in Blue Burst games hosted by newserv. On the proxy server, this command can cause desyncs with other players in the same game, since they will not see the overridden random seed. To remove the override, run `$rand` with no arguments. If the server does not allow cheat mode anywhere (that is, "CheatModeBehavior" is "Off" in config.json), this command does nothing. * `$ln [name-or-type]`: Set the lobby number. Visible only to you. This command exists because some non-lobby maps can be loaded as lobbies with invalid lobby numbers. See the "GC lobby types" and "Ep3 lobby types" entries in the information menu for acceptable values here. Note that non-lobby maps do not have a lobby counter, so there's no way to exit the lobby without using either `$ln` again or `$exit`. On the game server, `$ln` reloads the lobby immediately; on the proxy server, it doesn't take effect until you load another lobby yourself (which means you'll like have to use `$exit` to escape). Run this command with no argument to return to the default lobby. * `$swa`: Enable or disable switch assist. When enabled, the server will unlock two-player and four-player doors in non-quest games when you step on any of the required switches. @@ -719,33 +721,33 @@ newserv has many CLI options, which can be used to access functionality other th The data formats that newserv can convert to/from are: -| Format | Encode/compress action | Decode/extract action | -|--------------------------------|---------------------------|------------------------------| -| PRS compression | `compress-prs` | `decompress-prs` | -| PR2/PRC compression | `compress-pr2` | `decompress-pr2` | -| BC0 compression | `compress-bc0` | `decompress-bc0` | -| Raw encrypted data | `encrypt-data` | `decrypt-data` | -| Episode 3 command mask | `encrypt-trivial-data` | `decrypt-trivial-data` | -| Challenge Mode rank text | `encrypt-challenge-data` | `decrypt-challenge-data` | -| PSO DC quest file (.vms) | None | `decode-vms` | -| PSO GC quest file (.gci) | None | `decode-gci` | -| Download quest file (.dlq) | None | `decode-dlq` | -| Server quest file (.qst) | `encode-qst` | `decode-qst` | -| PSO DC save file (.vms) | `encrypt-vms-save` | `decrypt-vms-save` | -| PSO PC save file | `encrypt-pc-save` | `decrypt-pc-save` | -| PSO GC save file (.gci) | `encrypt-gci-save` | `decrypt-gci-save` | -| PSO GC snapshot file | None | `decode-gci-snapshot` | -| Quest script (.bin) | `assemble-quest-script` | `disassemble-quest-script` | -| Quest map (.dat) | None | `disassemble-quest-map` | -| AFS archive | None | `extract-afs` | -| BML archive | None | `extract-bml` | -| GSL archive | `generate-gsl` | `extract-gsl` | -| GVM texture | `encode-gvm` | None | -| Text archive | `encode-text-archive` | `decode-text-archive` | -| Unicode text set | `encode-unicode-text-set` | `decode-unicode-text-set` | -| Word Select data set | None | `decode-word-select-set` | -| Set data table | None | `disassemble-set-data-table` | -| Rare item table (AFS/GSL/JSON) | `convert-rare-item-set` | `convert-rare-item-set` | +| Format | Encode/compress action | Decode/extract action | +|-------------------------------------|---------------------------|------------------------------| +| PRS compression | `compress-prs` | `decompress-prs` | +| PR2/PRC compression | `compress-pr2` | `decompress-pr2` | +| BC0 compression | `compress-bc0` | `decompress-bc0` | +| Raw encrypted data | `encrypt-data` | `decrypt-data` | +| Episode 3 command mask | `encrypt-trivial-data` | `decrypt-trivial-data` | +| Challenge Mode rank text | `encrypt-challenge-data` | `decrypt-challenge-data` | +| PSO DC quest file (.vms) | None | `decode-vms` | +| PSO GC quest file (.gci) | None | `decode-gci` | +| Download quest file (.dlq) | None | `decode-dlq` | +| Server quest file (.qst) | `encode-qst` | `decode-qst` | +| PSO DC save file (.vms) | `encrypt-vms-save` | `decrypt-vms-save` | +| PSO PC save file | `encrypt-pc-save` | `decrypt-pc-save` | +| PSO GC save file (.gci) | `encrypt-gci-save` | `decrypt-gci-save` | +| PSO GC snapshot file | None | `decode-gci-snapshot` | +| Quest script (.bin) | `assemble-quest-script` | `disassemble-quest-script` | +| Quest map (.dat) | None | `disassemble-quest-map` | +| AFS archive | None | `extract-afs` | +| BML archive | None | `extract-bml` | +| GSL archive | `generate-gsl` | `extract-gsl` | +| GVM texture | `encode-gvm` | None | +| Text archive | `encode-text-archive` | `decode-text-archive` | +| Unicode text set | `encode-unicode-text-set` | `decode-unicode-text-set` | +| Word Select data set | None | `decode-word-select-set` | +| Set data table | None | `disassemble-set-data-table` | +| Rare item table (AFS/GSL/JSON/HTML) | `convert-rare-item-set` | `convert-rare-item-set` | There are several actions that don't fit well into the table above, which let you do other things: diff --git a/src/Client.cc b/src/Client.cc index 94a5d635..d2472c17 100644 --- a/src/Client.cc +++ b/src/Client.cc @@ -784,7 +784,7 @@ void Client::load_all_files() { if (this->character_data) { player_data_log.info("Using loaded character file %s", char_filename.c_str()); } else if (phosg::isfile(char_filename)) { - auto psochar = load_psochar(char_filename, !this->system_data); + auto psochar = PSOCHARFile::load_shared(char_filename, !this->system_data); this->character_data = psochar.character_file; files_manager->set_character(char_filename, this->character_data); player_data_log.info("Loaded character data from %s", char_filename.c_str()); @@ -966,7 +966,7 @@ void Client::save_character_file( const string& filename, shared_ptr system, shared_ptr character) { - save_psochar(filename, system, character); + PSOCHARFile::save(filename, system, character); player_data_log.info("Saved character file %s", filename.c_str()); } @@ -1008,7 +1008,7 @@ void Client::save_guild_card_file() const { void Client::load_backup_character(uint32_t account_id, size_t index) { string filename = this->backup_character_filename(account_id, index, false); - this->character_data = load_psochar(filename, false).character_file; + this->character_data = PSOCHARFile::load_shared(filename, false).character_file; this->update_character_data_after_load(this->character_data); this->v1_v2_last_reported_disp.reset(); } @@ -1096,7 +1096,7 @@ void Client::use_character_bank(int8_t index) { this->external_bank_character_index = index; player_data_log.info("Using loaded character file %s for external bank", filename.c_str()); } else if (phosg::isfile(filename)) { - this->external_bank_character = load_psochar(filename, false).character_file; + this->external_bank_character = PSOCHARFile::load_shared(filename, false).character_file; this->update_character_data_after_load(this->external_bank_character); this->external_bank_character_index = index; files_manager->set_character(filename, this->external_bank_character); diff --git a/src/EnemyType.cc b/src/EnemyType.cc index dc565d59..3c107931 100644 --- a/src/EnemyType.cc +++ b/src/EnemyType.cc @@ -9,1096 +9,175 @@ using namespace std; +static constexpr uint8_t EP1 = EnemyTypeDefinition::Flag::VALID_EP1; +static constexpr uint8_t EP2 = EnemyTypeDefinition::Flag::VALID_EP2; +static constexpr uint8_t EP4 = EnemyTypeDefinition::Flag::VALID_EP4; +static constexpr uint8_t RARE = EnemyTypeDefinition::Flag::IS_RARE; + +static const vector type_defs{ + // clang-format off + {EnemyType::UNKNOWN, 0, 0xFF, 0xFF, "UNKNOWN", "__UNKNOWN__", nullptr}, + {EnemyType::NONE, 0, 0xFF, 0xFF, "NONE", "__NONE__", nullptr}, + {EnemyType::NON_ENEMY_NPC, EP1 | EP2 | EP4, 0xFF, 0xFF, "NON_ENEMY_NPC", "__NPC__", nullptr}, + {EnemyType::AL_RAPPY, EP1 | RARE, 0x06, 0x19, "AL_RAPPY", "Al Rappy", "Pal Rappy"}, + {EnemyType::ASTARK, EP4, 0x41, 0x09, "ASTARK", "Astark", nullptr}, + {EnemyType::BA_BOOTA, EP4, 0x4F, 0x03, "BA_BOOTA", "Ba Boota", nullptr}, + {EnemyType::BARBA_RAY, EP2, 0x49, 0x0F, "BARBA_RAY", "Barba Ray", nullptr}, + {EnemyType::BARBAROUS_WOLF, EP1 | EP2, 0x08, 0x03, "BARBAROUS_WOLF", "Barbarous Wolf", "Gulgus-gue"}, + {EnemyType::BEE_L, EP1 | EP2, 0xFF, 0xFF, "BEE_L", "Bee L", "Gee L"}, + {EnemyType::BEE_R, EP1 | EP2, 0xFF, 0xFF, "BEE_R", "Bee R", "Gee R"}, + {EnemyType::BOOMA, EP1, 0x09, 0x4B, "BOOMA", "Booma", "Bartle"}, + {EnemyType::BOOTA, EP4, 0x4D, 0x00, "BOOTA", "Boota", nullptr}, + {EnemyType::BULCLAW, EP1, 0x28, 0x1F, "BULCLAW", "Bulclaw", nullptr}, + {EnemyType::BULK, EP1, 0x27, 0x1F, "BULK", "Bulk", nullptr}, + {EnemyType::CANADINE, EP1, 0x1C, 0x07, "CANADINE", "Canadine", "Canabin"}, + {EnemyType::CANADINE_GROUP, EP1, 0x1C, 0x08, "CANADINE_GROUP", "Canadine (group)", "Canabin (group)"}, + {EnemyType::CANANE, EP1, 0x1D, 0x09, "CANANE", "Canane", "Canune"}, + {EnemyType::CHAOS_BRINGER, EP1, 0x24, 0x0D, "CHAOS_BRINGER", "Chaos Bringer", "Dark Bringer"}, + {EnemyType::CHAOS_SORCERER, EP1 | EP2, 0x1F, 0x0A, "CHAOS_SORCERER", "Chaos Sorceror", "Gran Sorceror"}, + {EnemyType::CLAW, EP1, 0x26, 0x20, "CLAW", "Claw", nullptr}, + {EnemyType::DARK_BELRA, EP1 | EP2, 0x25, 0x0E, "DARK_BELRA", "Dark Belra", "Indi Belra"}, + {EnemyType::DARK_FALZ_1, EP1, 0xFF, 0x36, "DARK_FALZ_1", "Dark Falz (phase 1)", nullptr}, + {EnemyType::DARK_FALZ_2, EP1, 0x2F, 0x37, "DARK_FALZ_2", "Dark Falz (phase 2)", nullptr}, + {EnemyType::DARK_FALZ_3, EP1, 0x2F, 0x38, "DARK_FALZ_3", "Dark Falz (phase 3)", nullptr}, + {EnemyType::DARK_GUNNER, EP1, 0x22, 0x1E, "DARK_GUNNER", "Dark Gunner", nullptr}, + {EnemyType::DARVANT, EP1, 0xFF, 0x35, "DARVANT", "Darvant", nullptr}, + {EnemyType::DARVANT_ULTIMATE, EP1, 0xFF, 0x39, "DARVANT_ULTIMATE", "Darvant (ultimate)", nullptr}, + {EnemyType::DE_ROL_LE, EP1, 0x2D, 0x0F, "DE_ROL_LE", "De Rol Le", "Dal Ral Lie"}, + {EnemyType::DE_ROL_LE_BODY, EP1, 0xFF, 0xFF, "DE_ROL_LE_BODY", "De Rol Le (body)", "Dal Ral Lie (body)"}, + {EnemyType::DE_ROL_LE_MINE, EP1, 0xFF, 0xFF, "DE_ROL_LE_MINE", "De Rol Le (mine)", "Dal Ral Lie (mine)"}, + {EnemyType::DEATH_GUNNER, EP1, 0x23, 0x1E, "DEATH_GUNNER", "Death Gunner", nullptr}, + {EnemyType::DEL_LILY, EP2, 0x53, 0x25, "DEL_LILY", "Del Lily", nullptr}, + {EnemyType::DEL_RAPPY_CRATER, EP4, 0x57, 0x06, "DEL_RAPPY_CRATER", "Del Rappy (crater)", nullptr}, + {EnemyType::DEL_RAPPY_DESERT, EP4, 0x58, 0x18, "DEL_RAPPY_DESERT", "Del Rappy (desert)", nullptr}, + {EnemyType::DELBITER, EP2, 0x48, 0x0D, "DELBITER", "Delbiter", nullptr}, + {EnemyType::DELDEPTH, EP2, 0x47, 0x30, "DELDEPTH", "Deldepth", nullptr}, + {EnemyType::DELSABER, EP1 | EP2, 0x1E, 0x52, "DELSABER", "Delsaber", nullptr}, + {EnemyType::DIMENIAN, EP1 | EP2, 0x29, 0x53, "DIMENIAN", "Dimenian", "Arlan"}, + {EnemyType::DOLMDARL, EP2, 0x41, 0x50, "DOLMDARL", "Dolmdarl", nullptr}, + {EnemyType::DOLMOLM, EP2, 0x40, 0x4F, "DOLMOLM", "Dolmolm", nullptr}, + {EnemyType::DORPHON, EP4, 0x50, 0x0F, "DORPHON", "Dorphon", nullptr}, + {EnemyType::DORPHON_ECLAIR, EP4 | RARE, 0x51, 0x10, "DORPHON_ECLAIR", "Dorphon Eclair", nullptr}, + {EnemyType::DRAGON, EP1, 0x2C, 0x12, "DRAGON", "Dragon", "Sil Dragon"}, + {EnemyType::DUBCHIC, EP1 | EP2, 0x18, 0x1B, "DUBCHIC", "Dubchic", "Dubchich"}, + {EnemyType::DUBWITCH, EP1 | EP2, 0xFF, 0xFF, "DUBWITCH", "Dubwitch", "Duvuik"}, + {EnemyType::EGG_RAPPY, EP2, 0x51, 0x19, "EGG_RAPPY", "Egg Rappy", nullptr}, + {EnemyType::EPSIGARD, EP2, 0xFF, 0xFF, "EPSIGARD", "Episgard", nullptr}, + {EnemyType::EPSILON, EP2, 0x54, 0x23, "EPSILON", "Epsilon", nullptr}, + {EnemyType::EVIL_SHARK, EP1, 0x10, 0x4F, "EVIL_SHARK", "Evil Shark", "Vulmer"}, + {EnemyType::GAEL_OR_GIEL, EP2, 0xFF, 0x2E, "GAEL", "Gael/Giel", nullptr}, + {EnemyType::GAL_GRYPHON, EP2, 0x4D, 0x1E, "GAL_GRYPHON", "Gal Gryphon", nullptr}, + {EnemyType::GARANZ, EP1 | EP2, 0x19, 0x1D, "GARANZ", "Garanz", "Baranz"}, + {EnemyType::GEE, EP2, 0x36, 0x07, "GEE", "Gee", nullptr}, + {EnemyType::GI_GUE, EP2, 0x37, 0x1A, "GI_GUE", "Gi Gue", nullptr}, + {EnemyType::GIBBLES, EP2, 0x3D, 0x3D, "GIBBLES", "Gibbles", nullptr}, + {EnemyType::GIGOBOOMA, EP1, 0x0B, 0x4D, "GIGOBOOMA", "Gigobooma", "Tollaw"}, + {EnemyType::GILLCHIC, EP1 | EP2, 0x32, 0x1C, "GILLCHIC", "Gillchic", "Gillchich"}, + {EnemyType::GIRTABLULU, EP4, 0x48, 0x1F, "GIRTABLULU", "Girtablulu", nullptr}, + {EnemyType::GOBOOMA, EP1, 0x0A, 0x4C, "GOBOOMA", "Gobooma", "Barble"}, + {EnemyType::GOL_DRAGON, EP2, 0x4C, 0x12, "GOL_DRAGON", "Gol Dragon", nullptr}, + {EnemyType::GORAN, EP4, 0x52, 0x11, "GORAN", "Goran", nullptr}, + {EnemyType::GORAN_DETONATOR, EP4, 0x53, 0x13, "GORAN_DETONATOR", "Goran Detonator", nullptr}, + {EnemyType::GRASS_ASSASSIN, EP1 | EP2, 0x0C, 0x4E, "GRASS_ASSASSIN", "Grass Assassin", "Crimson Assassin"}, + {EnemyType::GUIL_SHARK, EP1, 0x12, 0x51, "GUIL_SHARK", "Guil Shark", "Melqueek"}, + {EnemyType::HALLO_RAPPY, EP2, 0x50, 0x19, "HALLO_RAPPY", "Hallo Rappy", nullptr}, + {EnemyType::HIDOOM, EP1 | EP2, 0x17, 0x32, "HIDOOM", "Hidoom", nullptr}, + {EnemyType::HILDEBEAR, EP1 | EP2, 0x01, 0x49, "HILDEBEAR", "Hildebear", "Hildelt"}, + {EnemyType::HILDEBLUE, EP1 | EP2 | RARE, 0x02, 0x4A, "HILDEBLUE", "Hildeblue", "Hildetorr"}, + {EnemyType::ILL_GILL, EP2, 0x52, 0x26, "ILL_GILL", "Ill Gill", nullptr}, + {EnemyType::KONDRIEU, EP4 | RARE, 0x5B, 0x2A, "KONDRIEU", "Kondrieu", nullptr}, + {EnemyType::LA_DIMENIAN, EP1 | EP2, 0x2A, 0x54, "LA_DIMENIAN", "La Dimenian", "Merlan"}, + {EnemyType::LOVE_RAPPY, EP2, 0x33, 0x19, "LOVE_RAPPY", "Love Rappy", nullptr}, + {EnemyType::MERICARAND, EP2, 0x38, 0x3A, "MERICARAND", "Mericarand", nullptr}, + {EnemyType::MERICAROL, EP2, 0x38, 0x3A, "MERICAROL", "Mericarol", nullptr}, + {EnemyType::MERICUS, EP2 | RARE, 0x3A, 0x46, "MERICUS", "Mericus", nullptr}, + {EnemyType::MERIKLE, EP2 | RARE, 0x39, 0x45, "MERIKLE", "Merikle", nullptr}, + {EnemyType::MERILLIA, EP2, 0x34, 0x4B, "MERILLIA", "Merillia", nullptr}, + {EnemyType::MERILTAS, EP2, 0x35, 0x4C, "MERILTAS", "Meriltas", nullptr}, + {EnemyType::MERISSA_A, EP4, 0x46, 0x19, "MERISSA_A", "Merissa A", nullptr}, + {EnemyType::MERISSA_AA, EP4 | RARE, 0x47, 0x1A, "MERISSA_AA", "Merissa AA", nullptr}, + {EnemyType::MIGIUM, EP1 | EP2, 0x16, 0x33, "MIGIUM", "Migium", nullptr}, + {EnemyType::MONEST, EP1 | EP2, 0x04, 0x01, "MONEST", "Monest", "Mothvist"}, + {EnemyType::MORFOS, EP2, 0x42, 0x40, "MORFOS", "Morfos", nullptr}, + {EnemyType::MOTHMANT, EP1 | EP2, 0x03, 0x00, "MOTHMANT", "Mothmant", "Mothvert"}, + {EnemyType::NANO_DRAGON, EP1, 0x0F, 0x1A, "NANO_DRAGON", "Nano Dragon", nullptr}, + {EnemyType::NAR_LILY, EP1 | EP2 | RARE, 0x0E, 0x05, "NAR_LILY", "Nar Lily", "Mil Lily"}, + {EnemyType::OLGA_FLOW_1, EP2, 0xFF, 0x2B, "OLGA_FLOW_1", "Olga Flow (phase 1)", nullptr}, + {EnemyType::OLGA_FLOW_2, EP2, 0x4E, 0x2C, "OLGA_FLOW_2", "Olga Flow (phase 2)", nullptr}, + {EnemyType::PAL_SHARK, EP1, 0x11, 0x50, "PAL_SHARK", "Pal Shark", "Govulmer"}, + {EnemyType::PAN_ARMS, EP1 | EP2, 0x15, 0x31, "PAN_ARMS", "Pan Arms", nullptr}, + {EnemyType::PAZUZU_CRATER, EP4 | RARE, 0x4B, 0x08, "PAZUZU_CRATER", "Pazuzu (crater)", nullptr}, + {EnemyType::PAZUZU_DESERT, EP4 | RARE, 0x4C, 0x1C, "PAZUZU_DESERT", "Pazuzu (desert)", nullptr}, + {EnemyType::PIG_RAY, EP2, 0xFF, 0xFF, "PIG_RAY", "Pig Ray", nullptr}, + {EnemyType::POFUILLY_SLIME, EP1, 0x13, 0x30, "POFUILLY_SLIME", "Pofuilly Slime", nullptr}, + {EnemyType::POUILLY_SLIME, EP1 | RARE, 0x14, 0x2F, "POUILLY_SLIME", "Pouilly Slime", nullptr}, + {EnemyType::POISON_LILY, EP1 | EP2, 0x0D, 0x04, "POISON_LILY", "Poison Lily", "Ob Lily"}, + {EnemyType::PYRO_GORAN, EP4, 0x54, 0x12, "PYRO_GORAN", "Pyro Goran", nullptr}, + {EnemyType::RAG_RAPPY, EP1 | EP2, 0x05, 0x18, "RAG_RAPPY", "Rag Rappy", "El Rappy"}, + {EnemyType::RECOBOX, EP2, 0x43, 0x41, "RECOBOX", "Recobox", nullptr}, + {EnemyType::RECON, EP2, 0x44, 0x42, "RECON", "Recon", nullptr}, + {EnemyType::SAINT_MILION, EP4, 0x59, 0x22, "SAINT_MILION", "Saint-Milion", nullptr}, + {EnemyType::SAINT_RAPPY, EP2, 0x4F, 0x19, "SAINT_RAPPY", "Saint Rappy", nullptr}, + {EnemyType::SAND_RAPPY_CRATER, EP4, 0x55, 0x05, "SAND_RAPPY_CRATER", "Sand Rappy (crater)", nullptr}, + {EnemyType::SAND_RAPPY_DESERT, EP4, 0x56, 0x17, "SAND_RAPPY_DESERT", "Sand Rappy (desert)", nullptr}, + {EnemyType::SATELLITE_LIZARD_CRATER, EP4, 0x44, 0x0D, "SATELLITE_LIZARD_CRATER", "Satellite Lizard (crater)", nullptr}, + {EnemyType::SATELLITE_LIZARD_DESERT, EP4, 0x45, 0x1D, "SATELLITE_LIZARD_DESERT", "Satellite Lizard (desert)", nullptr}, + {EnemyType::SAVAGE_WOLF, EP1 | EP2, 0x07, 0x02, "SAVAGE_WOLF", "Savage Wolf", "Gulgus"}, + {EnemyType::SHAMBERTIN, EP4, 0x5A, 0x26, "SHAMBERTIN", "Shambertin", nullptr}, + {EnemyType::SINOW_BEAT, EP1, 0x1A, 0x06, "SINOW_BEAT", "Sinow Beat", "Sinow Blue"}, + {EnemyType::SINOW_BERILL, EP2, 0x3E, 0x06, "SINOW_BERILL", "Sinow Berill", nullptr}, + {EnemyType::SINOW_GOLD, EP1, 0x1B, 0x13, "SINOW_GOLD", "Sinow Gold", "Sinow Red"}, + {EnemyType::SINOW_SPIGELL, EP2, 0x3F, 0x13, "SINOW_SPIGELL", "Sinow Spigell", nullptr}, + {EnemyType::SINOW_ZELE, EP2, 0x46, 0x44, "SINOW_ZELE", "Sinow Zele", nullptr}, + {EnemyType::SINOW_ZOA, EP2, 0x45, 0x43, "SINOW_ZOA", "Sinow Zoa", nullptr}, + {EnemyType::SO_DIMENIAN, EP1 | EP2, 0x2B, 0x55, "SO_DIMENIAN", "So Dimenian", "Del-D"}, + {EnemyType::UL_GIBBON, EP2, 0x3B, 0x3B, "UL_GIBBON", "Ul Gibbon", nullptr}, + {EnemyType::VOL_OPT_1, EP1, 0xFF, 0xFF, "VOL_OPT_1", "Vol Opt (phase 1)", "Vol Opt ver.2 (phase 1)"}, + {EnemyType::VOL_OPT_2, EP1, 0x2E, 0x25, "VOL_OPT_2", "Vol Opt (phase 2)", "Vol Opt ver.2 (phase 2)"}, + {EnemyType::VOL_OPT_AMP, EP1, 0xFF, 0xFF, "VOL_OPT_AMP", "Vol Opt (amp)", "Vol Opt ver.2 (amp)"}, + {EnemyType::VOL_OPT_CORE, EP1, 0xFF, 0xFF, "VOL_OPT_CORE", "Vol Opt (core)", "Vol Opt ver.2 (core)"}, + {EnemyType::VOL_OPT_MONITOR, EP1, 0xFF, 0xFF, "VOL_OPT_MONITOR", "Vol Opt (monitor)", "Vol Opt ver.2 (monitor)"}, + {EnemyType::VOL_OPT_PILLAR, EP1, 0xFF, 0xFF, "VOL_OPT_PILLAR", "Vol Opt (pillar)", "Vol Opt ver.2 (pillar)"}, + {EnemyType::YOWIE_CRATER, EP4, 0x42, 0x0E, "YOWIE_CRATER", "Yowie (crater)", nullptr}, + {EnemyType::YOWIE_DESERT, EP4, 0x43, 0x1E, "YOWIE_DESERT", "Yowie (desert)", nullptr}, + {EnemyType::ZE_BOOTA, EP4, 0x4E, 0x01, "ZE_BOOTA", "Ze Boota", nullptr}, + {EnemyType::ZOL_GIBBON, EP2, 0x3C, 0x3C, "ZOL_GIBBON", "Zol Gibbon", nullptr}, + {EnemyType::ZU_CRATER, EP4, 0x49, 0x07, "ZU_CRATER", "Zu (crater)", nullptr}, + {EnemyType::ZU_DESERT, EP4, 0x4A, 0x1B, "ZU_DESERT", "Zu (desert)", nullptr}, + // clang-format on +}; + +const EnemyTypeDefinition& type_definition_for_enemy(EnemyType type) { + return type_defs.at(static_cast(type)); +} + template <> const char* phosg::name_for_enum(EnemyType type) { - switch (type) { - case EnemyType::UNKNOWN: - return "UNKNOWN"; - case EnemyType::NONE: - return "NONE"; - case EnemyType::NON_ENEMY_NPC: - return "NON_ENEMY_NPC"; - case EnemyType::AL_RAPPY: - return "AL_RAPPY"; - case EnemyType::ASTARK: - return "ASTARK"; - case EnemyType::BA_BOOTA: - return "BA_BOOTA"; - case EnemyType::BARBA_RAY: - return "BARBA_RAY"; - case EnemyType::BARBAROUS_WOLF: - return "BARBAROUS_WOLF"; - case EnemyType::BEE_L: - return "BEE_L"; - case EnemyType::BEE_R: - return "BEE_R"; - case EnemyType::BOOMA: - return "BOOMA"; - case EnemyType::BOOTA: - return "BOOTA"; - case EnemyType::BULCLAW: - return "BULCLAW"; - case EnemyType::BULK: - return "BULK"; - case EnemyType::CANADINE: - return "CANADINE"; - case EnemyType::CANADINE_GROUP: - return "CANADINE_GROUP"; - case EnemyType::CANANE: - return "CANANE"; - case EnemyType::CHAOS_BRINGER: - return "CHAOS_BRINGER"; - case EnemyType::CHAOS_SORCERER: - return "CHAOS_SORCERER"; - case EnemyType::CLAW: - return "CLAW"; - case EnemyType::DARK_BELRA: - return "DARK_BELRA"; - case EnemyType::DARK_FALZ_1: - return "DARK_FALZ_1"; - case EnemyType::DARK_FALZ_2: - return "DARK_FALZ_2"; - case EnemyType::DARK_FALZ_3: - return "DARK_FALZ_3"; - case EnemyType::DARK_GUNNER: - return "DARK_GUNNER"; - case EnemyType::DARVANT: - return "DARVANT"; - case EnemyType::DARVANT_ULTIMATE: - return "DARVANT_ULTIMATE"; - case EnemyType::DE_ROL_LE: - return "DE_ROL_LE"; - case EnemyType::DE_ROL_LE_BODY: - return "DE_ROL_LE_BODY"; - case EnemyType::DE_ROL_LE_MINE: - return "DE_ROL_LE_MINE"; - case EnemyType::DEATH_GUNNER: - return "DEATH_GUNNER"; - case EnemyType::DEL_LILY: - return "DEL_LILY"; - case EnemyType::DEL_RAPPY: - return "DEL_RAPPY"; - case EnemyType::DEL_RAPPY_ALT: - return "DEL_RAPPY_ALT"; - case EnemyType::DELBITER: - return "DELBITER"; - case EnemyType::DELDEPTH: - return "DELDEPTH"; - case EnemyType::DELSABER: - return "DELSABER"; - case EnemyType::DIMENIAN: - return "DIMENIAN"; - case EnemyType::DOLMDARL: - return "DOLMDARL"; - case EnemyType::DOLMOLM: - return "DOLMOLM"; - case EnemyType::DORPHON: - return "DORPHON"; - case EnemyType::DORPHON_ECLAIR: - return "DORPHON_ECLAIR"; - case EnemyType::DRAGON: - return "DRAGON"; - case EnemyType::DUBCHIC: - return "DUBCHIC"; - case EnemyType::DUBWITCH: - return "DUBWITCH"; - case EnemyType::EGG_RAPPY: - return "EGG_RAPPY"; - case EnemyType::EPSIGUARD: - return "EPSIGUARD"; - case EnemyType::EPSILON: - return "EPSILON"; - case EnemyType::EVIL_SHARK: - return "EVIL_SHARK"; - case EnemyType::GAEL: - return "GAEL"; - case EnemyType::GAL_GRYPHON: - return "GAL_GRYPHON"; - case EnemyType::GARANZ: - return "GARANZ"; - case EnemyType::GEE: - return "GEE"; - case EnemyType::GI_GUE: - return "GI_GUE"; - case EnemyType::GIBBLES: - return "GIBBLES"; - case EnemyType::GIGOBOOMA: - return "GIGOBOOMA"; - case EnemyType::GILLCHIC: - return "GILLCHIC"; - case EnemyType::GIRTABLULU: - return "GIRTABLULU"; - case EnemyType::GOBOOMA: - return "GOBOOMA"; - case EnemyType::GOL_DRAGON: - return "GOL_DRAGON"; - case EnemyType::GORAN: - return "GORAN"; - case EnemyType::GORAN_DETONATOR: - return "GORAN_DETONATOR"; - case EnemyType::GRASS_ASSASSIN: - return "GRASS_ASSASSIN"; - case EnemyType::GUIL_SHARK: - return "GUIL_SHARK"; - case EnemyType::HALLO_RAPPY: - return "HALLO_RAPPY"; - case EnemyType::HIDOOM: - return "HIDOOM"; - case EnemyType::HILDEBEAR: - return "HILDEBEAR"; - case EnemyType::HILDEBLUE: - return "HILDEBLUE"; - case EnemyType::ILL_GILL: - return "ILL_GILL"; - case EnemyType::KONDRIEU: - return "KONDRIEU"; - case EnemyType::LA_DIMENIAN: - return "LA_DIMENIAN"; - case EnemyType::LOVE_RAPPY: - return "LOVE_RAPPY"; - case EnemyType::MERICAROL: - return "MERICAROL"; - case EnemyType::MERICARAND: - return "MERICARAND"; - case EnemyType::MERICUS: - return "MERICUS"; - case EnemyType::MERIKLE: - return "MERIKLE"; - case EnemyType::MERILLIA: - return "MERILLIA"; - case EnemyType::MERILTAS: - return "MERILTAS"; - case EnemyType::MERISSA_A: - return "MERISSA_A"; - case EnemyType::MERISSA_AA: - return "MERISSA_AA"; - case EnemyType::MIGIUM: - return "MIGIUM"; - case EnemyType::MONEST: - return "MONEST"; - case EnemyType::MORFOS: - return "MORFOS"; - case EnemyType::MOTHMANT: - return "MOTHMANT"; - case EnemyType::NANO_DRAGON: - return "NANO_DRAGON"; - case EnemyType::NAR_LILY: - return "NAR_LILY"; - case EnemyType::OLGA_FLOW_1: - return "OLGA_FLOW_1"; - case EnemyType::OLGA_FLOW_2: - return "OLGA_FLOW_2"; - case EnemyType::PAL_SHARK: - return "PAL_SHARK"; - case EnemyType::PAN_ARMS: - return "PAN_ARMS"; - case EnemyType::PAZUZU: - return "PAZUZU"; - case EnemyType::PAZUZU_ALT: - return "PAZUZU_ALT"; - case EnemyType::PIG_RAY: - return "PIG_RAY"; - case EnemyType::POFUILLY_SLIME: - return "POFUILLY_SLIME"; - case EnemyType::POUILLY_SLIME: - return "POUILLY_SLIME"; - case EnemyType::POISON_LILY: - return "POISON_LILY"; - case EnemyType::PYRO_GORAN: - return "PYRO_GORAN"; - case EnemyType::RAG_RAPPY: - return "RAG_RAPPY"; - case EnemyType::RECOBOX: - return "RECOBOX"; - case EnemyType::RECON: - return "RECON"; - case EnemyType::SAINT_MILLION: - return "SAINT_MILLION"; - case EnemyType::SAINT_RAPPY: - return "SAINT_RAPPY"; - case EnemyType::SAND_RAPPY: - return "SAND_RAPPY"; - case EnemyType::SAND_RAPPY_ALT: - return "SAND_RAPPY_ALT"; - case EnemyType::SATELLITE_LIZARD: - return "SATELLITE_LIZARD"; - case EnemyType::SATELLITE_LIZARD_ALT: - return "SATELLITE_LIZARD_ALT"; - case EnemyType::SAVAGE_WOLF: - return "SAVAGE_WOLF"; - case EnemyType::SHAMBERTIN: - return "SHAMBERTIN"; - case EnemyType::SINOW_BEAT: - return "SINOW_BEAT"; - case EnemyType::SINOW_BERILL: - return "SINOW_BERILL"; - case EnemyType::SINOW_GOLD: - return "SINOW_GOLD"; - case EnemyType::SINOW_SPIGELL: - return "SINOW_SPIGELL"; - case EnemyType::SINOW_ZELE: - return "SINOW_ZELE"; - case EnemyType::SINOW_ZOA: - return "SINOW_ZOA"; - case EnemyType::SO_DIMENIAN: - return "SO_DIMENIAN"; - case EnemyType::UL_GIBBON: - return "UL_GIBBON"; - case EnemyType::VOL_OPT_1: - return "VOL_OPT_1"; - case EnemyType::VOL_OPT_2: - return "VOL_OPT_2"; - case EnemyType::VOL_OPT_AMP: - return "VOL_OPT_AMP"; - case EnemyType::VOL_OPT_CORE: - return "VOL_OPT_CORE"; - case EnemyType::VOL_OPT_MONITOR: - return "VOL_OPT_MONITOR"; - case EnemyType::VOL_OPT_PILLAR: - return "VOL_OPT_PILLAR"; - case EnemyType::YOWIE: - return "YOWIE"; - case EnemyType::YOWIE_ALT: - return "YOWIE_ALT"; - case EnemyType::ZE_BOOTA: - return "ZE_BOOTA"; - case EnemyType::ZOL_GIBBON: - return "ZOL_GIBBON"; - case EnemyType::ZU: - return "ZU"; - case EnemyType::ZU_ALT: - return "ZU_ALT"; - case EnemyType::MAX_ENEMY_TYPE: - return "MAX_ENEMY_TYPE"; - default: - throw logic_error("invalid enemy type"); - } + return type_definition_for_enemy(type).enum_name; } template <> EnemyType phosg::enum_for_name(const char* name) { - static const unordered_map names({ - {"UNKNOWN", EnemyType::UNKNOWN}, - {"NONE", EnemyType::NONE}, - {"NON_ENEMY_NPC", EnemyType::NON_ENEMY_NPC}, - {"AL_RAPPY", EnemyType::AL_RAPPY}, - {"ASTARK", EnemyType::ASTARK}, - {"BA_BOOTA", EnemyType::BA_BOOTA}, - {"BARBA_RAY", EnemyType::BARBA_RAY}, - {"BARBAROUS_WOLF", EnemyType::BARBAROUS_WOLF}, - {"BEE_L", EnemyType::BEE_L}, - {"BEE_R", EnemyType::BEE_R}, - {"BOOMA", EnemyType::BOOMA}, - {"BOOTA", EnemyType::BOOTA}, - {"BULCLAW", EnemyType::BULCLAW}, - {"BULK", EnemyType::BULK}, - {"CANADINE", EnemyType::CANADINE}, - {"CANADINE_GROUP", EnemyType::CANADINE_GROUP}, - {"CANANE", EnemyType::CANANE}, - {"CHAOS_BRINGER", EnemyType::CHAOS_BRINGER}, - {"CHAOS_SORCERER", EnemyType::CHAOS_SORCERER}, - {"CLAW", EnemyType::CLAW}, - {"DARK_BELRA", EnemyType::DARK_BELRA}, - {"DARK_FALZ_1", EnemyType::DARK_FALZ_1}, - {"DARK_FALZ_2", EnemyType::DARK_FALZ_2}, - {"DARK_FALZ_3", EnemyType::DARK_FALZ_3}, - {"DARK_GUNNER", EnemyType::DARK_GUNNER}, - {"DARVANT", EnemyType::DARVANT}, - {"DARVANT_ULTIMATE", EnemyType::DARVANT_ULTIMATE}, - {"DE_ROL_LE", EnemyType::DE_ROL_LE}, - {"DE_ROL_LE_BODY", EnemyType::DE_ROL_LE_BODY}, - {"DE_ROL_LE_MINE", EnemyType::DE_ROL_LE_MINE}, - {"DEATH_GUNNER", EnemyType::DEATH_GUNNER}, - {"DEL_LILY", EnemyType::DEL_LILY}, - {"DEL_RAPPY", EnemyType::DEL_RAPPY}, - {"DEL_RAPPY_ALT", EnemyType::DEL_RAPPY_ALT}, - {"DELBITER", EnemyType::DELBITER}, - {"DELDEPTH", EnemyType::DELDEPTH}, - {"DELSABER", EnemyType::DELSABER}, - {"DIMENIAN", EnemyType::DIMENIAN}, - {"DOLMDARL", EnemyType::DOLMDARL}, - {"DOLMOLM", EnemyType::DOLMOLM}, - {"DORPHON", EnemyType::DORPHON}, - {"DORPHON_ECLAIR", EnemyType::DORPHON_ECLAIR}, - {"DRAGON", EnemyType::DRAGON}, - {"DUBCHIC", EnemyType::DUBCHIC}, - {"DUBWITCH", EnemyType::DUBWITCH}, - {"EGG_RAPPY", EnemyType::EGG_RAPPY}, - {"EPSIGUARD", EnemyType::EPSIGUARD}, - {"EPSILON", EnemyType::EPSILON}, - {"EVIL_SHARK", EnemyType::EVIL_SHARK}, - {"GAEL", EnemyType::GAEL}, - {"GAL_GRYPHON", EnemyType::GAL_GRYPHON}, - {"GARANZ", EnemyType::GARANZ}, - {"GEE", EnemyType::GEE}, - {"GI_GUE", EnemyType::GI_GUE}, - {"GIBBLES", EnemyType::GIBBLES}, - {"GIGOBOOMA", EnemyType::GIGOBOOMA}, - {"GILLCHIC", EnemyType::GILLCHIC}, - {"GIRTABLULU", EnemyType::GIRTABLULU}, - {"GOBOOMA", EnemyType::GOBOOMA}, - {"GOL_DRAGON", EnemyType::GOL_DRAGON}, - {"GORAN", EnemyType::GORAN}, - {"GORAN_DETONATOR", EnemyType::GORAN_DETONATOR}, - {"GRASS_ASSASSIN", EnemyType::GRASS_ASSASSIN}, - {"GUIL_SHARK", EnemyType::GUIL_SHARK}, - {"HALLO_RAPPY", EnemyType::HALLO_RAPPY}, - {"HIDOOM", EnemyType::HIDOOM}, - {"HILDEBEAR", EnemyType::HILDEBEAR}, - {"HILDEBLUE", EnemyType::HILDEBLUE}, - {"ILL_GILL", EnemyType::ILL_GILL}, - {"KONDRIEU", EnemyType::KONDRIEU}, - {"LA_DIMENIAN", EnemyType::LA_DIMENIAN}, - {"LOVE_RAPPY", EnemyType::LOVE_RAPPY}, - {"MERICARAND", EnemyType::MERICARAND}, - {"MERICAROL", EnemyType::MERICAROL}, - {"MERICUS", EnemyType::MERICUS}, - {"MERIKLE", EnemyType::MERIKLE}, - {"MERILLIA", EnemyType::MERILLIA}, - {"MERILTAS", EnemyType::MERILTAS}, - {"MERISSA_A", EnemyType::MERISSA_A}, - {"MERISSA_AA", EnemyType::MERISSA_AA}, - {"MIGIUM", EnemyType::MIGIUM}, - {"MONEST", EnemyType::MONEST}, - {"MORFOS", EnemyType::MORFOS}, - {"MOTHMANT", EnemyType::MOTHMANT}, - {"NANO_DRAGON", EnemyType::NANO_DRAGON}, - {"NAR_LILY", EnemyType::NAR_LILY}, - {"OLGA_FLOW_1", EnemyType::OLGA_FLOW_1}, - {"OLGA_FLOW_2", EnemyType::OLGA_FLOW_2}, - {"PAL_SHARK", EnemyType::PAL_SHARK}, - {"PAN_ARMS", EnemyType::PAN_ARMS}, - {"PAZUZU", EnemyType::PAZUZU}, - {"PAZUZU_ALT", EnemyType::PAZUZU_ALT}, - {"PIG_RAY", EnemyType::PIG_RAY}, - {"POFUILLY_SLIME", EnemyType::POFUILLY_SLIME}, - {"POUILLY_SLIME", EnemyType::POUILLY_SLIME}, - {"POISON_LILY", EnemyType::POISON_LILY}, - {"PYRO_GORAN", EnemyType::PYRO_GORAN}, - {"RAG_RAPPY", EnemyType::RAG_RAPPY}, - {"RECOBOX", EnemyType::RECOBOX}, - {"RECON", EnemyType::RECON}, - {"SAINT_MILLION", EnemyType::SAINT_MILLION}, - {"SAINT_RAPPY", EnemyType::SAINT_RAPPY}, - {"SAND_RAPPY", EnemyType::SAND_RAPPY}, - {"SAND_RAPPY_ALT", EnemyType::SAND_RAPPY_ALT}, - {"SATELLITE_LIZARD", EnemyType::SATELLITE_LIZARD}, - {"SATELLITE_LIZARD_ALT", EnemyType::SATELLITE_LIZARD_ALT}, - {"SAVAGE_WOLF", EnemyType::SAVAGE_WOLF}, - {"SHAMBERTIN", EnemyType::SHAMBERTIN}, - {"SINOW_BEAT", EnemyType::SINOW_BEAT}, - {"SINOW_BERILL", EnemyType::SINOW_BERILL}, - {"SINOW_GOLD", EnemyType::SINOW_GOLD}, - {"SINOW_SPIGELL", EnemyType::SINOW_SPIGELL}, - {"SINOW_ZELE", EnemyType::SINOW_ZELE}, - {"SINOW_ZOA", EnemyType::SINOW_ZOA}, - {"SO_DIMENIAN", EnemyType::SO_DIMENIAN}, - {"UL_GIBBON", EnemyType::UL_GIBBON}, - {"VOL_OPT_1", EnemyType::VOL_OPT_1}, - {"VOL_OPT_2", EnemyType::VOL_OPT_2}, - {"VOL_OPT_AMP", EnemyType::VOL_OPT_AMP}, - {"VOL_OPT_CORE", EnemyType::VOL_OPT_CORE}, - {"VOL_OPT_MONITOR", EnemyType::VOL_OPT_MONITOR}, - {"VOL_OPT_PILLAR", EnemyType::VOL_OPT_PILLAR}, - {"YOWIE", EnemyType::YOWIE}, - {"YOWIE_ALT", EnemyType::YOWIE_ALT}, - {"ZE_BOOTA", EnemyType::ZE_BOOTA}, - {"ZOL_GIBBON", EnemyType::ZOL_GIBBON}, - {"ZU", EnemyType::ZU}, - {"ZU_ALT", EnemyType::ZU_ALT}, - {"MAX_ENEMY_TYPE", EnemyType::MAX_ENEMY_TYPE}, - }); - return names.at(name); -} - -bool enemy_type_valid_for_episode(Episode episode, EnemyType enemy_type) { - switch (episode) { - case Episode::EP1: - switch (enemy_type) { - case EnemyType::AL_RAPPY: - case EnemyType::BARBAROUS_WOLF: - case EnemyType::BOOMA: - case EnemyType::BULCLAW: - case EnemyType::BULK: - case EnemyType::CANADINE_GROUP: - case EnemyType::CANADINE: - case EnemyType::CANANE: - case EnemyType::CHAOS_BRINGER: - case EnemyType::CHAOS_SORCERER: - case EnemyType::CLAW: - case EnemyType::DARK_BELRA: - case EnemyType::DARK_FALZ_1: - case EnemyType::DARK_FALZ_2: - case EnemyType::DARK_FALZ_3: - case EnemyType::DARK_GUNNER: - case EnemyType::DARVANT_ULTIMATE: - case EnemyType::DARVANT: - case EnemyType::DE_ROL_LE: - case EnemyType::DEATH_GUNNER: - case EnemyType::DELSABER: - case EnemyType::DIMENIAN: - case EnemyType::DRAGON: - case EnemyType::DUBCHIC: - case EnemyType::EVIL_SHARK: - case EnemyType::GARANZ: - case EnemyType::GIGOBOOMA: - case EnemyType::GILLCHIC: - case EnemyType::GOBOOMA: - case EnemyType::GRASS_ASSASSIN: - case EnemyType::GUIL_SHARK: - case EnemyType::HIDOOM: - case EnemyType::HILDEBEAR: - case EnemyType::HILDEBLUE: - case EnemyType::LA_DIMENIAN: - case EnemyType::MIGIUM: - case EnemyType::MONEST: - case EnemyType::MOTHMANT: - case EnemyType::NANO_DRAGON: - case EnemyType::NAR_LILY: - case EnemyType::PAL_SHARK: - case EnemyType::PAN_ARMS: - case EnemyType::POFUILLY_SLIME: - case EnemyType::POISON_LILY: - case EnemyType::POUILLY_SLIME: - case EnemyType::RAG_RAPPY: - case EnemyType::SAVAGE_WOLF: - case EnemyType::SINOW_BEAT: - case EnemyType::SINOW_GOLD: - case EnemyType::SO_DIMENIAN: - case EnemyType::VOL_OPT_2: - return true; - default: - return false; + static unordered_map index; + if (index.empty()) { + for (const auto& def : type_defs) { + if (!index.emplace(def.enum_name, def.type).second) { + throw logic_error(phosg::string_printf("duplicate enemy enum name: %s", def.enum_name)); } - case Episode::EP2: - switch (enemy_type) { - case EnemyType::BARBA_RAY: - case EnemyType::BARBAROUS_WOLF: - case EnemyType::CHAOS_SORCERER: - case EnemyType::DARK_BELRA: - case EnemyType::DEL_LILY: - case EnemyType::DELBITER: - case EnemyType::DELDEPTH: - case EnemyType::DELSABER: - case EnemyType::DIMENIAN: - case EnemyType::DOLMDARL: - case EnemyType::DOLMOLM: - case EnemyType::DUBCHIC: - case EnemyType::EGG_RAPPY: - case EnemyType::EPSILON: - case EnemyType::GAEL: - case EnemyType::GAL_GRYPHON: - case EnemyType::GARANZ: - case EnemyType::GEE: - case EnemyType::GI_GUE: - case EnemyType::GIBBLES: - case EnemyType::GILLCHIC: - case EnemyType::GOL_DRAGON: - case EnemyType::GRASS_ASSASSIN: - case EnemyType::HALLO_RAPPY: - case EnemyType::HIDOOM: - case EnemyType::HILDEBEAR: - case EnemyType::HILDEBLUE: - case EnemyType::ILL_GILL: - case EnemyType::LA_DIMENIAN: - case EnemyType::LOVE_RAPPY: - case EnemyType::MERICAROL: - case EnemyType::MERICARAND: - case EnemyType::MERICUS: - case EnemyType::MERIKLE: - case EnemyType::MERILLIA: - case EnemyType::MERILTAS: - case EnemyType::MIGIUM: - case EnemyType::MONEST: - case EnemyType::MORFOS: - case EnemyType::MOTHMANT: - case EnemyType::NAR_LILY: - case EnemyType::OLGA_FLOW_1: - case EnemyType::OLGA_FLOW_2: - case EnemyType::PAN_ARMS: - case EnemyType::POISON_LILY: - case EnemyType::RAG_RAPPY: - case EnemyType::RECOBOX: - case EnemyType::RECON: - case EnemyType::SAINT_RAPPY: - case EnemyType::SAVAGE_WOLF: - case EnemyType::SINOW_BERILL: - case EnemyType::SINOW_SPIGELL: - case EnemyType::SINOW_ZELE: - case EnemyType::SINOW_ZOA: - case EnemyType::SO_DIMENIAN: - case EnemyType::UL_GIBBON: - case EnemyType::ZOL_GIBBON: - return true; - default: - return false; - } - case Episode::EP4: - switch (enemy_type) { - case EnemyType::ASTARK: - case EnemyType::BA_BOOTA: - case EnemyType::BOOTA: - case EnemyType::DEL_RAPPY_ALT: - case EnemyType::DEL_RAPPY: - case EnemyType::DORPHON_ECLAIR: - case EnemyType::DORPHON: - case EnemyType::GIRTABLULU: - case EnemyType::GORAN_DETONATOR: - case EnemyType::GORAN: - case EnemyType::KONDRIEU: - case EnemyType::MERISSA_A: - case EnemyType::MERISSA_AA: - case EnemyType::PAZUZU_ALT: - case EnemyType::PAZUZU: - case EnemyType::PYRO_GORAN: - case EnemyType::SAINT_MILLION: - case EnemyType::SAND_RAPPY_ALT: - case EnemyType::SAND_RAPPY: - case EnemyType::SATELLITE_LIZARD_ALT: - case EnemyType::SATELLITE_LIZARD: - case EnemyType::SHAMBERTIN: - case EnemyType::YOWIE_ALT: - case EnemyType::YOWIE: - case EnemyType::ZE_BOOTA: - case EnemyType::ZU_ALT: - case EnemyType::ZU: - return true; - default: - return false; - } - default: - return false; - } -} - -uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type) { - switch (episode) { - case Episode::EP1: - switch (enemy_type) { - case EnemyType::MOTHMANT: - return 0x00; - case EnemyType::MONEST: - return 0x01; - case EnemyType::SAVAGE_WOLF: - return 0x02; - case EnemyType::BARBAROUS_WOLF: - return 0x03; - case EnemyType::POISON_LILY: - return 0x04; - case EnemyType::NAR_LILY: - return 0x05; - case EnemyType::SINOW_BEAT: - return 0x06; - case EnemyType::CANADINE: - return 0x07; - case EnemyType::CANADINE_GROUP: - return 0x08; - case EnemyType::CANANE: - return 0x09; - case EnemyType::CHAOS_SORCERER: - return 0x0A; - case EnemyType::CHAOS_BRINGER: - return 0x0D; - case EnemyType::DARK_BELRA: - return 0x0E; - case EnemyType::DE_ROL_LE: - return 0x0F; - case EnemyType::DRAGON: - return 0x12; - case EnemyType::SINOW_GOLD: - return 0x13; - case EnemyType::RAG_RAPPY: - return 0x18; - case EnemyType::AL_RAPPY: - return 0x19; - case EnemyType::NANO_DRAGON: - return 0x1A; - case EnemyType::DUBCHIC: - return 0x1B; - case EnemyType::GILLCHIC: - return 0x1C; - case EnemyType::GARANZ: - return 0x1D; - case EnemyType::DARK_GUNNER: - case EnemyType::DEATH_GUNNER: - return 0x1E; - case EnemyType::BULCLAW: - case EnemyType::BULK: - return 0x1F; - case EnemyType::CLAW: - return 0x20; - case EnemyType::VOL_OPT_2: - return 0x25; - case EnemyType::POFUILLY_SLIME: - return 0x30; - case EnemyType::POUILLY_SLIME: - return 0x2F; - case EnemyType::PAN_ARMS: - return 0x31; - case EnemyType::HIDOOM: - return 0x32; - case EnemyType::MIGIUM: - return 0x33; - case EnemyType::DARVANT: - return 0x35; - case EnemyType::DARVANT_ULTIMATE: - return 0x39; - case EnemyType::DARK_FALZ_1: - return 0x36; - case EnemyType::DARK_FALZ_2: - return 0x37; - case EnemyType::DARK_FALZ_3: - return 0x38; - case EnemyType::HILDEBEAR: - return 0x49; - case EnemyType::HILDEBLUE: - return 0x4A; - case EnemyType::BOOMA: - return 0x4B; - case EnemyType::GOBOOMA: - return 0x4C; - case EnemyType::GIGOBOOMA: - return 0x4D; - case EnemyType::GRASS_ASSASSIN: - return 0x4E; - case EnemyType::EVIL_SHARK: - return 0x4F; - case EnemyType::PAL_SHARK: - return 0x50; - case EnemyType::GUIL_SHARK: - return 0x51; - case EnemyType::DELSABER: - return 0x52; - case EnemyType::DIMENIAN: - return 0x53; - case EnemyType::LA_DIMENIAN: - return 0x54; - case EnemyType::SO_DIMENIAN: - return 0x55; - default: - throw out_of_range(phosg::string_printf( - "%s does not have battle parameters in Episode 1", phosg::name_for_enum(enemy_type))); - } - break; - case Episode::EP2: - switch (enemy_type) { - case EnemyType::MOTHMANT: - return 0x00; - case EnemyType::MONEST: - return 0x01; - case EnemyType::SAVAGE_WOLF: - return 0x02; - case EnemyType::BARBAROUS_WOLF: - return 0x03; - case EnemyType::POISON_LILY: - return 0x04; - case EnemyType::NAR_LILY: - return 0x05; - case EnemyType::SINOW_BERILL: - return 0x06; - case EnemyType::GEE: - return 0x07; - case EnemyType::CHAOS_SORCERER: - return 0x0A; - case EnemyType::DELBITER: - return 0x0D; - case EnemyType::DARK_BELRA: - return 0x0E; - case EnemyType::BARBA_RAY: - return 0x0F; - case EnemyType::GOL_DRAGON: - return 0x12; - case EnemyType::SINOW_SPIGELL: - return 0x13; - case EnemyType::RAG_RAPPY: - return 0x18; - case EnemyType::LOVE_RAPPY: - case EnemyType::SAINT_RAPPY: - case EnemyType::EGG_RAPPY: - case EnemyType::HALLO_RAPPY: - return 0x19; - case EnemyType::GI_GUE: - return 0x1A; - case EnemyType::DUBCHIC: - return 0x1B; - case EnemyType::GILLCHIC: - return 0x1C; - case EnemyType::GARANZ: - return 0x1D; - case EnemyType::GAL_GRYPHON: - return 0x1E; - case EnemyType::EPSILON: - return 0x23; - case EnemyType::DEL_LILY: - return 0x25; - case EnemyType::ILL_GILL: - return 0x26; - case EnemyType::OLGA_FLOW_1: - return 0x2B; - case EnemyType::OLGA_FLOW_2: - return 0x2C; - case EnemyType::GAEL: - return 0x2E; - case EnemyType::DELDEPTH: - return 0x30; - case EnemyType::PAN_ARMS: - return 0x31; - case EnemyType::HIDOOM: - return 0x32; - case EnemyType::MIGIUM: - return 0x33; - case EnemyType::MERICAROL: - case EnemyType::MERICARAND: - return 0x3A; - case EnemyType::UL_GIBBON: - return 0x3B; - case EnemyType::ZOL_GIBBON: - return 0x3C; - case EnemyType::GIBBLES: - return 0x3D; - case EnemyType::MORFOS: - return 0x40; - case EnemyType::RECOBOX: - return 0x41; - case EnemyType::RECON: - return 0x42; - case EnemyType::SINOW_ZOA: - return 0x43; - case EnemyType::SINOW_ZELE: - return 0x44; - case EnemyType::MERIKLE: - return 0x45; - case EnemyType::MERICUS: - return 0x46; - case EnemyType::HILDEBEAR: - return 0x49; - case EnemyType::HILDEBLUE: - return 0x4A; - case EnemyType::MERILLIA: - return 0x4B; - case EnemyType::MERILTAS: - return 0x4C; - case EnemyType::GRASS_ASSASSIN: - return 0x4E; - case EnemyType::DOLMOLM: - return 0x4F; - case EnemyType::DOLMDARL: - return 0x50; - case EnemyType::DELSABER: - return 0x52; - case EnemyType::DIMENIAN: - return 0x53; - case EnemyType::LA_DIMENIAN: - return 0x54; - case EnemyType::SO_DIMENIAN: - return 0x55; - default: - throw out_of_range(phosg::string_printf( - "%s does not have battle parameters in Episode 2", phosg::name_for_enum(enemy_type))); - } - break; - case Episode::EP4: - switch (enemy_type) { - case EnemyType::BOOTA: - return 0x00; - case EnemyType::ZE_BOOTA: - return 0x01; - case EnemyType::BA_BOOTA: - return 0x03; - case EnemyType::SAND_RAPPY: - return 0x05; - case EnemyType::DEL_RAPPY: - return 0x06; - case EnemyType::ZU: - return 0x07; - case EnemyType::PAZUZU: - return 0x08; - case EnemyType::ASTARK: - return 0x09; - case EnemyType::SATELLITE_LIZARD: - return 0x0D; - case EnemyType::YOWIE: - return 0x0E; - case EnemyType::DORPHON: - return 0x0F; - case EnemyType::DORPHON_ECLAIR: - return 0x10; - case EnemyType::GORAN: - return 0x11; - case EnemyType::PYRO_GORAN: - return 0x12; - case EnemyType::GORAN_DETONATOR: - return 0x13; - case EnemyType::SAND_RAPPY_ALT: - return 0x17; - case EnemyType::DEL_RAPPY_ALT: - return 0x18; - case EnemyType::MERISSA_A: - return 0x19; - case EnemyType::MERISSA_AA: - return 0x1A; - case EnemyType::ZU_ALT: - return 0x1B; - case EnemyType::PAZUZU_ALT: - return 0x1C; - case EnemyType::SATELLITE_LIZARD_ALT: - return 0x1D; - case EnemyType::YOWIE_ALT: - return 0x1E; - case EnemyType::GIRTABLULU: - return 0x1F; - case EnemyType::SAINT_MILLION: - return 0x22; - case EnemyType::SHAMBERTIN: - return 0x26; - case EnemyType::KONDRIEU: - return 0x2A; - default: - throw out_of_range(phosg::string_printf( - "%s does not have battle parameters in Episode 4", phosg::name_for_enum(enemy_type))); - } - break; - default: - throw logic_error("incorrect episode in battle param lookup"); - } - throw logic_error("fallthrough case in battle param lookup"); -} - -uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type) { - switch (enemy_type) { - case EnemyType::AL_RAPPY: - return 0x06; - case EnemyType::ASTARK: - return 0x41; - case EnemyType::BA_BOOTA: - return 0x4F; - case EnemyType::BARBA_RAY: - return 0x49; - case EnemyType::BARBAROUS_WOLF: - return 0x08; - case EnemyType::BOOMA: - return 0x09; - case EnemyType::BOOTA: - return 0x4D; - case EnemyType::BULK: - return 0x27; - case EnemyType::BULCLAW: - return 0x28; - case EnemyType::CANADINE: - case EnemyType::CANADINE_GROUP: - return 0x1C; - case EnemyType::CANANE: - return 0x1D; - case EnemyType::CHAOS_BRINGER: - return 0x24; - case EnemyType::CHAOS_SORCERER: - return 0x1F; - case EnemyType::CLAW: - return 0x26; - case EnemyType::DARK_BELRA: - return 0x25; - case EnemyType::DARK_FALZ_2: - return 0x2F; - case EnemyType::DARK_FALZ_3: - return 0x2F; - case EnemyType::DARK_GUNNER: - return 0x22; - case EnemyType::DEATH_GUNNER: - return 0x23; - case EnemyType::DE_ROL_LE: - return 0x2D; - case EnemyType::DEL_LILY: - return 0x53; - case EnemyType::DEL_RAPPY: - return 0x57; - case EnemyType::DEL_RAPPY_ALT: - return 0x58; - case EnemyType::DELBITER: - return 0x48; - case EnemyType::DELDEPTH: - return 0x47; - case EnemyType::DELSABER: - return 0x1E; - case EnemyType::DIMENIAN: - return 0x29; - case EnemyType::DOLMDARL: - return 0x41; - case EnemyType::DOLMOLM: - return 0x40; - case EnemyType::DORPHON: - return 0x50; - case EnemyType::DORPHON_ECLAIR: - return 0x51; - case EnemyType::DRAGON: - return 0x2C; - case EnemyType::DUBCHIC: - return 0x18; - case EnemyType::EGG_RAPPY: - return 0x51; - case EnemyType::EPSILON: - return 0x54; - case EnemyType::EVIL_SHARK: - return 0x10; - case EnemyType::GAL_GRYPHON: - return 0x4D; - case EnemyType::GARANZ: - return 0x19; - case EnemyType::GEE: - return 0x36; - case EnemyType::GI_GUE: - return 0x37; - case EnemyType::GIBBLES: - return 0x3D; - case EnemyType::GIGOBOOMA: - return 0x0B; - case EnemyType::GILLCHIC: - return 0x32; - case EnemyType::GIRTABLULU: - return 0x48; - case EnemyType::GOBOOMA: - return 0x0A; - case EnemyType::GOL_DRAGON: - return 0x4C; - case EnemyType::GORAN: - return 0x52; - case EnemyType::GORAN_DETONATOR: - return 0x53; - case EnemyType::GRASS_ASSASSIN: - return 0x0C; - case EnemyType::GUIL_SHARK: - return 0x12; - case EnemyType::HALLO_RAPPY: - return 0x50; - case EnemyType::HIDOOM: - return 0x17; - case EnemyType::HILDEBEAR: - return 0x01; - case EnemyType::HILDEBLUE: - return 0x02; - case EnemyType::ILL_GILL: - return 0x52; - case EnemyType::KONDRIEU: - return 0x5B; - case EnemyType::LA_DIMENIAN: - return 0x2A; - case EnemyType::LOVE_RAPPY: - return 0x33; - case EnemyType::MERICAROL: - case EnemyType::MERICARAND: - return 0x38; - case EnemyType::MERICUS: - return 0x3A; - case EnemyType::MERIKLE: - return 0x39; - case EnemyType::MERILLIA: - return 0x34; - case EnemyType::MERILTAS: - return 0x35; - case EnemyType::MERISSA_A: - return 0x46; - case EnemyType::MERISSA_AA: - return 0x47; - case EnemyType::MIGIUM: - return 0x16; - case EnemyType::MONEST: - return 0x04; - case EnemyType::MORFOS: - return 0x42; - case EnemyType::MOTHMANT: - return 0x03; - case EnemyType::NANO_DRAGON: - return 0x0F; - case EnemyType::NAR_LILY: - return 0x0E; - case EnemyType::OLGA_FLOW_2: - return 0x4E; - case EnemyType::PAL_SHARK: - return 0x11; - case EnemyType::PAN_ARMS: - return 0x15; - case EnemyType::PAZUZU: - return 0x4B; - case EnemyType::PAZUZU_ALT: - return 0x4C; - case EnemyType::POFUILLY_SLIME: - return 0x13; - case EnemyType::POUILLY_SLIME: - return 0x14; - case EnemyType::POISON_LILY: - return 0x0D; - case EnemyType::PYRO_GORAN: - return 0x54; - case EnemyType::RAG_RAPPY: - return 0x05; - case EnemyType::RECOBOX: - return 0x43; - case EnemyType::RECON: - return 0x44; - case EnemyType::SAINT_RAPPY: - return 0x4F; - case EnemyType::SAINT_MILLION: - return 0x59; - case EnemyType::SAND_RAPPY: - return 0x55; - case EnemyType::SAND_RAPPY_ALT: - return 0x56; - case EnemyType::SATELLITE_LIZARD: - return 0x44; - case EnemyType::SATELLITE_LIZARD_ALT: - return 0x45; - case EnemyType::SAVAGE_WOLF: - return 0x07; - case EnemyType::SHAMBERTIN: - return 0x5A; - case EnemyType::SINOW_BEAT: - return 0x1A; - case EnemyType::SINOW_BERILL: - return 0x3E; - case EnemyType::SINOW_GOLD: - return 0x1B; - case EnemyType::SINOW_SPIGELL: - return 0x3F; - case EnemyType::SINOW_ZELE: - return 0x46; - case EnemyType::SINOW_ZOA: - return 0x45; - case EnemyType::SO_DIMENIAN: - return 0x2B; - case EnemyType::UL_GIBBON: - return 0x3B; - case EnemyType::VOL_OPT_2: - return 0x2E; - case EnemyType::YOWIE: - return 0x42; - case EnemyType::YOWIE_ALT: - return 0x43; - case EnemyType::ZE_BOOTA: - return 0x4E; - case EnemyType::ZOL_GIBBON: - return 0x3C; - case EnemyType::ZU: - return 0x49; - case EnemyType::ZU_ALT: - return 0x4A; - default: - throw runtime_error(phosg::string_printf("%s does not have a rare table entry", phosg::name_for_enum(enemy_type))); + } } + return index.at(name); } const vector& enemy_types_for_rare_table_index(Episode episode, uint8_t rt_index) { const auto& generate_table = +[](Episode episode) -> vector> { vector> ret; - for (size_t z = 0; z < static_cast(EnemyType::MAX_ENEMY_TYPE); z++) { - EnemyType t = static_cast(z); - try { - uint8_t rt_index = rare_table_index_for_enemy_type(t); - if (enemy_type_valid_for_episode(episode, t)) { - if (rt_index >= ret.size()) { - ret.resize(rt_index + 1); - } - ret[rt_index].emplace_back(t); + for (const auto& def : type_defs) { + if (def.valid_in_episode(episode) && (def.rt_index != 0xFF)) { + if (def.rt_index >= ret.size()) { + ret.resize(def.rt_index + 1); } - } catch (const exception&) { + ret[def.rt_index].emplace_back(def.type); } } return ret; @@ -1117,21 +196,8 @@ const vector& enemy_types_for_rare_table_index(Episode episode, uint8 } } -bool enemy_type_is_rare(EnemyType type) { - return ((type == EnemyType::HILDEBLUE) || - (type == EnemyType::AL_RAPPY) || - (type == EnemyType::NAR_LILY) || - (type == EnemyType::POUILLY_SLIME) || - (type == EnemyType::MERICUS) || - (type == EnemyType::MERIKLE) || - (type == EnemyType::MERISSA_AA) || - (type == EnemyType::PAZUZU_ALT) || - (type == EnemyType::DORPHON_ECLAIR) || - (type == EnemyType::KONDRIEU)); -} - -EnemyType rare_type_for_enemy_type(EnemyType base_type, Episode episode, uint8_t event, uint8_t floor) { - switch (base_type) { +EnemyType EnemyTypeDefinition::rare_type(Episode episode, uint8_t event, uint8_t floor) const { + switch (this->type) { case EnemyType::HILDEBEAR: return EnemyType::HILDEBLUE; case EnemyType::RAG_RAPPY: @@ -1150,7 +216,7 @@ EnemyType rare_type_for_enemy_type(EnemyType base_type, Episode episode, uint8_t return EnemyType::LOVE_RAPPY; } case Episode::EP4: - return (floor > 0x05) ? EnemyType::DEL_RAPPY_ALT : EnemyType::DEL_RAPPY; + return (floor > 0x05) ? EnemyType::DEL_RAPPY_DESERT : EnemyType::DEL_RAPPY_CRATER; default: throw logic_error("invalid episode"); } @@ -1158,22 +224,22 @@ EnemyType rare_type_for_enemy_type(EnemyType base_type, Episode episode, uint8_t return EnemyType::NAR_LILY; case EnemyType::POFUILLY_SLIME: return EnemyType::POUILLY_SLIME; - case EnemyType::SAND_RAPPY: - return EnemyType::DEL_RAPPY; - case EnemyType::SAND_RAPPY_ALT: - return EnemyType::DEL_RAPPY_ALT; + case EnemyType::SAND_RAPPY_CRATER: + return EnemyType::DEL_RAPPY_CRATER; + case EnemyType::SAND_RAPPY_DESERT: + return EnemyType::DEL_RAPPY_DESERT; case EnemyType::MERISSA_A: return EnemyType::MERISSA_AA; - case EnemyType::ZU: - return EnemyType::PAZUZU; - case EnemyType::ZU_ALT: - return EnemyType::PAZUZU_ALT; + case EnemyType::ZU_CRATER: + return EnemyType::PAZUZU_CRATER; + case EnemyType::ZU_DESERT: + return EnemyType::PAZUZU_DESERT; case EnemyType::DORPHON: return EnemyType::DORPHON_ECLAIR; - case EnemyType::SAINT_MILLION: + case EnemyType::SAINT_MILION: case EnemyType::SHAMBERTIN: return EnemyType::KONDRIEU; default: - return base_type; + return this->type; } } diff --git a/src/EnemyType.hh b/src/EnemyType.hh index 7e705794..20de215e 100644 --- a/src/EnemyType.hh +++ b/src/EnemyType.hh @@ -7,9 +7,9 @@ #include "StaticGameData.hh" #include "Types.hh" -enum class EnemyType { - UNKNOWN = -1, - NONE = 0, +enum class EnemyType : uint8_t { + UNKNOWN = 0, + NONE, NON_ENEMY_NPC, AL_RAPPY, ASTARK, @@ -40,8 +40,8 @@ enum class EnemyType { DE_ROL_LE_MINE, DEATH_GUNNER, DEL_LILY, - DEL_RAPPY, - DEL_RAPPY_ALT, + DEL_RAPPY_CRATER, + DEL_RAPPY_DESERT, DELBITER, DELDEPTH, DELSABER, @@ -54,10 +54,10 @@ enum class EnemyType { DUBCHIC, DUBWITCH, // Has no entry in battle params EGG_RAPPY, - EPSIGUARD, + EPSIGARD, EPSILON, EVIL_SHARK, - GAEL, + GAEL_OR_GIEL, GAL_GRYPHON, GARANZ, GEE, @@ -98,8 +98,8 @@ enum class EnemyType { OLGA_FLOW_2, PAL_SHARK, PAN_ARMS, - PAZUZU, - PAZUZU_ALT, + PAZUZU_CRATER, + PAZUZU_DESERT, PIG_RAY, POFUILLY_SLIME, POUILLY_SLIME, @@ -108,12 +108,12 @@ enum class EnemyType { RAG_RAPPY, RECOBOX, RECON, - SAINT_MILLION, + SAINT_MILION, SAINT_RAPPY, - SAND_RAPPY, - SAND_RAPPY_ALT, - SATELLITE_LIZARD, - SATELLITE_LIZARD_ALT, + SAND_RAPPY_CRATER, + SAND_RAPPY_DESERT, + SATELLITE_LIZARD_CRATER, + SATELLITE_LIZARD_DESERT, SAVAGE_WOLF, SHAMBERTIN, SINOW_BEAT, @@ -130,23 +130,53 @@ enum class EnemyType { VOL_OPT_CORE, VOL_OPT_MONITOR, VOL_OPT_PILLAR, - YOWIE, - YOWIE_ALT, + YOWIE_CRATER, + YOWIE_DESERT, ZE_BOOTA, ZOL_GIBBON, - ZU, - ZU_ALT, + ZU_CRATER, + ZU_DESERT, MAX_ENEMY_TYPE, }; +struct EnemyTypeDefinition { + enum Flag : uint8_t { + VALID_EP1 = 0x01, + VALID_EP2 = 0x02, + VALID_EP4 = 0x04, + IS_RARE = 0x08, + }; + EnemyType type; + uint8_t flags; + uint8_t rt_index; // 0xFF if not valid (e.g. not an enemy) + uint8_t bp_index; // 0xFF if not valid (e.g. not an enemy) + const char* enum_name; + const char* in_game_name; + const char* ultimate_name; // May be null if same as in_game_name + + inline bool valid_in_episode(Episode ep) const { + switch (ep) { + case Episode::EP1: + return (this->flags & Flag::VALID_EP1); + case Episode::EP2: + return (this->flags & Flag::VALID_EP2); + case Episode::EP4: + return (this->flags & Flag::VALID_EP4); + default: + throw std::logic_error("invalid episode number"); + } + } + inline bool is_rare() const { + return (this->flags & Flag::IS_RARE); + } + EnemyType rare_type(Episode episode, uint8_t event, uint8_t floor) const; +}; + +const EnemyTypeDefinition& type_definition_for_enemy(EnemyType type); + template <> const char* phosg::name_for_enum(EnemyType type); template <> EnemyType phosg::enum_for_name(const char* name); -bool enemy_type_valid_for_episode(Episode episode, EnemyType enemy_type); -uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type); -uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type); const std::vector& enemy_types_for_rare_table_index(Episode episode, uint8_t rt_index); -bool enemy_type_is_rare(EnemyType type); -EnemyType rare_type_for_enemy_type(EnemyType base_type, Episode episode, uint8_t event, uint8_t floor); diff --git a/src/ItemNameIndex.cc b/src/ItemNameIndex.cc index bb188f90..3b9caa89 100644 --- a/src/ItemNameIndex.cc +++ b/src/ItemNameIndex.cc @@ -97,7 +97,7 @@ const array name_for_s_rank_special = { "King\'s", }; -std::string ItemNameIndex::describe_item(const ItemData& item, bool include_color_escapes) const { +std::string ItemNameIndex::describe_item(const ItemData& item, bool include_color_escapes, bool hide_mag_stats) const { if (item.data1[0] == 0x04) { return phosg::string_printf("%s%" PRIu32 " Meseta", include_color_escapes ? "$C7" : "", item.data2d.load()); } @@ -166,8 +166,8 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo } } - // For weapons, add the grind and bonuses, or S-rank name if applicable if (item.data1[0] == 0x00) { + // For weapons, add the grind and bonuses, or S-rank name if applicable if (item.data1[3] > 0) { ret_tokens.emplace_back(phosg::string_printf("+%hhu", item.data1[3])); } @@ -232,8 +232,8 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo } } - // For armors, add the slots, unit modifiers, and/or DEF/EVP bonuses } else if (item.data1[0] == 0x01) { + // For armors, add the slots, unit modifiers, and/or DEF/EVP bonuses if (item.data1[1] == 0x03) { // Units int16_t modifier = item.data1w[3]; if (modifier == 1 || modifier == 2) { @@ -266,8 +266,8 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo } } + } else if (!hide_mag_stats && (item.data1[0] == 0x02)) { // For mags, add tons of info - } else if (item.data1[0] == 0x02) { ret_tokens.emplace_back(phosg::string_printf("LV%hhu", item.data1[2])); uint16_t def = item.data1w[2]; @@ -327,8 +327,8 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo ret_tokens.emplace_back(phosg::string_printf("(!CL:%02hhX)", item.data2[3])); } - // For tools, add the amount (if applicable) } else if (item.data1[0] == 0x03) { + // For tools, add the amount (if applicable) if (item.max_stack_size(*this->limits) > 1) { ret_tokens.emplace_back(phosg::string_printf("x%hhu", item.data1[5])); } diff --git a/src/ItemNameIndex.hh b/src/ItemNameIndex.hh index bf311cbb..ecbf7f53 100644 --- a/src/ItemNameIndex.hh +++ b/src/ItemNameIndex.hh @@ -38,7 +38,7 @@ public: inline bool exists(const ItemData& item) const { return this->primary_identifier_index.count(item.primary_identifier()); } - std::string describe_item(const ItemData& item, bool include_color_escapes = false) const; + std::string describe_item(const ItemData& item, bool include_color_escapes = false, bool hide_mag_stats = false) const; ItemData parse_item_description(const std::string& description) const; void print_table(FILE* stream) const; diff --git a/src/Main.cc b/src/Main.cc index 9b57bb92..8a516007 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -1456,23 +1456,25 @@ Action a_disassemble_quest_map( if (!args.get("decompressed")) { *data = prs_decompress(*data); } - string result = MapFile(data).disassemble(); + bool reassembly = args.get("reassembly"); + string result = MapFile(data).disassemble(reassembly); write_output_data(args, result.data(), result.size(), "txt"); }); Action a_disassemble_free_map( "disassemble-free-map", "\ disassemble-free-map INPUT-FILENAME [OUTPUT-FILENAME]\n\ Disassemble the input free-play map (.dat or .evt file) into a text\n\ - representation of the data it contains. Unlike othe disassembly actions,\n\ + representation of the data it contains. Unlike other disassembly actions,\n\ this action expects its input to be already decompressed. If the input is\n\ compressed, use the --compressed option. Also unlike other options, the\n\ input must be from a file (that is, INPUT-FILENAME is required and cannot\n\ be \"-\").\n", +[](phosg::Arguments& args) { const string& input_filename = args.get(1, true); - bool is_events = phosg::ends_with(input_filename, ".evt"); - bool is_enemies = phosg::ends_with(input_filename, "e.dat") || phosg::ends_with(input_filename, "e_s.dat") || phosg::ends_with(input_filename, "e_c1.dat") || phosg::ends_with(input_filename, "e_d.dat"); - bool is_objects = phosg::ends_with(input_filename, "o.dat") || phosg::ends_with(input_filename, "o_s.dat") || phosg::ends_with(input_filename, "o_c1.dat") || phosg::ends_with(input_filename, "o_d.dat"); + string input_filename_lower = phosg::tolower(input_filename); + bool is_events = phosg::ends_with(input_filename_lower, ".evt"); + bool is_enemies = phosg::ends_with(input_filename_lower, "e.dat") || phosg::ends_with(input_filename_lower, "e_s.dat") || phosg::ends_with(input_filename_lower, "e_c1.dat") || phosg::ends_with(input_filename_lower, "e_d.dat"); + bool is_objects = phosg::ends_with(input_filename_lower, "o.dat") || phosg::ends_with(input_filename_lower, "o_s.dat") || phosg::ends_with(input_filename_lower, "o_c1.dat") || phosg::ends_with(input_filename_lower, "o_d.dat"); if (!is_objects && !is_enemies && !is_events) { throw runtime_error("cannot determine input file type"); } @@ -1483,13 +1485,14 @@ Action a_disassemble_free_map( } uint8_t floor = args.get("floor", 0); + bool reassembly = args.get("reassembly"); string result; if (is_objects) { - result = MapFile(floor, data, nullptr, nullptr).disassemble(); + result = MapFile(floor, data, nullptr, nullptr).disassemble(reassembly); } else if (is_enemies) { - result = MapFile(floor, nullptr, data, nullptr).disassemble(); + result = MapFile(floor, nullptr, data, nullptr).disassemble(reassembly); } else if (is_events) { - result = MapFile(floor, nullptr, nullptr, data).disassemble(); + result = MapFile(floor, nullptr, nullptr, data).disassemble(reassembly); } else { throw logic_error("unhandled input type"); } @@ -1867,7 +1870,7 @@ Action a_download_files( } shared_ptr base(event_base_new(), event_base_free); auto remote = phosg::make_sockaddr_storage(phosg::parse_netloc(args.get(1))).first; - auto character = load_psochar(args.get("character", true), false).character_file; + auto character = PSOCHARFile::load_shared(args.get("character", true), false).character_file; auto ship_menu_selections_str = args.get("ship-menu-selections", false); unordered_set ship_menu_selections; @@ -1924,11 +1927,10 @@ Action a_convert_rare_item_set( .gslb (PSO GC big-endian GSL archive)\n\ .afs (PSO V2 little-endian AFS archive)\n\ .rel (Schtserv rare table; cannot be used in output filename)\n\ + .html (HTML rare table; cannot be used in input filename)\n\ If the --multiply=X option is given, multiplies all drop rates by X (given\n\ as a decimal value).\n", +[](phosg::Arguments& args) { - auto version = get_cli_version(args); - double rate_factor = args.get("multiply", 1.0); auto s = make_shared(get_config_filename(args)); s->load_config_early(); @@ -1942,17 +1944,18 @@ Action a_convert_rare_item_set( throw runtime_error("input filename must be given"); } + string input_filename_lower = phosg::tolower(input_filename); auto data = make_shared(read_input_data(args)); shared_ptr rs; - if (phosg::ends_with(input_filename, ".json")) { - rs = make_shared(phosg::JSON::parse(*data), s->item_name_index_opt(version)); - } else if (phosg::ends_with(input_filename, ".gsl")) { + if (phosg::ends_with(input_filename_lower, ".json")) { + rs = make_shared(phosg::JSON::parse(*data), s->item_name_index_opt(get_cli_version(args, Version::BB_V4))); + } else if (phosg::ends_with(input_filename_lower, ".gsl")) { rs = make_shared(GSLArchive(data, false), false); - } else if (phosg::ends_with(input_filename, ".gslb")) { + } else if (phosg::ends_with(input_filename_lower, ".gslb")) { rs = make_shared(GSLArchive(data, true), true); - } else if (phosg::ends_with(input_filename, ".afs")) { - rs = make_shared(AFSArchive(data), is_v1(version)); - } else if (phosg::ends_with(input_filename, ".rel")) { + } else if (phosg::ends_with(input_filename_lower, ".afs")) { + rs = make_shared(AFSArchive(data), is_v1(get_cli_version(args, Version::DC_V2))); + } else if (phosg::ends_with(input_filename_lower, ".rel")) { rs = make_shared(*data, true); } else { throw runtime_error("cannot determine input format; use a filename ending with .json, .gsl, .gslb, .afs, or .rel"); @@ -1963,22 +1966,38 @@ Action a_convert_rare_item_set( } string output_filename = args.get(2, false); + string output_filename_lower = phosg::tolower(output_filename); if (output_filename.empty() || (output_filename == "-")) { - rs->print_all_collections(stdout, s->item_name_index_opt(version)); - } else if (phosg::ends_with(output_filename, ".json")) { - auto json = rs->json(s->item_name_index_opt(version)); + rs->print_all_collections(stdout, s->item_name_index_opt(get_cli_version(args, Version::BB_V4))); + } else if (phosg::ends_with(output_filename_lower, ".json")) { + auto json = rs->json(s->item_name_index_opt(get_cli_version(args, Version::BB_V4))); string data = json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::HEX_INTEGERS | phosg::JSON::SerializeOption::SORT_DICT_KEYS); write_output_data(args, data.data(), data.size(), nullptr); - } else if (phosg::ends_with(output_filename, ".gsl")) { + } else if (phosg::ends_with(output_filename_lower, ".gsl")) { string data = rs->serialize_gsl(args.get("big-endian")); write_output_data(args, data.data(), data.size(), nullptr); - } else if (phosg::ends_with(output_filename, ".gslb")) { + } else if (phosg::ends_with(output_filename_lower, ".gslb")) { string data = rs->serialize_gsl(true); write_output_data(args, data.data(), data.size(), nullptr); - } else if (phosg::ends_with(output_filename, ".afs")) { - bool is_v1 = ::is_v1(get_cli_version(args, Version::GC_V3)); + } else if (phosg::ends_with(output_filename_lower, ".afs")) { + bool is_v1 = ::is_v1(get_cli_version(args, Version::DC_V2)); string data = rs->serialize_afs(is_v1); write_output_data(args, data.data(), data.size(), nullptr); + } else if (phosg::ends_with(output_filename_lower, ".html")) { + bool is_v1 = ::is_v1(get_cli_version(args, Version::BB_V4)); + static const array modes = {GameMode::NORMAL, GameMode::BATTLE, GameMode::CHALLENGE, GameMode::SOLO}; + for (GameMode mode : modes) { + static const array episodes = {Episode::EP1, Episode::EP2, Episode::EP4}; + for (Episode episode : episodes) { + for (size_t difficulty = 0; difficulty < (is_v1 ? 3 : 4); difficulty++) { + auto item_name_index = s->item_name_index(get_cli_version(args, Version::BB_V4)); + string data = rs->serialize_html(mode, episode, difficulty, item_name_index); + string out_filename = output_filename.substr(0, output_filename.size() - 5) + "." + name_for_mode(mode) + "." + name_for_episode(episode) + "." + name_for_difficulty(difficulty) + output_filename.substr(output_filename.size() - 5); + phosg::save_file(out_filename, data); + phosg::log_info("... %s", out_filename.c_str()); + } + } + } } else { throw runtime_error("cannot determine output format; use a filename ending with .json, .gsl, .gslb, or .afs"); } diff --git a/src/Map.cc b/src/Map.cc index e9f2ec7d..c9b19455 100644 --- a/src/Map.cc +++ b/src/Map.cc @@ -1678,35 +1678,59 @@ string MapFile::disassemble_action_stream(const void* data, size_t size) { return phosg::join(ret, "\n"); } -string MapFile::disassemble() const { +string MapFile::disassemble(bool reassembly) const { deque ret; for (uint8_t floor = 0; floor < this->sections_for_floor.size(); floor++) { const auto& sf = this->sections_for_floor[floor]; phosg::StringReader as_r(sf.event_action_stream, sf.event_action_stream_bytes); if (sf.object_sets) { - ret.emplace_back(phosg::string_printf(".object_sets %hhu /* 0x%zX in file; 0x%zX bytes */", - floor, sf.object_sets_file_offset, sf.object_sets_file_size)); + if (reassembly) { + ret.emplace_back(phosg::string_printf(".object_sets %hhu", floor)); + } else { + ret.emplace_back(phosg::string_printf(".object_sets %hhu /* 0x%zX in file; 0x%zX bytes */", + floor, sf.object_sets_file_offset, sf.object_sets_file_size)); + } for (size_t z = 0; z < sf.object_set_count; z++) { - size_t k_id = z + sf.first_object_set_index; - ret.emplace_back(phosg::string_printf("/* K-%03zX */ ", k_id) + sf.object_sets[z].str()); + if (reassembly) { + ret.emplace_back(sf.object_sets[z].str()); + } else { + size_t k_id = z + sf.first_object_set_index; + ret.emplace_back(phosg::string_printf("/* K-%03zX */ ", k_id) + sf.object_sets[z].str()); + } } } if (sf.enemy_sets) { - ret.emplace_back(phosg::string_printf(".enemy_sets %hhu /* 0x%zX in file; 0x%zX bytes */", - floor, sf.enemy_sets_file_offset, sf.enemy_sets_file_size)); + if (reassembly) { + ret.emplace_back(phosg::string_printf(".enemy_sets %hhu", floor)); + } else { + ret.emplace_back(phosg::string_printf(".enemy_sets %hhu /* 0x%zX in file; 0x%zX bytes */", + floor, sf.enemy_sets_file_offset, sf.enemy_sets_file_size)); + } for (size_t z = 0; z < sf.enemy_set_count; z++) { - size_t s_id = z + sf.first_enemy_set_index; - ret.emplace_back(phosg::string_printf("/* S-%03zX */ ", s_id) + sf.enemy_sets[z].str()); + if (reassembly) { + ret.emplace_back(sf.enemy_sets[z].str()); + } else { + size_t s_id = z + sf.first_enemy_set_index; + ret.emplace_back(phosg::string_printf("/* S-%03zX */ ", s_id) + sf.enemy_sets[z].str()); + } } } if (sf.events1) { - ret.emplace_back(phosg::string_printf(".events %hhu /* 0x%zX in file; 0x%zX bytes; 0x%zX bytes in action stream */", - floor, sf.events_file_offset, sf.events_file_size, sf.event_action_stream_bytes)); + if (reassembly) { + ret.emplace_back(phosg::string_printf(".events %hhu", floor)); + } else { + ret.emplace_back(phosg::string_printf(".events %hhu /* 0x%zX in file; 0x%zX bytes; 0x%zX bytes in action stream */", + floor, sf.events_file_offset, sf.events_file_size, sf.event_action_stream_bytes)); + } for (size_t z = 0; z < sf.event_count; z++) { const auto& ev = sf.events1[z]; - size_t w_id = z + sf.first_event_set_index; - ret.emplace_back(phosg::string_printf("/* W-%03zX */ ", w_id) + ev.str()); + if (reassembly) { + ret.emplace_back(ev.str()); + } else { + size_t w_id = z + sf.first_event_set_index; + ret.emplace_back(phosg::string_printf("/* W-%03zX */ ", w_id) + ev.str()); + } if (ev.action_stream_offset >= sf.event_action_stream_bytes) { ret.emplace_back(phosg::string_printf( " // WARNING: Event action stream offset (0x%" PRIX32 ") is outside of this section", @@ -1717,11 +1741,20 @@ string MapFile::disassemble() const { } } if (sf.events2) { - ret.emplace_back(phosg::string_printf(".random_events %hhu /* 0x%zX in file; 0x%zX bytes; 0x%zX bytes in action stream */", - floor, sf.events_file_offset, sf.events_file_size, sf.event_action_stream_bytes)); + if (reassembly) { + ret.emplace_back(phosg::string_printf(".random_events %hhu", floor)); + } else { + ret.emplace_back(phosg::string_printf( + ".random_events %hhu /* 0x%zX in file; 0x%zX bytes; 0x%zX bytes in action stream */", + floor, sf.events_file_offset, sf.events_file_size, sf.event_action_stream_bytes)); + } for (size_t z = 0; z < sf.event_count; z++) { const auto& ev = sf.events2[z]; - ret.emplace_back(phosg::string_printf("/* index %zu */", z) + ev.str()); + if (reassembly) { + ret.emplace_back(ev.str()); + } else { + ret.emplace_back(phosg::string_printf("/* index %zu */", z) + ev.str()); + } if (ev.action_stream_offset >= sf.event_action_stream_bytes) { ret.emplace_back(phosg::string_printf( " // WARNING: Event action stream offset (0x%" PRIX32 ") is outside of this section", @@ -1732,13 +1765,21 @@ string MapFile::disassemble() const { } } if (sf.random_enemy_locations_data) { - ret.emplace_back(phosg::string_printf(".random_enemy_locations %hhu /* 0x%zX in file; 0x%zX bytes */", - floor, sf.random_enemy_locations_file_offset, sf.random_enemy_locations_file_size)); + if (reassembly) { + ret.emplace_back(phosg::string_printf(".random_enemy_locations %hhu", floor)); + } else { + ret.emplace_back(phosg::string_printf(".random_enemy_locations %hhu /* 0x%zX in file; 0x%zX bytes */", + floor, sf.random_enemy_locations_file_offset, sf.random_enemy_locations_file_size)); + } ret.emplace_back(phosg::format_data(sf.random_enemy_locations_data, sf.random_enemy_locations_data_size)); } if (sf.random_enemy_definitions_data) { - ret.emplace_back(phosg::string_printf(".random_enemy_definitions %hhu /* 0x%zX in file; 0x%zX bytes */", - floor, sf.random_enemy_definitions_file_offset, sf.random_enemy_definitions_file_size)); + if (reassembly) { + ret.emplace_back(phosg::string_printf(".random_enemy_definitions %hhu", floor)); + } else { + ret.emplace_back(phosg::string_printf(".random_enemy_definitions %hhu /* 0x%zX in file; 0x%zX bytes */", + floor, sf.random_enemy_definitions_file_offset, sf.random_enemy_definitions_file_size)); + } ret.emplace_back(phosg::format_data(sf.random_enemy_definitions_data, sf.random_enemy_definitions_data_size)); } } @@ -2050,7 +2091,7 @@ shared_ptr SuperMap::add_enemy_and_children( add(EnemyType::RAG_RAPPY, is_rare_v123, is_rare_bb); break; case Episode::EP4: - add((floor > 0x05) ? EnemyType::SAND_RAPPY_ALT : EnemyType::SAND_RAPPY, is_rare_v123, is_rare_bb); + add((floor > 0x05) ? EnemyType::SAND_RAPPY_DESERT : EnemyType::SAND_RAPPY_CRATER, is_rare_v123, is_rare_bb); break; default: throw logic_error("invalid episode"); @@ -2290,7 +2331,7 @@ shared_ptr SuperMap::add_enemy_and_children( if ((episode == Episode::EP2) && (floor > 0x0F)) { add(EnemyType::EPSILON); default_num_children = 4; - child_type = EnemyType::EPSIGUARD; + child_type = EnemyType::EPSIGARD; } else { add((set_entry->uparam1 & 0x01) ? EnemyType::SINOW_ZELE : EnemyType::SINOW_ZOA); } @@ -2303,9 +2344,9 @@ shared_ptr SuperMap::add_enemy_and_children( break; case 0x0111: if (floor > 0x05) { - add(set_entry->fparam2 ? EnemyType::YOWIE_ALT : EnemyType::SATELLITE_LIZARD_ALT); + add(set_entry->fparam2 ? EnemyType::YOWIE_DESERT : EnemyType::SATELLITE_LIZARD_DESERT); } else { - add(set_entry->fparam2 ? EnemyType::YOWIE : EnemyType::SATELLITE_LIZARD); + add(set_entry->fparam2 ? EnemyType::YOWIE_CRATER : EnemyType::SATELLITE_LIZARD_CRATER); } break; case 0x0112: { @@ -2318,7 +2359,7 @@ shared_ptr SuperMap::add_enemy_and_children( break; case 0x0114: { bool is_rare = (set_entry->uparam1 & 0x01); - add((floor > 0x05) ? EnemyType::ZU_ALT : EnemyType::ZU, is_rare, is_rare); + add((floor > 0x05) ? EnemyType::ZU_DESERT : EnemyType::ZU_CRATER, is_rare, is_rare); break; } case 0x0115: @@ -2341,7 +2382,7 @@ shared_ptr SuperMap::add_enemy_and_children( case 0x0119: { // TODO: It appears BB doesn't have a way to force Kondrieu to appear via // constructor args. Is this true? - add((set_entry->uparam1 & 1) ? EnemyType::SHAMBERTIN : EnemyType::SAINT_MILLION); + add((set_entry->uparam1 & 1) ? EnemyType::SHAMBERTIN : EnemyType::SAINT_MILION); default_num_children = 0x18; break; } @@ -3378,8 +3419,8 @@ uint32_t MapState::RareEnemyRates::for_enemy_type(EnemyType type) const { case EnemyType::HILDEBEAR: return this->hildeblue; case EnemyType::RAG_RAPPY: - case EnemyType::SAND_RAPPY: - case EnemyType::SAND_RAPPY_ALT: + case EnemyType::SAND_RAPPY_CRATER: + case EnemyType::SAND_RAPPY_DESERT: return this->rappy; case EnemyType::POISON_LILY: return this->nar_lily; @@ -3389,12 +3430,12 @@ uint32_t MapState::RareEnemyRates::for_enemy_type(EnemyType type) const { return this->mericarand; case EnemyType::MERISSA_A: return this->merissa_aa; - case EnemyType::ZU: - case EnemyType::ZU_ALT: + case EnemyType::ZU_CRATER: + case EnemyType::ZU_DESERT: return this->pazuzu; case EnemyType::DORPHON: return this->dorphon_eclair; - case EnemyType::SAINT_MILLION: + case EnemyType::SAINT_MILION: case EnemyType::SHAMBERTIN: return this->kondrieu; default: @@ -3643,7 +3684,7 @@ void MapState::index_super_map(const FloorConfig& fc, shared_ptrtype; } - auto rare_type = rare_type_for_enemy_type(type, fc.super_map->get_episode(), this->event, ene->floor); + auto rare_type = type_definition_for_enemy(type).rare_type(fc.super_map->get_episode(), this->event, ene->floor); if ((type == EnemyType::MERICARAND) || (rare_type != type)) { unordered_map det_cache; uint32_t bb_rare_rate = this->bb_rare_rates->for_enemy_type(type); diff --git a/src/Map.hh b/src/Map.hh index 40f87738..0feee77a 100644 --- a/src/Map.hh +++ b/src/Map.hh @@ -417,7 +417,7 @@ public: size_t count_events() const; static std::string disassemble_action_stream(const void* data, size_t size); - std::string disassemble() const; + std::string disassemble(bool reassembly = false) const; protected: void link_data(std::shared_ptr data); @@ -661,7 +661,7 @@ public: uint32_t merissa_aa; // MERISSA_A -> MERISSA_AA uint32_t pazuzu; // ZU -> PAZUZU (and _ALT variants) uint32_t dorphon_eclair; // DORPHON -> DORPHON_ECLAIR - uint32_t kondrieu; // {SAINT_MILLION, SHAMBERTIN} -> KONDRIEU + uint32_t kondrieu; // {SAINT_MILION, SHAMBERTIN} -> KONDRIEU RareEnemyRates(uint32_t enemy_rate, uint32_t mericarand_rate, uint32_t boss_rate); explicit RareEnemyRates(const phosg::JSON& json); @@ -768,7 +768,7 @@ public: } } else { return this->is_rare(version) - ? rare_type_for_enemy_type(this->super_ene->type, episode, event, this->super_ene->floor) + ? type_definition_for_enemy(this->super_ene->type).rare_type(episode, event, this->super_ene->floor) : this->super_ene->type; } } diff --git a/src/RareItemSet.cc b/src/RareItemSet.cc index 35ed1628..2c65e56c 100644 --- a/src/RareItemSet.cc +++ b/src/RareItemSet.cc @@ -330,11 +330,14 @@ RareItemSet::RareItemSet(const phosg::JSON& json, shared_ptr(item_it.first.c_str())); - if (collection.rt_index_to_specs.size() <= index) { - collection.rt_index_to_specs.resize(index + 1); + size_t rt_index = type_definition_for_enemy(phosg::enum_for_name(item_it.first.c_str())).rt_index; + if (rt_index == 0xFF) { + throw runtime_error("enemy type " + item_it.first + " does not have an rt_index"); } - target = &collection.rt_index_to_specs[index]; + if (collection.rt_index_to_specs.size() <= rt_index) { + collection.rt_index_to_specs.resize(rt_index + 1); + } + target = &collection.rt_index_to_specs[rt_index]; } for (const auto& spec_json : item_it.second->as_list()) { @@ -422,6 +425,260 @@ std::string RareItemSet::serialize_gsl(bool big_endian) const { return GSLArchive::generate(files, big_endian); } +string RareItemSet::serialize_html( + GameMode mode, + Episode episode, + uint8_t difficulty, + shared_ptr name_index) const { + + struct ZoneTypes { + const char* name; + vector floors; + vector types; + }; + + // clang-format off + static const std::map> zone_types_for_episode{ + {Episode::EP1, { + {"Forest", {0x01, 0x02, 0x0B}, { + EnemyType::BOOMA, EnemyType::GOBOOMA, EnemyType::GIGOBOOMA, + EnemyType::SAVAGE_WOLF, EnemyType::BARBAROUS_WOLF, + EnemyType::RAG_RAPPY, EnemyType::AL_RAPPY, + EnemyType::MONEST, EnemyType::MOTHMANT, + EnemyType::HILDEBEAR, EnemyType::HILDEBLUE, + EnemyType::DRAGON, + }}, + {"Caves", {0x03, 0x04, 0x05, 0x0C}, { + EnemyType::EVIL_SHARK, EnemyType::PAL_SHARK, EnemyType::GUIL_SHARK, + EnemyType::POISON_LILY, EnemyType::NAR_LILY, + EnemyType::POFUILLY_SLIME, EnemyType::POUILLY_SLIME, + EnemyType::NANO_DRAGON, + EnemyType::GRASS_ASSASSIN, + EnemyType::PAN_ARMS, EnemyType::HIDOOM, EnemyType::MIGIUM, + EnemyType::DE_ROL_LE_BODY, EnemyType::DE_ROL_LE_MINE, EnemyType::DE_ROL_LE, + }}, + {"Mines", {0x06, 0x07, 0x0D}, { + EnemyType::GILLCHIC, EnemyType::DUBCHIC, EnemyType::DUBWITCH, + EnemyType::CANADINE, EnemyType::CANADINE_GROUP, EnemyType::CANANE, + EnemyType::SINOW_BEAT, EnemyType::SINOW_GOLD, + EnemyType::GARANZ, + EnemyType::VOL_OPT_AMP, EnemyType::VOL_OPT_CORE, EnemyType::VOL_OPT_MONITOR, EnemyType::VOL_OPT_PILLAR, EnemyType::VOL_OPT_1, EnemyType::VOL_OPT_2, + }}, + {"Ruins", {0x08, 0x09, 0x0A, 0x0E}, { + EnemyType::DIMENIAN, EnemyType::LA_DIMENIAN, EnemyType::SO_DIMENIAN, + EnemyType::CLAW, EnemyType::BULK, EnemyType::BULCLAW, + EnemyType::DELSABER, + EnemyType::CHAOS_SORCERER, EnemyType::BEE_L, EnemyType::BEE_R, + EnemyType::DARK_BELRA, + EnemyType::DARK_GUNNER, EnemyType::DEATH_GUNNER, + EnemyType::CHAOS_BRINGER, + EnemyType::DARVANT, EnemyType::DARVANT_ULTIMATE, EnemyType::DARK_FALZ_1, EnemyType::DARK_FALZ_2, EnemyType::DARK_FALZ_3, + }}, + }}, + {Episode::EP2, { + {"VR Temple", {0x01, 0x02, 0x0E}, { + EnemyType::RAG_RAPPY, EnemyType::LOVE_RAPPY, EnemyType::EGG_RAPPY, EnemyType::HALLO_RAPPY, EnemyType::SAINT_RAPPY, + EnemyType::DIMENIAN, EnemyType::LA_DIMENIAN, EnemyType::SO_DIMENIAN, + EnemyType::POISON_LILY, EnemyType::NAR_LILY, + EnemyType::MONEST, EnemyType::MOTHMANT, + EnemyType::GRASS_ASSASSIN, + EnemyType::HILDEBEAR, EnemyType::HILDEBLUE, + EnemyType::DARK_BELRA, + EnemyType::PIG_RAY, EnemyType::BARBA_RAY, + }}, + {"VR Spaceship", {0x03, 0x04, 0x0F}, { + EnemyType::SAVAGE_WOLF, EnemyType::BARBAROUS_WOLF, + EnemyType::GILLCHIC, EnemyType::DUBCHIC, EnemyType::DUBWITCH, + EnemyType::PAN_ARMS, EnemyType::HIDOOM, EnemyType::MIGIUM, + EnemyType::DELSABER, + EnemyType::GARANZ, + EnemyType::CHAOS_SORCERER, EnemyType::BEE_L, EnemyType::BEE_R, + EnemyType::GOL_DRAGON, + }}, + {"Central Control Area", {0x05, 0x06, 0x07, 0x08, 0x09, 0x0C, 0x10}, { + EnemyType::MERILLIA, EnemyType::MERILTAS, + EnemyType::GEE, + EnemyType::UL_GIBBON, EnemyType::ZOL_GIBBON, + EnemyType::SINOW_BERILL, EnemyType::SINOW_SPIGELL, + EnemyType::GI_GUE, + EnemyType::GIBBLES, + EnemyType::MERICARAND, EnemyType::MERICAROL, EnemyType::MERICUS, EnemyType::MERIKLE, + EnemyType::GAL_GRYPHON, + }}, + {"Seabed", {0x0A, 0x0B, 0x0D}, { + EnemyType::DOLMOLM, EnemyType::DOLMDARL, + EnemyType::SINOW_ZOA, EnemyType::SINOW_ZELE, + EnemyType::RECOBOX, EnemyType::RECON, + EnemyType::MORFOS, + EnemyType::DELDEPTH, + EnemyType::DELBITER, + EnemyType::GAEL_OR_GIEL, EnemyType::OLGA_FLOW_1, EnemyType::OLGA_FLOW_2, + }}, + {"Control Tower", {0x11}, { + EnemyType::MERICARAND, EnemyType::MERICAROL, EnemyType::MERICUS, EnemyType::MERIKLE, + EnemyType::GIBBLES, + EnemyType::GI_GUE, + EnemyType::DELBITER, + EnemyType::ILL_GILL, + EnemyType::DEL_LILY, + EnemyType::EPSILON, EnemyType::EPSIGARD, + }}, + }}, + {Episode::EP4, { + {"Crater", {0x01, 0x02, 0x03, 0x04, 0x05}, { + EnemyType::SAND_RAPPY_CRATER, EnemyType::DEL_RAPPY_CRATER, + EnemyType::SATELLITE_LIZARD_CRATER, + EnemyType::YOWIE_CRATER, + EnemyType::BOOTA, EnemyType::ZE_BOOTA, EnemyType::BA_BOOTA, + EnemyType::ZU_CRATER, EnemyType::PAZUZU_CRATER, + EnemyType::ASTARK, + EnemyType::DORPHON, EnemyType::DORPHON_ECLAIR, + }}, + {"Desert", {0x06, 0x07, 0x08, 0x09}, { + EnemyType::SAND_RAPPY_DESERT, EnemyType::DEL_RAPPY_DESERT, + EnemyType::SATELLITE_LIZARD_DESERT, + EnemyType::YOWIE_DESERT, + EnemyType::GORAN, EnemyType::PYRO_GORAN, EnemyType::GORAN_DETONATOR, + EnemyType::MERISSA_A, EnemyType::MERISSA_AA, + EnemyType::ZU_DESERT, EnemyType::PAZUZU_DESERT, + EnemyType::GIRTABLULU, + EnemyType::SAINT_MILION, EnemyType::SHAMBERTIN, EnemyType::KONDRIEU, + }}, + }}}; + // clang-format on + + static const std::array bg_colors{ + // Vrd Grn Sky Blu Prp Pnk Red Orn Ylw Wht + 0x00A562, 0x76FE43, 0x59F9F9, 0x4488FF, 0xCC00FF, 0xFF87CB, 0xF70F0F, 0xF7830F, 0xF7F715, 0xFFFFFF}; + static const std::array text_colors{ + // Vrd Grn Sky Blu Prp Pnk Red Orn Ylw Wht + 0xFFFFFF, 0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF, 0x000000, 0xFFFFFF, 0x000000, 0x000000, 0x000000}; + + deque blocks; + blocks.emplace_back(phosg::string_printf("\ +\n\ +\n\ + Drop charts for %s %s\n\ + \n\ +\n"); + + blocks.emplace_back(""); + auto add_location_header = [&](const char* location_name) -> void { + blocks.emplace_back(""); + blocks.emplace_back(""); + for (size_t z = 0; z < 10; z++) { + blocks.emplace_back(phosg::string_printf("", z, name_for_section_id(z))); + } + blocks.emplace_back(""); + }; + + auto add_specs_row = [&](const char* loc_name, const array, 10>& specs_lists) -> void { + bool any_list_nonempty = false; + for (const auto& specs_list : specs_lists) { + any_list_nonempty |= !specs_list.empty(); + } + if (!any_list_nonempty) { + return; + } + + blocks.emplace_back(phosg::string_printf("", loc_name)); + for (uint8_t section_id = 0; section_id < 10; section_id++) { + blocks.emplace_back(phosg::string_printf(""); + } + blocks.emplace_back(""); + }; + + const auto& zone_types = zone_types_for_episode.at(episode); + for (const auto& zone_type : zone_types) { + add_location_header(zone_type.name); + for (EnemyType type : zone_type.types) { + uint8_t rt_index = type_definition_for_enemy(type).rt_index; + if (rt_index == 0xFF) { + continue; + } + array, 10> specs_lists; + for (uint8_t section_id = 0; section_id < 10; section_id++) { + specs_lists[section_id] = this->get_enemy_specs(mode, episode, difficulty, section_id, rt_index); + } + add_specs_row(phosg::name_for_enum(type), specs_lists); + } + for (uint8_t floor : zone_type.floors) { + array, 10> specs_lists; + for (uint8_t section_id = 0; section_id < 10; section_id++) { + specs_lists[section_id] = this->get_box_specs(mode, episode, difficulty, section_id, floor); + } + auto loc_name = phosg::string_printf("%s (box)", name_for_floor(episode, floor)); + add_specs_row(loc_name.c_str(), specs_lists); + } + } + blocks.emplace_back("
"); + blocks.emplace_back(location_name); + blocks.emplace_back("%s
%s", section_id)); + vector tokens; + for (const auto& spec : specs_lists[section_id]) { + auto frac = phosg::reduce_fraction(spec.probability, 0x100000000); + + ItemData example_item = spec.data; + if (example_item.can_be_encoded_in_rel_rare_table()) { + if (example_item.data1[0] == 2) { + example_item.data1[1] = 0x00; + example_item.assign_mag_stats(ItemMagStats()); + } else if (example_item.data1[0] == 3) { + example_item.set_tool_item_amount(ItemData::StackLimits::DEFAULT_STACK_LIMITS_V3_V4, 1); + } + } + + tokens.emplace_back(name_index->describe_item(example_item, false, true)); + float denom = static_cast(frac.second) / static_cast(frac.first); + string denom_token = (floor(denom) == denom) + ? phosg::string_printf("1 / %g", denom) + : phosg::string_printf("1 / %.02f", denom); + tokens.emplace_back(phosg::string_printf( + "%s", + frac.first, frac.second, denom_token.c_str())); + } + if (!blocks.empty()) { + blocks.emplace_back(phosg::join(tokens, "
")); + } + blocks.emplace_back("
"); + + return phosg::join(blocks, ""); +} + phosg::JSON RareItemSet::json(shared_ptr name_index) const { auto modes_dict = phosg::JSON::dict(); static const array modes = {GameMode::NORMAL, GameMode::BATTLE, GameMode::CHALLENGE, GameMode::SOLO}; @@ -455,7 +712,7 @@ phosg::JSON RareItemSet::json(shared_ptr name_index) const spec_json.emplace_back(name_index->describe_item(spec.data)); } for (const auto& enemy_type : enemy_types) { - if (enemy_type_valid_for_episode(episode, enemy_type)) { + if (type_definition_for_enemy(enemy_type).valid_in_episode(episode)) { phosg::JSON this_spec_json = spec_json; collection_dict.emplace(phosg::name_for_enum(enemy_type), phosg::JSON::list()).first->second->emplace_back(std::move(this_spec_json)); } diff --git a/src/RareItemSet.hh b/src/RareItemSet.hh index 77635de0..738216c2 100644 --- a/src/RareItemSet.hh +++ b/src/RareItemSet.hh @@ -37,6 +37,11 @@ public: std::string serialize_afs(bool is_v1) const; std::string serialize_gsl(bool big_endian) const; + std::string serialize_html( + GameMode mode, + Episode episode, + uint8_t difficulty, + std::shared_ptr name_index = nullptr) const; phosg::JSON json(std::shared_ptr name_index = nullptr) const; void multiply_all_rates(double factor); diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index f3f12b22..3ccf4fe6 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -2808,7 +2808,7 @@ DropReconcileResult reconcile_drop_request_with_map( res.ene_st = map->enemy_state_for_index(version, cmd.floor, cmd.entity_index); EnemyType type = res.ene_st->type(version, episode, event); log.info("Drop check for E-%03zX %s", res.ene_st->e_id, phosg::name_for_enum(type)); - res.effective_rt_index = rare_table_index_for_enemy_type(type); + res.effective_rt_index = type_definition_for_enemy(type).rt_index; // rt_indexes in Episode 4 don't match those sent in the command; we just // ignore what the client sends. if ((episode != Episode::EP4) && (cmd.rt_index != res.effective_rt_index)) { @@ -3106,7 +3106,7 @@ static void on_set_quest_flag(shared_ptr c, uint8_t command, uint8_t fla { {0x60, 0x06, 0x0000}, static_cast(c->floor), - rare_table_index_for_enemy_type(boss_enemy_type), + type_definition_for_enemy(boss_enemy_type).rt_index, enemy_index == 0xFFFF ? 0x0B4F : enemy_index, pos, 2, @@ -3758,7 +3758,7 @@ static uint32_t base_exp_for_enemy_type( for (const auto& episode : episode_order) { try { const auto& bp_table = bp_index->get_table(is_solo, episode); - uint32_t bp_index = battle_param_index_for_enemy_type(episode, enemy_type); + uint32_t bp_index = type_definition_for_enemy(enemy_type).bp_index; return bp_table.stats[difficulty][bp_index].experience; } catch (const out_of_range&) { } diff --git a/src/SaveFileFormats.cc b/src/SaveFileFormats.cc index 200c9e73..98a22ca0 100644 --- a/src/SaveFileFormats.cc +++ b/src/SaveFileFormats.cc @@ -1161,7 +1161,7 @@ PSOBBCharacterFile::operator PSOXBCharacterFileCharacter() const { return ret; } -LoadedPSOCHARFile load_psochar(const string& filename, bool load_system) { +PSOCHARFile::LoadSharedResult PSOCHARFile::load_shared(const string& filename, bool load_system) { auto f = phosg::fopen_unique(filename, "rb"); auto header = phosg::freadx(f.get()); if (header.size != 0x399C) { @@ -1175,7 +1175,7 @@ LoadedPSOCHARFile load_psochar(const string& filename, bool load_system) { } static_assert(sizeof(PSOBBCharacterFile) + sizeof(PSOBBBaseSystemFile) + sizeof(PSOBBTeamMembership) == 0x3994, ".psochar size is incorrect"); - LoadedPSOCHARFile ret; + LoadSharedResult ret; ret.character_file = make_shared(phosg::freadx(f.get())); if (load_system) { ret.system_file = make_shared(phosg::freadx(f.get())); @@ -1183,7 +1183,7 @@ LoadedPSOCHARFile load_psochar(const string& filename, bool load_system) { return ret; } -void save_psochar( +void PSOCHARFile::save( const std::string& filename, std::shared_ptr system, std::shared_ptr character) { diff --git a/src/SaveFileFormats.hh b/src/SaveFileFormats.hh index 9de3e617..e411fe1e 100644 --- a/src/SaveFileFormats.hh +++ b/src/SaveFileFormats.hh @@ -749,8 +749,9 @@ struct PSOXBCharacterFileCharacter { struct PSOBBCharacterFile { // Most fields have the same meanings as in PSOGCCharacterFile::Character. - // This is the character data used by the server for all game versions, and - // is also the format used in .psochar files. + // This is part of the .psochar file format, but it is not the first member + // of that structure, so add 8 to all the offsets here if you're working with + // a .psochar file. See PSOCHARFile below for the full file format. /* 0000 */ PlayerInventory inventory; /* 034C */ PlayerDispDataBB disp; @@ -838,17 +839,28 @@ struct PSOBBCharacterFile { void recompute_stats(std::shared_ptr level_table); } __packed_ws__(PSOBBCharacterFile, 0x2EA4); -struct LoadedPSOCHARFile { - std::shared_ptr system_file; // Null if load_system is false - std::shared_ptr character_file; // Never null - // Team membership is present in the file, but ignored by newserv -}; +struct PSOCHARFile { + // This is the format of .psochar files used by newserv and Ephinea (and + // perhaps other servers as well). newserv doesn't actually use this + // structure in its logic, so it's here primarily for documentation. -LoadedPSOCHARFile load_psochar(const std::string& filename, bool load_system); -void save_psochar( - const std::string& filename, - std::shared_ptr system, - std::shared_ptr character); + /* 0000 */ PSOCommandHeaderBB header; // command = 0x00E7, size = 0x399C, flag = 0 + /* 0008 */ PSOBBCharacterFile character; + /* 2EAC */ PSOBBBaseSystemFile system; + /* 3164 */ PSOBBTeamMembership team_membership; + /* 399C */ + + struct LoadSharedResult { + std::shared_ptr character_file; // Never null + std::shared_ptr system_file; // Null if load_system is false + // Team membership is present in the file, but newserv ignores it + }; + static LoadSharedResult load_shared(const std::string& filename, bool load_system); + static void save( + const std::string& filename, + std::shared_ptr system, + std::shared_ptr character); +} __packed_ws__(PSOCHARFile, 0x399C); //////////////////////////////////////////////////////////////////////////////// // Guild Card files diff --git a/system/item-tables/rare-table-v4.json b/system/item-tables/rare-table-v4.json index afacf25d..29987685 100644 --- a/system/item-tables/rare-table-v4.json +++ b/system/item-tables/rare-table-v4.json @@ -6782,8 +6782,8 @@ ["7/1024", 0x000B02] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000806]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x000B06]], @@ -6792,18 +6792,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000405]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x008901]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000D00]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000D00]], - "YOWIE": [["7/2048", 0x000205]], - "YOWIE_ALT": [["7/2048", 0x000205]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000D00]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000D00]], + "YOWIE_CRATER": [["7/2048", 0x000205]], + "YOWIE_DESERT": [["7/2048", 0x000205]], "ZE_BOOTA": [["11/2048", 0x000A05]], - "ZU": [["7/1024", 0x000406]], - "ZU_ALT": [["7/1024", 0x000406]], + "ZU_CRATER": [["7/1024", 0x000406]], + "ZU_DESERT": [["7/1024", 0x000406]], }, "Greennill": { "ASTARK": [["1/256", 0x000707]], @@ -6825,8 +6825,8 @@ ["7/1024", 0x000304] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000605]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x001400]], @@ -6835,18 +6835,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000705]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000306]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000D00]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000D00]], - "YOWIE": [["7/2048", 0x000307]], - "YOWIE_ALT": [["7/2048", 0x000307]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000D00]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000D00]], + "YOWIE_CRATER": [["7/2048", 0x000307]], + "YOWIE_DESERT": [["7/2048", 0x000307]], "ZE_BOOTA": [["11/2048", 0x000606]], - "ZU": [["7/1024", 0x000706]], - "ZU_ALT": [["7/1024", 0x000706]], + "ZU_CRATER": [["7/1024", 0x000706]], + "ZU_DESERT": [["7/1024", 0x000706]], }, "Oran": { "ASTARK": [["1/256", 0x000105]], @@ -6868,8 +6868,8 @@ ["7/1024", 0x000204] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000307]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x005600]], @@ -6878,18 +6878,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000A04]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000607]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000D00]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000D00]], - "YOWIE": [["7/2048", 0x000F01]], - "YOWIE_ALT": [["7/2048", 0x000F01]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000D00]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000D00]], + "YOWIE_CRATER": [["7/2048", 0x000F01]], + "YOWIE_DESERT": [["7/2048", 0x000F01]], "ZE_BOOTA": [["11/2048", 0x000305]], - "ZU": [["7/1024", 0x000606]], - "ZU_ALT": [["7/1024", 0x000606]], + "ZU_CRATER": [["7/1024", 0x000606]], + "ZU_DESERT": [["7/1024", 0x000606]], }, "Pinkal": { "ASTARK": [["1/256", 0x008C00]], @@ -6911,8 +6911,8 @@ ["7/1024", 0x000C03] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000805]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x000F01]], @@ -6921,18 +6921,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000A06]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000606]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000D00]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000D00]], - "YOWIE": [["7/2048", 0x000A04]], - "YOWIE_ALT": [["7/2048", 0x000A04]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000D00]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000D00]], + "YOWIE_CRATER": [["7/2048", 0x000A04]], + "YOWIE_DESERT": [["7/2048", 0x000A04]], "ZE_BOOTA": [["11/2048", 0x000F00]], - "ZU": [["7/1024", 0x000C06]], - "ZU_ALT": [["7/1024", 0x000C06]], + "ZU_CRATER": [["7/1024", 0x000C06]], + "ZU_DESERT": [["7/1024", 0x000C06]], }, "Purplenum": { "ASTARK": [["1/256", 0x000606]], @@ -6954,8 +6954,8 @@ ["7/1024", 0x000304] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000307]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x001400]], @@ -6964,18 +6964,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000805]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x00CD00]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000606]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000606]], - "YOWIE": [["7/2048", 0x000A04]], - "YOWIE_ALT": [["7/2048", 0x000A04]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000606]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000606]], + "YOWIE_CRATER": [["7/2048", 0x000A04]], + "YOWIE_DESERT": [["7/2048", 0x000A04]], "ZE_BOOTA": [["11/2048", 0x000A06]], - "ZU": [["7/1024", 0x000306]], - "ZU_ALT": [["7/1024", 0x000306]], + "ZU_CRATER": [["7/1024", 0x000306]], + "ZU_DESERT": [["7/1024", 0x000306]], }, "Redria": { "ASTARK": [["1/256", 0x008B01]], @@ -6997,8 +6997,8 @@ ["7/1024", 0x000504] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000E01]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x008902]], @@ -7007,18 +7007,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000507]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000505]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000F01]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000F01]], - "YOWIE": [["7/2048", 0x000E00]], - "YOWIE_ALT": [["7/2048", 0x000E00]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000F01]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000F01]], + "YOWIE_CRATER": [["7/2048", 0x000E00]], + "YOWIE_DESERT": [["7/2048", 0x000E00]], "ZE_BOOTA": [["11/2048", 0x000F00]], - "ZU": [["7/1024", 0x000607]], - "ZU_ALT": [["7/1024", 0x000607]], + "ZU_CRATER": [["7/1024", 0x000607]], + "ZU_DESERT": [["7/1024", 0x000607]], }, "Skyly": { "ASTARK": [["1/256", 0x000E00]], @@ -7040,8 +7040,8 @@ ["7/1024", 0x000204] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000E01]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x000E02]], @@ -7050,18 +7050,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000106]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000305]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000705]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000705]], - "YOWIE": [["7/2048", 0x000E00]], - "YOWIE_ALT": [["7/2048", 0x000E00]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000705]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000705]], + "YOWIE_CRATER": [["7/2048", 0x000E00]], + "YOWIE_DESERT": [["7/2048", 0x000E00]], "ZE_BOOTA": [["11/2048", 0x000B04]], - "ZU": [["7/1024", 0x000105]], - "ZU_ALT": [["7/1024", 0x000105]], + "ZU_CRATER": [["7/1024", 0x000105]], + "ZU_DESERT": [["7/1024", 0x000105]], }, "Viridia": { "ASTARK": [["1/256", 0x000105]], @@ -7083,8 +7083,8 @@ ["7/1024", 0x000404] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000906]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x001400]], @@ -7093,18 +7093,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000D00]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000407]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000406]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000406]], - "YOWIE": [["7/2048", 0x000405]], - "YOWIE_ALT": [["7/2048", 0x000405]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000406]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000406]], + "YOWIE_CRATER": [["7/2048", 0x000405]], + "YOWIE_DESERT": [["7/2048", 0x000405]], "ZE_BOOTA": [["11/2048", 0x000605]], - "ZU": [["7/1024", 0x000207]], - "ZU_ALT": [["7/1024", 0x000207]], + "ZU_CRATER": [["7/1024", 0x000207]], + "ZU_DESERT": [["7/1024", 0x000207]], }, "Whitill": { "ASTARK": [["1/256", 0x000205]], @@ -7126,8 +7126,8 @@ ["7/1024", 0x000504] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000906]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x000E02]], @@ -7136,18 +7136,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000507]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000F01]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000E00]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000E00]], - "YOWIE": [["7/2048", 0x000806]], - "YOWIE_ALT": [["7/2048", 0x000806]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000E00]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000E00]], + "YOWIE_CRATER": [["7/2048", 0x000806]], + "YOWIE_DESERT": [["7/2048", 0x000806]], "ZE_BOOTA": [["11/2048", 0x000605]], - "ZU": [["7/1024", 0x000306]], - "ZU_ALT": [["7/1024", 0x000306]], + "ZU_CRATER": [["7/1024", 0x000306]], + "ZU_DESERT": [["7/1024", 0x000306]], }, "Yellowboze": { "ASTARK": [["1/256", 0x000606]], @@ -7167,8 +7167,8 @@ ["7/1024", 0x030F00] ], "Box-Desert3": [["5/4096", 0x01014D]], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["13/2048", 0x000607]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GIRTABLULU": [["13/1024", 0x000E02]], @@ -7177,18 +7177,18 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/2048", 0x000F01]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], "PYRO_GORAN": [["9/1024", 0x000A04]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], - "SATELLITE_LIZARD": [["7/2048", 0x000D00]], - "SATELLITE_LIZARD_ALT": [["7/2048", 0x000D00]], - "YOWIE": [["7/2048", 0x000605]], - "YOWIE_ALT": [["7/2048", 0x000605]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/2048", 0x000D00]], + "SATELLITE_LIZARD_DESERT": [["7/2048", 0x000D00]], + "YOWIE_CRATER": [["7/2048", 0x000605]], + "YOWIE_DESERT": [["7/2048", 0x000605]], "ZE_BOOTA": [["11/2048", 0x000107]], - "ZU": [["7/1024", 0x000C06]], - "ZU_ALT": [["7/1024", 0x000C06]], + "ZU_CRATER": [["7/1024", 0x000C06]], + "ZU_DESERT": [["7/1024", 0x000C06]], } }, "Normal": { @@ -7217,17 +7217,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Greennill": { "Box-CraterInterior": [ @@ -7254,17 +7254,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Oran": { "Box-CraterInterior": [ @@ -7291,17 +7291,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Pinkal": { "Box-CraterInterior": [ @@ -7328,17 +7328,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Purplenum": { "Box-CraterInterior": [ @@ -7365,17 +7365,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Redria": { "Box-CraterInterior": [ @@ -7402,17 +7402,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Skyly": { "Box-CraterInterior": [ @@ -7439,17 +7439,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Viridia": { "Box-CraterInterior": [ @@ -7476,17 +7476,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Whitill": { "Box-CraterInterior": [ @@ -7513,17 +7513,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], }, "Yellowboze": { "Box-CraterEast": [["13/8192", 0x030F00]], @@ -7546,17 +7546,17 @@ ["13/8192", 0x030F00], ["5/4096", 0x010153] ], - "DEL_RAPPY": [["9/16", 0x031002]], - "DEL_RAPPY_ALT": [["9/16", 0x031002]], + "DEL_RAPPY_CRATER": [["9/16", 0x031002]], + "DEL_RAPPY_DESERT": [["9/16", 0x031002]], "DORPHON": [["5/512", 0x031002]], "DORPHON_ECLAIR": [["9/16", 0x031002]], "GORAN_DETONATOR": [["9/1024", 0x030F00]], "KONDRIEU": [["13/128", 0x031002]], "MERISSA_AA": [["11/16", 0x031002]], - "PAZUZU": [["9/16", 0x031002]], - "PAZUZU_ALT": [["9/16", 0x031002]], - "SAND_RAPPY": [["1/512", 0x031807]], - "SAND_RAPPY_ALT": [["1/512", 0x031807]], + "PAZUZU_CRATER": [["9/16", 0x031002]], + "PAZUZU_DESERT": [["9/16", 0x031002]], + "SAND_RAPPY_CRATER": [["1/512", 0x031807]], + "SAND_RAPPY_DESERT": [["1/512", 0x031807]], } }, "Ultimate": { @@ -7604,8 +7604,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x010353]], - "DEL_RAPPY_ALT": [["11/32", 0x010353]], + "DEL_RAPPY_CRATER": [["11/32", 0x010353]], + "DEL_RAPPY_DESERT": [["11/32", 0x010353]], "DORPHON": [["9/2048", 0x010136]], "DORPHON_ECLAIR": [["11/32", 0x000408]], "GIRTABLULU": [["1/256", 0x00AA00]], @@ -7614,20 +7614,20 @@ "KONDRIEU": [["13/128", 0x00BF00]], "MERISSA_A": [["9/4096", 0x00070C]], "MERISSA_AA": [["7/16", 0x00CB00]], - "PAZUZU": [["11/32", 0x00C400]], - "PAZUZU_ALT": [["11/32", 0x00C400]], + "PAZUZU_CRATER": [["11/32", 0x00C400]], + "PAZUZU_DESERT": [["11/32", 0x00C400]], "PYRO_GORAN": [["5/2048", 0x00CD00]], - "SAINT_MILLION": [["3/256", 0x031803]], - "SAND_RAPPY": [["5/4096", 0x010154]], - "SAND_RAPPY_ALT": [["5/4096", 0x010154]], - "SATELLITE_LIZARD": [["1/512", 0x00C500]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00C500]], + "SAINT_MILION": [["3/256", 0x031803]], + "SAND_RAPPY_CRATER": [["5/4096", 0x010154]], + "SAND_RAPPY_DESERT": [["5/4096", 0x010154]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00C500]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00C500]], "SHAMBERTIN": [["7/512", 0x031803]], - "YOWIE": [["1/512", 0x010299]], - "YOWIE_ALT": [["1/512", 0x010299]], + "YOWIE_CRATER": [["1/512", 0x010299]], + "YOWIE_DESERT": [["1/512", 0x010299]], "ZE_BOOTA": [["13/4096", 0x000D03]], - "ZU": [["5/2048", 0x010137]], - "ZU_ALT": [["5/2048", 0x010137]], + "ZU_CRATER": [["5/2048", 0x010137]], + "ZU_DESERT": [["5/2048", 0x010137]], }, "Greennill": { "ASTARK": [["1/512", 0x00B400]], @@ -7673,8 +7673,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x00070D]], - "DEL_RAPPY_ALT": [["11/32", 0x00070D]], + "DEL_RAPPY_CRATER": [["11/32", 0x00070D]], + "DEL_RAPPY_DESERT": [["11/32", 0x00070D]], "DORPHON": [["9/2048", 0x00D200]], "DORPHON_ECLAIR": [["11/32", 0x00C000]], "GIRTABLULU": [["1/256", 0x010299]], @@ -7683,20 +7683,20 @@ "KONDRIEU": [["13/128", 0x010286]], "MERISSA_A": [["9/4096", 0x00AF00]], "MERISSA_AA": [["7/16", 0x010288]], - "PAZUZU": [["11/32", 0x00070A]], - "PAZUZU_ALT": [["11/32", 0x00070A]], + "PAZUZU_CRATER": [["11/32", 0x00070A]], + "PAZUZU_DESERT": [["11/32", 0x00070A]], "PYRO_GORAN": [["5/2048", 0x01014C]], - "SAINT_MILLION": [["3/256", 0x010287]], - "SAND_RAPPY": [["5/4096", 0x010354]], - "SAND_RAPPY_ALT": [["5/4096", 0x010354]], - "SATELLITE_LIZARD": [["1/512", 0x00BE00]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00BE00]], + "SAINT_MILION": [["3/256", 0x010287]], + "SAND_RAPPY_CRATER": [["5/4096", 0x010354]], + "SAND_RAPPY_DESERT": [["5/4096", 0x010354]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00BE00]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00BE00]], "SHAMBERTIN": [["7/512", 0x010289]], - "YOWIE": [["1/512", 0x000D03]], - "YOWIE_ALT": [["1/512", 0x000D03]], + "YOWIE_CRATER": [["1/512", 0x000D03]], + "YOWIE_DESERT": [["1/512", 0x000D03]], "ZE_BOOTA": [["13/4096", 0x000705]], - "ZU": [["5/2048", 0x010137]], - "ZU_ALT": [["5/2048", 0x010137]], + "ZU_CRATER": [["5/2048", 0x010137]], + "ZU_DESERT": [["5/2048", 0x010137]], }, "Oran": { "ASTARK": [["13/8192", 0x01034B]], @@ -7742,8 +7742,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x010149]], - "DEL_RAPPY_ALT": [["11/32", 0x010149]], + "DEL_RAPPY_CRATER": [["11/32", 0x010149]], + "DEL_RAPPY_DESERT": [["11/32", 0x010149]], "DORPHON": [["9/2048", 0x000308]], "DORPHON_ECLAIR": [["11/32", 0x00070B]], "GIRTABLULU": [["1/256", 0x00AB00]], @@ -7752,20 +7752,20 @@ "KONDRIEU": [["13/128", 0x00C800]], "MERISSA_A": [["1/512", 0x01034A]], "MERISSA_AA": [["7/16", 0x00BC00]], - "PAZUZU": [["11/32", 0x00B300]], - "PAZUZU_ALT": [["11/32", 0x00B300]], + "PAZUZU_CRATER": [["11/32", 0x00B300]], + "PAZUZU_DESERT": [["11/32", 0x00B300]], "PYRO_GORAN": [["5/2048", 0x000C07]], - "SAINT_MILLION": [["3/256", 0x00C800]], - "SAND_RAPPY": [["5/4096", 0x01014D]], - "SAND_RAPPY_ALT": [["5/4096", 0x01014D]], - "SATELLITE_LIZARD": [["1/512", 0x00AA00]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00AA00]], + "SAINT_MILION": [["3/256", 0x00C800]], + "SAND_RAPPY_CRATER": [["5/4096", 0x01014D]], + "SAND_RAPPY_DESERT": [["5/4096", 0x01014D]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00AA00]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00AA00]], "SHAMBERTIN": [["7/512", 0x00B700]], - "YOWIE": [["1/512", 0x01014F]], - "YOWIE_ALT": [["1/512", 0x01014F]], + "YOWIE_CRATER": [["1/512", 0x01014F]], + "YOWIE_DESERT": [["1/512", 0x01014F]], "ZE_BOOTA": [["13/4096", 0x010139]], - "ZU": [["5/2048", 0x010137]], - "ZU_ALT": [["5/2048", 0x010137]], + "ZU_CRATER": [["5/2048", 0x010137]], + "ZU_DESERT": [["5/2048", 0x010137]], }, "Pinkal": { "ASTARK": [["1/512", 0x000C07]], @@ -7811,8 +7811,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x00C300]], - "DEL_RAPPY_ALT": [["11/32", 0x00C300]], + "DEL_RAPPY_CRATER": [["11/32", 0x00C300]], + "DEL_RAPPY_DESERT": [["11/32", 0x00C300]], "DORPHON": [["9/2048", 0x000408]], "DORPHON_ECLAIR": [["11/32", 0x010287]], "GIRTABLULU": [["1/256", 0x00C400]], @@ -7821,20 +7821,20 @@ "KONDRIEU": [["13/128", 0x010143]], "MERISSA_A": [["1/512", 0x01034A]], "MERISSA_AA": [["7/16", 0x010147]], - "PAZUZU": [["11/32", 0x01034C]], - "PAZUZU_ALT": [["11/32", 0x01034C]], + "PAZUZU_CRATER": [["11/32", 0x01034C]], + "PAZUZU_DESERT": [["11/32", 0x01034C]], "PYRO_GORAN": [["5/2048", 0x031002]], - "SAINT_MILLION": [["3/256", 0x00C200]], - "SAND_RAPPY": [["5/4096", 0x010135]], - "SAND_RAPPY_ALT": [["5/4096", 0x010135]], - "SATELLITE_LIZARD": [["1/512", 0x00C500]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00C500]], + "SAINT_MILION": [["3/256", 0x00C200]], + "SAND_RAPPY_CRATER": [["5/4096", 0x010135]], + "SAND_RAPPY_DESERT": [["5/4096", 0x010135]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00C500]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00C500]], "SHAMBERTIN": [["7/512", 0x010142]], - "YOWIE": [["1/512", 0x000709]], - "YOWIE_ALT": [["1/512", 0x000709]], + "YOWIE_CRATER": [["1/512", 0x000709]], + "YOWIE_DESERT": [["1/512", 0x000709]], "ZE_BOOTA": [["13/4096", 0x00C900]], - "ZU": [["5/2048", 0x010351]], - "ZU_ALT": [["5/2048", 0x010351]], + "ZU_CRATER": [["5/2048", 0x010351]], + "ZU_DESERT": [["5/2048", 0x010351]], }, "Purplenum": { "ASTARK": [["1/512", 0x01028A]], @@ -7880,8 +7880,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x01013B]], - "DEL_RAPPY_ALT": [["11/32", 0x01013B]], + "DEL_RAPPY_CRATER": [["11/32", 0x01013B]], + "DEL_RAPPY_DESERT": [["11/32", 0x01013B]], "DORPHON": [["9/2048", 0x010135]], "DORPHON_ECLAIR": [["11/32", 0x00B400]], "GIRTABLULU": [["5/4096", 0x01034F]], @@ -7890,20 +7890,20 @@ "KONDRIEU": [["13/128", 0x00BF00]], "MERISSA_A": [["9/4096", 0x008B03]], "MERISSA_AA": [["7/16", 0x010288]], - "PAZUZU": [["11/32", 0x00AF00]], - "PAZUZU_ALT": [["11/32", 0x00AF00]], + "PAZUZU_CRATER": [["11/32", 0x00AF00]], + "PAZUZU_DESERT": [["11/32", 0x00AF00]], "PYRO_GORAN": [["5/2048", 0x00CD00]], - "SAINT_MILLION": [["3/256", 0x010289]], - "SAND_RAPPY": [["5/4096", 0x01013A]], - "SAND_RAPPY_ALT": [["5/4096", 0x01013A]], - "SATELLITE_LIZARD": [["1/512", 0x00C500]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00C500]], + "SAINT_MILION": [["3/256", 0x010289]], + "SAND_RAPPY_CRATER": [["5/4096", 0x01013A]], + "SAND_RAPPY_DESERT": [["5/4096", 0x01013A]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00C500]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00C500]], "SHAMBERTIN": [["7/512", 0x01013A]], - "YOWIE": [["1/512", 0x00BB00]], - "YOWIE_ALT": [["1/512", 0x00BB00]], + "YOWIE_CRATER": [["1/512", 0x00BB00]], + "YOWIE_DESERT": [["1/512", 0x00BB00]], "ZE_BOOTA": [["13/4096", 0x010139]], - "ZU": [["11/8192", 0x010349]], - "ZU_ALT": [["11/8192", 0x010349]], + "ZU_CRATER": [["11/8192", 0x010349]], + "ZU_DESERT": [["11/8192", 0x010349]], }, "Redria": { "ASTARK": [["1/512", 0x010348]], @@ -7949,8 +7949,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x010143]], - "DEL_RAPPY_ALT": [["11/32", 0x010143]], + "DEL_RAPPY_CRATER": [["11/32", 0x010143]], + "DEL_RAPPY_DESERT": [["11/32", 0x010143]], "DORPHON": [["9/2048", 0x010286]], "DORPHON_ECLAIR": [["11/32", 0x010148]], "GIRTABLULU": [["1/256", 0x000B07]], @@ -7959,20 +7959,20 @@ "KONDRIEU": [["13/128", 0x010289]], "MERISSA_A": [["9/4096", 0x000709]], "MERISSA_AA": [["7/16", 0x00B900]], - "PAZUZU": [["11/32", 0x01034C]], - "PAZUZU_ALT": [["11/32", 0x01034C]], + "PAZUZU_CRATER": [["11/32", 0x01034C]], + "PAZUZU_DESERT": [["11/32", 0x01034C]], "PYRO_GORAN": [["5/2048", 0x00D200]], - "SAINT_MILLION": [["3/256", 0x010141]], - "SAND_RAPPY": [["5/4096", 0x010142]], - "SAND_RAPPY_ALT": [["5/4096", 0x010142]], - "SATELLITE_LIZARD": [["1/512", 0x00C000]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00C000]], + "SAINT_MILION": [["3/256", 0x010141]], + "SAND_RAPPY_CRATER": [["5/4096", 0x010142]], + "SAND_RAPPY_DESERT": [["5/4096", 0x010142]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00C000]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00C000]], "SHAMBERTIN": [["7/512", 0x010228]], - "YOWIE": [["1/512", 0x010288]], - "YOWIE_ALT": [["1/512", 0x010288]], + "YOWIE_CRATER": [["1/512", 0x010288]], + "YOWIE_DESERT": [["1/512", 0x010288]], "ZE_BOOTA": [["13/4096", 0x010139]], - "ZU": [["5/2048", 0x010137]], - "ZU_ALT": [["5/2048", 0x010137]], + "ZU_CRATER": [["5/2048", 0x010137]], + "ZU_DESERT": [["5/2048", 0x010137]], }, "Skyly": { "ASTARK": [["1/512", 0x00C600]], @@ -8018,8 +8018,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x01035A]], - "DEL_RAPPY_ALT": [["11/32", 0x01035A]], + "DEL_RAPPY_CRATER": [["11/32", 0x01035A]], + "DEL_RAPPY_DESERT": [["11/32", 0x01035A]], "DORPHON": [["9/2048", 0x010136]], "DORPHON_ECLAIR": [["11/32", 0x00B600]], "GIRTABLULU": [["1/256", 0x010285]], @@ -8028,20 +8028,20 @@ "KONDRIEU": [["13/128", 0x01013B]], "MERISSA_A": [["9/4096", 0x00AA00]], "MERISSA_AA": [["7/16", 0x00B900]], - "PAZUZU": [["11/32", 0x00B300]], - "PAZUZU_ALT": [["11/32", 0x00B300]], + "PAZUZU_CRATER": [["11/32", 0x00B300]], + "PAZUZU_DESERT": [["11/32", 0x00B300]], "PYRO_GORAN": [["5/4096", 0x010352]], - "SAINT_MILLION": [["3/256", 0x002001]], - "SAND_RAPPY": [["5/4096", 0x00B700]], - "SAND_RAPPY_ALT": [["5/4096", 0x00B700]], - "SATELLITE_LIZARD": [["1/512", 0x00BA00]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00BA00]], + "SAINT_MILION": [["3/256", 0x002001]], + "SAND_RAPPY_CRATER": [["5/4096", 0x00B700]], + "SAND_RAPPY_DESERT": [["5/4096", 0x00B700]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00BA00]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00BA00]], "SHAMBERTIN": [["7/512", 0x01013A]], - "YOWIE": [["1/512", 0x00BB00]], - "YOWIE_ALT": [["1/512", 0x00BB00]], + "YOWIE_CRATER": [["1/512", 0x00BB00]], + "YOWIE_DESERT": [["1/512", 0x00BB00]], "ZE_BOOTA": [["13/4096", 0x010152]], - "ZU": [["5/2048", 0x010351]], - "ZU_ALT": [["5/2048", 0x010351]], + "ZU_CRATER": [["5/2048", 0x010351]], + "ZU_DESERT": [["5/2048", 0x010351]], }, "Viridia": { "ASTARK": [["1/512", 0x01028A]], @@ -8087,8 +8087,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x010353]], - "DEL_RAPPY_ALT": [["11/32", 0x010353]], + "DEL_RAPPY_CRATER": [["11/32", 0x010353]], + "DEL_RAPPY_DESERT": [["11/32", 0x010353]], "DORPHON": [["9/2048", 0x010285]], "DORPHON_ECLAIR": [["11/32", 0x00B600]], "GIRTABLULU": [["5/4096", 0x01034D]], @@ -8097,20 +8097,20 @@ "KONDRIEU": [["13/128", 0x01035B]], "MERISSA_A": [["1/512", 0x01034A]], "MERISSA_AA": [["7/16", 0x001402]], - "PAZUZU": [["11/32", 0x000709]], - "PAZUZU_ALT": [["11/32", 0x000709]], + "PAZUZU_CRATER": [["11/32", 0x000709]], + "PAZUZU_DESERT": [["11/32", 0x000709]], "PYRO_GORAN": [["5/2048", 0x01014C]], - "SAINT_MILLION": [["3/256", 0x01035A]], - "SAND_RAPPY": [["5/4096", 0x010354]], - "SAND_RAPPY_ALT": [["5/4096", 0x010354]], - "SATELLITE_LIZARD": [["1/512", 0x00BA00]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00BA00]], + "SAINT_MILION": [["3/256", 0x01035A]], + "SAND_RAPPY_CRATER": [["5/4096", 0x010354]], + "SAND_RAPPY_DESERT": [["5/4096", 0x010354]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00BA00]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00BA00]], "SHAMBERTIN": [["7/512", 0x00AB00]], - "YOWIE": [["1/512", 0x01014F]], - "YOWIE_ALT": [["1/512", 0x01014F]], + "YOWIE_CRATER": [["1/512", 0x01014F]], + "YOWIE_DESERT": [["1/512", 0x01014F]], "ZE_BOOTA": [["13/4096", 0x010152]], - "ZU": [["11/8192", 0x010349]], - "ZU_ALT": [["11/8192", 0x010349]], + "ZU_CRATER": [["11/8192", 0x010349]], + "ZU_DESERT": [["11/8192", 0x010349]], }, "Whitill": { "ASTARK": [["1/512", 0x010348]], @@ -8156,8 +8156,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x00AF00]], - "DEL_RAPPY_ALT": [["11/32", 0x00AF00]], + "DEL_RAPPY_CRATER": [["11/32", 0x00AF00]], + "DEL_RAPPY_DESERT": [["11/32", 0x00AF00]], "DORPHON": [["9/2048", 0x010136]], "DORPHON_ECLAIR": [["11/32", 0x00B600]], "GIRTABLULU": [["1/256", 0x00AA00]], @@ -8166,20 +8166,20 @@ "KONDRIEU": [["13/128", 0x010150]], "MERISSA_A": [["1/512", 0x01034A]], "MERISSA_AA": [["7/16", 0x01034B]], - "PAZUZU": [["11/32", 0x000D03]], - "PAZUZU_ALT": [["11/32", 0x000D03]], + "PAZUZU_CRATER": [["11/32", 0x000D03]], + "PAZUZU_DESERT": [["11/32", 0x000D03]], "PYRO_GORAN": [["5/2048", 0x010146]], - "SAINT_MILLION": [["3/256", 0x010140]], - "SAND_RAPPY": [["5/4096", 0x010154]], - "SAND_RAPPY_ALT": [["5/4096", 0x010154]], - "SATELLITE_LIZARD": [["1/512", 0x00BE00]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x00BE00]], + "SAINT_MILION": [["3/256", 0x010140]], + "SAND_RAPPY_CRATER": [["5/4096", 0x010154]], + "SAND_RAPPY_DESERT": [["5/4096", 0x010154]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x00BE00]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x00BE00]], "SHAMBERTIN": [["7/512", 0x01034D]], - "YOWIE": [["1/512", 0x01014F]], - "YOWIE_ALT": [["1/512", 0x01014F]], + "YOWIE_CRATER": [["1/512", 0x01014F]], + "YOWIE_DESERT": [["1/512", 0x01014F]], "ZE_BOOTA": [["13/4096", 0x00D200]], - "ZU": [["11/8192", 0x010349]], - "ZU_ALT": [["11/8192", 0x010349]], + "ZU_CRATER": [["11/8192", 0x010349]], + "ZU_DESERT": [["11/8192", 0x010349]], }, "Yellowboze": { "ASTARK": [["1/512", 0x00C600]], @@ -8225,8 +8225,8 @@ ["7/131072", 0x010140], ["5/524288", 0x010141] ], - "DEL_RAPPY": [["11/32", 0x00C300]], - "DEL_RAPPY_ALT": [["11/32", 0x00C300]], + "DEL_RAPPY_CRATER": [["11/32", 0x00C300]], + "DEL_RAPPY_DESERT": [["11/32", 0x00C300]], "DORPHON": [["9/2048", 0x010136]], "DORPHON_ECLAIR": [["11/32", 0x00C000]], "GIRTABLULU": [["1/256", 0x010285]], @@ -8235,20 +8235,20 @@ "KONDRIEU": [["13/128", 0x00AB00]], "MERISSA_A": [["9/4096", 0x00C500]], "MERISSA_AA": [["7/16", 0x00B900]], - "PAZUZU": [["11/32", 0x01014A]], - "PAZUZU_ALT": [["11/32", 0x01014A]], + "PAZUZU_CRATER": [["11/32", 0x01014A]], + "PAZUZU_DESERT": [["11/32", 0x01014A]], "PYRO_GORAN": [["5/2048", 0x031002]], - "SAINT_MILLION": [["3/256", 0x031802]], - "SAND_RAPPY": [["3/65536", 0x000108]], - "SAND_RAPPY_ALT": [["3/65536", 0x000108]], - "SATELLITE_LIZARD": [["9/8192", 0x01034B]], - "SATELLITE_LIZARD_ALT": [["9/8192", 0x01034B]], + "SAINT_MILION": [["3/256", 0x031802]], + "SAND_RAPPY_CRATER": [["3/65536", 0x000108]], + "SAND_RAPPY_DESERT": [["3/65536", 0x000108]], + "SATELLITE_LIZARD_CRATER": [["9/8192", 0x01034B]], + "SATELLITE_LIZARD_DESERT": [["9/8192", 0x01034B]], "SHAMBERTIN": [["7/512", 0x01034F]], - "YOWIE": [["1/512", 0x00070A]], - "YOWIE_ALT": [["1/512", 0x00070A]], + "YOWIE_CRATER": [["1/512", 0x00070A]], + "YOWIE_DESERT": [["1/512", 0x00070A]], "ZE_BOOTA": [["13/4096", 0x00070B]], - "ZU": [["11/8192", 0x010349]], - "ZU_ALT": [["11/8192", 0x010349]], + "ZU_CRATER": [["11/8192", 0x010349]], + "ZU_DESERT": [["11/8192", 0x010349]], } }, "VeryHard": { @@ -8290,8 +8290,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x010146]], - "DEL_RAPPY_ALT": [["11/32", 0x010146]], + "DEL_RAPPY_CRATER": [["11/32", 0x010146]], + "DEL_RAPPY_DESERT": [["11/32", 0x010146]], "DORPHON": [["13/2048", 0x01014A]], "DORPHON_ECLAIR": [["11/32", 0x010345]], "GIRTABLULU": [["9/1024", 0x00BA00]], @@ -8300,18 +8300,18 @@ "KONDRIEU": [["13/128", 0x000708]], "MERISSA_A": [["9/4096", 0x000406]], "MERISSA_AA": [["7/16", 0x00BE00]], - "PAZUZU": [["11/32", 0x010359]], - "PAZUZU_ALT": [["11/32", 0x010359]], + "PAZUZU_CRATER": [["11/32", 0x010359]], + "PAZUZU_DESERT": [["11/32", 0x010359]], "PYRO_GORAN": [["7/2048", 0x00D200]], - "SAND_RAPPY": [["13/8192", 0x031807]], - "SAND_RAPPY_ALT": [["13/8192", 0x031807]], - "SATELLITE_LIZARD": [["7/8192", 0x010356]], - "SATELLITE_LIZARD_ALT": [["7/8192", 0x010356]], - "YOWIE": [["1/512", 0x031002]], - "YOWIE_ALT": [["1/512", 0x031002]], + "SAND_RAPPY_CRATER": [["13/8192", 0x031807]], + "SAND_RAPPY_DESERT": [["13/8192", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/8192", 0x010356]], + "SATELLITE_LIZARD_DESERT": [["7/8192", 0x010356]], + "YOWIE_CRATER": [["1/512", 0x031002]], + "YOWIE_DESERT": [["1/512", 0x031002]], "ZE_BOOTA": [["1/256", 0x008902]], - "ZU": [["1/256", 0x010147]], - "ZU_ALT": [["1/256", 0x010147]], + "ZU_CRATER": [["1/256", 0x010147]], + "ZU_DESERT": [["1/256", 0x010147]], }, "Greennill": { "ASTARK": [["1/512", 0x010153]], @@ -8351,8 +8351,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x010358]], - "DEL_RAPPY_ALT": [["11/32", 0x010358]], + "DEL_RAPPY_CRATER": [["11/32", 0x010358]], + "DEL_RAPPY_DESERT": [["11/32", 0x010358]], "DORPHON": [["13/2048", 0x008B01]], "DORPHON_ECLAIR": [["11/32", 0x001300]], "GIRTABLULU": [["9/1024", 0x00BE00]], @@ -8361,19 +8361,19 @@ "KONDRIEU": [["13/128", 0x00C500]], "MERISSA_A": [["9/4096", 0x010288]], "MERISSA_AA": [["7/16", 0x00BB00]], - "PAZUZU": [["11/32", 0x000708]], - "PAZUZU_ALT": [["11/32", 0x000708]], + "PAZUZU_CRATER": [["11/32", 0x000708]], + "PAZUZU_DESERT": [["11/32", 0x000708]], "PYRO_GORAN": [["7/2048", 0x00D200]], - "SAND_RAPPY": [["13/8192", 0x031807]], - "SAND_RAPPY_ALT": [["13/8192", 0x031807]], - "SATELLITE_LIZARD": [["7/8192", 0x010356]], - "SATELLITE_LIZARD_ALT": [["7/8192", 0x010356]], + "SAND_RAPPY_CRATER": [["13/8192", 0x031807]], + "SAND_RAPPY_DESERT": [["13/8192", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["7/8192", 0x010356]], + "SATELLITE_LIZARD_DESERT": [["7/8192", 0x010356]], "SHAMBERTIN": [["7/512", 0x010149]], - "YOWIE": [["1/512", 0x01014E]], - "YOWIE_ALT": [["1/512", 0x01014E]], + "YOWIE_CRATER": [["1/512", 0x01014E]], + "YOWIE_DESERT": [["1/512", 0x01014E]], "ZE_BOOTA": [["1/256", 0x01014D]], - "ZU": [["1/256", 0x00BB00]], - "ZU_ALT": [["1/256", 0x00BB00]], + "ZU_CRATER": [["1/256", 0x00BB00]], + "ZU_DESERT": [["1/256", 0x00BB00]], }, "Oran": { "ASTARK": [["1/512", 0x010153]], @@ -8413,8 +8413,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x031002]], - "DEL_RAPPY_ALT": [["11/32", 0x031002]], + "DEL_RAPPY_CRATER": [["11/32", 0x031002]], + "DEL_RAPPY_DESERT": [["11/32", 0x031002]], "DORPHON": [["13/2048", 0x01014A]], "DORPHON_ECLAIR": [["11/32", 0x031002]], "GIRTABLULU": [["9/1024", 0x010299]], @@ -8423,20 +8423,20 @@ "KONDRIEU": [["13/128", 0x000708]], "MERISSA_A": [["9/4096", 0x010151]], "MERISSA_AA": [["7/16", 0x00BE00]], - "PAZUZU": [["11/32", 0x010359]], - "PAZUZU_ALT": [["11/32", 0x010359]], + "PAZUZU_CRATER": [["11/32", 0x010359]], + "PAZUZU_DESERT": [["11/32", 0x010359]], "PYRO_GORAN": [["7/2048", 0x008901]], - "SAINT_MILLION": [["3/256", 0x010354]], - "SAND_RAPPY": [["13/8192", 0x031807]], - "SAND_RAPPY_ALT": [["13/8192", 0x031807]], - "SATELLITE_LIZARD": [["1/512", 0x01014D]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x01014D]], + "SAINT_MILION": [["3/256", 0x010354]], + "SAND_RAPPY_CRATER": [["13/8192", 0x031807]], + "SAND_RAPPY_DESERT": [["13/8192", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x01014D]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x01014D]], "SHAMBERTIN": [["7/512", 0x010355]], - "YOWIE": [["1/512", 0x01014E]], - "YOWIE_ALT": [["1/512", 0x01014E]], + "YOWIE_CRATER": [["1/512", 0x01014E]], + "YOWIE_DESERT": [["1/512", 0x01014E]], "ZE_BOOTA": [["1/256", 0x010147]], - "ZU": [["1/256", 0x000F01]], - "ZU_ALT": [["1/256", 0x000F01]], + "ZU_CRATER": [["1/256", 0x000F01]], + "ZU_DESERT": [["1/256", 0x000F01]], }, "Pinkal": { "ASTARK": [["1/512", 0x002200]], @@ -8476,8 +8476,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x031002]], - "DEL_RAPPY_ALT": [["11/32", 0x031002]], + "DEL_RAPPY_CRATER": [["11/32", 0x031002]], + "DEL_RAPPY_DESERT": [["11/32", 0x031002]], "DORPHON": [["13/2048", 0x010149]], "DORPHON_ECLAIR": [["11/32", 0x010355]], "GIRTABLULU": [["9/1024", 0x010299]], @@ -8486,20 +8486,20 @@ "KONDRIEU": [["13/128", 0x00C500]], "MERISSA_A": [["9/4096", 0x010151]], "MERISSA_AA": [["7/16", 0x01014B]], - "PAZUZU": [["11/32", 0x010359]], - "PAZUZU_ALT": [["11/32", 0x010359]], + "PAZUZU_CRATER": [["11/32", 0x010359]], + "PAZUZU_DESERT": [["11/32", 0x010359]], "PYRO_GORAN": [["7/2048", 0x00CB00]], - "SAINT_MILLION": [["3/256", 0x00C900]], - "SAND_RAPPY": [["13/8192", 0x010153]], - "SAND_RAPPY_ALT": [["13/8192", 0x010153]], - "SATELLITE_LIZARD": [["1/512", 0x000A05]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x000A05]], + "SAINT_MILION": [["3/256", 0x00C900]], + "SAND_RAPPY_CRATER": [["13/8192", 0x010153]], + "SAND_RAPPY_DESERT": [["13/8192", 0x010153]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x000A05]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x000A05]], "SHAMBERTIN": [["7/512", 0x00C900]], - "YOWIE": [["1/512", 0x000B04]], - "YOWIE_ALT": [["1/512", 0x000B04]], + "YOWIE_CRATER": [["1/512", 0x000B04]], + "YOWIE_DESERT": [["1/512", 0x000B04]], "ZE_BOOTA": [["1/256", 0x000C05]], - "ZU": [["1/256", 0x010147]], - "ZU_ALT": [["1/256", 0x010147]], + "ZU_CRATER": [["1/256", 0x010147]], + "ZU_DESERT": [["1/256", 0x010147]], }, "Purplenum": { "ASTARK": [["1/512", 0x000306]], @@ -8539,8 +8539,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x00CD00]], - "DEL_RAPPY_ALT": [["11/32", 0x00CD00]], + "DEL_RAPPY_CRATER": [["11/32", 0x00CD00]], + "DEL_RAPPY_DESERT": [["11/32", 0x00CD00]], "DORPHON": [["13/2048", 0x01014A]], "DORPHON_ECLAIR": [["11/32", 0x010354]], "GIRTABLULU": [["9/1024", 0x010299]], @@ -8549,18 +8549,18 @@ "KONDRIEU": [["13/128", 0x000708]], "MERISSA_A": [["9/4096", 0x010151]], "MERISSA_AA": [["7/16", 0x00BE00]], - "PAZUZU": [["11/32", 0x00BA00]], - "PAZUZU_ALT": [["11/32", 0x00BA00]], + "PAZUZU_CRATER": [["11/32", 0x00BA00]], + "PAZUZU_DESERT": [["11/32", 0x00BA00]], "PYRO_GORAN": [["7/2048", 0x00CB00]], - "SAND_RAPPY": [["13/8192", 0x031807]], - "SAND_RAPPY_ALT": [["13/8192", 0x031807]], - "SATELLITE_LIZARD": [["1/512", 0x01014D]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x01014D]], - "YOWIE": [["1/512", 0x031002]], - "YOWIE_ALT": [["1/512", 0x031002]], + "SAND_RAPPY_CRATER": [["13/8192", 0x031807]], + "SAND_RAPPY_DESERT": [["13/8192", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x01014D]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x01014D]], + "YOWIE_CRATER": [["1/512", 0x031002]], + "YOWIE_DESERT": [["1/512", 0x031002]], "ZE_BOOTA": [["1/256", 0x008901]], - "ZU": [["1/256", 0x00BB00]], - "ZU_ALT": [["1/256", 0x00BB00]], + "ZU_CRATER": [["1/256", 0x00BB00]], + "ZU_DESERT": [["1/256", 0x00BB00]], }, "Redria": { "ASTARK": [["1/512", 0x008C01]], @@ -8600,8 +8600,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x000708]], - "DEL_RAPPY_ALT": [["11/32", 0x000708]], + "DEL_RAPPY_CRATER": [["11/32", 0x000708]], + "DEL_RAPPY_DESERT": [["11/32", 0x000708]], "DORPHON": [["13/2048", 0x010149]], "DORPHON_ECLAIR": [["11/32", 0x031002]], "GIRTABLULU": [["9/1024", 0x00BA00]], @@ -8610,19 +8610,19 @@ "KONDRIEU": [["13/128", 0x010148]], "MERISSA_A": [["9/4096", 0x031002]], "MERISSA_AA": [["7/16", 0x010343]], - "PAZUZU": [["11/32", 0x00CD00]], - "PAZUZU_ALT": [["11/32", 0x00CD00]], + "PAZUZU_CRATER": [["11/32", 0x00CD00]], + "PAZUZU_DESERT": [["11/32", 0x00CD00]], "PYRO_GORAN": [["7/2048", 0x00CB00]], - "SAND_RAPPY": [["13/8192", 0x010153]], - "SAND_RAPPY_ALT": [["13/8192", 0x010153]], - "SATELLITE_LIZARD": [["7/8192", 0x010356]], - "SATELLITE_LIZARD_ALT": [["7/8192", 0x010356]], + "SAND_RAPPY_CRATER": [["13/8192", 0x010153]], + "SAND_RAPPY_DESERT": [["13/8192", 0x010153]], + "SATELLITE_LIZARD_CRATER": [["7/8192", 0x010356]], + "SATELLITE_LIZARD_DESERT": [["7/8192", 0x010356]], "SHAMBERTIN": [["7/512", 0x010147]], - "YOWIE": [["1/512", 0x01014E]], - "YOWIE_ALT": [["1/512", 0x01014E]], + "YOWIE_CRATER": [["1/512", 0x01014E]], + "YOWIE_DESERT": [["1/512", 0x01014E]], "ZE_BOOTA": [["1/256", 0x000506]], - "ZU": [["1/256", 0x00BB00]], - "ZU_ALT": [["1/256", 0x00BB00]], + "ZU_CRATER": [["1/256", 0x00BB00]], + "ZU_DESERT": [["1/256", 0x00BB00]], }, "Skyly": { "ASTARK": [["1/512", 0x000206]], @@ -8662,8 +8662,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x000708]], - "DEL_RAPPY_ALT": [["11/32", 0x000708]], + "DEL_RAPPY_CRATER": [["11/32", 0x000708]], + "DEL_RAPPY_DESERT": [["11/32", 0x000708]], "DORPHON": [["13/2048", 0x010149]], "DORPHON_ECLAIR": [["11/32", 0x002100]], "GIRTABLULU": [["9/1024", 0x010299]], @@ -8672,19 +8672,19 @@ "KONDRIEU": [["13/128", 0x010359]], "MERISSA_A": [["5/4096", 0x010357]], "MERISSA_AA": [["7/16", 0x031002]], - "PAZUZU": [["11/32", 0x010341]], - "PAZUZU_ALT": [["11/32", 0x010341]], + "PAZUZU_CRATER": [["11/32", 0x010341]], + "PAZUZU_DESERT": [["11/32", 0x010341]], "PYRO_GORAN": [["7/2048", 0x00D200]], - "SAND_RAPPY": [["13/8192", 0x010153]], - "SAND_RAPPY_ALT": [["13/8192", 0x010153]], - "SATELLITE_LIZARD": [["1/512", 0x01014D]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x01014D]], + "SAND_RAPPY_CRATER": [["13/8192", 0x010153]], + "SAND_RAPPY_DESERT": [["13/8192", 0x010153]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x01014D]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x01014D]], "SHAMBERTIN": [["7/512", 0x01014B]], - "YOWIE": [["1/512", 0x000106]], - "YOWIE_ALT": [["1/512", 0x000106]], + "YOWIE_CRATER": [["1/512", 0x000106]], + "YOWIE_DESERT": [["1/512", 0x000106]], "ZE_BOOTA": [["1/256", 0x000107]], - "ZU": [["1/256", 0x00BB00]], - "ZU_ALT": [["1/256", 0x00BB00]], + "ZU_CRATER": [["1/256", 0x00BB00]], + "ZU_DESERT": [["1/256", 0x00BB00]], }, "Viridia": { "ASTARK": [["1/512", 0x00BB00]], @@ -8723,8 +8723,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x010358]], - "DEL_RAPPY_ALT": [["11/32", 0x010358]], + "DEL_RAPPY_CRATER": [["11/32", 0x010358]], + "DEL_RAPPY_DESERT": [["11/32", 0x010358]], "DORPHON": [["13/2048", 0x008B02]], "DORPHON_ECLAIR": [["11/32", 0x00CD00]], "GIRTABLULU": [["9/1024", 0x00BA00]], @@ -8733,19 +8733,19 @@ "KONDRIEU": [["13/128", 0x000D03]], "MERISSA_A": [["5/4096", 0x010357]], "MERISSA_AA": [["7/16", 0x00BE00]], - "PAZUZU": [["11/32", 0x000708]], - "PAZUZU_ALT": [["11/32", 0x000708]], + "PAZUZU_CRATER": [["11/32", 0x000708]], + "PAZUZU_DESERT": [["11/32", 0x000708]], "PYRO_GORAN": [["7/2048", 0x010146]], - "SAINT_MILLION": [["3/256", 0x01014B]], - "SAND_RAPPY": [["13/8192", 0x031807]], - "SAND_RAPPY_ALT": [["13/8192", 0x031807]], - "SATELLITE_LIZARD": [["1/512", 0x01014D]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x01014D]], - "YOWIE": [["1/512", 0x01014E]], - "YOWIE_ALT": [["1/512", 0x01014E]], + "SAINT_MILION": [["3/256", 0x01014B]], + "SAND_RAPPY_CRATER": [["13/8192", 0x031807]], + "SAND_RAPPY_DESERT": [["13/8192", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x01014D]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x01014D]], + "YOWIE_CRATER": [["1/512", 0x01014E]], + "YOWIE_DESERT": [["1/512", 0x01014E]], "ZE_BOOTA": [["1/256", 0x010149]], - "ZU": [["1/256", 0x031002]], - "ZU_ALT": [["1/256", 0x031002]], + "ZU_CRATER": [["1/256", 0x031002]], + "ZU_DESERT": [["1/256", 0x031002]], }, "Whitill": { "ASTARK": [["1/512", 0x000506]], @@ -8785,8 +8785,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x000708]], - "DEL_RAPPY_ALT": [["11/32", 0x000708]], + "DEL_RAPPY_CRATER": [["11/32", 0x000708]], + "DEL_RAPPY_DESERT": [["11/32", 0x000708]], "DORPHON": [["13/2048", 0x031002]], "DORPHON_ECLAIR": [["11/32", 0x010358]], "GIRTABLULU": [["9/1024", 0x00BA00]], @@ -8795,18 +8795,18 @@ "KONDRIEU": [["13/128", 0x000D03]], "MERISSA_A": [["9/4096", 0x010151]], "MERISSA_AA": [["7/16", 0x01014C]], - "PAZUZU": [["11/32", 0x00CD00]], - "PAZUZU_ALT": [["11/32", 0x00CD00]], + "PAZUZU_CRATER": [["11/32", 0x00CD00]], + "PAZUZU_DESERT": [["11/32", 0x00CD00]], "PYRO_GORAN": [["7/2048", 0x000807]], - "SAND_RAPPY": [["13/8192", 0x031807]], - "SAND_RAPPY_ALT": [["13/8192", 0x031807]], - "SATELLITE_LIZARD": [["1/512", 0x01014D]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x01014D]], - "YOWIE": [["1/512", 0x01014E]], - "YOWIE_ALT": [["1/512", 0x01014E]], + "SAND_RAPPY_CRATER": [["13/8192", 0x031807]], + "SAND_RAPPY_DESERT": [["13/8192", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x01014D]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x01014D]], + "YOWIE_CRATER": [["1/512", 0x01014E]], + "YOWIE_DESERT": [["1/512", 0x01014E]], "ZE_BOOTA": [["1/256", 0x000505]], - "ZU": [["1/256", 0x00BB00]], - "ZU_ALT": [["1/256", 0x00BB00]], + "ZU_CRATER": [["1/256", 0x00BB00]], + "ZU_DESERT": [["1/256", 0x00BB00]], }, "Yellowboze": { "ASTARK": [["5/4096", 0x010356]], @@ -8846,8 +8846,8 @@ ["5/4096", 0x031002], ["11/131072", 0x01014E] ], - "DEL_RAPPY": [["11/32", 0x010146]], - "DEL_RAPPY_ALT": [["11/32", 0x010146]], + "DEL_RAPPY_CRATER": [["11/32", 0x010146]], + "DEL_RAPPY_DESERT": [["11/32", 0x010146]], "DORPHON": [["13/2048", 0x010148]], "DORPHON_ECLAIR": [["11/32", 0x010147]], "GIRTABLULU": [["9/1024", 0x00BA00]], @@ -8856,19 +8856,19 @@ "KONDRIEU": [["13/128", 0x031802]], "MERISSA_A": [["9/4096", 0x010151]], "MERISSA_AA": [["7/16", 0x00BE00]], - "PAZUZU": [["11/32", 0x000708]], - "PAZUZU_ALT": [["11/32", 0x000708]], + "PAZUZU_CRATER": [["11/32", 0x000708]], + "PAZUZU_DESERT": [["11/32", 0x000708]], "PYRO_GORAN": [["7/2048", 0x00CB00]], - "SAND_RAPPY": [["13/8192", 0x031807]], - "SAND_RAPPY_ALT": [["13/8192", 0x031807]], - "SATELLITE_LIZARD": [["1/512", 0x01014D]], - "SATELLITE_LIZARD_ALT": [["1/512", 0x01014D]], + "SAND_RAPPY_CRATER": [["13/8192", 0x031807]], + "SAND_RAPPY_DESERT": [["13/8192", 0x031807]], + "SATELLITE_LIZARD_CRATER": [["1/512", 0x01014D]], + "SATELLITE_LIZARD_DESERT": [["1/512", 0x01014D]], "SHAMBERTIN": [["7/512", 0x031802]], - "YOWIE": [["1/512", 0x01014E]], - "YOWIE_ALT": [["1/512", 0x01014E]], + "YOWIE_CRATER": [["1/512", 0x01014E]], + "YOWIE_DESERT": [["1/512", 0x01014E]], "ZE_BOOTA": [["1/256", 0x010153]], - "ZU": [["1/256", 0x031002]], - "ZU_ALT": [["1/256", 0x031002]], + "ZU_CRATER": [["1/256", 0x031002]], + "ZU_DESERT": [["1/256", 0x031002]], } } }