Compare commits

...

34 Commits

Author SHA1 Message Date
incentive f05e68492d PSO Peeps Start
Docker / Build (push) Has been cancelled
2026-05-01 23:14:17 -04:00
Martin Michelsen 7f68d41bac fix port name in game server lookup 2026-04-25 22:21:46 -07:00
Martin Michelsen 75e7232096 handle BB not sending C6 after 08E8 2026-04-25 12:06:43 -07:00
Martin Michelsen 7a29b39771 allow 6xCB in free-play 2026-04-24 20:36:45 -07:00
Martin Michelsen cfcb56b13f update command notes 2026-04-24 20:17:48 -07:00
Martin Michelsen 9e6740b778 update 6x30 notes 2026-04-20 20:00:11 -07:00
Martin Michelsen 590f937959 add release script 2026-04-19 13:32:26 -07:00
Martin Michelsen 31abc24e81 don't allow players to pick up items if they are too far away 2026-04-19 09:35:20 -07:00
Martin Michelsen 507fbf0451 add another useless AR code 2026-04-19 08:57:49 -07:00
Martin Michelsen 1fa660129d add last-hit tracking for target subcommands 2026-04-11 08:28:40 -07:00
Martin Michelsen 67082f7b6b update static 2026-04-11 08:14:12 -07:00
Martin Michelsen b34c9a7c88 improve error message for missing quest common/rare item sets 2026-04-05 21:50:53 -07:00
Martin Michelsen 87e85932a4 switch rare drops to stacked space logic 2026-04-03 19:52:42 -07:00
Martin Michelsen b704d827ed add support for direct Xbox connections 2026-04-01 21:47:21 -07:00
Martin Michelsen 598ecf88e3 revise death_flags notes 2026-04-01 08:48:19 -07:00
Martin Michelsen a05971017d explain a few of the unknown player_flags bits 2026-03-30 19:38:15 -07:00
Martin Michelsen b7819413b0 handle missing DAR entries in HTML generator 2026-03-27 07:55:44 -07:00
Martin Michelsen 80e4b0e6fe clean up formatting on Ep3 drop rates comment 2026-03-23 20:39:44 -07:00
Martin Michelsen daee47b722 use new phosg parallel functions 2026-03-22 21:37:52 -07:00
Martin Michelsen 5724fb9a12 add $allrare debug command; closes #739 2026-03-22 21:37:43 -07:00
Martin Michelsen 983753f840 add FogDebug patch 2026-03-21 09:30:59 -07:00
Martin Michelsen 53d2318873 more details on player_flags 2026-03-20 22:21:21 -07:00
Martin Michelsen 83291d5501 more details on player_flags 2026-03-19 23:01:30 -07:00
Martin Michelsen 55be92a56f add game duration to info window 2026-03-19 10:42:01 -07:00
Martin Michelsen 6a23e5da0a make some sense out of game_flags and player_flags 2026-03-18 22:44:02 -07:00
Martin Michelsen 4571cf7fdc fix attribute count check in 6xDA 2026-03-11 07:19:53 -07:00
Martin Michelsen 4e3549ba6b use EnemyType in ItemCreator; fix incorrect drop tables 2026-03-08 20:40:15 -07:00
Martin Michelsen 3cbf64dda2 update quest collision opcode docs 2026-03-08 12:55:57 -07:00
Martin Michelsen 382bc6b7ce don't allow error cases for bb_exchange_pd_percent to destroy items 2026-03-04 21:37:54 -08:00
Martin Michelsen e05991ffb3 add test for trade window sequence 2026-03-03 20:43:46 -08:00
Martin Michelsen ffda97222d document --language option in disassemble-quest-script 2026-03-02 08:46:38 -08:00
Martin Michelsen 8f21604367 clean up CMakeLists a bit 2026-03-02 08:46:25 -08:00
Martin Michelsen 4045504b61 also send combatant info board entries in spectator teams 2026-02-28 20:49:36 -08:00
Martin Michelsen 4aad1514c2 port a few more bug fix patches to Xbox 2026-02-28 20:49:19 -08:00
99 changed files with 7731 additions and 1232 deletions
+12 -1
View File
@@ -3,6 +3,7 @@
# Build products # Build products
newserv newserv
newserv.exe
src/Revision.cc src/Revision.cc
# CMake files # CMake files
@@ -37,12 +38,22 @@ system/teams/*.json
# Files fuzziqersoftware uses that don't make sense to be committed to the main # Files fuzziqersoftware uses that don't make sense to be committed to the main
# repository # repository
*.dec *.dec
*.WIP-s
files files
make_release.py
notes-private notes-private
old-khyller old-khyller
old-newserv old-newserv
release release
release.zip release.zip
all-quests
system/dol system/dol
system/patch-bb/data system/patch-bb/data
system/client-functions/Debug-Private
system/config.2.json
system/ep3/banners
system/ep3/cardtex
system/ep3/cardtex-trial
system/players
system/quests/includes
system/quests/private
.vscode
+5 -4
View File
@@ -134,11 +134,12 @@ set(SOURCES
add_executable(newserv ${SOURCES}) add_executable(newserv ${SOURCES})
target_include_directories(newserv PUBLIC ${ASIO_INCLUDE_DIR} ${Iconv_INCLUDE_DIRS}) target_include_directories(newserv PUBLIC ${ASIO_INCLUDE_DIR} ${Iconv_INCLUDE_DIRS})
target_link_libraries(newserv phosg::phosg ${Iconv_LIBRARIES} pthread resource_file::resource_file) target_link_libraries(newserv phosg::phosg ${Iconv_LIBRARIES} resource_file::resource_file)
if (WIN32) if (WIN32)
target_compile_definitions(newserv PUBLIC -DWINVER=0x0A00 -D_WIN32_WINNT=0x0A00) target_compile_definitions(newserv PUBLIC WINVER=0x0A00 _WIN32_WINNT=0x0A00)
target_link_libraries(newserv ws2_32 mswsock bcrypt iphlpapi -static -static-libgcc -static-libstdc++) target_compile_options(newserv PRIVATE -Wa,-mbig-obj -Wno-mismatched-new-delete)
target_compile_options(newserv PRIVATE -Wa,-mbig-obj) target_link_options(newserv PRIVATE -static -static-libgcc -static-libstdc++)
target_link_libraries(newserv ws2_32 mswsock bcrypt iphlpapi)
endif() endif()
add_dependencies(newserv newserv-Revision-cc) add_dependencies(newserv newserv-Revision-cc)
+2
View File
@@ -603,8 +603,10 @@ Some commands only work for clients not in proxy sessions. The chat commands are
* `$qsyncall <reg-num> <value>`: Set a quest register's value for everyone in the game. `<reg-num>` should be either rXX (e.g. r60) or fXX (e.g. f60); if the latter, `<value>` is parsed as a floating-point value instead of as an integer. * `$qsyncall <reg-num> <value>`: Set a quest register's value for everyone in the game. `<reg-num>` should be either rXX (e.g. r60) or fXX (e.g. f60); if the latter, `<value>` is parsed as a floating-point value instead of as an integer.
* `$swset [floor] <flag-num>` and `$swclear [floor] <flag-num>`: Set or clear a switch flag. If floor is not given, sets or clears the flag on your current floor. * `$swset [floor] <flag-num>` and `$swclear [floor] <flag-num>`: Set or clear a switch flag. If floor is not given, sets or clears the flag on your current floor.
* `$swsetall`: Set all switch flags on your current floor. This unlocks all doors, disables all laser fences, triggers all light/poison switches, etc. * `$swsetall`: Set all switch flags on your current floor. This unlocks all doors, disables all laser fences, triggers all light/poison switches, etc.
* `$allrare`: Make all enemies and boxes drop their rare items every time.
* `$gc` (non-proxy only): Send your own Guild Card to yourself. * `$gc` (non-proxy only): Send your own Guild Card to yourself.
* `$sc <data>`: Send a command to yourself. * `$sc <data>`: Send a command to yourself.
* `$scp <data>`: Send a protected command to yourself.
* `$ss <data>`: Send a command to the remote server (if in a proxy session) or to the game server. * `$ss <data>`: Send a command to the remote server (if in a proxy session) or to the game server.
* `$sb <data>`: Send a command to yourself, and to the remote server or game server. * `$sb <data>`: Send a command to yourself, and to the remote server or game server.
* `$auction` (Episode 3 only): Bring up the CARD Auction menu, even if there are fewer than 4 players are in the game or you don't have a VIP card. * `$auction` (Episode 3 only): Bring up the CARD Auction menu, even if there are fewer than 4 players are in the game or you don't have a VIP card.
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
import os
import shutil
import subprocess
import sys
from typing import Callable
def filter_directory(dir: str, predicate: Callable[[str], bool]):
for filename in os.listdir(dir):
if not predicate(filename):
path = os.path.join(dir, filename)
if os.path.isfile(path):
os.remove(path)
else:
shutil.rmtree(path)
def main():
print("Deleting existing release directory")
if os.path.exists("release"):
shutil.rmtree("release")
if os.path.exists("release.zip"):
os.remove("release.zip")
os.mkdir("release")
print("Adding executables")
shutil.copy("newserv", "release/newserv-macos")
shutil.copy("newserv.exe", "release/newserv-windows.exe")
shutil.copy("README.md", "release/README.md")
print("Adding system directory")
shutil.copytree("system", "release/system")
print("Removing instance-based and temporary files")
filter_directory(
"release/system",
lambda filename: (not filename.endswith(".json"))
or filename == "config.example.json",
)
filter_directory(
"release/system/ep3", lambda filename: not filename.startswith("cardtex")
)
filter_directory(
"release/system/client-functions",
lambda filename: filename not in ("Debug-Private", "FastLoading", "notes.txt"),
)
filter_directory("release/system/dol", lambda filename: False)
filter_directory("release/system/ep3/banners", lambda filename: False)
filter_directory("release/system/ep3/battle-records", lambda filename: False)
filter_directory("release/system/licenses", lambda filename: False)
filter_directory("release/system/players", lambda filename: False)
filter_directory(
"release/system/quests",
lambda filename: filename not in ("private", "includes"),
)
filter_directory("release/system/teams", lambda filename: filename == "base.json")
subprocess.check_call(["find", "release", "-name", ".DS_Store", "-delete"])
subprocess.check_call(["find", "release", "-name", "*.WIP-s", "-delete"])
print("Setting up configuration")
os.rename("release/system/config.example.json", "release/system/config.json")
if __name__ == "__main__":
sys.exit(main())
+34
View File
@@ -1074,3 +1074,37 @@ Enable quest board menu in free play (for use with the above code)
3OJ3 => 04262E44 38600001 3OJ3 => 04262E44 38600001
3OJ4 => 04263EB8 38600001 3OJ4 => 04263EB8 38600001
3OP0 => 0426374C 38600001 3OP0 => 0426374C 38600001
All classes' footsteps sound like RAcast's
(Change the 2 in 38600002 to 0 for human/Newman, 1 for lighter androids, or 3 if you want to be annoyed)
3OE0 => 041B3ED0 38600002
041B3ED4 4E800020
3OE1 => 041B3ED0 38600002
041B3ED4 4E800020
3OE2 => 041B4068 38600002
041B406C 4E800020
3OJ2 => 041B3AE4 38600002
041B3AE8 4E800020
3OJ3 => 041B3F38 38600002
041B3F3C 4E800020
3OJ4 => 041B552C 38600002
041B5530 4E800020
3OJ5 => 041B4004 38600002
041B4008 4E800020
3OJT => 0420A120 38600002
0420A124 4E800020
3OP0 => 041B4524 38600002
041B4528 4E800020
3SE0 => 040D0378 38600002
040D037C 4E800020
3SJ0 => 040D0394 38600002
040D0398 4E800020
3SJT => 040D431C 38600002
040D4320 4E800020
3SP0 => 040D07BC 38600002
040D07C0 4E800020
Rappy size modifier
3OE1 => 040C1E24 48000020 // Disable flag check in render
045D0718 40800000 // X/Z scale as float (here, 4.0)
045D071C 40800000 // Y scale as float (here, 4.0)
+2 -2
View File
@@ -538,8 +538,8 @@ fparam4 = TODO: 3OE1:802D7490; NNF: Jump cooldown time (Higher value = less wait
iparam1 = TODO: 3OE1:802D7484 iparam1 = TODO: 3OE1:802D7484
MOVEMENT DATA 40 (MORFOS) MOVEMENT DATA 40 (MORFOS)
fparam1 = TODO: 3OE1:80335A98, 3OE1:80335DBC; NNF: Laser speed (also affects hitbox property - needs retest with others for opinion). fparam1 = laser speed; hitbox radius is fparam1 * 1.5
fparam2 = TODO: 3OE1:80335ADC; NNF: Laser damage. fparam2 = laser damage
iparam1 = TODO: 3OE1:80332298, 3OE1:803321C4; NNF: Firing rate of regular laser attack. Laser attack when aggressive (charging) is unaffected. iparam1 = TODO: 3OE1:80332298, 3OE1:803321C4; NNF: Firing rate of regular laser attack. Laser attack when aggressive (charging) is unaffected.
iparam2 = TODO: 3OE1:8033161C, 3OE1:8033192C, 3OE1:80331B4C, 3OE1:80331D00, 3OE1:80331FA0; NNF: Speed at which Morphos spins after firing laser. iparam2 = TODO: 3OE1:8033161C, 3OE1:8033192C, 3OE1:80331B4C, 3OE1:80331D00, 3OE1:80331FA0; NNF: Speed at which Morphos spins after firing laser.
iparam3 = TODO: 3OE1:80331F04; NNF: Interval in frames of attacks iparam3 = TODO: 3OE1:80331F04; NNF: Interval in frames of attacks
+24 -5
View File
@@ -2227,6 +2227,15 @@ ChatCommandDefinition cc_fastkill(
} }
co_return; co_return;
}); });
ChatCommandDefinition cc_allrare(
{"$allrare"},
+[](const Args& a) -> asio::awaitable<void> {
a.check_debug_enabled();
a.c->toggle_flag(Client::Flag::ALL_RARES_ENABLED);
send_text_message_fmt(
a.c, "$C6All-rares {}", a.c->check_flag(Client::Flag::ALL_RARES_ENABLED) ? "enabled" : "disabled");
co_return;
});
ChatCommandDefinition cc_rand( ChatCommandDefinition cc_rand(
{"$rand"}, {"$rand"},
@@ -2349,14 +2358,18 @@ ChatCommandDefinition cc_saverec(
co_return; co_return;
}); });
static asio::awaitable<void> command_send_command(const Args& a, bool to_client, bool to_server) { static asio::awaitable<void> command_send_command(const Args& a, bool to_client, bool to_server, bool send_protected) {
if (!a.c->proxy_session) { if (!a.c->proxy_session) {
a.check_debug_enabled(); a.check_debug_enabled();
} }
string data = phosg::parse_data_string(a.text); string data = phosg::parse_data_string(a.text);
data.resize((data.size() + 3) & (~3)); data.resize((data.size() + 3) & (~3));
if (to_client) { if (to_client) {
a.c->channel->send(data); if (send_protected) {
co_await send_protected_command(a.c, data.data(), data.size(), false);
} else {
a.c->channel->send(data);
}
} }
if (to_server) { if (to_server) {
if (a.c->proxy_session) { if (a.c->proxy_session) {
@@ -2371,13 +2384,19 @@ static asio::awaitable<void> command_send_command(const Args& a, bool to_client,
ChatCommandDefinition cc_sb( ChatCommandDefinition cc_sb(
{"$sb"}, {"$sb"},
+[](const Args& a) -> asio::awaitable<void> { +[](const Args& a) -> asio::awaitable<void> {
return command_send_command(a, true, true); return command_send_command(a, true, true, false);
}); });
ChatCommandDefinition cc_sc( ChatCommandDefinition cc_sc(
{"$sc"}, {"$sc"},
+[](const Args& a) -> asio::awaitable<void> { +[](const Args& a) -> asio::awaitable<void> {
return command_send_command(a, true, false); return command_send_command(a, true, false, false);
});
ChatCommandDefinition cc_scp(
{"$scp"},
+[](const Args& a) -> asio::awaitable<void> {
return command_send_command(a, true, false, true);
}); });
ChatCommandDefinition cc_secid( ChatCommandDefinition cc_secid(
@@ -2571,7 +2590,7 @@ ChatCommandDefinition cc_spec(
ChatCommandDefinition cc_ss( ChatCommandDefinition cc_ss(
{"$ss"}, {"$ss"},
+[](const Args& a) -> asio::awaitable<void> { +[](const Args& a) -> asio::awaitable<void> {
return command_send_command(a, false, true); return command_send_command(a, false, true, false);
}); });
ChatCommandDefinition cc_stat( ChatCommandDefinition cc_stat(
+3 -3
View File
@@ -1008,9 +1008,9 @@ void Client::load_all_files() {
auto stack_limits = s->item_stack_limits(this->version()); auto stack_limits = s->item_stack_limits(this->version());
this->blocked_senders.clear(); this->blocked_senders.clear();
for (size_t z = 0; z < this->guild_card_data->blocked.size(); z++) { for (size_t z = 0; z < this->guild_card_data->blocked_senders.size(); z++) {
if (this->guild_card_data->blocked[z].present) { if (this->guild_card_data->blocked_senders[z].present) {
this->blocked_senders.emplace(this->guild_card_data->blocked[z].guild_card_number); this->blocked_senders.emplace(this->guild_card_data->blocked_senders[z].guild_card_number);
} }
} }
+3
View File
@@ -78,6 +78,7 @@ public:
INFINITE_HP_ENABLED = 0x0000000040000000, INFINITE_HP_ENABLED = 0x0000000040000000,
INFINITE_TP_ENABLED = 0x0000000080000000, INFINITE_TP_ENABLED = 0x0000000080000000,
FAST_KILLS_ENABLED = 0x0000000100000000, FAST_KILLS_ENABLED = 0x0000000100000000,
ALL_RARES_ENABLED = 0x0000100000000000,
DEBUG_ENABLED = 0x0000000200000000, DEBUG_ENABLED = 0x0000000200000000,
ITEM_DROP_NOTIFICATIONS_1 = 0x0000000400000000, ITEM_DROP_NOTIFICATIONS_1 = 0x0000000400000000,
ITEM_DROP_NOTIFICATIONS_2 = 0x0000000800000000, ITEM_DROP_NOTIFICATIONS_2 = 0x0000000800000000,
@@ -139,6 +140,7 @@ public:
std::shared_ptr<Channel> channel; std::shared_ptr<Channel> channel;
std::shared_ptr<PSOBBMultiKeyDetectorEncryption> bb_detector_crypt; std::shared_ptr<PSOBBMultiKeyDetectorEncryption> bb_detector_crypt;
ServerBehavior server_behavior; ServerBehavior server_behavior;
uint16_t listener_port = 0;
std::unordered_map<std::string, std::function<void()>> disconnect_hooks; std::unordered_map<std::string, std::function<void()>> disconnect_hooks;
uint64_t ping_start_time = 0; uint64_t ping_start_time = 0;
@@ -149,6 +151,7 @@ public:
uint8_t override_lobby_event = 0xFF; // FF = no override uint8_t override_lobby_event = 0xFF; // FF = no override
uint8_t override_lobby_number = 0x80; // 80 = no override uint8_t override_lobby_number = 0x80; // 80 = no override
int64_t override_random_seed = -1; int64_t override_random_seed = -1;
int8_t selected_blueballz_tier = -1; // -1 = normal lobby/game; 0..10 = requested Blueballz tier
std::unique_ptr<Variations> override_variations; std::unique_ptr<Variations> override_variations;
VectorXYZF pos; VectorXYZF pos;
uint32_t floor = 0x0F; uint32_t floor = 0x0F;
+243 -191
View File
@@ -144,7 +144,7 @@ struct S_ServerInit_Patch_02 {
} __packed_ws__(S_ServerInit_Patch_02, 0x48); } __packed_ws__(S_ServerInit_Patch_02, 0x48);
// 02 (C->S): Encryption started // 02 (C->S): Encryption started
// No arguments // No arguments.
// 03: Invalid command // 03: Invalid command
@@ -163,7 +163,7 @@ struct C_Login_Patch_04 {
} __packed_ws__(C_Login_Patch_04, 0x6C); } __packed_ws__(C_Login_Patch_04, 0x6C);
// 05 (S->C): Disconnect // 05 (S->C): Disconnect
// No arguments // No arguments.
// This command is not used in the normal flow (described above). Generally the server should disconnect after sending // This command is not used in the normal flow (described above). Generally the server should disconnect after sending
// a 12 or 15 command instead of an 05. // a 12 or 15 command instead of an 05.
@@ -203,10 +203,10 @@ struct S_EnterDirectory_Patch_09 {
} __packed_ws__(S_EnterDirectory_Patch_09, 0x40); } __packed_ws__(S_EnterDirectory_Patch_09, 0x40);
// 0A (S->C): Exit directory // 0A (S->C): Exit directory
// No arguments // No arguments.
// 0B (S->C): Start patch session and go to patch root directory // 0B (S->C): Start patch session and go to patch root directory
// No arguments // No arguments.
// 0C (S->C): File checksum request // 0C (S->C): File checksum request
@@ -216,7 +216,7 @@ struct S_FileChecksumRequest_Patch_0C {
} __packed_ws__(S_FileChecksumRequest_Patch_0C, 0x24); } __packed_ws__(S_FileChecksumRequest_Patch_0C, 0x24);
// 0D (S->C): End of file checksum requests // 0D (S->C): End of file checksum requests
// No arguments // No arguments.
// 0E: Invalid command // 0E: Invalid command
@@ -229,7 +229,7 @@ struct C_FileInformation_Patch_0F {
} __packed_ws__(C_FileInformation_Patch_0F, 0x0C); } __packed_ws__(C_FileInformation_Patch_0F, 0x0C);
// 10 (C->S): End of file information command list // 10 (C->S): End of file information command list
// No arguments // No arguments.
// 11 (S->C): Start file downloads // 11 (S->C): Start file downloads
@@ -239,7 +239,7 @@ struct S_StartFileDownloads_Patch_11 {
} __packed_ws__(S_StartFileDownloads_Patch_11, 0x08); } __packed_ws__(S_StartFileDownloads_Patch_11, 0x08);
// 12 (S->C): End patch session successfully // 12 (S->C): End patch session successfully
// No arguments // No arguments.
// 13 (S->C): Message box // 13 (S->C): Message box
// Same format and usage as commands 1A/D5 on the game server (described below). On PSOBB, the message box appears in // Same format and usage as commands 1A/D5 on the game server (described below). On PSOBB, the message box appears in
@@ -293,10 +293,10 @@ struct SC_TextHeader_01_06_11_B0_EE {
// Command 17 should be used instead for the first connection. // Command 17 should be used instead for the first connection.
// All commands after this command will be encrypted with PSO V2 encryption on DC, PC, and GC Episodes 1&2 Trial // All commands after this command will be encrypted with PSO V2 encryption on DC, PC, and GC Episodes 1&2 Trial
// Edition, or PSO V3 encryption on other V3 versions. The (encrypted) response depends on the client's version: // Edition, or PSO V3 encryption on other V3 versions. The (encrypted) response depends on the client's version:
// - DC NTE clients will respond with 8B. // - DC NTE clients will respond with an 8B command.
// - DC 11/2000 and DCv1 clients will respond with 93. // - DC 11/2000 and DCv1 clients will respond with a 93 command.
// - DCv2, PCv2, and GC NTE clients will respond with an 9A, 9D, or 9E. // - DCv2, PCv2, and GC NTE clients will respond with a 9A, 9D, or 9E command.
// - V3 clients will respond with 9A or 9E command. // - V3 clients will respond with a 9A or 9E command.
// The copyright field in the below structure must contain "DreamCast Lobby Server. Copyright SEGA Enterprises. 1999". // The copyright field in the below structure must contain "DreamCast Lobby Server. Copyright SEGA Enterprises. 1999".
// (The above text is required on all versions that use this command, including those versions that don't run on the // (The above text is required on all versions that use this command, including those versions that don't run on the
// DreamCast.) // DreamCast.)
@@ -494,16 +494,16 @@ struct S_MenuItemT {
// - On BB, 0x40/0x41 mean Episodes 1/2 as on GC, and 0x43 means Episode 4. // - On BB, 0x40/0x41 mean Episodes 1/2 as on GC, and 0x43 means Episode 4.
uint8_t episode = 0; uint8_t episode = 0;
// Flags (01 and 02 are used for all menus; the rest are only used for the game menu): // Flags (01 and 02 are used for all menus; the rest are only used for the game menu):
// 01 = Send name? (client sends the name field in the 10 command if this item is chosen, but it's blank) // 01 = Send name? (client sends the name field in the 10 command if this item is chosen, but it's blank)
// 02 = Locked (lock icon appears in the menu; player is prompted for a password if they choose this game) // 02 = Locked (lock icon appears in the menu; player is prompted for a password if they choose this game)
// 04 = In battle (Episode 3 only; a sword icon appears in the menu) // 04 = In battle (Episode 3 only; a sword icon appears in the menu)
// 04 = Disabled (BB only; used for solo games) // 04 = Disabled (BB only; used for solo games)
// 10 = Is battle mode // 10 = Is battle mode
// 20 = Is challenge mode // 20 = Is challenge mode
// 40 = Is v2 only (DCv2/PC); game name renders in orange // 40 = Is v2 only (DCv2/PC); game name renders in orange
// 40 = Is Episode 1 (V3/BB) // 40 = Is Episode 1 (V3/BB)
// 80 = Is Episode 2 (V3/BB) // 80 = Is Episode 2 (V3/BB)
// C0 = Is Episode 4 (BB) // C0 = Is Episode 4 (BB)
uint8_t flags = 0; uint8_t flags = 0;
} __attribute__((packed)); } __attribute__((packed));
using S_MenuItem_PC_BB_08 = S_MenuItemT<TextEncoding::UTF16>; using S_MenuItem_PC_BB_08 = S_MenuItemT<TextEncoding::UTF16>;
@@ -513,7 +513,7 @@ check_struct_size(S_MenuItem_DC_V3_08_Ep3_E6, 0x1C);
// 08 (C->S): Request game list // 08 (C->S): Request game list
// Internal name: SndGameList // Internal name: SndGameList
// No arguments // No arguments.
// 08 (S->C): Game list // 08 (S->C): Game list
// Internal name: RcvGameList // Internal name: RcvGameList
@@ -530,6 +530,7 @@ struct C_MenuItemInfoRequest_09 {
le_uint32_t item_id = 0; le_uint32_t item_id = 0;
} __packed_ws__(C_MenuItemInfoRequest_09, 8); } __packed_ws__(C_MenuItemInfoRequest_09, 8);
// 0A: Invalid command
// 0B: Invalid command // 0B: Invalid command
// 0C (C->S): Create game (DCv1) // 0C (C->S): Create game (DCv1)
@@ -709,10 +710,10 @@ struct C_WriteFileConfirmation_V3_BB_13_A7 {
// Internal name: RcvPsoRegistConnectV2 // Internal name: RcvPsoRegistConnectV2
// Same format as 02 command, but a different copyright: "DreamCast Port Map. Copyright SEGA Enterprises. 1999" // Same format as 02 command, but a different copyright: "DreamCast Port Map. Copyright SEGA Enterprises. 1999"
// The response depends on the client's version: // The response depends on the client's version:
// - DC NTE will respond with 8B. // - DC NTE will respond with an 8B command.
// - DC 11/2000 and DCv1 will respond with 90. // - DC 11/2000 and DCv1 will respond with a 90 command.
// - DCv2, PCv2, and GC NTE clients will respond with 9A or 9D. // - DCv2, PCv2, and GC NTE clients will respond with a 9A or 9D command.
// - V3 (GC/Xbox) clients will respond with a DB command when they receive a 17 command in any online // - V3 (GC/Xbox) clients will respond with a DB command (but see the notes on DB for Xbox clients).
// 18 (S->C): Account verification result (PC/V3) // 18 (S->C): Account verification result (PC/V3)
// Behaves exactly the same as 9A (S->C). No arguments except header.flag. // Behaves exactly the same as 9A (S->C). No arguments except header.flag.
@@ -861,7 +862,7 @@ struct S_GallonPlanResult_BB_25 {
// 2D: Invalid command // 2D: Invalid command
// 2E: Invalid command // 2E: Invalid command
// 2F: Invalid command // 2F: Invalid command
// 30: Invalid command // 30: Invalid command (but used as a newserv extension; see end of this file)
// 31: Invalid command // 31: Invalid command
// 32: Invalid command // 32: Invalid command
// 33: Invalid command // 33: Invalid command
@@ -1234,12 +1235,12 @@ struct S_JoinGame_BB_64 : S_JoinGameT_DC_PC<PlayerLobbyDataBB> {
// Similarly to 64, the client will ignore 64 and 65 commands while loading, and will buffer all other commands except // Similarly to 64, the client will ignore 64 and 65 commands while loading, and will buffer all other commands except
// 1D until loading is done. // 1D until loading is done.
struct LobbyFlags_DCNTE { struct LobbyFlagsDCNTE {
uint8_t client_id = 0; uint8_t client_id = 0;
uint8_t leader_id = 0; uint8_t leader_id = 0;
uint8_t disable_udp = 1; uint8_t disable_udp = 1;
uint8_t unused = 0; uint8_t unused = 0;
} __packed_ws__(LobbyFlags_DCNTE, 4); } __packed_ws__(LobbyFlagsDCNTE, 4);
struct LobbyFlags { struct LobbyFlags {
uint8_t client_id = 0; uint8_t client_id = 0;
@@ -1273,7 +1274,7 @@ struct S_JoinLobbyT {
return offsetof(S_JoinLobbyT, entries) + used_entries * sizeof(Entry); return offsetof(S_JoinLobbyT, entries) + used_entries * sizeof(Entry);
} }
} __attribute__((packed)); } __attribute__((packed));
using S_JoinLobby_DCNTE_65_67_68 = S_JoinLobbyT<LobbyFlags_DCNTE, PlayerLobbyDataDCGC, PlayerDispDataDCPCV3>; using S_JoinLobby_DCNTE_65_67_68 = S_JoinLobbyT<LobbyFlagsDCNTE, PlayerLobbyDataDCGC, PlayerDispDataDCPCV3>;
using S_JoinLobby_PC_65_67_68 = S_JoinLobbyT<LobbyFlags, PlayerLobbyDataPC, PlayerDispDataDCPCV3>; using S_JoinLobby_PC_65_67_68 = S_JoinLobbyT<LobbyFlags, PlayerLobbyDataPC, PlayerDispDataDCPCV3>;
using S_JoinLobby_DC_GC_65_67_68_Ep3_EB = S_JoinLobbyT<LobbyFlags, PlayerLobbyDataDCGC, PlayerDispDataDCPCV3>; using S_JoinLobby_DC_GC_65_67_68_Ep3_EB = S_JoinLobbyT<LobbyFlags, PlayerLobbyDataDCGC, PlayerDispDataDCPCV3>;
using S_JoinLobby_BB_65_67_68 = S_JoinLobbyT<LobbyFlags, PlayerLobbyDataBB, PlayerDispDataBB>; using S_JoinLobby_BB_65_67_68 = S_JoinLobbyT<LobbyFlags, PlayerLobbyDataBB, PlayerDispDataBB>;
@@ -1523,7 +1524,7 @@ struct C_ConnectionInfo_DCNTE_8A {
// client responds with an 8B command. // client responds with an 8B command.
// 8A (C->S): Request lobby/game name (except DC NTE) // 8A (C->S): Request lobby/game name (except DC NTE)
// No arguments // No arguments.
// 8A (S->C): Lobby/game name (except DC NTE) // 8A (S->C): Lobby/game name (except DC NTE)
// Contents is a string containing the lobby or game name. All versions after DCv1 send an 8A command to request the // Contents is a string containing the lobby or game name. All versions after DCv1 send an 8A command to request the
@@ -1576,7 +1577,7 @@ struct C_LoginV1_DC_PC_V3_90 {
// despite its size not being a multiple of 4. This is fixed in later versions, so we have to handle both cases. // despite its size not being a multiple of 4. This is fixed in later versions, so we have to handle both cases.
} __packed_ws__(C_LoginV1_DC_PC_V3_90, 0x22); } __packed_ws__(C_LoginV1_DC_PC_V3_90, 0x22);
// 90 (S->C): Account verification result (V3) // 90 (S->C): Account verification result (DC/PC/V3)
// Behaves exactly the same as 9A (S->C). No arguments except header.flag. // Behaves exactly the same as 9A (S->C). No arguments except header.flag.
// 91 (S->C): Start encryption at login server (legacy; non-BB only) // 91 (S->C): Start encryption at login server (legacy; non-BB only)
@@ -1604,7 +1605,7 @@ struct C_RegisterV1_DC_92 {
// Internal name: RcvPsoRegist // Internal name: RcvPsoRegist
// Same format and usage as 9C (S->C) command. // Same format and usage as 9C (S->C) command.
// 93 (C->S): Log in (DCv1) // 93 (C->S): Log in (DCv1, BB)
struct C_LoginV1_DC_93 { struct C_LoginV1_DC_93 {
/* 00 */ le_uint32_t player_tag = 0x00010000; /* 00 */ le_uint32_t player_tag = 0x00010000;
@@ -1627,8 +1628,6 @@ struct C_LoginExtendedV1_DC_93 : C_LoginV1_DC_93 {
SC_MeetUserExtension_DC_V3 extension; SC_MeetUserExtension_DC_V3 extension;
} __packed_ws__(C_LoginExtendedV1_DC_93, 0x110); } __packed_ws__(C_LoginExtendedV1_DC_93, 0x110);
// 93 (C->S): Log in (BB)
struct C_LoginBase_BB_93 { struct C_LoginBase_BB_93 {
/* 00 */ le_uint32_t player_tag = 0x00010000; /* 00 */ le_uint32_t player_tag = 0x00010000;
/* 04 */ le_uint32_t guild_card_number = 0; /* 04 */ le_uint32_t guild_card_number = 0;
@@ -1674,7 +1673,7 @@ struct C_LoginWithHardwareInfo_BB_93 : C_LoginBase_BB_93 {
// 95 (S->C): Request player data // 95 (S->C): Request player data
// Internal name: RcvRecognition // Internal name: RcvRecognition
// No arguments // No arguments.
// For some reason, some servers send high values in the header.flag field here. The header.flag field is completely // For some reason, some servers send high values in the header.flag field here. The header.flag field is completely
// unused by the client, however - sending zero works just fine. The original Sega servers had some uninitialized // unused by the client, however - sending zero works just fine. The original Sega servers had some uninitialized
// memory bugs, of which that may have been one, and other private servers may have just duplicated Sega's behavior. // memory bugs, of which that may have been one, and other private servers may have just duplicated Sega's behavior.
@@ -1698,7 +1697,7 @@ struct C_CharSaveInfo_DCv2_PC_V3_BB_96 {
// 97 (S->C): Save to memory card // 97 (S->C): Save to memory card
// Internal name: RcvSaveCountCheck // Internal name: RcvSaveCountCheck
// No arguments // No arguments.
// Internally, this command is called RcvSaveCountCheck, even though the counter in the 96 command (to which 97 is a // Internally, this command is called RcvSaveCountCheck, even though the counter in the 96 command (to which 97 is a
// reply) counts more events than saves. Sending this command with header.flag == 0 will show a message saying that // reply) counts more events than saves. Sending this command with header.flag == 0 will show a message saying that
// "character data was improperly saved", and will delete the character's items and challenge mode records. newserv // "character data was improperly saved", and will delete the character's items and challenge mode records. newserv
@@ -1718,7 +1717,7 @@ struct C_CharSaveInfo_DCv2_PC_V3_BB_96 {
// 99 (C->S): Server time accepted // 99 (C->S): Server time accepted
// Internal name: SndPsoDirList // Internal name: SndPsoDirList
// No arguments // No arguments.
// This command's internal name suggests that it's actually a request for the ship select menu, but it's only sent as // This command's internal name suggests that it's actually a request for the ship select menu, but it's only sent as
// the response to a B1 command (server time) and the client doesn't set any state to indicate it's waiting for a ship // the response to a B1 command (server time) and the client doesn't set any state to indicate it's waiting for a ship
// select menu, so we just treat it as confirmation of a received B1 command instead. // select menu, so we just treat it as confirmation of a received B1 command instead.
@@ -1763,14 +1762,13 @@ struct C_Login_DC_PC_V3_9A {
// 13 = servers under maintenance (118) // 13 = servers under maintenance (118)
// Seems like most (all?) of the rest of the codes are "network error" (119). // Seems like most (all?) of the rest of the codes are "network error" (119).
// 9B (S->C): Secondary server init (non-BB, non-DCv1) // 9B (S->C): Secondary server init (DCv2 and later)
// Behaves exactly the same as 17 (S->C). // On versions before BB, this command behaves exactly the same as 17 (S->C).
// On BB, the format of this command is the same as 03 (and the client uses the same encryption afterward). The only
// 9B (S->C): Secondary server init (BB) // differences are:
// Format is the same as 03 (and the client uses the same encryption afterward). The only differences:
// - 9B does not work during the data-server phase (before the client has reached the ship select menu), but 03 does. // - 9B does not work during the data-server phase (before the client has reached the ship select menu), but 03 does.
// - For command 9B, the copyright string must be "PSO NEW PM Server. Copyright 1999-2002 SONICTEAM.". // - For command 9B, the copyright string must be "PSO NEW PM Server. Copyright 1999-2002 SONICTEAM.".
// - The client will respond to 9B with DB instead of 93. // - The client will respond to this command with a DB command instead of a 93 command.
// 9C (C->S): Register // 9C (C->S): Register
// Internal name: SndPsoRegist // Internal name: SndPsoRegist
@@ -1826,13 +1824,13 @@ struct C_Login_DC_PC_GC_9D {
/* 08 */ be_uint64_t hardware_id; /* 08 */ be_uint64_t hardware_id;
/* 10 */ le_uint32_t sub_version = 0; /* 10 */ le_uint32_t sub_version = 0;
/* 14 */ uint8_t is_extended = 0; // If 1, structure has extended format /* 14 */ uint8_t is_extended = 0; // If 1, structure has extended format
/* 15 */ Language language = Language::JAPANESE; // 0 = JP, 1 = EN, 2 = DE, 3 = FR, 4 = ES /* 15 */ Language language = Language::JAPANESE;
/* 16 */ parray<uint8_t, 0x2> unused3; // Always zeroes /* 16 */ parray<uint8_t, 0x2> unused3; // Always zeroes
/* 18 */ pstring<TextEncoding::ASCII, 0x10> v1_serial_number; /* 18 */ pstring<TextEncoding::ASCII, 0x10> v1_serial_number;
/* 28 */ pstring<TextEncoding::ASCII, 0x10> v1_access_key; /* 28 */ pstring<TextEncoding::ASCII, 0x10> v1_access_key;
/* 38 */ pstring<TextEncoding::ASCII, 0x10> serial_number; // On XB, this is the XBL gamertag /* 38 */ pstring<TextEncoding::ASCII, 0x10> serial_number; // On XB, this is the XBL gamertag
/* 48 */ pstring<TextEncoding::ASCII, 0x10> access_key; // On XB, this is the XBL user ID /* 48 */ pstring<TextEncoding::ASCII, 0x10> access_key; // On XB, this is the XBL user ID
/* 58 */ pstring<TextEncoding::ASCII, 0x30> serial_number2; // On DCv2, this is the hardware ID; on XB, this is the XBL gamertag /* 58 */ pstring<TextEncoding::ASCII, 0x30> serial_number2; // DCv2: hardware ID; XB: XBL gamertag
/* 88 */ pstring<TextEncoding::ASCII, 0x30> access_key2; // On XB, this is the XBL user ID /* 88 */ pstring<TextEncoding::ASCII, 0x30> access_key2; // On XB, this is the XBL user ID
/* B8 */ pstring<TextEncoding::ASCII, 0x10> login_character_name; /* B8 */ pstring<TextEncoding::ASCII, 0x10> login_character_name;
/* C8 */ /* C8 */
@@ -1936,7 +1934,7 @@ struct C_ChangeShipOrBlock_A0_A1 {
// Same as 07 command. // Same as 07 command.
// A2 (C->S): Request quest menu // A2 (C->S): Request quest menu
// No arguments // No arguments.
// A2 (S->C): Quest menu // A2 (S->C): Quest menu
// Client will respond with an 09, 10, or A9 command. For 09, the server should send the category or quest description // Client will respond with an 09, 10, or A9 command. For 09, the server should send the category or quest description
@@ -2014,7 +2012,7 @@ struct S_QuestMenuEntry_BB_A2_A4 {
// A9 (C->S): Quest menu closed (canceled) // A9 (C->S): Quest menu closed (canceled)
// Internal name: SndQuestEnd // Internal name: SndQuestEnd
// No arguments // No arguments.
// This command is sent when the in-game quest menu (A2) is closed. This is used by the server to unlock the game if // This command is sent when the in-game quest menu (A2) is closed. This is used by the server to unlock the game if
// the players don't select a quest, since players are forbidden from joining while the quest menu is open. When the // the players don't select a quest, since players are forbidden from joining while the quest menu is open. When the
// download quest menu is closed, either by downloading a quest or canceling, the client sends A0 instead. // download quest menu is closed, either by downloading a quest or canceling, the client sends A0 instead.
@@ -2148,7 +2146,7 @@ struct S_RankUpdate_Ep3_B7 {
} __packed_ws__(S_RankUpdate_Ep3_B7, 0x1C); } __packed_ws__(S_RankUpdate_Ep3_B7, 0x1C);
// B7 (C->S): Confirm rank update (Episode 3) // B7 (C->S): Confirm rank update (Episode 3)
// No arguments // No arguments.
// The client sends this after it receives a B7 from the server. // The client sends this after it receives a B7 from the server.
// B8 (S->C): Update card definitions (Episode 3) // B8 (S->C): Update card definitions (Episode 3)
@@ -2159,7 +2157,7 @@ struct S_RankUpdate_Ep3_B7 {
// Note: PSO BB accepts this command as well, but ignores it. // Note: PSO BB accepts this command as well, but ignores it.
// B8 (C->S): Confirm updated card definitions (Episode 3) // B8 (C->S): Confirm updated card definitions (Episode 3)
// No arguments // No arguments.
// The client sends this after it receives a B8 from the server. // The client sends this after it receives a B8 from the server.
// B8 (C->S): Valid but ignored (BB) // B8 (C->S): Valid but ignored (BB)
@@ -2457,21 +2455,33 @@ struct S_ConfirmTournamentEntry_Ep3_CC {
// CF: Invalid command // CF: Invalid command
// D0 (C->S): Start trade sequence (V3/BB) // D0 (C->S): Start trade sequence (V3/BB)
// The trade window sequence is a bit complicated. On pre-BB versions, the normal flow is: // The trade window sequence is a bit complicated. On pre-BB versions, the sequence is:
// - Clients sync trade state with 6xA6 commands // - Clients sync trade state with 6xA6 commands
// - When both have confirmed, one client (the initiator) sends D0 // - When both have confirmed, one client (the initiator) sends D0 with the items it intends to give to the other
// - The server sends D1 to the other client (the responder) // player (the responder)
// - The responder sends D0 // - The server sends D1 to the responder
// - The responder sends D0 with its own item list
// - The server sends D1 to both clients // - The server sends D1 to both clients
// - Both clients delete the sent items from their inventories and send the appropriate subcommand (6x29) // - Both clients delete the sent items from their inventories and send the appropriate subcommands (6x29)
// - Both clients send D2; similarly to how AC works, the server doesn't proceed until both D2 commands are received // - Both clients send D2; similarly to how AC works, the server doesn't proceed until both D2 commands are received
// - The server sends D3 to both clients with each other's data from their D0 commands, followed immediately by D4 01 // - The server sends D3 to both clients with each other's data from their D0 commands, followed immediately by D4 01
// to both clients, which completes the trade // to both clients, which completes the trade
// - Both clients send the appropriate subcommand to create inventory items // - Both clients send the appropriate subcommands to create inventory items (6x5E)
// On BB, the flow is similar, except after both D2 commands are received, the server instead handles the rest of the // On BB, the sequence is:
// process - it sends 6x29 commands to delete the inventory items and 6xBE to create the traded items. // - Clients sync trade state with 6xA6 commands
// At any point if an error occurs, either client may send a D4 00, which cancels the entire sequence. The server // - When both have confirmed, one client (the initiator) sends D0 with the items it intends to give to the other
// should then send D4 00 to both clients. // player (the responder)
// - The server sends D1 to the responder
// - The responder sends D0 with its own item list
// - The server sends D1 to both clients
// - Both clients send D2; similarly to how AC works, the server doesn't proceed until both D2 commands are received
// - The server executes the trade by sending 6x29 for each item given away from each player, followed by 6xBE to
// create each item in the other player's inventory (note that all 6x29 commands must be sent before any 6xBE
// command, since the client's item state may desync if one player's inventory is full and they receive a 6xBE)
// - The server sends D3 followed immediately by D4 01 to both clients, which completes the trade; unlike in the pre-BB
// case, the D3 commands are empty (no item list is sent)
// At any point if an error occurs, either client may send D4 00, which cancels the entire sequence. The server should
// then send D4 00 to both clients.
struct SC_TradeItems_D0_D3 { // D0 when sent by client, D3 when sent by server struct SC_TradeItems_D0_D3 { // D0 when sent by client, D3 when sent by server
le_uint16_t target_client_id = 0; le_uint16_t target_client_id = 0;
@@ -2492,19 +2502,20 @@ struct SC_TradeItems_D0_D3 { // D0 when sent by client, D3 when sent by server
// On BB, this command has no arguments (and the server generates the appropriate delete and create inventory item // On BB, this command has no arguments (and the server generates the appropriate delete and create inventory item
// commands), but the D3 command must still must be sent before the D4 command to advance the trade state. // commands), but the D3 command must still must be sent before the D4 command to advance the trade state.
// D4 (C->S): Trade failed (V3/BB) // D4 (C->S): Cancel/fail trade sequence (V3/BB)
// No arguments. See the description of D0 for usage information. // No arguments. See the description of D0 for usage information.
// D4 (S->C): Trade complete (V3/BB) // D4 (S->C): Trade complete (V3/BB)
// header.flag must be 0 (trade failed) or 1 (trade complete). See the description of D0 for usage information. // header.flag must be 0 (trade failed) or 1 (trade complete). See the description of D0 for usage information.
// D5: Large message box (V3/BB) // D5 (S->C): Large message box (V3/BB)
// Same as 1A command, except the maximum length of the message is 0x1000 bytes. On BB, this command is not valid // Same as 1A command, except the maximum length of the message is 0x1000 bytes. On BB, this command is not valid
// during the data server phase (whereas 1A is valid there). The BB client ignores all D5 commands after the first one // during the data server phase (whereas 1A is valid there). The BB client ignores all D5 commands after the first one
// sent in each connection; this logic does not apply to 1A. // sent in each connection; this logic does not apply to 1A. This logic was added for some reason in BB; V3 does not
// have this restriction.
// D6 (C->S): Large message box closed (V3) // D6 (C->S): Large message box closed (V3)
// No arguments // No arguments.
// DC, PC, and BB do not send this command at all. GC US v1.0 and v1.1 will send this command when any large message // DC, PC, and BB do not send this command at all. GC US v1.0 and v1.1 will send this command when any large message
// box (1A/D5) is closed; GC Plus and Episode 3 will send D6 only for large message boxes that occur before the client // box (1A/D5) is closed; GC Plus and Episode 3 will send D6 only for large message boxes that occur before the client
// has joined a lobby. (After joining a lobby, large message boxes will still be displayed if sent by the server, but // has joined a lobby. (After joining a lobby, large message boxes will still be displayed if sent by the server, but
@@ -2523,7 +2534,7 @@ struct C_GBAGameRequest_V3_D7 {
} __packed_ws__(C_GBAGameRequest_V3_D7, 0x10); } __packed_ws__(C_GBAGameRequest_V3_D7, 0x10);
// D7 (S->C): GBA file not found (V3/BB) // D7 (S->C): GBA file not found (V3/BB)
// No arguments // No arguments.
// This command is not valid on PSO GC Episodes 1&2 Trial Edition. PSO BB accepts but completely ignores this command. // This command is not valid on PSO GC Episodes 1&2 Trial Edition. PSO BB accepts but completely ignores this command.
// This command tells the client that the file it requested via a D7 command does not exist. This causes the F8C1 // This command tells the client that the file it requested via a D7 command does not exist. This causes the F8C1
// (get_dl_status) quest opcode to return 0 (file not found), rather than 1 (download in progress) or 2 (complete). // (get_dl_status) quest opcode to return 0 (file not found), rather than 1 (download in progress) or 2 (complete).
@@ -2554,7 +2565,10 @@ check_struct_size(S_InfoBoardEntry_BB_D8, 0x178);
// This command is not valid on PSO GC Episodes 1&2 Trial Edition. // This command is not valid on PSO GC Episodes 1&2 Trial Edition.
// DB (C->S): Verify license (V3/BB) // DB (C->S): Verify license (V3/BB)
// Server should respond with a 9A command. // Server should respond with a 9A command. But Insignia's proxy never sends this command to the remote server, so
// newserv will only see this command from an Xbox client if it's connected through a different Xbox Live
// implementation. For this reason, newserv does not check the credentials when it receives DB from an Xbox client; it
// instead sends 9A and checks the credentials when the client subsequently sends 9E.
struct C_VerifyAccount_V3_DB { struct C_VerifyAccount_V3_DB {
pstring<TextEncoding::ASCII, 0x10> v1_serial_number; // Unused pstring<TextEncoding::ASCII, 0x10> v1_serial_number; // Unused
@@ -3161,7 +3175,7 @@ struct SC_TeamChat_BB_07EA {
} __packed_ws__(SC_TeamChat_BB_07EA, 0x20); } __packed_ws__(SC_TeamChat_BB_07EA, 0x20);
// 08EA (C->S): Get team member list // 08EA (C->S): Get team member list
// No arguments // No arguments.
// 09EA (S->C): Team member list // 09EA (S->C): Team member list
@@ -3188,7 +3202,7 @@ struct S_Unknown_BB_0CEA {
} __packed_ws__(S_Unknown_BB_0CEA, 0x20); } __packed_ws__(S_Unknown_BB_0CEA, 0x20);
// 0DEA (C->S): Get team name // 0DEA (C->S): Get team name
// No arguments // No arguments.
// 0EEA (S->C): Team name // 0EEA (S->C): Team name
@@ -3251,7 +3265,7 @@ struct S_TeamInfoForPlayer_BB_13EA_15EA_Entry {
// No arguments except header.flag, which is zero if the transfer failed or nonzero if it succeeded. // No arguments except header.flag, which is zero if the transfer failed or nonzero if it succeeded.
// 18EA: Intra-team ranking information // 18EA: Intra-team ranking information
// No arguments (C->S) // No arguments (C->S).
struct S_IntraTeamRanking_BB_18EA { struct S_IntraTeamRanking_BB_18EA {
/* 0000 */ le_uint32_t ranking_points = 0; /* 0000 */ le_uint32_t ranking_points = 0;
@@ -3271,7 +3285,7 @@ struct S_IntraTeamRanking_BB_18EA {
} __packed_ws__(S_IntraTeamRanking_BB_18EA, 0x10); } __packed_ws__(S_IntraTeamRanking_BB_18EA, 0x10);
// 19EA: Team reward list // 19EA: Team reward list
// No arguments (C->S) // No arguments (C->S).
struct S_TeamRewardList_BB_19EA_1AEA { struct S_TeamRewardList_BB_19EA_1AEA {
le_uint32_t num_entries; le_uint32_t num_entries;
@@ -3434,7 +3448,7 @@ struct S_AdvanceCardTradeState_Ep3_EE_FlagD1 {
} __packed_ws__(S_AdvanceCardTradeState_Ep3_EE_FlagD1, 4); } __packed_ws__(S_AdvanceCardTradeState_Ep3_EE_FlagD1, 4);
// EE D2 (C->S): Trade can proceed // EE D2 (C->S): Trade can proceed
// No arguments // No arguments.
// EE D3 (S->C): Execute trade // EE D3 (S->C): Execute trade
// Same format as EE D0 // Same format as EE D0
@@ -3710,6 +3724,49 @@ struct G_UpdateEnemyStateT_6x0A {
G_EntityIDHeader header; G_EntityIDHeader header;
le_uint16_t enemy_index = 0; // [0, 0xB50) le_uint16_t enemy_index = 0; // [0, 0xB50)
le_uint16_t total_damage = 0; le_uint16_t total_damage = 0;
// The bits in game_flags mean (all addresses in TODOs are for 3OE1):
// 00000001 = is poisoned
// 00000002 = is paralyzed
// 00000004 = is shocked
// 00000008 = is slow
// 00000010 = is confused
// 00000020 = is frozen
// 00000040 = cures and prevents all negative status effects
// 00000080 = appears to be unused (TODO: look for any usage of this flag)
// 00000100 = missed by attack (often set immediately before showing red "MISS" text)
// 00000200 = hit by attack (causes flinch for most enemies)
// 00000400 = last hit did damage greater than 25% of enemy's max HP (some enemies don't clear this)
// 00000800 = is dead (when set for most enemies, plays the death animation and then destroys the enemy)
// 00001000 = unknown (TODO: see TObjEnemyV8048ee80_v1C, TObjEnemyV8048ee80_v3B, TObjEneDolmOlm_v3B)
// 00002000 = unknown (TODO: see TObjGrass_v1E, 8011EA08, TObjEneIllGill_v1E, TObjEneIllGill_init)
// 00004000 = unknown (TODO: has status effect in slot 5; De Rol Le uses this; Vol Opt uses it too at
// TBoss3Volopt_update, TBoss3VoloptCore_update, TBoss3VoloptP01_update, TBoss3VolOptP02_update,
// TObjectV8047c128_v39, TObjectV8047c128_v38; related to paralysis somehow? see
// TObjectV8047c128_v24_update_paralysis_effect)
// 00008000 = immune to freeze (TODO: see TBoss3VolOptP02_init_inner; maybe other things use it too)
// 00010000 = unknown (TODO: see 801BA1F8)
// 00020000 = can't attack, cast techs, or use items (e.g. Vol Opt cage and Ruins falling traps set this)
// 00040000 = untargetable (e.g. TObjEneBeast sets this at construction time; it's cleared when it roars)
// 00080000 = appears to be unused (TODO: look for any usage of this flag)
// 00100000 = for players, is near enemy; for some enemies, is activated (not set if in idle animations, e.g. for
// TObjEneBeast and related classes) (unverified on v2)
// 00200000 = is attacking? (TODO: also set when TObjEneMoja is jumping though; also see TObjEnemyV8048ee80_v3C,
// TObjEneMerillLia_v3C, TObjEneSaver_v3A)
// 00400000 = unknown (TODO: see TOSensor_vF, 801CC358, 801CD224)
// 00800000 = affected by gravity? can be aerial? (wolves don't have this, perhaps their jumps are hardcoded; see
// TObjEnemyV8048ee80_v5B) (unverified on v2)
// 01000000 = immune to shock and freeze and paralysis (for Canadine/Mothmant/etc, only set when they're higher
// than player level; TODO: maybe other things too; also used by TObjPlayer, see 801B84B4; also has a
// meaning for weapons, see TItemWeapon_v10) (unverified on v2)
// 02000000 = invisible (also suppresses particles, some sounds, and hit/miss text)
// 04000000 = temporarily invincible (e.g. Dragon while it roars to advance to phase 2) (unverified on v2)
// 08000000 = unknown (TODO; see 80113384, TItemMag_v1B, TItemMag_v1A, 801182B0, TObjPlayer_render; probably
// graphical effects only)
// 10000000 = entity is player
// 20000000 = entity is enemy
// 40000000 = entity is object (some entities have both this and 20000000 set; this appears to make TWindowLockOn
// not show anything but the entity is still attackable, see TWindowLockOn_should_show_for_entity)
// 80000000 = entity is item
typename std::conditional_t<BE, be_uint32_t, le_uint32_t> game_flags = 0; typename std::conditional_t<BE, be_uint32_t, le_uint32_t> game_flags = 0;
} __attribute__((packed)); } __attribute__((packed));
using G_UpdateEnemyState_GC_6x0A = G_UpdateEnemyStateT_6x0A<true>; using G_UpdateEnemyState_GC_6x0A = G_UpdateEnemyStateT_6x0A<true>;
@@ -3726,13 +3783,14 @@ struct G_UpdateObjectState_6x0B {
} __packed_ws__(G_UpdateObjectState_6x0B, 0x0C); } __packed_ws__(G_UpdateObjectState_6x0B, 0x0C);
// 6x0C: Add status effect (poison/slow/etc.) (protected on V3/V4) // 6x0C: Add status effect (poison/slow/etc.) (protected on V3/V4)
// 6x0D: Remove status effect (protected on V3/V4)
struct G_AddStatusEffect_6x0C { struct G_AddOrRemoveStatusEffect_6x0C_6x0D {
G_ClientIDHeader header; G_ClientIDHeader header;
// Each status effect has an assigned slot; there are 5 slots and each slot may only hold one effect at a time. (The // Each status effect has an assigned slot; there are 5 slots and each slot may only hold one effect at a time. (The
// last slot, slot 4, is unused.) If a new status effect is added to a slot that already contains one, the existing // last slot, slot 4, may be used by certain boss effects; this is unconfirmed.) If a new status effect is added to a
// status effect is replaced. Non-technique status effects have fixed or indefinite durations; technique-based // slot that already contains one, the existing status effect is replaced. Non-technique status effects have fixed or
// effects have durations based on the technique's level. // indefinite durations; technique-based effects have durations based on the technique's level.
// Values for effect_type: // Values for effect_type:
// 02 = Freeze (slot 1; 5 seconds) // 02 = Freeze (slot 1; 5 seconds)
// 03 = Shock (slot 1; 10 seconds) // 03 = Shock (slot 1; 10 seconds)
@@ -3747,16 +3805,8 @@ struct G_AddStatusEffect_6x0C {
// 12 = Confuse (slot 1; 10 seconds) // 12 = Confuse (slot 1; 10 seconds)
// Anything else = command is ignored // Anything else = command is ignored
le_uint32_t effect_type = 0; le_uint32_t effect_type = 0;
le_float amount = 0; // Only used for Shifta/Deband/Jellen/Zalure le_float amount = 0; // Only used in 6x0C for Shifta/Deband/Jellen/Zalure; unused in 6x0D
} __packed_ws__(G_AddStatusEffect_6x0C, 0x0C); } __packed_ws__(G_AddOrRemoveStatusEffect_6x0C_6x0D, 0x0C);
// 6x0D: Clear status effect slot (protected on V3/V4)
struct G_RemoveStatusEffect_6x0D {
G_ClientIDHeader header;
le_uint32_t slot = 0; // See 6x0C description for slot values
le_uint32_t unused = 0;
} __packed_ws__(G_RemoveStatusEffect_6x0D, 0x0C);
// 6x0E: Clear all negative status effects (protected on V3/V4) // 6x0E: Clear all negative status effects (protected on V3/V4)
// It seems that the client never sends this command. // It seems that the client never sends this command.
@@ -3873,7 +3923,7 @@ struct G_DisablePKModeForPlayer_6x1C {
// 6x1D: Request partial player data (pre-v1 only) // 6x1D: Request partial player data (pre-v1 only)
// The subcommand number 6x1D is not used in any final version of PSO; this number is assigned based on what the // The subcommand number 6x1D is not used in any final version of PSO; this number is assigned based on what the
// command number would be if it were. On DC NTE, this is subcommand 6x19; on 11/2000, it's 6x1B. This command does not // command number would be if it were. On DC NTE, this is subcommand 6x19; on 11/2000, it's 6x1B. This command does not
// appear to ever be sent by the client; however, it will respond with 6x1E if it receives this command. // appear to ever be sent by the client; however, it will respond with a 6x1E command if it receives this command.
struct G_RequestPartialPlayerData_DCProtos_6x1D { struct G_RequestPartialPlayerData_DCProtos_6x1D {
G_UnusedHeader header; G_UnusedHeader header;
@@ -4045,8 +4095,8 @@ struct G_ChangePlayerHP_6x2F {
} __packed_ws__(G_ChangePlayerHP_6x2F, 0x0C); } __packed_ws__(G_ChangePlayerHP_6x2F, 0x0C);
// 6x30: Change player level (protected on GC NTE/V3 but not V4) // 6x30: Change player level (protected on GC NTE/V3 but not V4)
// On DC NTE, the updated stats aren't sent, and the client may only gain a single level at once. On other versions, // On DC NTE and 11/2000, the updated stats aren't sent, and the client may only gain a single level at once. On other
// this is not the case. // versions, this is not the case.
struct G_ChangePlayerLevel_DCNTE_6x30 { struct G_ChangePlayerLevel_DCNTE_6x30 {
G_ClientIDHeader header; G_ClientIDHeader header;
@@ -4112,7 +4162,7 @@ struct G_Unknown_6x36 {
struct G_PhotonBlast_6x37 { struct G_PhotonBlast_6x37 {
G_ClientIDHeader header; G_ClientIDHeader header;
le_uint16_t unknown_a1 = 0; le_uint16_t amount = 0; // Amount of PB energy to expend (ignored by client upon receipt)
le_uint16_t unused = 0; le_uint16_t unused = 0;
} __packed_ws__(G_PhotonBlast_6x37, 8); } __packed_ws__(G_PhotonBlast_6x37, 8);
@@ -4199,7 +4249,9 @@ struct G_SetPosition_6x3F {
struct G_WalkToPosition_6x40 { struct G_WalkToPosition_6x40 {
G_ClientIDHeader header; G_ClientIDHeader header;
VectorXZF pos; VectorXZF pos;
le_uint32_t action = 0; // In the flags field, bit 00000008 is set if game_flag 00100000 is set (same as is_near_enemy in 6x3E and 6x3F). The
// meanings of the other bits are unknown.
le_uint32_t flags = 0;
} __packed_ws__(G_WalkToPosition_6x40, 0x10); } __packed_ws__(G_WalkToPosition_6x40, 0x10);
// 6x41: Move to position (v1) // 6x41: Move to position (v1)
@@ -4277,8 +4329,8 @@ struct G_ShieldAttack_6x4A {
G_ClientIDHeader header; G_ClientIDHeader header;
} __packed_ws__(G_ShieldAttack_6x4A, 4); } __packed_ws__(G_ShieldAttack_6x4A, 4);
// 6x4B: Hit by enemy (protected on GC NTE/V3/V4) // 6x4B: Minor hit by enemy (<= 25% of max HP; protected on GC NTE/V3/V4)
// 6x4C: Hit by enemy (protected on GC NTE/V3/V4) // 6x4C: Major hit by enemy (> 25% of max HP; protected on GC NTE/V3/V4)
struct G_HitByEnemy_6x4B_6x4C { struct G_HitByEnemy_6x4B_6x4C {
G_ClientIDHeader header; G_ClientIDHeader header;
@@ -4380,7 +4432,7 @@ struct G_Unknown_6x57 {
struct G_LobbyAnimation_6x58 { struct G_LobbyAnimation_6x58 {
G_ClientIDHeader header; G_ClientIDHeader header;
le_uint16_t animation_number = 0; le_uint16_t animation_number = 0;
le_uint16_t unused = 0; le_uint16_t flags = 0; // 0 = normal, 1 = use opposite gender's animation
} __packed_ws__(G_LobbyAnimation_6x58, 8); } __packed_ws__(G_LobbyAnimation_6x58, 8);
// 6x59: Pick up item // 6x59: Pick up item
@@ -4675,7 +4727,7 @@ struct G_6x70_Sub_Telepipe {
struct G_6x70_Base_DCNTE { struct G_6x70_Base_DCNTE {
/* 0000 */ le_uint16_t client_id = 0; /* 0000 */ le_uint16_t client_id = 0;
/* 0002 */ le_uint16_t room_id = 0; /* 0002 */ le_uint16_t room_id = 0;
/* 0004 */ le_uint32_t flags1 = 0; /* 0004 */ le_uint32_t game_flags = 0;
/* 0008 */ VectorXYZF pos; /* 0008 */ VectorXYZF pos;
/* 0014 */ VectorXYZI angle; /* 0014 */ VectorXYZI angle;
/* 0020 */ le_uint16_t phase = 0; /* 0020 */ le_uint16_t phase = 0;
@@ -4683,41 +4735,39 @@ struct G_6x70_Base_DCNTE {
} __packed_ws__(G_6x70_Base_DCNTE, 0x24); } __packed_ws__(G_6x70_Base_DCNTE, 0x24);
struct G_SyncPlayerDispAndInventory_DCNTE_6x70 { struct G_SyncPlayerDispAndInventory_DCNTE_6x70 {
// Offsets in this struct are relative to the overall command header /* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x60, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DCNTE_6x70)};
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x60, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DCNTE_6x70)}; /* 0008 */ G_6x70_Base_DCNTE base;
/* 000C */ G_6x70_Base_DCNTE base;
// The following two fields appear to contain uninitialized data // The following two fields appear to contain uninitialized data
/* 0030 */ le_uint32_t unknown_a5 = 0; /* 002C */ le_uint32_t unknown_a5 = 0;
/* 0034 */ le_uint32_t unknown_a6 = 0; /* 0030 */ le_uint32_t unknown_a6 = 0;
/* 0038 */ G_6x70_Sub_Telepipe telepipe; /* 0034 */ G_6x70_Sub_Telepipe telepipe;
/* 0054 */ le_uint32_t death_flags = 0; /* 0050 */ le_uint32_t death_flags = 0;
/* 0058 */ PlayerHoldState_DCProtos hold_state; /* 0054 */ PlayerHoldState_DCProtos hold_state;
/* 0068 */ le_uint32_t area = 0; /* 0064 */ le_uint32_t area = 0;
/* 006C */ le_uint32_t game_flags = 0; /* 0068 */ le_uint32_t player_flags = 0;
/* 0070 */ PlayerVisualConfig visual; /* 006C */ PlayerVisualConfig visual;
/* 00C0 */ PlayerStats stats; /* 00BC */ PlayerStats stats;
/* 00E4 */ le_uint32_t num_items = 0; /* 00E0 */ le_uint32_t num_items = 0;
/* 00E8 */ parray<PlayerInventoryItem, 0x1E> items; /* 00E4 */ parray<PlayerInventoryItem, 0x1E> items;
/* 0430 */ /* 042C */
} __packed_ws__(G_SyncPlayerDispAndInventory_DCNTE_6x70, 0x42C); } __packed_ws__(G_SyncPlayerDispAndInventory_DCNTE_6x70, 0x42C);
struct G_SyncPlayerDispAndInventory_DC112000_6x70 { struct G_SyncPlayerDispAndInventory_DC112000_6x70 {
// Offsets in this struct are relative to the overall command header /* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x67, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC112000_6x70)};
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x67, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC112000_6x70)}; /* 0008 */ G_6x70_Base_DCNTE base;
/* 000C */ G_6x70_Base_DCNTE base; /* 002C */ le_uint16_t bonus_hp_from_materials = 0;
/* 0030 */ le_uint16_t bonus_hp_from_materials = 0; /* 002E */ le_uint16_t bonus_tp_from_materials = 0;
/* 0032 */ le_uint16_t bonus_tp_from_materials = 0; /* 0030 */ parray<uint8_t, 0x10> unknown_a5;
/* 0034 */ parray<uint8_t, 0x10> unknown_a5; /* 0040 */ G_6x70_Sub_Telepipe telepipe;
/* 0044 */ G_6x70_Sub_Telepipe telepipe; /* 005C */ le_uint32_t death_flags = 0;
/* 0060 */ le_uint32_t death_flags = 0; /* 0060 */ PlayerHoldState_DCProtos hold_state;
/* 0064 */ PlayerHoldState_DCProtos hold_state; /* 0070 */ le_uint32_t area = 0;
/* 0074 */ le_uint32_t area = 0; /* 0074 */ le_uint32_t player_flags = 0;
/* 0078 */ le_uint32_t game_flags = 0; /* 0078 */ PlayerVisualConfig visual;
/* 007C */ PlayerVisualConfig visual; /* 00C8 */ PlayerStats stats;
/* 00CC */ PlayerStats stats; /* 00EC */ le_uint32_t num_items = 0;
/* 00F0 */ le_uint32_t num_items = 0; /* 00F0 */ parray<PlayerInventoryItem, 0x1E> items;
/* 00F4 */ parray<PlayerInventoryItem, 0x1E> items; /* 0438 */
/* 043C */
} __packed_ws__(G_SyncPlayerDispAndInventory_DC112000_6x70, 0x438); } __packed_ws__(G_SyncPlayerDispAndInventory_DC112000_6x70, 0x438);
struct G_6x70_Base_V1 { struct G_6x70_Base_V1 {
@@ -4728,71 +4778,71 @@ struct G_6x70_Base_V1 {
/* 0034 */ StatusEffectState temporary_status_effect; /* 0034 */ StatusEffectState temporary_status_effect;
/* 0040 */ StatusEffectState attack_status_effect; /* 0040 */ StatusEffectState attack_status_effect;
/* 004C */ StatusEffectState defense_status_effect; /* 004C */ StatusEffectState defense_status_effect;
/* 0058 */ StatusEffectState unused_status_effect; /* 0058 */ StatusEffectState unknown_a1_status_effect;
/* 0064 */ le_uint32_t language32 = 0; /* 0064 */ le_uint32_t language32 = 0;
/* 0068 */ le_uint32_t player_tag = 0; /* 0068 */ le_uint32_t player_tag = 0;
/* 006C */ le_uint32_t guild_card_number = 0; /* 006C */ le_uint32_t guild_card_number = 0;
/* 0070 */ le_uint32_t unknown_a6 = 0; // Probably battle-related (assigned together with battle_team_number) /* 0070 */ le_uint32_t unknown_a6 = 0; // Probably battle-related (assigned together with battle_team_number)
/* 0074 */ le_uint32_t battle_team_number = 0; /* 0074 */ le_uint32_t battle_team_number = 0;
/* 0078 */ G_6x70_Sub_Telepipe telepipe; /* 0078 */ G_6x70_Sub_Telepipe telepipe;
/* 0094 */ le_uint32_t death_flags = 0; // Only a few bits are used. 4 = player is dead // Only a few bits appear to be used in death_flags. Known values:
// 00000001 = should drop weapon/item on death
// 00000002 = does not have any automatic revival item (Scape Doll or Ragol Ring)
// 00000004 = was revived by automatic revival item
/* 0094 */ le_uint32_t death_flags = 0;
/* 0098 */ PlayerHoldState hold_state; /* 0098 */ PlayerHoldState hold_state;
/* 00AC */ le_uint32_t area = 0; /* 00AC */ le_uint32_t area = 0;
/* 00B0 */ le_uint32_t game_flags = 0; /* 00B0 */ le_uint32_t player_flags = 0;
/* 00B4 */ parray<uint8_t, 0x14> technique_levels_v1 = 0xFF; // Last byte is uninitialized /* 00B4 */ parray<uint8_t, 0x14> technique_levels_v1 = 0xFF; // Last byte is uninitialized
/* 00C8 */ PlayerVisualConfig visual; /* 00C8 */ PlayerVisualConfig visual;
/* 0118 */ /* 0118 */
} __packed_ws__(G_6x70_Base_V1, 0x118); } __packed_ws__(G_6x70_Base_V1, 0x118);
struct G_SyncPlayerDispAndInventory_DC_PC_6x70 { struct G_SyncPlayerDispAndInventory_DC_PC_6x70 {
// Offsets in this struct are relative to the overall command header /* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC_PC_6x70)};
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC_PC_6x70)}; /* 0008 */ G_6x70_Base_V1 base;
/* 000C */ G_6x70_Base_V1 base; /* 0120 */ PlayerStats stats;
/* 0124 */ PlayerStats stats; /* 0144 */ le_uint32_t num_items = 0;
/* 0148 */ le_uint32_t num_items = 0; /* 0148 */ parray<PlayerInventoryItem, 0x1E> items;
/* 014C */ parray<PlayerInventoryItem, 0x1E> items; /* 0490 */
/* 0494 */
} __packed_ws__(G_SyncPlayerDispAndInventory_DC_PC_6x70, 0x490); } __packed_ws__(G_SyncPlayerDispAndInventory_DC_PC_6x70, 0x490);
// GC NTE also uses this format. // GC NTE also uses this format
struct G_SyncPlayerDispAndInventory_GC_6x70 { struct G_SyncPlayerDispAndInventory_GC_6x70 {
// Offsets in this struct are relative to the overall command header /* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_GC_6x70)};
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_GC_6x70)}; /* 0008 */ G_6x70_Base_V1 base;
/* 000C */ G_6x70_Base_V1 base; /* 0120 */ PlayerStats stats;
/* 0124 */ PlayerStats stats; /* 0144 */ le_uint32_t num_items = 0;
/* 0148 */ le_uint32_t num_items = 0; /* 0148 */ parray<PlayerInventoryItem, 0x1E> items;
/* 014C */ parray<PlayerInventoryItem, 0x1E> items; /* 0490 */ le_uint32_t floor = 0;
/* 0494 */ le_uint32_t floor = 0; /* 0494 */
/* 0498 */
} __packed_ws__(G_SyncPlayerDispAndInventory_GC_6x70, 0x494); } __packed_ws__(G_SyncPlayerDispAndInventory_GC_6x70, 0x494);
struct G_SyncPlayerDispAndInventory_XB_6x70 { struct G_SyncPlayerDispAndInventory_XB_6x70 {
// Offsets in this struct are relative to the overall command header /* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_XB_6x70)};
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_XB_6x70)}; /* 0008 */ G_6x70_Base_V1 base;
/* 000C */ G_6x70_Base_V1 base; /* 0120 */ PlayerStats stats;
/* 0124 */ PlayerStats stats; /* 0144 */ le_uint32_t num_items = 0;
/* 0148 */ le_uint32_t num_items = 0; /* 0148 */ parray<PlayerInventoryItem, 0x1E> items;
/* 014C */ parray<PlayerInventoryItem, 0x1E> items; /* 0490 */ le_uint32_t floor = 0;
/* 0494 */ le_uint32_t floor = 0; /* 0494 */ le_uint32_t xb_user_id_high = 0;
/* 0498 */ le_uint32_t xb_user_id_high = 0; /* 0498 */ le_uint32_t xb_user_id_low = 0;
/* 049C */ le_uint32_t xb_user_id_low = 0; /* 049C */ le_uint32_t unknown_a16 = 0;
/* 04A0 */ le_uint32_t unknown_a16 = 0; /* 04A0 */
/* 04A4 */
} __packed_ws__(G_SyncPlayerDispAndInventory_XB_6x70, 0x4A0); } __packed_ws__(G_SyncPlayerDispAndInventory_XB_6x70, 0x4A0);
struct G_SyncPlayerDispAndInventory_BB_6x70 { struct G_SyncPlayerDispAndInventory_BB_6x70 {
// Offsets in this struct are relative to the overall command header /* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_BB_6x70)};
/* 0008 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_BB_6x70)}; /* 0008 */ G_6x70_Base_V1 base;
/* 0010 */ G_6x70_Base_V1 base; /* 0120 */ pstring<TextEncoding::UTF16_ALWAYS_MARKED, 0x10> name;
/* 0128 */ pstring<TextEncoding::UTF16_ALWAYS_MARKED, 0x10> name; /* 0140 */ PlayerStats stats;
/* 0148 */ PlayerStats stats; /* 0164 */ le_uint32_t num_items = 0;
/* 016C */ le_uint32_t num_items = 0; /* 0168 */ parray<PlayerInventoryItem, 0x1E> items;
/* 0170 */ parray<PlayerInventoryItem, 0x1E> items; /* 04B0 */ le_uint32_t floor = 0;
/* 04B8 */ le_uint32_t floor = 0; /* 04B4 */ le_uint32_t xb_user_id_high = 0;
/* 04BC */ le_uint32_t xb_user_id_high = 0; /* 04B8 */ le_uint32_t xb_user_id_low = 0;
/* 04C0 */ le_uint32_t xb_user_id_low = 0; /* 04BC */ le_uint32_t unknown_a16 = 0;
/* 04C4 */ le_uint32_t unknown_a16 = 0; /* 04C0 */
/* 04C8 */
} __packed_ws__(G_SyncPlayerDispAndInventory_BB_6x70, 0x4C0); } __packed_ws__(G_SyncPlayerDispAndInventory_BB_6x70, 0x4C0);
// 6x71: Unblock game join (used while loading into game) // 6x71: Unblock game join (used while loading into game)
@@ -4994,6 +5044,8 @@ struct G_EnableDropWeaponOnDeath_6x82 {
struct G_PlaceTrap_6x83 { struct G_PlaceTrap_6x83 {
G_ClientIDHeader header; G_ClientIDHeader header;
le_uint16_t trap_type = 0; le_uint16_t trap_type = 0;
// trap_index is actually the number of traps remaining for this client after setting this one (so it counts backward
// from their total trap count)
le_uint16_t trap_index = 0; le_uint16_t trap_index = 0;
} __packed_ws__(G_PlaceTrap_6x83, 8); } __packed_ws__(G_PlaceTrap_6x83, 8);
@@ -5192,13 +5244,18 @@ struct G_LevelUpAllTechniques_6x9B {
parray<uint8_t, 3> unused; parray<uint8_t, 3> unused;
} __packed_ws__(G_LevelUpAllTechniques_6x9B, 8); } __packed_ws__(G_LevelUpAllTechniques_6x9B, 8);
// 6x9C: Set enemy low game flags (not valid on Episode 3) // 6x9C: Set enemy status effect flags (not valid on Episode 3)
// This command only has an effect in Ultimate mode; it sets the low 6 bits of game_flags (those that match 0x3F). // This command only has an effect in Ultimate mode; it sets the low 6 bits of game_flags (those that match 0x3F). This
// essentially separates status effects from the 6x0A command. It's not clear why Sega did this only in Ultimate mode.
struct G_SetEnemyLowGameFlagsUltimate_6x9C { struct G_SetEnemyLowGameFlagsUltimate_6x9C {
G_EntityIDHeader header; G_EntityIDHeader header;
// A virtual function is called on the enemy if low_game_flags is equal to any of 0x02, 0x04, 0x10, or 0x20. // This field is expected to have one of these values (it should not actually be treated as a bit field):
le_uint32_t low_game_flags = 0; // 0x00000002 = add paralysis status
// 0x00000004 = add shock status
// 0x00000010 = add confuse status
// 0x00000020 = add freeze status
le_uint32_t status_effect_flags = 0;
} __packed_ws__(G_SetEnemyLowGameFlagsUltimate_6x9C, 8); } __packed_ws__(G_SetEnemyLowGameFlagsUltimate_6x9C, 8);
// 6x9D: Set dead flag (Challenge mode; not valid on Episode 3) // 6x9D: Set dead flag (Challenge mode; not valid on Episode 3)
@@ -5389,25 +5446,20 @@ struct G_SetAnimationState_6xAE {
G_ClientIDHeader header; G_ClientIDHeader header;
le_uint16_t animation_number = 0; le_uint16_t animation_number = 0;
le_uint16_t unused = 0; le_uint16_t unused = 0;
// This field contains the flags field on the sender's TObjPlayer object. If the bit 04000000 is set in this field, // This field contains the player_flags field on the sender's TObjPlayer object. If the bit 04000000 is set in this
// then (flags & 1C000000) is or'ed into the TObjPlayer's flags field. All other bits are ignored. // field, then (flags & 1C000000) is or'ed into the TObjPlayer's player_flags field on the receiver's end; all other
le_uint32_t flags = 0; // bits are ignored. (For the meanings of these bits, see Parsed6x70Data::convert_player_flags.)
le_uint32_t player_flags = 0;
le_float animation_timer = 0; le_float animation_timer = 0;
} __packed_ws__(G_SetAnimationState_6xAE, 0x10); } __packed_ws__(G_SetAnimationState_6xAE, 0x10);
// 6xAF: Turn lobby chair (not valid on pre-V3 or GC Trial Edition) (protected on V3/V4) // 6xAF: Turn lobby chair (not valid on pre-V3 or GC Trial Edition) (protected on V3/V4)
struct G_TurnLobbyChair_6xAF {
G_ClientIDHeader header;
le_uint32_t angle = 0; // In range [0x0000, 0xFFFF]
} __packed_ws__(G_TurnLobbyChair_6xAF, 8);
// 6xB0: Move lobby chair (not valid on pre-V3 or GC Trial Edition) (protected on V3/V4) // 6xB0: Move lobby chair (not valid on pre-V3 or GC Trial Edition) (protected on V3/V4)
struct G_MoveLobbyChair_6xB0 { struct G_TurnOrMoveLobbyChair_6xAF_6xB0 {
G_ClientIDHeader header; G_ClientIDHeader header;
le_uint32_t unknown_a1 = 0; le_uint32_t angle = 0; // In range [0x0000, 0xFFFF]
} __packed_ws__(G_MoveLobbyChair_6xB0, 8); } __packed_ws__(G_TurnOrMoveLobbyChair_6xAF_6xB0, 8);
// 6xB1: Unknown (not valid on pre-V3 or GC Trial Edition) // 6xB1: Unknown (not valid on pre-V3 or GC Trial Edition)
// This subcommand is completely ignored. // This subcommand is completely ignored.
@@ -5673,7 +5725,7 @@ struct G_BankAction_BB_6xBD {
G_UnusedHeader header; G_UnusedHeader header;
le_uint32_t item_id = 0; le_uint32_t item_id = 0;
le_uint32_t meseta_amount = 0; le_uint32_t meseta_amount = 0;
uint8_t action = 0; // 0 = deposit, 1 = take, 3 = done (close bank window) uint8_t action = 0; // 0 = deposit, 1 = take, 2 = unknown (compact contents?), 3 = commit (close bank window)
uint8_t item_amount = 0; uint8_t item_amount = 0;
le_uint16_t item_index = 0; // 0xFFFF = meseta le_uint16_t item_index = 0; // 0xFFFF = meseta
} __packed_ws__(G_BankAction_BB_6xBD, 0x10); } __packed_ws__(G_BankAction_BB_6xBD, 0x10);
@@ -6059,7 +6111,7 @@ struct G_SetMesetaSlotPrizeResult_BB_6xE3 {
ItemData item; ItemData item;
} __packed_ws__(G_SetMesetaSlotPrizeResult_BB_6xE3, 0x18); } __packed_ws__(G_SetMesetaSlotPrizeResult_BB_6xE3, 0x18);
// 6xE4: Invalid subcommand (but used as an extension; see end of this file) // 6xE4: Invalid subcommand (but used as a newserv extension; see end of this file)
// 6xE5: Invalid subcommand // 6xE5: Invalid subcommand
// 6xE6: Invalid subcommand // 6xE6: Invalid subcommand
// 6xE7: Invalid subcommand // 6xE7: Invalid subcommand
@@ -6325,7 +6377,7 @@ struct G_SetPlayerDeck_Ep3_CAx14 {
struct G_HardResetServerState_Ep3_CAx15 { struct G_HardResetServerState_Ep3_CAx15 {
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_HardResetServerState_Ep3_CAx15) / 4, 0, 0x15, 0, 0, 0, 0, 0}; G_CardServerDataCommandHeader header = {0xB3, sizeof(G_HardResetServerState_Ep3_CAx15) / 4, 0, 0x15, 0, 0, 0, 0, 0};
// No arguments // No arguments.
} __packed_ws__(G_HardResetServerState_Ep3_CAx15, 0x10); } __packed_ws__(G_HardResetServerState_Ep3_CAx15, 0x10);
// 6xB5x17: Unknown // 6xB5x17: Unknown
@@ -6333,7 +6385,7 @@ struct G_HardResetServerState_Ep3_CAx15 {
struct G_Unknown_Ep3_6xB5x17 { struct G_Unknown_Ep3_6xB5x17 {
G_CardBattleCommandHeader header = {0xB5, sizeof(G_Unknown_Ep3_6xB5x17) / 4, 0, 0x17, 0, 0, 0}; G_CardBattleCommandHeader header = {0xB5, sizeof(G_Unknown_Ep3_6xB5x17) / 4, 0, 0x17, 0, 0, 0};
// No arguments // No arguments.
} __packed_ws__(G_Unknown_Ep3_6xB5x17, 8); } __packed_ws__(G_Unknown_Ep3_6xB5x17, 8);
// 6xB5x1A: Force disconnect // 6xB5x1A: Force disconnect
@@ -6343,7 +6395,7 @@ struct G_Unknown_Ep3_6xB5x17 {
struct G_ForceDisconnect_Ep3_6xB5x1A { struct G_ForceDisconnect_Ep3_6xB5x1A {
G_CardBattleCommandHeader header = {0xB5, sizeof(G_ForceDisconnect_Ep3_6xB5x1A) / 4, 0, 0x1A, 0, 0, 0}; G_CardBattleCommandHeader header = {0xB5, sizeof(G_ForceDisconnect_Ep3_6xB5x1A) / 4, 0, 0x1A, 0, 0, 0};
// No arguments // No arguments.
} __packed_ws__(G_ForceDisconnect_Ep3_6xB5x1A, 8); } __packed_ws__(G_ForceDisconnect_Ep3_6xB5x1A, 8);
// 6xB3x1B / CAx1B: Set player name // 6xB3x1B / CAx1B: Set player name
@@ -6416,7 +6468,7 @@ struct G_EndBattle_Ep3_CAx21 {
struct G_Unknown_Ep3_6xB4x22 { struct G_Unknown_Ep3_6xB4x22 {
G_CardBattleCommandHeader header = {0xB4, sizeof(G_Unknown_Ep3_6xB4x22) / 4, 0, 0x22, 0, 0, 0}; G_CardBattleCommandHeader header = {0xB4, sizeof(G_Unknown_Ep3_6xB4x22) / 4, 0, 0x22, 0, 0, 0};
// No arguments // No arguments.
} __packed_ws__(G_Unknown_Ep3_6xB4x22, 8); } __packed_ws__(G_Unknown_Ep3_6xB4x22, 8);
// 6xB4x23: Unknown // 6xB4x23: Unknown
@@ -6559,7 +6611,7 @@ struct G_SetDeckInBattleSetupMenu_Ep3_6xB5x2F {
struct G_Unused_Ep3_6xB5x30 { struct G_Unused_Ep3_6xB5x30 {
G_CardBattleCommandHeader header = {0xB5, sizeof(G_Unused_Ep3_6xB5x30) / 4, 0, 0x30, 0, 0, 0}; G_CardBattleCommandHeader header = {0xB5, sizeof(G_Unused_Ep3_6xB5x30) / 4, 0, 0x30, 0, 0, 0};
// No arguments // No arguments.
} __packed_ws__(G_Unused_Ep3_6xB5x30, 8); } __packed_ws__(G_Unused_Ep3_6xB5x30, 8);
// 6xB5x31: Confirm deck selection // 6xB5x31: Confirm deck selection
@@ -7064,7 +7116,7 @@ struct G_RejectBattleStartRequest_Ep3_6xB4x53 {
// 30 (C->S): Extended player info // 30 (C->S): Extended player info
// Requested with the GetExtendedPlayerInfo patch. Format depends on version: // Requested with the GetExtendedPlayerInfo patch. Format depends on version:
// DC v2: PSODCV2CharacterFile // DC v2: PSODCV2CharacterFile
// GC v3: PSOGCCharacterFile::Character // GC v3: PSOGCCharacterFile::Character (including big-endian fields, unlike 61)
// XB v3: PSOXBCharacterFile::Character // XB v3: PSOXBCharacterFile::Character
// 6xE4: Increment enemy damage // 6xE4: Increment enemy damage
+8
View File
@@ -37,6 +37,14 @@ struct VectorXZF {
inline double norm2() const { inline double norm2() const {
return ((this->x * this->x) + (this->z * this->z)); return ((this->x * this->x) + (this->z * this->z));
} }
inline double dist(const VectorXZF& other) const {
return sqrt(this->dist2(other));
}
inline double dist2(const VectorXZF& other) const {
double x = this->x - other.x;
double z = this->z - other.z;
return ((x * x) + (z * z));
}
inline VectorXZF rotate_y(double angle) const { inline VectorXZF rotate_y(double angle) const {
double s = sin(angle); double s = sin(angle);
+150 -130
View File
@@ -134,67 +134,57 @@ CommonItemSet::Table::Table(std::shared_ptr<const Table> prev_table, const phosg
parse_field("UnitMaxStarsTable", this->unit_max_stars_table, prev_table ? &prev_table->unit_max_stars_table : nullptr); parse_field("UnitMaxStarsTable", this->unit_max_stars_table, prev_table ? &prev_table->unit_max_stars_table : nullptr);
parse_field("BoxItemClassProbTable", this->box_item_class_prob_table, prev_table ? &prev_table->box_item_class_prob_table : nullptr); parse_field("BoxItemClassProbTable", this->box_item_class_prob_table, prev_table ? &prev_table->box_item_class_prob_table : nullptr);
const auto* enemy_meseta_ranges_json = json.count("EnemyMesetaRanges") ? &json.at("EnemyMesetaRanges").as_dict() : nullptr; if (json.count("EnemyMesetaRanges")) {
const auto* enemy_type_drop_probs_json = json.count("EnemyTypeDropProbs") ? &json.at("EnemyTypeDropProbs").as_dict() : nullptr; const auto& dict = json.at("EnemyMesetaRanges").as_dict();
const auto* enemy_item_classes_json = json.count("EnemyItemClasses") ? &json.at("EnemyItemClasses").as_dict() : nullptr; for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
if (enemy_item_classes_json) { try {
// Unspecified is 0xFF, not 0, unlike the other enemy-indexed arrays (except for [0], apparently... sigh) from_json_into(*dict.at(phosg::name_for_enum(enemy_type)), this->enemy_type_meseta_ranges[enemy_type]);
this->enemy_item_classes[0] = 0; } catch (const out_of_range&) {
this->enemy_item_classes.clear_after(1, 0xFF); }
}
} else {
this->enemy_type_meseta_ranges = prev_table->enemy_type_meseta_ranges;
} }
for (size_t z = 0; z < NUM_RT_INDEXES_V4; z++) {
auto types = enemy_types_for_rare_table_index(this->episode, z); if (json.count("EnemyTypeDropProbs")) {
vector<string> names; const auto& dict = json.at("EnemyTypeDropProbs").as_dict();
if (types.empty()) { for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
names.emplace_back(std::format("!{:02X}", z)); try {
} else { this->enemy_type_drop_probs[enemy_type] = dict.at(phosg::name_for_enum(enemy_type))->as_int();
for (auto type : types) { } catch (const out_of_range&) {
names.emplace_back(phosg::name_for_enum(type));
} }
} }
for (const auto& name : names) { } else {
if (enemy_meseta_ranges_json) { this->enemy_type_drop_probs = prev_table->enemy_type_drop_probs;
try { }
from_json_into(*enemy_meseta_ranges_json->at(name), this->enemy_meseta_ranges[z]);
} catch (const out_of_range&) { if (json.count("EnemyItemClasses")) {
} const auto& dict = json.at("EnemyItemClasses").as_dict();
} else if (prev_table) { for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
this->enemy_meseta_ranges = prev_table->enemy_meseta_ranges; try {
} this->enemy_type_item_classes[enemy_type] = dict.at(phosg::name_for_enum(enemy_type))->as_int();
if (enemy_type_drop_probs_json) { } catch (const out_of_range&) {
try {
this->enemy_type_drop_probs[z] = enemy_type_drop_probs_json->at(name)->as_int();
} catch (const out_of_range&) {
}
} else if (prev_table) {
this->enemy_type_drop_probs = prev_table->enemy_type_drop_probs;
}
if (enemy_item_classes_json) {
try {
this->enemy_item_classes[z] = enemy_item_classes_json->at(name)->as_int();
} catch (const out_of_range&) {
}
} else if (prev_table) {
this->enemy_item_classes = prev_table->enemy_item_classes;
} }
} }
} else {
this->enemy_type_item_classes = prev_table->enemy_type_item_classes;
} }
} }
static const char* name_for_common_item_class(uint8_t item_class) { static const char* name_for_common_item_class(uint8_t item_class) {
switch (item_class) { switch (item_class) {
case 0x00: case 0x00:
return "WEAPON "; return "WEAPON";
case 0x01: case 0x01:
return "ARMOR "; return "ARMOR";
case 0x02: case 0x02:
return "SHIELD "; return "SHIELD";
case 0x03: case 0x03:
return "UNIT "; return "UNIT";
case 0x04: case 0x04:
return "TOOL "; return "TOOL";
case 0x05: case 0x05:
return "MESETA "; return "MESETA";
case 0x06: case 0x06:
return "NOTHING"; return "NOTHING";
default: default:
@@ -203,42 +193,29 @@ static const char* name_for_common_item_class(uint8_t item_class) {
} }
void CommonItemSet::Table::print(FILE* stream) const { void CommonItemSet::Table::print(FILE* stream) const {
const auto& meseta_ranges = this->enemy_meseta_ranges; const auto& meseta_ranges = this->enemy_type_meseta_ranges;
const auto& drop_probs = this->enemy_type_drop_probs; const auto& drop_probs = this->enemy_type_drop_probs;
const auto& item_classes = this->enemy_item_classes; const auto& item_classes = this->enemy_type_item_classes;
phosg::fwrite_fmt(stream, "Enemy tables:\n"); phosg::fwrite_fmt(stream, "Enemy tables:\n");
phosg::fwrite_fmt(stream, " ## $LOW $HIGH DAR% ITEM ENEMIES\n"); phosg::fwrite_fmt(stream, " ##:ENEMY $LOW $HIGH DAR% ITEM\n");
for (size_t z = 0; z < NUM_RT_INDEXES_V4; z++) { for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
string enemies_str; const auto& def = type_definition_for_enemy(enemy_type);
for (EnemyType enemy_type : enemy_types_for_rare_table_index(this->episode, z)) { try {
if (!enemies_str.empty()) { const auto& meseta_range = meseta_ranges.at(enemy_type);
enemies_str += ", "; const auto& drop_prob = drop_probs.at(enemy_type);
} const auto& item_class = item_classes.at(enemy_type);
enemies_str += phosg::name_for_enum(enemy_type); phosg::fwrite_fmt(stream, " {:02X}:{:<23} {:5} {:5} {:3}% {:02X}:{:<7}\n",
} def.rt_index, phosg::name_for_enum(enemy_type),
if (drop_probs[z] || !enemies_str.empty()) { meseta_range.min, meseta_range.max, drop_prob, item_class,
phosg::fwrite_fmt(stream, " {:02X} {:5} {:5} {:3}% {:02X}:{} {}\n", name_for_common_item_class(item_class));
z, meseta_ranges[z].min, meseta_ranges[z].max, drop_probs[z], item_classes[z], } catch (const out_of_range&) {
name_for_common_item_class(item_classes[z]), enemies_str); phosg::fwrite_fmt(stream, " {:02X}:{:<23} ----- ----- ---- --:-------\n",
} else { def.rt_index, phosg::name_for_enum(enemy_type));
phosg::fwrite_fmt(stream, " {:02X} ----- ----- 0% --\n", z);
} }
} }
static const array<const char*, 12> base_weapon_type_names = { static const array<const char*, 12> base_weapon_type_names = {
"SABER ", "SABER", "SWORD", "DAGGER", "PARTISAN", "SLICER", "HANDGUN", "RIFLE", "MECHGUN", "SHOT", "CANE", "ROD", "WAND"};
"SWORD ",
"DAGGER ",
"PARTISAN",
"SLICER ",
"HANDGUN ",
"RIFLE ",
"MECHGUN ",
"SHOT ",
"CANE ",
"ROD ",
"WAND ",
};
phosg::fwrite_fmt(stream, "Base weapon config:\n"); phosg::fwrite_fmt(stream, "Base weapon config:\n");
phosg::fwrite_fmt(stream, " TYPE PROB [SB AL] FLOORS\n"); phosg::fwrite_fmt(stream, " TYPE PROB [SB AL] FLOORS\n");
for (size_t z = 0; z < 12; z++) { for (size_t z = 0; z < 12; z++) {
@@ -256,7 +233,7 @@ void CommonItemSet::Table::print(FILE* stream) const {
floor_to_class[x] = this->subtype_base_table[z] + (x / this->subtype_area_length_table[z]); floor_to_class[x] = this->subtype_base_table[z] + (x / this->subtype_area_length_table[z]);
} }
} }
phosg::fwrite_fmt(stream, " {:02X}:{} {:3}% [{:02X} {:02X}] {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}\n", phosg::fwrite_fmt(stream, " {:02X}:{:<8} {:3}% [{:02X} {:02X}] {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}\n",
z, base_weapon_type_names[z], this->base_weapon_type_prob_table[z], z, base_weapon_type_names[z], this->base_weapon_type_prob_table[z],
this->subtype_base_table[z], this->subtype_area_length_table[z], this->subtype_base_table[z], this->subtype_area_length_table[z],
floor_to_class[0], floor_to_class[1], floor_to_class[2], floor_to_class[3], floor_to_class[4], floor_to_class[0], floor_to_class[1], floor_to_class[2], floor_to_class[3], floor_to_class[4],
@@ -413,20 +390,50 @@ void CommonItemSet::Table::print_diff(FILE* stream, const Table& other) const {
phosg::format_data_string(&this->armor_slot_count_prob_table, sizeof(this->armor_slot_count_prob_table)), phosg::format_data_string(&this->armor_slot_count_prob_table, sizeof(this->armor_slot_count_prob_table)),
phosg::format_data_string(&other.armor_slot_count_prob_table, sizeof(other.armor_slot_count_prob_table))); phosg::format_data_string(&other.armor_slot_count_prob_table, sizeof(other.armor_slot_count_prob_table)));
} }
if (this->enemy_meseta_ranges != other.enemy_meseta_ranges) {
phosg::fwrite_fmt(stream, "> enemy_meseta_ranges: {} -> {}\n", auto format_enemy_range_table = [&](const std::unordered_map<EnemyType, Range<uint16_t>>& table) -> std::string {
phosg::format_data_string(&this->enemy_meseta_ranges, sizeof(this->enemy_meseta_ranges)), string ret = "";
phosg::format_data_string(&other.enemy_meseta_ranges, sizeof(other.enemy_meseta_ranges))); for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
try {
const auto& range = table.at(enemy_type);
if (!ret.empty()) {
ret += ",";
}
ret += std::format("{}=[{},{}]", phosg::name_for_enum(enemy_type), range.min, range.max);
} catch (const out_of_range&) {
}
}
return ret;
};
auto format_enemy_u8_table = [&](const std::unordered_map<EnemyType, uint8_t>& table) -> std::string {
string ret = "";
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
try {
uint8_t value = table.at(enemy_type);
if (!ret.empty()) {
ret += ",";
}
ret += std::format("{}={}", phosg::name_for_enum(enemy_type), value);
} catch (const out_of_range&) {
}
}
return ret;
};
if (this->enemy_type_meseta_ranges != other.enemy_type_meseta_ranges) {
phosg::fwrite_fmt(stream, "> enemy_type_meseta_ranges: {} -> {}\n",
format_enemy_range_table(this->enemy_type_meseta_ranges),
format_enemy_range_table(other.enemy_type_meseta_ranges));
} }
if (this->enemy_type_drop_probs != other.enemy_type_drop_probs) { if (this->enemy_type_drop_probs != other.enemy_type_drop_probs) {
phosg::fwrite_fmt(stream, "> enemy_type_drop_probs: {} -> {}\n", phosg::fwrite_fmt(stream, "> enemy_type_drop_probs: {} -> {}\n",
phosg::format_data_string(&this->enemy_type_drop_probs, sizeof(this->enemy_type_drop_probs)), format_enemy_u8_table(this->enemy_type_drop_probs),
phosg::format_data_string(&other.enemy_type_drop_probs, sizeof(other.enemy_type_drop_probs))); format_enemy_u8_table(other.enemy_type_drop_probs));
} }
if (this->enemy_item_classes != other.enemy_item_classes) { if (this->enemy_type_item_classes != other.enemy_type_item_classes) {
phosg::fwrite_fmt(stream, "> enemy_item_classes: {} -> {}\n", phosg::fwrite_fmt(stream, "> enemy_type_item_classes: {} -> {}\n",
phosg::format_data_string(&this->enemy_item_classes, sizeof(this->enemy_item_classes)), format_enemy_u8_table(this->enemy_type_item_classes),
phosg::format_data_string(&other.enemy_item_classes, sizeof(other.enemy_item_classes))); format_enemy_u8_table(other.enemy_type_item_classes));
} }
if (this->box_meseta_ranges != other.box_meseta_ranges) { if (this->box_meseta_ranges != other.box_meseta_ranges) {
phosg::fwrite_fmt(stream, "> box_meseta_ranges: {} -> {}\n", phosg::fwrite_fmt(stream, "> box_meseta_ranges: {} -> {}\n",
@@ -517,44 +524,45 @@ phosg::JSON CommonItemSet::Table::json(std::shared_ptr<const Table> prev_table)
ret.emplace("ArmorSlotCountProbTable", to_json(this->armor_slot_count_prob_table)); ret.emplace("ArmorSlotCountProbTable", to_json(this->armor_slot_count_prob_table));
} }
bool needs_enemy_meseta_ranges = (!prev_table || (this->enemy_meseta_ranges != prev_table->enemy_meseta_ranges)); bool needs_enemy_type_meseta_ranges = (!prev_table ||
bool needs_enemy_type_drop_probs = (!prev_table || (this->enemy_type_drop_probs != prev_table->enemy_type_drop_probs)); (this->enemy_type_meseta_ranges != prev_table->enemy_type_meseta_ranges));
bool needs_enemy_item_classes = (!prev_table || (this->enemy_item_classes != prev_table->enemy_item_classes)); bool needs_enemy_type_drop_probs = (!prev_table ||
if (needs_enemy_meseta_ranges || needs_enemy_type_drop_probs || needs_enemy_item_classes) { (this->enemy_type_drop_probs != prev_table->enemy_type_drop_probs));
phosg::JSON enemy_meseta_ranges_json = phosg::JSON::dict(); bool needs_enemy_type_item_classes = (!prev_table ||
(this->enemy_type_item_classes != prev_table->enemy_type_item_classes));
if (needs_enemy_type_meseta_ranges || needs_enemy_type_drop_probs || needs_enemy_type_item_classes) {
phosg::JSON enemy_type_meseta_ranges_json = phosg::JSON::dict();
phosg::JSON enemy_type_drop_probs_json = phosg::JSON::dict(); phosg::JSON enemy_type_drop_probs_json = phosg::JSON::dict();
phosg::JSON enemy_item_classes_json = phosg::JSON::dict(); phosg::JSON enemy_type_item_classes_json = phosg::JSON::dict();
for (size_t z = 0; z < NUM_RT_INDEXES_V4; z++) { for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
auto types = enemy_types_for_rare_table_index(this->episode, z); auto name = phosg::name_for_enum(enemy_type);
vector<string> names; if (needs_enemy_type_meseta_ranges) {
if (types.empty()) { try {
names.emplace_back(std::format("!{:02X}", z)); enemy_type_meseta_ranges_json.emplace(name, to_json(this->enemy_type_meseta_ranges.at(enemy_type)));
} else { } catch (const std::out_of_range&) {
for (auto type : types) {
names.emplace_back(phosg::name_for_enum(type));
} }
} }
for (const auto& name : names) { if (needs_enemy_type_drop_probs) {
if (needs_enemy_meseta_ranges && (!types.empty() || !this->enemy_meseta_ranges[z].empty())) { try {
enemy_meseta_ranges_json.emplace(name, to_json(this->enemy_meseta_ranges[z])); enemy_type_drop_probs_json.emplace(name, this->enemy_type_drop_probs.at(enemy_type));
} catch (const std::out_of_range&) {
} }
if (needs_enemy_type_drop_probs && (!types.empty() || this->enemy_type_drop_probs[z])) { }
enemy_type_drop_probs_json.emplace(name, this->enemy_type_drop_probs[z]); if (needs_enemy_type_item_classes) {
} try {
if (needs_enemy_item_classes && (!types.empty() || (this->enemy_item_classes[z] != ((z == 0) ? 0x00 : 0xFF)))) { enemy_type_item_classes_json.emplace(name, this->enemy_type_item_classes.at(enemy_type));
enemy_item_classes_json.emplace(name, this->enemy_item_classes[z]); } catch (const std::out_of_range&) {
} }
} }
} }
if (needs_enemy_type_meseta_ranges) {
if (needs_enemy_meseta_ranges) { ret.emplace("EnemyMesetaRanges", std::move(enemy_type_meseta_ranges_json));
ret.emplace("EnemyMesetaRanges", std::move(enemy_meseta_ranges_json));
} }
if (needs_enemy_type_drop_probs) { if (needs_enemy_type_drop_probs) {
ret.emplace("EnemyTypeDropProbs", std::move(enemy_type_drop_probs_json)); ret.emplace("EnemyTypeDropProbs", std::move(enemy_type_drop_probs_json));
} }
if (needs_enemy_item_classes) { if (needs_enemy_type_item_classes) {
ret.emplace("EnemyItemClasses", std::move(enemy_item_classes_json)); ret.emplace("EnemyItemClasses", std::move(enemy_type_item_classes_json));
} }
} }
@@ -705,13 +713,27 @@ void CommonItemSet::Table::parse_itempt_t(const phosg::StringReader& r, bool is_
this->grind_prob_table = r.pget<parray<parray<uint8_t, 4>, 9>>(offsets.grind_prob_table_offset); this->grind_prob_table = r.pget<parray<parray<uint8_t, 4>, 9>>(offsets.grind_prob_table_offset);
this->armor_shield_type_index_prob_table = r.pget<parray<uint8_t, 0x05>>(offsets.armor_shield_type_index_prob_table_offset); this->armor_shield_type_index_prob_table = r.pget<parray<uint8_t, 0x05>>(offsets.armor_shield_type_index_prob_table_offset);
this->armor_slot_count_prob_table = r.pget<parray<uint8_t, 0x05>>(offsets.armor_slot_count_prob_table_offset); this->armor_slot_count_prob_table = r.pget<parray<uint8_t, 0x05>>(offsets.armor_slot_count_prob_table_offset);
const auto& data = r.pget<parray<Range<U16T<BE>>, NUM_RT_INDEXES_V3>>(offsets.enemy_meseta_ranges_offset); const auto& enemy_rt_index_meseta_ranges = r.pget<parray<Range<U16T<BE>>, NUM_RT_INDEXES_V3>>(
for (size_t z = 0; z < data.size(); z++) { offsets.enemy_rt_index_meseta_ranges_offset);
this->enemy_meseta_ranges[z] = Range<uint16_t>{data[z].min, data[z].max}; const auto& enemy_rt_index_drop_probs = r.pget<parray<uint8_t, NUM_RT_INDEXES_V3>>(
offsets.enemy_rt_index_drop_probs_offset);
const auto& enemy_rt_index_item_classes = r.pget<parray<uint8_t, NUM_RT_INDEXES_V3>>(
offsets.enemy_rt_index_item_classes_offset);
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
const auto& def = type_definition_for_enemy(enemy_type);
if (def.valid_in_episode(this->episode) && (def.rt_index < enemy_rt_index_meseta_ranges.size())) {
const auto& meseta_range = enemy_rt_index_meseta_ranges[def.rt_index];
if (meseta_range.max > 0) {
this->enemy_type_meseta_ranges.emplace(enemy_type, Range<uint16_t>{meseta_range.min, meseta_range.max});
}
if (enemy_rt_index_drop_probs[def.rt_index] > 0) {
this->enemy_type_drop_probs.emplace(enemy_type, enemy_rt_index_drop_probs[def.rt_index]);
}
if (enemy_rt_index_item_classes[def.rt_index] != 0xFF) {
this->enemy_type_item_classes.emplace(enemy_type, enemy_rt_index_item_classes[def.rt_index]);
}
}
} }
this->enemy_type_drop_probs = r.pget<parray<uint8_t, NUM_RT_INDEXES_V3>>(offsets.enemy_type_drop_probs_offset);
this->enemy_item_classes = r.pget<parray<uint8_t, NUM_RT_INDEXES_V3>>(offsets.enemy_item_classes_offset);
this->enemy_item_classes.clear_after(NUM_RT_INDEXES_V3, 0xFF);
{ {
const auto& data = r.pget<parray<Range<U16T<BE>>, 0x0A>>(offsets.box_meseta_ranges_offset); const auto& data = r.pget<parray<Range<U16T<BE>>, 0x0A>>(offsets.box_meseta_ranges_offset);
for (size_t z = 0; z < data.size(); z++) { for (size_t z = 0; z < data.size(); z++) {
@@ -873,7 +895,7 @@ GSLV3V4CommonItemSet::GSLV3V4CommonItemSet(std::shared_ptr<const std::string> gs
section_id); section_id);
}; };
for (Episode episode : ALL_EPISODES_V4) { for (Episode episode : ALL_EPISODES_V3) {
for (Difficulty difficulty : ALL_DIFFICULTIES_V234) { for (Difficulty difficulty : ALL_DIFFICULTIES_V234) {
for (size_t section_id = 0; section_id < 10; section_id++) { for (size_t section_id = 0; section_id < 10; section_id++) {
phosg::StringReader r; phosg::StringReader r;
@@ -898,17 +920,15 @@ GSLV3V4CommonItemSet::GSLV3V4CommonItemSet(std::shared_ptr<const std::string> gs
} }
} }
if (episode != Episode::EP4) { for (Difficulty difficulty : ALL_DIFFICULTIES_V234) {
for (Difficulty difficulty : ALL_DIFFICULTIES_V234) { try {
try { auto r = gsl.get_reader(filename_for_table(episode, difficulty, 0, true));
auto r = gsl.get_reader(filename_for_table(episode, difficulty, 0, true)); auto table = make_shared<Table>(r, is_big_endian, true, episode);
auto table = make_shared<Table>(r, is_big_endian, true, episode); for (size_t section_id = 0; section_id < 10; section_id++) {
for (size_t section_id = 0; section_id < 10; section_id++) { this->tables.emplace(this->key_for_table(episode, GameMode::CHALLENGE, difficulty, section_id), table);
this->tables.emplace(this->key_for_table(episode, GameMode::CHALLENGE, difficulty, section_id), table);
}
} catch (const out_of_range&) {
// GC NTE doesn't have Ep2 challenge; just skip adding the table
} }
} catch (const out_of_range&) {
// GC NTE doesn't have Ep2 challenge; just skip adding the table
} }
} }
} }
+11 -10
View File
@@ -42,9 +42,10 @@ public:
parray<parray<uint8_t, 4>, 9> grind_prob_table; parray<parray<uint8_t, 4>, 9> grind_prob_table;
parray<uint8_t, 0x05> armor_shield_type_index_prob_table; parray<uint8_t, 0x05> armor_shield_type_index_prob_table;
parray<uint8_t, 0x05> armor_slot_count_prob_table; parray<uint8_t, 0x05> armor_slot_count_prob_table;
parray<Range<uint16_t>, NUM_RT_INDEXES_V4> enemy_meseta_ranges; // Note: PSO originally uses arrays indexed by rt_index here, but we index enemies by the EnemyType enum instead
parray<uint8_t, NUM_RT_INDEXES_V4> enemy_type_drop_probs; std::unordered_map<EnemyType, Range<uint16_t>> enemy_type_meseta_ranges;
parray<uint8_t, NUM_RT_INDEXES_V4> enemy_item_classes; std::unordered_map<EnemyType, uint8_t> enemy_type_drop_probs;
std::unordered_map<EnemyType, uint8_t> enemy_type_item_classes;
parray<Range<uint16_t>, 0x0A> box_meseta_ranges; parray<Range<uint16_t>, 0x0A> box_meseta_ranges;
bool has_rare_bonus_value_prob_table; bool has_rare_bonus_value_prob_table;
parray<parray<uint16_t, 6>, 0x17> bonus_value_prob_table; parray<parray<uint16_t, 6>, 0x17> bonus_value_prob_table;
@@ -126,17 +127,17 @@ public:
// V2/V3: -> parray<uint8_t, 0x05> // V2/V3: -> parray<uint8_t, 0x05>
/* 14 */ U32T<BE> armor_slot_count_prob_table_offset; /* 14 */ U32T<BE> armor_slot_count_prob_table_offset;
// This array (indexed by enemy_type) specifies the range of meseta values that each enemy can drop. // This array (indexed by rt_index) specifies the range of meseta values that each enemy can drop.
// V2/V3: -> parray<Range<U16T>, NUM_RT_INDEXES_V3> // V2/V3: -> parray<Range<U16T>, NUM_RT_INDEXES_V3>
/* 18 */ U32T<BE> enemy_meseta_ranges_offset; /* 18 */ U32T<BE> enemy_rt_index_meseta_ranges_offset;
// Each byte in this table (indexed by enemy_type) represents the percent chance that the enemy drops anything at // Each byte in this table (indexed by rt_index) represents the percent chance that the enemy drops anything at
// all. (This check is done before the rare drop check, so the chance of getting a rare item from an enemy is // all. (This check is done before the rare drop check, so the chance of getting a rare item from an enemy is
// essentially this probability multiplied by the rare drop rate.) // essentially this probability multiplied by the rare drop rate.)
// V2/V3: -> parray<uint8_t, NUM_RT_INDEXES_V3> // V2/V3: -> parray<uint8_t, NUM_RT_INDEXES_V3>
/* 1C */ U32T<BE> enemy_type_drop_probs_offset; /* 1C */ U32T<BE> enemy_rt_index_drop_probs_offset;
// Each byte in this table (indexed by enemy_type) represents the class of item that can drop. The values are: // Each byte in this table (indexed by rt_index) represents the class of item that can drop. The values are:
// 00 = weapon // 00 = weapon
// 01 = armor // 01 = armor
// 02 = shield // 02 = shield
@@ -145,7 +146,7 @@ public:
// 05 = meseta // 05 = meseta
// Anything else = no item // Anything else = no item
// V2/V3: -> parray<uint8_t, NUM_RT_INDEXES_V3> // V2/V3: -> parray<uint8_t, NUM_RT_INDEXES_V3>
/* 20 */ U32T<BE> enemy_item_classes_offset; /* 20 */ U32T<BE> enemy_rt_index_item_classes_offset;
// This table (indexed by area - 1) specifies the ranges of meseta values that can drop from boxes. // This table (indexed by area - 1) specifies the ranges of meseta values that can drop from boxes.
// V2/V3: -> parray<Range<U16T>, 0x0A> // V2/V3: -> parray<Range<U16T>, 0x0A>
@@ -229,7 +230,7 @@ public:
// This index probability table determines which type of items drop from boxes. The table is indexed as // This index probability table determines which type of items drop from boxes. The table is indexed as
// [item_class][area - 1], with item_class as the result value (that is, in the example below, the game looks at // [item_class][area - 1], with item_class as the result value (that is, in the example below, the game looks at
// a single column and sums the values going down, then the chosen item class is one of the row indexes based on // a single column and sums the values going down, then the chosen item class is one of the row indexes based on
// the weight values in the column.) The resulting value has the same meaning as in enemy_item_classes above. // the weight values in the column.) The resulting value has the same meaning as in enemy_rt_index_item_classes.
// For example, this array might look like the following: // For example, this array might look like the following:
// [07 07 08 08 06 07 08 09 09 0A] // Chances per area of a weapon drop // [07 07 08 08 06 07 08 09 09 0A] // Chances per area of a weapon drop
// [02 02 02 02 03 02 02 02 03 03] // Chances per area of an armor drop // [02 02 02 02 03 02 02 02 03 03] // Chances per area of an armor drop
+2 -1
View File
@@ -13,6 +13,7 @@ static constexpr size_t NUM_RT_INDEXES_V3 = 0x64;
static constexpr size_t NUM_RT_INDEXES_V4 = 0x70; static constexpr size_t NUM_RT_INDEXES_V4 = 0x70;
enum class EnemyType : uint8_t { enum class EnemyType : uint8_t {
MIN_VALUE = 0,
UNKNOWN = 0, UNKNOWN = 0,
NONE, NONE,
NON_ENEMY_NPC, NON_ENEMY_NPC,
@@ -146,7 +147,7 @@ enum class EnemyType : uint8_t {
ZOL_GIBBON, ZOL_GIBBON,
ZU_CRATER, ZU_CRATER,
ZU_DESERT, ZU_DESERT,
MAX_ENEMY_TYPE, MAX_VALUE,
}; };
struct EnemyTypeDefinition { struct EnemyTypeDefinition {
+24 -22
View File
@@ -675,8 +675,8 @@ struct CardDefinition {
// - (rate / 10) % 100 (that is, the tens and hundreds decimal places) specify the environment number + 1. For // - (rate / 10) % 100 (that is, the tens and hundreds decimal places) specify the environment number + 1. For
// example, if this field contains 5, then this drop only applies if the battle took place at Molae Venti // example, if this field contains 5, then this drop only applies if the battle took place at Molae Venti
// (environment number 4). If this field is zero, the drop applies regardless of where the battle took place. // (environment number 4). If this field is zero, the drop applies regardless of where the battle took place.
// - rate / 1000 (the thousands decimal place) specifies the rarity class. This can be any number in the range [0, // - (rate / 1000) % 10 (the thousands decimal place) specifies the rarity class. This can be any number in the range
// 9], and affects how likely the card is to appear based on the player's level. See below for details. // [0, 9], and affects how likely the card is to appear based on the player's level. See below for details.
// - rate / 10000 (the ten-thousands decimal place) specifies if the drop rate applies only if the player used a // - rate / 10000 (the ten-thousands decimal place) specifies if the drop rate applies only if the player used a
// Hunters deck (1), only if they used an Arkz deck (2), or if they used any deck (0). // Hunters deck (1), only if they used an Arkz deck (2), or if they used any deck (0).
// //
@@ -684,16 +684,16 @@ struct CardDefinition {
// that applies, the game adds the card ID into an appropriate bucket based on the rarity class. (If both drop rates // that applies, the game adds the card ID into an appropriate bucket based on the rarity class. (If both drop rates
// for a card apply, the card ID is added twice.) The player's level class is then computed according to the // for a card apply, the card ID is added twice.) The player's level class is then computed according to the
// following table: // following table:
// 1 2 3 4 5 6 7 8 9 10 // Level class 1 2 3 4 5 6 7 8 9 10
// CLvOff 1-2 3-4 5-9 10-14 15-19 20-25 26-29 30-39 40-49 50+ // CLvOff 1-2 3-4 5-9 10-14 15-19 20-25 26-29 30-39 40-49 50+
// CLvOn 1-2 3-4 5-10 11-16 17-23 24-32 33-39 40-49 50-99 100+ // CLvOn 1-2 3-4 5-10 11-16 17-23 24-32 33-39 40-49 50-99 100+
// For the purposes of this computation, the player's level is used by default (CLvOn or CLvOff), but the map may // For the purposes of this computation, the player's level is used by default (CLvOn or CLvOff), but the map may
// override it - see win_level_override and loss_level_override in MapDefinition. This specifies which row in the // override it - see win_level_override and loss_level_override in MapDefinition. This specifies which row in the
// following tables will be used. // following tables will be used.
// //
// Cards are then chosen from the buckets with a weighted distribution according to these tables (row is player's // Cards are then chosen from the buckets with a weighted distribution according to these tables (row is player's
// level class, column is card's rarity class): // level class, column is card's rarity class):
// Offline: // Offline ---------------------------------------------------------------
// LC | RC = 0 1 2 3 4 5 6 7 8 9 // LC | RC = 0 1 2 3 4 5 6 7 8 9
// 1 | 8000 2000 50 // 1 | 8000 2000 50
// 2 | 6000 3500 500 20 // 2 | 6000 3500 500 20
@@ -705,7 +705,7 @@ struct CardDefinition {
// 8 | 1789 2100 2100 2100 1100 800 10 1 // 8 | 1789 2100 2100 2100 1100 800 10 1
// 9 | 14620 20000 21000 22000 13000 9000 300 80 // 9 | 14620 20000 21000 22000 13000 9000 300 80
// 10 | 133997 190000 200000 200000 150000 120000 5000 1000 2 1 // 10 | 133997 190000 200000 200000 150000 120000 5000 1000 2 1
// Online: // Online --------------------------------------------------------------------
// LC | RC = 0 1 2 3 4 5 6 7 8 9 // LC | RC = 0 1 2 3 4 5 6 7 8 9
// 1 | 8000 2000 50 // 1 | 8000 2000 50
// 2 | 6000 3500 500 50 // 2 | 6000 3500 500 50
@@ -729,31 +729,33 @@ struct CardDefinition {
// - In the blue pack, the restricted cards must be creature cards. // - In the blue pack, the restricted cards must be creature cards.
// - In the red pack, the restricted cards must be item cards. // - In the red pack, the restricted cards must be item cards.
// - In the green pack, the restricted cards must be action cards. // - In the green pack, the restricted cards must be action cards.
// - In the black pack, the restricted cards may be any card type.
// For example, if you get a B+ rank after winning a battle and pick the green pack, you will always get at least two // For example, if you get a B+ rank after winning a battle and pick the green pack, you will always get at least two
// action cards. // action cards. The remaining cards can be any type, so this restriction essentially biases the blue, red, and green
// packs toward specific card types.
// //
// The game then samples N card IDs from the appropriate buckets (where N is the number chosen above), but for the // The game then samples N card IDs from the appropriate buckets (where N is the number chosen above based on the
// first 1 or 2 cards, it applies the restriction described above and re-draws if the card is the wrong type. After // post-battle rank), but for the first 1 or 2 cards, it applies the restriction described above and re-draws if the
// sampling the N card IDs, it sorts them and presents them to the player. // card is the wrong type. After sampling the N card IDs, it sorts them and presents them to the player.
// //
// There is one more effect to consider after cards are chosen: cards may randomly transform into VIP cards or into // There is one more effect to consider after cards are chosen: cards may randomly transform into VIP cards or into
// stronger (and rarer) cards. The chance of each of these occurring is based on the rarity of that card that may // stronger (and rarer) cards. The chance of each of these occurring is based on the rarity of the card that may
// transform, and the number of copies of that card which the player already has. In the below table, P(activate) is // transform, and the number of copies of that card which the player already has. In the below table, P(activate) is
// the probability that any transformation is attempted at all; if this check passes, the player sees the glow effect // the probability that any transformation is attempted at all; if this check passes, the player sees the glow effect
// and "The change will occur..." text. P(vip) is the probability that the card becomes a VIP card, after the glow // and "The change will occur..." text. P(vip) is the probability that the card becomes a VIP card, after the glow
// effect plays. P(rare) is the probability of the card becoming a rarer card after the glow effect. Therefore, the // effect plays. P(rare) is the probability of the card becoming a rarer card after the glow effect. Therefore, the
// final probability that a card will transform into a VIP card is P(activate) * P(vip), and the final probability of // final probability that a card will transform into a VIP card is P(activate) * P(vip), and the final probability of
// transforming into a rarer card is P(activate) * P(rare). // transforming into a rarer card is P(activate) * P(rare).
// ======== Card rank N4-N1 ======== ======== Card rank R4-R1 ======== // ========= Card rank N4-N1 ========= ========= Card rank R4-R1 =========
// Count P(activate) P(rare) P(vip) P(activate) P(rare) P(vip) // Count P(activate) P(rare) P(vip) P(activate) P(rare) P(vip)
// 0-4 0% 0% 0% 0% 0% 0% // 0-4 0% 0% 0% 0% 0% 0%
// 5-10 1.923077% 55% 0.5% 2.0408163% 55% 0.5% // 5-10 1.923077% 55% 0.5% 2.0408163% 55% 0.5%
// 11-16 2.1276595% 60% 0.45454544% 2.2727273% 60% 0.4761905% // 11-16 2.1276595% 60% 0.45454544% 2.2727273% 60% 0.4761905%
// 17-24 2.3809524% 70% 0.4347826% 2.5641026% 70% 0.45454544% // 17-24 2.3809524% 70% 0.4347826% 2.5641026% 70% 0.45454544%
// 25-32 2.7027028% 70% 0.4% 2.9411765% 70% 0.5% // 25-32 2.7027028% 70% 0.4% 2.9411765% 70% 0.5%
// 33-40 3.125% 80% 0.38461538% 3.448276% 70% 0.5% // 33-40 3.125% 80% 0.38461538% 3.448276% 70% 0.5%
// 41-52 3.7037037% 80% 0.35714286% 4.1666668% 80% 0.45454544% // 41-52 3.7037037% 80% 0.35714286% 4.1666668% 80% 0.45454544%
// 53-99 5% 90% 0.33333334% 5.263158% 90% 0.4347826% // 53-99 5% 90% 0.33333334% 5.263158% 90% 0.4347826%
// //
// If a transformation occurs, the card transforms to a card of a different rank. First, the game consults the // If a transformation occurs, the card transforms to a card of a different rank. First, the game consults the
// following table to determine the rank of the resulting card (original card's rank on the left, new card's rank // following table to determine the rank of the resulting card (original card's rank on the left, new card's rank
+2
View File
@@ -44,6 +44,7 @@ void GameServer::listen(
shared_ptr<Client> GameServer::connect_channel(shared_ptr<Channel> ch, uint16_t port, ServerBehavior initial_state) { shared_ptr<Client> GameServer::connect_channel(shared_ptr<Channel> ch, uint16_t port, ServerBehavior initial_state) {
auto c = make_shared<Client>(this->shared_from_this(), ch, initial_state); auto c = make_shared<Client>(this->shared_from_this(), ch, initial_state);
c->listener_port = port;
this->log.info_f("Client connected: C-{:X} via TSI-{}-{}-{}", this->log.info_f("Client connected: C-{:X} via TSI-{}-{}-{}",
c->id, port, phosg::name_for_enum(ch->version), phosg::name_for_enum(initial_state)); c->id, port, phosg::name_for_enum(ch->version), phosg::name_for_enum(initial_state));
@@ -133,6 +134,7 @@ shared_ptr<Client> GameServer::create_client(
phosg::TerminalFormat::FG_YELLOW, phosg::TerminalFormat::FG_YELLOW,
phosg::TerminalFormat::FG_GREEN); phosg::TerminalFormat::FG_GREEN);
auto c = make_shared<Client>(this->shared_from_this(), channel, listen_sock->behavior); auto c = make_shared<Client>(this->shared_from_this(), channel, listen_sock->behavior);
c->listener_port = listen_sock->endpoint.port();
this->log.info_f("Client connected: C-{:X} via {}", c->id, listen_sock->name); this->log.info_f("Client connected: C-{:X} via {}", c->id, listen_sock->name);
return c; return c;
+151
View File
@@ -5,6 +5,7 @@
#include <phosg/Network.hh> #include <phosg/Network.hh>
#include <string> #include <string>
#include <map>
#include <vector> #include <vector>
#include "GameServer.hh" #include "GameServer.hh"
@@ -54,6 +55,156 @@ HTTPServer::HTTPServer(shared_ptr<ServerState> state)
co_return nullptr; co_return nullptr;
}); });
this->router.add(HTTPRequest::Method::GET, "/metrics", [this](ArgsT&&) -> RetT {
auto version_label = +[](Version v) -> const char* {
if (is_patch(v)) {
return "patch";
} else if (is_v4(v)) {
return "v4";
} else if (is_v3(v)) {
return "v3";
} else if (is_v1_or_v2(v)) {
return "v2";
} else {
return "other";
}
};
auto escape_label = +[](const string& in) -> string {
string out;
for (char ch : in) {
if (ch == '\\') {
out += "\\\\";
} else if (ch == '"') {
out += "\\\"";
} else if (ch == '\n') {
out += "\\n";
} else {
out += ch;
}
}
return out;
};
auto add_metric = [](string& out, const string& name, uint64_t value) -> void {
out += name;
out += " ";
out += std::to_string(value);
out += "\n";
};
auto add_metric_1label = [](string& out, const string& name, const string& label_name, const string& label_value, uint64_t value) -> void {
out += name;
out += "{";
out += label_name;
out += "=\"";
out += label_value;
out += "\"} ";
out += std::to_string(value);
out += "\n";
};
map<string, uint64_t> connected_by_version;
map<string, uint64_t> lobby_players_by_version;
map<string, uint64_t> game_players_by_version;
uint64_t connected_total = 0;
uint64_t lobbies_total = 0;
uint64_t games_total = 0;
uint64_t players_in_lobbies_total = 0;
uint64_t players_in_games_total = 0;
for (const auto& c : this->state->game_server->all_clients()) {
connected_total++;
connected_by_version[version_label(c->version())]++;
}
for (const auto& [_, l] : this->state->id_to_lobby) {
if (l->is_game()) {
games_total++;
} else {
lobbies_total++;
}
for (size_t z = 0; z < l->max_clients; z++) {
auto lc = l->clients[z];
if (!lc) {
continue;
}
const char* v = version_label(lc->version());
if (l->is_game()) {
players_in_games_total++;
game_players_by_version[v]++;
} else {
players_in_lobbies_total++;
lobby_players_by_version[v]++;
}
}
}
string server_name = escape_label(this->state->name);
string revision = escape_label(GIT_REVISION_HASH);
string out;
out += "# HELP pso_newserv_up Whether this newserv HTTP metrics endpoint is reachable\n";
out += "# TYPE pso_newserv_up gauge\n";
add_metric(out, "pso_newserv_up", 1);
out += "# HELP pso_newserv_build_info Build and server identity info\n";
out += "# TYPE pso_newserv_build_info gauge\n";
out += "pso_newserv_build_info{server_name=\"";
out += server_name;
out += "\",revision=\"";
out += revision;
out += "\",build_time=\"";
out += std::to_string(BUILD_TIMESTAMP);
out += "\"} 1\n";
out += "# HELP pso_newserv_clients_connected_total Connected clients, including patch/proxy/menu states\n";
out += "# TYPE pso_newserv_clients_connected_total gauge\n";
add_metric(out, "pso_newserv_clients_connected_total", connected_total);
out += "# HELP pso_newserv_clients_connected Connected clients by coarse version family\n";
out += "# TYPE pso_newserv_clients_connected gauge\n";
for (const auto& [version, count] : connected_by_version) {
add_metric_1label(out, "pso_newserv_clients_connected", "version", version, count);
}
out += "# HELP pso_newserv_lobbies_total Non-game lobby count\n";
out += "# TYPE pso_newserv_lobbies_total gauge\n";
add_metric(out, "pso_newserv_lobbies_total", lobbies_total);
out += "# HELP pso_newserv_games_total Game room count\n";
out += "# TYPE pso_newserv_games_total gauge\n";
add_metric(out, "pso_newserv_games_total", games_total);
out += "# HELP pso_newserv_players_in_lobbies_total Players currently in non-game lobbies\n";
out += "# TYPE pso_newserv_players_in_lobbies_total gauge\n";
add_metric(out, "pso_newserv_players_in_lobbies_total", players_in_lobbies_total);
out += "# HELP pso_newserv_players_in_games_total Players currently in game rooms\n";
out += "# TYPE pso_newserv_players_in_games_total gauge\n";
add_metric(out, "pso_newserv_players_in_games_total", players_in_games_total);
out += "# HELP pso_newserv_players_in_lobbies Players currently in non-game lobbies by coarse version family\n";
out += "# TYPE pso_newserv_players_in_lobbies gauge\n";
for (const auto& [version, count] : lobby_players_by_version) {
add_metric_1label(out, "pso_newserv_players_in_lobbies", "version", version, count);
}
out += "# HELP pso_newserv_players_in_games Players currently in game rooms by coarse version family\n";
out += "# TYPE pso_newserv_players_in_games gauge\n";
for (const auto& [version, count] : game_players_by_version) {
add_metric_1label(out, "pso_newserv_players_in_games", "version", version, count);
}
co_return RouterRetT(RawResponse{
.content_type = "text/plain; version=0.0.4; charset=utf-8",
.data = std::move(out),
});
});
this->router.add(HTTPRequest::Method::GET, "/y/clients", [this](ArgsT&&) -> RetT { this->router.add(HTTPRequest::Method::GET, "/y/clients", [this](ArgsT&&) -> RetT {
auto res = make_shared<phosg::JSON>(phosg::JSON::list()); auto res = make_shared<phosg::JSON>(phosg::JSON::list());
for (const auto& c : this->state->game_server->all_clients()) { for (const auto& c : this->state->game_server->all_clients()) {
+110 -92
View File
@@ -38,6 +38,7 @@ ItemCreator::ItemCreator(
shared_ptr<const BattleRules> restrictions) shared_ptr<const BattleRules> restrictions)
: log(std::format("[ItemCreator:{}/{}/{}/{}] ", phosg::name_for_enum(stack_limits->version), abbreviation_for_mode(mode), abbreviation_for_difficulty(difficulty), section_id), lobby_log.min_level), : log(std::format("[ItemCreator:{}/{}/{}/{}] ", phosg::name_for_enum(stack_limits->version), abbreviation_for_mode(mode), abbreviation_for_difficulty(difficulty), section_id), lobby_log.min_level),
logic_version(stack_limits->version), logic_version(stack_limits->version),
is_legacy_replay(false),
stack_limits(stack_limits), stack_limits(stack_limits),
mode(mode), mode(mode),
difficulty(difficulty), difficulty(difficulty),
@@ -136,13 +137,13 @@ uint8_t ItemCreator::table_index_for_area(uint8_t area) const {
return data[area]; return data[area];
} }
ItemCreator::DropResult ItemCreator::on_box_item_drop(uint8_t area) { ItemCreator::DropResult ItemCreator::on_box_item_drop(uint8_t area, bool force_rare) {
try { try {
uint8_t table_index = this->table_index_for_area(area); uint8_t table_index = this->table_index_for_area(area);
this->log.info_f("Box drop checks for area {:02X} (table index {:02X})", area, table_index); this->log.info_f("Box drop checks for area {:02X} (table index {:02X})", area, table_index);
DropResult res; DropResult res;
res.item = this->check_rare_specs_and_create_rare_box_item(area); res.item = this->check_rare_specs_and_create_rare_box_item(area, force_rare);
if (!res.item.empty()) { if (!res.item.empty()) {
res.is_from_rare_table = true; res.is_from_rare_table = true;
} else { } else {
@@ -188,34 +189,40 @@ ItemCreator::DropResult ItemCreator::on_box_item_drop(uint8_t area) {
} }
} }
ItemCreator::DropResult ItemCreator::on_monster_item_drop(uint32_t enemy_type, uint8_t area) { ItemCreator::DropResult ItemCreator::on_monster_item_drop(EnemyType enemy_type, uint8_t area, bool force_rare) {
try { try {
// Note: The original GC implementation uses (enemy_type > 0x58) here; we extend it to the full array size for BB // Note: The original implementation has a bounds check for enemy_type here, because it uses rt_index instead
if (enemy_type >= NUM_RT_INDEXES_V4) { // if (enemy_type >= NUM_RT_INDEXES_V4) {
this->log.warning_f("Invalid enemy type: {:X}", enemy_type); // this->log.warning_f("Invalid enemy type: {:X}", enemy_type);
return DropResult(); // return DropResult();
} // }
this->log.info_f("Enemy type: {:X}", enemy_type); this->log.info_f("Enemy type: {}", phosg::name_for_enum(enemy_type));
auto pt = this->pt(area); auto pt = this->pt(area);
uint8_t type_drop_prob = pt->enemy_type_drop_probs.at(enemy_type); uint8_t type_drop_prob = 0;
uint8_t drop_sample = this->rand_int(100); try {
if (drop_sample >= type_drop_prob) { type_drop_prob = pt->enemy_type_drop_probs.at(enemy_type);
this->log.info_f("Drop not chosen ({} >= {})", drop_sample, type_drop_prob); } catch (const std::out_of_range&) {
this->log.info_f("No drop probability is set for this enemy type");
return DropResult(); return DropResult();
} else { }
this->log.info_f("Drop chosen ({} < {})", drop_sample, type_drop_prob); if (!force_rare) {
uint8_t drop_sample = this->rand_int(100);
if (drop_sample >= type_drop_prob) {
this->log.info_f("Drop not chosen ({} >= {})", drop_sample, type_drop_prob);
return DropResult();
} else {
this->log.info_f("Drop chosen ({} < {})", drop_sample, type_drop_prob);
}
} }
DropResult res; DropResult res;
res.item = this->check_rare_spec_and_create_rare_enemy_item(enemy_type, area); res.item = this->check_rare_spec_and_create_rare_enemy_item(enemy_type, area, force_rare);
if (!res.item.empty()) { if (!res.item.empty()) {
res.is_from_rare_table = true; res.is_from_rare_table = true;
} else { } else {
uint32_t item_class_determinant = uint8_t item_class_determinant = this->should_allow_meseta_drops() ? this->rand_int(3) : (this->rand_int(2) + 1);
this->should_allow_meseta_drops() ? this->rand_int(3) : (this->rand_int(2) + 1); uint8_t item_class;
uint32_t item_class;
switch (item_class_determinant) { switch (item_class_determinant) {
case 0: case 0:
item_class = 5; item_class = 5;
@@ -224,7 +231,12 @@ ItemCreator::DropResult ItemCreator::on_monster_item_drop(uint32_t enemy_type, u
item_class = 4; item_class = 4;
break; break;
case 2: case 2:
item_class = pt->enemy_item_classes.at(enemy_type); try {
item_class = pt->enemy_type_item_classes.at(enemy_type);
} catch (const out_of_range&) {
this->log.info_f("Item class is not set for this enemy type");
item_class = 0xFF;
}
break; break;
default: default:
throw logic_error("invalid item class determinant"); throw logic_error("invalid item class determinant");
@@ -251,7 +263,12 @@ ItemCreator::DropResult ItemCreator::on_monster_item_drop(uint32_t enemy_type, u
break; break;
case 5: // Meseta case 5: // Meseta
res.item.data1[0] = 0x04; res.item.data1[0] = 0x04;
res.item.data2d = this->choose_meseta_amount(pt->enemy_meseta_ranges, enemy_type) & 0xFFFF; try {
res.item.data2d = this->choose_meseta_amount(pt->enemy_type_meseta_ranges.at(enemy_type)) & 0xFFFF;
} catch (const out_of_range&) {
this->log.info_f("Meseta range is not set for this enemy type");
return DropResult();
}
break; break;
default: default:
return res; return res;
@@ -270,30 +287,56 @@ ItemCreator::DropResult ItemCreator::on_monster_item_drop(uint32_t enemy_type, u
} }
} }
ItemData ItemCreator::check_rare_specs_and_create_rare_box_item(uint8_t area) { ItemData ItemCreator::check_rare_specs_and_create_rare_item(
ItemData item; const std::vector<RareItemSet::ExpandedDrop>& specs, uint8_t area, bool force_rare) {
if (specs.empty()) {
return ItemData();
}
// This logic differs from the original client logic. This logic "stacks" all rare rates into a single probability
// space, whereas the original client logic chooses a new random number for each rare spec that it checks. The
// stacking logic makes the order of specs irrelevant, whereas the original client logic means that later specs are
// actually more rare than they should be. In the original client, this only matters for boxes, because enemies could
// not have multiple specs. Also, the original code uses 0xFFFFFFFF as the maximum here; we use 0x100000000 instead,
// which makes all rare items SLIGHTLY more rare.
int64_t det = force_rare ? 0 : this->rand_int(0x100000000);
if (this->is_legacy_replay) {
// For some old tests, we waste a few replay values because they used the old (non-stacked) logic. New tests should
// not use this codepath.
for (size_t z = 1; z < specs.size(); z++) {
this->rand_int(0x100000000);
}
}
this->log.info_f("{} specs to check with det={:08X} rare_mult={:g}", specs.size(), det, this->rare_drop_rate_multiplier);
for (const auto& spec : specs) {
uint64_t effective_probability = spec.probability;
if (this->rare_drop_rate_multiplier != 1.0) {
double multiplied_probability = static_cast<double>(spec.probability) * this->rare_drop_rate_multiplier;
effective_probability = (multiplied_probability >= 4294967296.0)
? 0x100000000ULL
: static_cast<uint64_t>(multiplied_probability);
}
if (this->log.should_log(phosg::LogLevel::L_INFO)) {
this->log.info_f("Checking spec {:08X} => effective {:08X} => {} with det={:08X}",
spec.probability, effective_probability, spec.data.hex(), det);
}
det -= effective_probability;
if (det < 0) {
return this->create_rare_item(spec.data, area);
}
}
return ItemData();
}
ItemData ItemCreator::check_rare_specs_and_create_rare_box_item(uint8_t area, bool force_rare) {
if (!this->are_rare_drops_allowed()) { if (!this->are_rare_drops_allowed()) {
return item; return ItemData();
} }
uint8_t table_index = this->table_index_for_area(area); uint8_t table_index = this->table_index_for_area(area);
Episode episode = episode_for_area(area); Episode episode = episode_for_area(area);
auto rare_specs = this->rare_item_set->get_box_specs(this->mode, episode, this->difficulty, this->section_id, table_index); auto specs = this->rare_item_set->get_box_specs(this->mode, episode, this->difficulty, this->section_id, table_index);
for (const auto& spec : rare_specs) { return this->check_rare_specs_and_create_rare_item(specs, area, force_rare);
item = this->check_rate_and_create_rare_item(spec, area);
if (!item.empty()) {
if (this->log.should_log(phosg::LogLevel::L_INFO)) {
auto hex = spec.data.hex();
this->log.info_f("Box spec {:08X} produced item {}", spec.probability, hex);
}
break;
}
if (this->log.should_log(phosg::LogLevel::L_INFO)) {
auto hex = spec.data.hex();
this->log.info_f("Box spec {:08X} did not produce item {}", spec.probability, hex);
}
}
return item;
} }
uint32_t ItemCreator::rand_int(uint64_t max) { uint32_t ItemCreator::rand_int(uint64_t max) {
@@ -305,24 +348,18 @@ float ItemCreator::rand_float_0_1_from_crypt() {
return (static_cast<double>(this->rand_crypt->next() >> 16) / 65536.0); return (static_cast<double>(this->rand_crypt->next() >> 16) / 65536.0);
} }
template <size_t NumRanges> uint32_t ItemCreator::choose_meseta_amount(const CommonItemSet::Table::Range<uint16_t>& range) {
uint32_t ItemCreator::choose_meseta_amount(
const parray<CommonItemSet::Table::Range<uint16_t>, NumRanges> ranges,
size_t table_index) {
uint16_t min = ranges[table_index].min;
uint16_t max = ranges[table_index].max;
// Note: The original code returns 0xFF here if either limit is equal to 0xFF (despite them being 16-bit integers!) // Note: The original code returns 0xFF here if either limit is equal to 0xFF (despite them being 16-bit integers!)
uint16_t ret; uint16_t ret;
if (min == max) { if (range.min == range.max) {
ret = min; ret = range.min;
} else if (max < min) { } else if (range.max < range.min) {
ret = this->rand_int((min - max) + 1) + max; ret = this->rand_int((range.min - range.max) + 1) + range.max;
} else { } else {
ret = this->rand_int((max - min) + 1) + min; ret = this->rand_int((range.max - range.min) + 1) + range.min;
} }
this->log.info_f("Chose {} Meseta from range [{}, {}]", ret, min, max); this->log.info_f("Chose {} Meseta from range [{}, {}]", ret, range.min, range.max);
return ret; return ret;
} }
@@ -330,45 +367,24 @@ bool ItemCreator::should_allow_meseta_drops() const {
return (this->mode != GameMode::CHALLENGE); return (this->mode != GameMode::CHALLENGE);
} }
ItemData ItemCreator::check_rare_spec_and_create_rare_enemy_item(uint32_t enemy_type, uint8_t area) { ItemData ItemCreator::check_rare_spec_and_create_rare_enemy_item(EnemyType enemy_type, uint8_t area, bool force_rare) {
ItemData item; // Note: The original implementation has a bounds check for enemy_type here, since it uses rt_index instead.
if (this->are_rare_drops_allowed() && (enemy_type > 0) && (enemy_type < NUM_RT_INDEXES_V4)) { // if ((enemy_type <= 0) || (enemy_type >= NUM_RT_INDEXES_V4)) return ItemData{};
// Note: In the original implementation, enemies can only have one possible rare drop. In our implementation, they if (!this->are_rare_drops_allowed()) {
// can have multiple rare drops if JSONRareItemSet is used (the other RareItemSet implementations never return return ItemData{};
// multiple drops for an enemy type).
Episode episode = episode_for_area(area);
auto rare_specs = this->rare_item_set->get_enemy_specs(
this->mode, episode, this->difficulty, this->section_id, enemy_type);
for (const auto& spec : rare_specs) {
item = this->check_rate_and_create_rare_item(spec, area);
if (!item.empty()) {
if (this->log.should_log(phosg::LogLevel::L_INFO)) {
auto hex = spec.data.hex();
this->log.info_f("Enemy spec {:08X} produced item {}", spec.probability, hex);
}
break;
}
if (this->log.should_log(phosg::LogLevel::L_INFO)) {
auto hex = spec.data.hex();
this->log.info_f("Enemy spec {:08X} did not produce item {}", spec.probability, hex);
}
}
} }
return item;
// Note: In the original implementation, enemies can only have one possible rare drop. In our implementation, they
// can have multiple rare drops if JSONRareItemSet is used (the other RareItemSet implementations never return
// multiple drops for an enemy type).
Episode episode = episode_for_area(area);
auto specs = this->rare_item_set->get_enemy_specs(
this->mode, episode, this->difficulty, this->section_id, enemy_type);
return this->check_rare_specs_and_create_rare_item(specs, area, force_rare);
} }
ItemData ItemCreator::check_rate_and_create_rare_item(const RareItemSet::ExpandedDrop& drop, uint8_t area) { ItemData ItemCreator::create_rare_item(const ItemData& drop_item, uint8_t area) {
if (drop.probability == 0) { ItemData item = drop_item;
return ItemData();
}
// Note: The original code uses 0xFFFFFFFF as the maximum here. We use 0x100000000 instead, which makes all rare
// items SLIGHTLY more rare.
if (this->rand_int(0x100000000) >= drop.probability) {
return ItemData();
}
ItemData item = drop.data;
if (item.can_be_encoded_in_rel_rare_table()) { if (item.can_be_encoded_in_rel_rare_table()) {
switch (item.data1[0]) { switch (item.data1[0]) {
case 0: case 0:
@@ -617,9 +633,11 @@ void ItemCreator::generate_common_item_variances(ItemData& item, uint8_t area) {
case 3: case 3:
this->generate_common_tool_variances(item, area); this->generate_common_tool_variances(item, area);
break; break;
case 4: case 4: {
item.data2d = this->choose_meseta_amount(this->pt(area)->box_meseta_ranges, this->table_index_for_area(area)) & 0xFFFF; const auto& range = this->pt(area)->box_meseta_ranges.at(this->table_index_for_area(area));
item.data2d = this->choose_meseta_amount(range) & 0xFFFF;
break; break;
}
default: default:
// Note: The original code does the following here: // Note: The original code does the following here:
// item.clear(); // item.clear();
+19 -8
View File
@@ -37,10 +37,18 @@ public:
bool is_from_rare_table = false; bool is_from_rare_table = false;
}; };
DropResult on_monster_item_drop(uint32_t enemy_type, uint8_t area); inline void set_legacy_replay() {
DropResult on_box_item_drop(uint8_t area); this->is_legacy_replay = true;
}
inline void set_rare_drop_rate_multiplier(double multiplier) {
this->rare_drop_rate_multiplier = multiplier;
}
DropResult on_monster_item_drop(EnemyType enemy_type, uint8_t area, bool force_rare);
DropResult on_box_item_drop(uint8_t area, bool force_rare);
// Note: param3-6 refer to the corresponding fields of the object definition // Note: param3-6 refer to the corresponding fields of the object definition
DropResult on_specialized_box_item_drop(uint8_t area, float param3, uint32_t param4, uint32_t param5, uint32_t param6); DropResult on_specialized_box_item_drop(
uint8_t area, float param3, uint32_t param4, uint32_t param5, uint32_t param6);
ItemData base_item_for_specialized_box(uint32_t param4, uint32_t param5, uint32_t param6) const; ItemData base_item_for_specialized_box(uint32_t param4, uint32_t param5, uint32_t param6) const;
std::vector<ItemData> generate_armor_shop_contents(Episode episode, size_t player_level); std::vector<ItemData> generate_armor_shop_contents(Episode episode, size_t player_level);
@@ -69,6 +77,8 @@ private:
phosg::PrefixedLogger log; phosg::PrefixedLogger log;
Version logic_version; Version logic_version;
bool is_legacy_replay;
double rare_drop_rate_multiplier = 1.0;
std::shared_ptr<const ItemData::StackLimits> stack_limits; std::shared_ptr<const ItemData::StackLimits> stack_limits;
GameMode mode; GameMode mode;
Difficulty difficulty; Difficulty difficulty;
@@ -116,14 +126,15 @@ private:
uint32_t rand_int(uint64_t max); uint32_t rand_int(uint64_t max);
float rand_float_0_1_from_crypt(); float rand_float_0_1_from_crypt();
template <size_t NumRanges> uint32_t choose_meseta_amount(const CommonItemSet::Table::Range<uint16_t>& range);
uint32_t choose_meseta_amount(const parray<CommonItemSet::Table::Range<uint16_t>, NumRanges> ranges, size_t table_index);
bool should_allow_meseta_drops() const; bool should_allow_meseta_drops() const;
ItemData check_rare_spec_and_create_rare_enemy_item(uint32_t enemy_type, uint8_t area); ItemData check_rare_spec_and_create_rare_enemy_item(EnemyType enemy_type, uint8_t area, bool force_rare);
ItemData check_rare_specs_and_create_rare_box_item(uint8_t area); ItemData check_rare_specs_and_create_rare_box_item(uint8_t area, bool force_rare);
ItemData check_rate_and_create_rare_item(const RareItemSet::ExpandedDrop& drop, uint8_t area); ItemData check_rare_specs_and_create_rare_item(
const std::vector<RareItemSet::ExpandedDrop>& specs, uint8_t area, bool force_rare);
ItemData create_rare_item(const ItemData& drop_item, uint8_t area);
void generate_rare_weapon_bonuses(ItemData& item, Episode episode, uint32_t random_sample); void generate_rare_weapon_bonuses(ItemData& item, Episode episode, uint32_t random_sample);
void deduplicate_weapon_bonuses(ItemData& item) const; void deduplicate_weapon_bonuses(ItemData& item) const;
+9
View File
@@ -145,6 +145,7 @@ uint32_t Lobby::FloorItemManager::reassign_all_item_ids(uint32_t next_item_id) {
Lobby::Lobby(shared_ptr<ServerState> s, uint32_t id, bool is_game) Lobby::Lobby(shared_ptr<ServerState> s, uint32_t id, bool is_game)
: server_state(s), : server_state(s),
log(std::format("[{}:{:X}] ", is_game ? "Game" : "Lobby", id), lobby_log.min_level), log(std::format("[{}:{:X}] ", is_game ? "Game" : "Lobby", id), lobby_log.min_level),
creation_time(phosg::now()),
lobby_id(id), lobby_id(id),
random_seed(phosg::random_object<uint32_t>()), random_seed(phosg::random_object<uint32_t>()),
rand_crypt(make_shared<DisabledRandomGenerator>()), rand_crypt(make_shared<DisabledRandomGenerator>()),
@@ -229,6 +230,14 @@ void Lobby::create_item_creator(Version logic_version) {
effective_section_id, effective_section_id,
rand_crypt, rand_crypt,
this->quest ? this->quest->meta.battle_rules : nullptr); this->quest ? this->quest->meta.battle_rules : nullptr);
if (this->blueballz_tier >= 0) {
double rare_mult = 1.25 + (static_cast<double>(this->blueballz_tier) * 0.25);
this->item_creator->set_rare_drop_rate_multiplier(rare_mult);
this->log.info_f("Blueballz +{} rare drop rate multiplier set to {:g}x", this->blueballz_tier, rare_mult);
}
if (s->use_legacy_item_random_behavior) {
this->item_creator->set_legacy_replay();
}
} }
uint8_t Lobby::effective_section_id() const { uint8_t Lobby::effective_section_id() const {
+4
View File
@@ -81,6 +81,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
START_BATTLE_PLAYER_IMMEDIATELY = 0x00010000, START_BATTLE_PLAYER_IMMEDIATELY = 0x00010000,
CANNOT_CHANGE_CHEAT_MODE = 0x00020000, CANNOT_CHANGE_CHEAT_MODE = 0x00020000,
USE_CREATOR_SECTION_ID = 0x00040000, USE_CREATOR_SECTION_ID = 0x00040000,
BLUEBALLZ_PLUS0 = 0x00080000,
// Flags used only for lobbies // Flags used only for lobbies
PUBLIC = 0x01000000, PUBLIC = 0x01000000,
DEFAULT = 0x02000000, DEFAULT = 0x02000000,
@@ -91,6 +92,8 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
std::weak_ptr<ServerState> server_state; std::weak_ptr<ServerState> server_state;
phosg::PrefixedLogger log; phosg::PrefixedLogger log;
uint64_t creation_time;
uint32_t lobby_id; uint32_t lobby_id;
uint32_t min_level = 0; uint32_t min_level = 0;
@@ -116,6 +119,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
Episode episode = Episode::NONE; Episode episode = Episode::NONE;
GameMode mode = GameMode::NORMAL; GameMode mode = GameMode::NORMAL;
Difficulty difficulty = Difficulty::NORMAL; Difficulty difficulty = Difficulty::NORMAL;
int8_t blueballz_tier = -1; // -1 = disabled; 0..10 = Blueballz +0..+10
float base_exp_multiplier = 1.0f; float base_exp_multiplier = 1.0f;
float exp_share_multiplier = 0.5f; float exp_share_multiplier = 0.5f;
float challenge_exp_multiplier = 1.0f; float challenge_exp_multiplier = 1.0f;
+99 -69
View File
@@ -464,7 +464,7 @@ Action a_psov2_encrypt_single_test(
current_value, num_mismatches, phosg::format_duration(crypt_time), phosg::format_duration(single_time), current_value, num_mismatches, phosg::format_duration(crypt_time), phosg::format_duration(single_time),
static_cast<float>(crypt_time) / single_time); static_cast<float>(crypt_time) / single_time);
}; };
phosg::parallel_range_blocks<uint64_t>(thread_fn, 0, 0x100000000, 0x1000, num_threads, progress_fn); phosg::parallel_blocks<uint64_t>(thread_fn, 0, 0x100000000, 0x1000, num_threads, progress_fn);
progress_fn(0, 0, 0xFFFFFFFF, 0); progress_fn(0, 0, 0xFFFFFFFF, 0);
}); });
@@ -813,7 +813,7 @@ static void a_encrypt_decrypt_vms_save_fn(phosg::Arguments& args) {
} }
} else { } else {
uint64_t seed = phosg::parallel_range_blocks<uint64_t>([&](uint64_t serial_number, size_t) -> bool { uint64_t seed = phosg::parallel_blocks<uint64_t>([&](uint64_t serial_number, size_t) -> bool {
try { try {
auto decrypted = decrypt_fixed_size_data_section_t<StructT, false, ChecksumLength>( auto decrypted = decrypt_fixed_size_data_section_t<StructT, false, ChecksumLength>(
data_section, sizeof(StructT), serial_number, skip_checksum, override_round2_seed); data_section, sizeof(StructT), serial_number, skip_checksum, override_round2_seed);
@@ -1136,9 +1136,8 @@ Action a_decrypt_dcv2_executable(
executable (DP_ADDRESS.JPN), INDEXES should be the path to the index fixup\n\ executable (DP_ADDRESS.JPN), INDEXES should be the path to the index fixup\n\
table (KATSUO.SEA), and VALUES should be the path to the value fixup table\n\ table (KATSUO.SEA), and VALUES should be the path to the value fixup table\n\
(IWASHI.SEA). The output is written to EXEC.dec.\n\ (IWASHI.SEA). The output is written to EXEC.dec.\n\
If --simple is given, uses the simpler encryption method used in some\n\ If --simple is given, uses the encryption method used in Ives\' Enhancement\n\
community modifications of the game (Enhancement Pack, for example). In\n\ Pack. In this case, --seed is not required; if not given, finds the seed\n\
this case, --seed is not required; if not given, finds the seed\n\
automatically, and prints it to stderr so you will be able to use it when\n\ automatically, and prints it to stderr so you will be able to use it when\n\
re-encrypting.\n", re-encrypting.\n",
+[](phosg::Arguments& args) { +[](phosg::Arguments& args) {
@@ -1166,8 +1165,8 @@ Action a_encrypt_dcv2_executable(
executable (DP_ADDRESS.JPN) and INDEXES should be the path to the index\n\ executable (DP_ADDRESS.JPN) and INDEXES should be the path to the index\n\
fixup table (KATSUO.SEA). The output is written to EXEC.enc and\n\ fixup table (KATSUO.SEA). The output is written to EXEC.enc and\n\
INDEXES.enc.\n\ INDEXES.enc.\n\
If --simple is given, uses the simpler encryption method used in some\n\ If --simple is given, uses the simpler encryption method used in Ives\'\n\
community modifications of the game. In this case, --seed is required.\n", Enhancement Pack. In this case, --seed is required.\n",
+[](phosg::Arguments& args) { +[](phosg::Arguments& args) {
string executable_filename = args.get<string>("executable", true); string executable_filename = args.get<string>("executable", true);
string executable_data = phosg::load_file(executable_filename); string executable_data = phosg::load_file(executable_filename);
@@ -1188,7 +1187,7 @@ Action a_encrypt_dcv2_executable(
Action a_decode_gci_snapshot( Action a_decode_gci_snapshot(
"decode-gci-snapshot", "\ "decode-gci-snapshot", "\
decode-gci-snapshot [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ decode-gci-snapshot [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
Decode a PSO GC snapshot file into a Windows BMP image.\n", Decode a PSO GC snapshot file (in GCI format) into a Windows BMP image.\n",
+[](phosg::Arguments& args) { +[](phosg::Arguments& args) {
auto data = read_input_data(args); auto data = read_input_data(args);
phosg::StringReader r(data); phosg::StringReader r(data);
@@ -1366,7 +1365,7 @@ Action a_salvage_gci(
}; };
if (!round2) { if (!round2) {
phosg::parallel_range_blocks<uint64_t>( phosg::parallel_blocks<uint64_t>(
[&](uint64_t seed, size_t thread_num) -> bool { [&](uint64_t seed, size_t thread_num) -> bool {
auto decrypted = decrypt_fixed_size_data_section_t<StructT, true>( auto decrypted = decrypt_fixed_size_data_section_t<StructT, true>(
data_section, header.data_size, seed, true); data_section, header.data_size, seed, true);
@@ -1386,7 +1385,7 @@ Action a_salvage_gci(
// high half, which is much faster than trying all possible seeds. Unfortunately, this relies on the // high half, which is much faster than trying all possible seeds. Unfortunately, this relies on the
// distribution of values in the plaintext, so it only works for the round-2 seed - the decrypted data after // distribution of values in the plaintext, so it only works for the round-2 seed - the decrypted data after
// round 1 is still essentially random. // round 1 is still essentially random.
phosg::parallel_range_blocks<uint64_t>(try_round2_seed, 0, 0x100000, 0x1000, num_threads); phosg::parallel_blocks<uint64_t>(try_round2_seed, 0, 0x100000, 0x1000, num_threads);
auto intermediate_top_seeds = merge_top_seeds(top_seeds_by_thread); auto intermediate_top_seeds = merge_top_seeds(top_seeds_by_thread);
if (intermediate_top_seeds.empty()) { if (intermediate_top_seeds.empty()) {
throw logic_error("no intermediate seeds were found"); throw logic_error("no intermediate seeds were found");
@@ -1397,7 +1396,7 @@ Action a_salvage_gci(
for (auto& top_seeds : top_seeds_by_thread) { for (auto& top_seeds : top_seeds_by_thread) {
top_seeds.clear(); top_seeds.clear();
} }
phosg::parallel_range_blocks<uint64_t>( phosg::parallel_blocks<uint64_t>(
[&](uint64_t seed, size_t thread_num) -> bool { [&](uint64_t seed, size_t thread_num) -> bool {
return try_round2_seed((seed << 16) | round2_lower_half, thread_num); return try_round2_seed((seed << 16) | round2_lower_half, thread_num);
}, },
@@ -1405,7 +1404,7 @@ Action a_salvage_gci(
} else { } else {
// The user requested not to take any shortcuts, so burn a lot of CPU power // The user requested not to take any shortcuts, so burn a lot of CPU power
phosg::parallel_range_blocks<uint64_t>(try_round2_seed, 0, 0x100000000, 0x1000, num_threads); phosg::parallel_blocks<uint64_t>(try_round2_seed, 0, 0x100000000, 0x1000, num_threads);
} }
print_top_seeds(merge_top_seeds(top_seeds_by_thread)); print_top_seeds(merge_top_seeds(top_seeds_by_thread));
@@ -1474,7 +1473,7 @@ Action a_find_decryption_seed(
return true; return true;
}; };
uint64_t seed = phosg::parallel_range_blocks<uint64_t>([&](uint64_t seed, size_t) -> bool { uint64_t seed = phosg::parallel_blocks<uint64_t>([&](uint64_t seed, size_t) -> bool {
string be_decrypt_buf = ciphertext.substr(0, max_plaintext_size); string be_decrypt_buf = ciphertext.substr(0, max_plaintext_size);
string le_decrypt_buf = ciphertext.substr(0, max_plaintext_size); string le_decrypt_buf = ciphertext.substr(0, max_plaintext_size);
if (uses_v3_encryption(version)) { if (uses_v3_encryption(version)) {
@@ -1622,13 +1621,17 @@ Action a_disassemble_quest_script(
disassemble-quest-script [OPTIONS] [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ disassemble-quest-script [OPTIONS] [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
Disassemble the input quest script (.bin file) into a text representation\n\ Disassemble the input quest script (.bin file) into a text representation\n\
of the commands and metadata it contains. Specify the quest\'s game version\n\ of the commands and metadata it contains. Specify the quest\'s game version\n\
with one of the --dc-nte, --dc-v1, --dc-v2, --pc, --gc-nte, --gc, --gc-ep3,\n\ with one of the --dc-nte, --dc-v1, --dc-v2, --pc, --gc-nte, --gc,\n\
--xb, or --bb options. newserv uses more descriptive opcode mnemonics by\n\ --gc-ep3, --xb, or --bb options. Other options:\n\
default; the --qedit option will result in names matching those used by\n\ --qedit: newserv uses more descriptive opcode mnemonics by default; this\n\
QEdit. If you intend to reassemble the script, after editing it, use the\n\ option will result in names matching those used by QEdit.\n\
--reassembly option to add explicit label numbers and remove offsets and\n\ --reassembly: If you intend to reassemble the script after editing it,\n\
data in code sections. To include script references from the map, use the\n\ use this option to add explicit label numbers and remove offsets and\n\
--map-file=FILENAME option.\n", data in code sections.\n\
--map-file=FILENAME: Include references to script labels from this map.\n\
--language=L: Decode strings using this language. L may be J, E, G, F,\n\
S, B, T, or K, for Japanese, English, German, French, Spanish,\n\
Simplified Chinese, Traditional Chinese, or Korean respectively.\n",
+[](phosg::Arguments& args) { +[](phosg::Arguments& args) {
string data = read_input_data(args); string data = read_input_data(args);
auto version = get_cli_version(args); auto version = get_cli_version(args);
@@ -1641,7 +1644,8 @@ Action a_disassemble_quest_script(
auto map_data = make_shared<string>(prs_decompress(phosg::load_file(map_filename))); auto map_data = make_shared<string>(prs_decompress(phosg::load_file(map_filename)));
map_file = make_shared<MapFile>(map_data); map_file = make_shared<MapFile>(map_data);
} }
Language language = static_cast<Language>(args.get<uint8_t>("language", 0xFF)); const auto& language_str = args.get<string>("language");
Language language = language_str.empty() ? Language::ENGLISH : language_for_name(language_str);
bool reassembly_mode = args.get<bool>("reassembly"); bool reassembly_mode = args.get<bool>("reassembly");
bool use_qedit_names = args.get<bool>("qedit"); bool use_qedit_names = args.get<bool>("qedit");
string result = disassemble_quest_script( string result = disassemble_quest_script(
@@ -1917,8 +1921,7 @@ Action a_extract_ppk("extract-ppk", "\
PC/BB format. For PPK archives, the --password= option is required.\n", PC/BB format. For PPK archives, the --password= option is required.\n",
a_extract_archive_fn); a_extract_archive_fn);
Action a_encode_sjis( Action a_transcode_text("transcode-text", nullptr, +[](phosg::Arguments& args) {
"transcode-text", nullptr, +[](phosg::Arguments& args) {
TextTranscoder* tt_from = nullptr; TextTranscoder* tt_from = nullptr;
{ {
std::string from_name = args.get<std::string>("from"); std::string from_name = args.get<std::string>("from");
@@ -1958,8 +1961,7 @@ Action a_encode_sjis(
if (tt_to) { if (tt_to) {
data = (*tt_to)(data); data = (*tt_to)(data);
} }
write_output_data(args, data.data(), data.size(), "txt"); write_output_data(args, data.data(), data.size(), "txt"); });
});
Action a_decode_text_archive( Action a_decode_text_archive(
"decode-text-archive", "\ "decode-text-archive", "\
@@ -2199,6 +2201,25 @@ Action a_download_files(
io_context->run(); io_context->run();
}); });
std::shared_ptr<RareItemSet> load_rare_item_set(
const std::string& filename, bool is_v1, std::shared_ptr<const ItemNameIndex> v4_item_name_index) {
string filename_lower = phosg::tolower(filename);
auto data = make_shared<string>(phosg::load_file(filename));
if (filename_lower.ends_with(".json")) {
return make_shared<RareItemSet>(phosg::JSON::parse(*data), v4_item_name_index);
} else if (filename_lower.ends_with(".gsl")) {
return make_shared<RareItemSet>(GSLArchive(data, false), false);
} else if (filename_lower.ends_with(".gslb")) {
return make_shared<RareItemSet>(GSLArchive(data, true), true);
} else if (filename_lower.ends_with(".afs")) {
return make_shared<RareItemSet>(AFSArchive(data), is_v1);
} else if (filename_lower.ends_with(".rel")) {
return make_shared<RareItemSet>(*data, true);
} else {
throw runtime_error("cannot determine input format; use a filename ending with .json, .gsl, .gslb, .afs, or .rel");
}
}
Action a_convert_rare_item_set( Action a_convert_rare_item_set(
"convert-rare-item-set", "\ "convert-rare-item-set", "\
convert-rare-item-set INPUT-FILENAME [OUTPUT-FILENAME] [OPTIONS]\n\ convert-rare-item-set INPUT-FILENAME [OUTPUT-FILENAME] [OPTIONS]\n\
@@ -2228,24 +2249,8 @@ Action a_convert_rare_item_set(
if (input_filename.empty() || (input_filename == "-")) { if (input_filename.empty() || (input_filename == "-")) {
throw runtime_error("input filename must be given"); throw runtime_error("input filename must be given");
} }
auto rs = load_rare_item_set(
string input_filename_lower = phosg::tolower(input_filename); input_filename, is_v1(get_cli_version(args, Version::BB_V4)), s->item_name_index(Version::BB_V4));
auto data = make_shared<string>(read_input_data(args));
shared_ptr<RareItemSet> rs;
if (input_filename_lower.ends_with(".json")) {
rs = make_shared<RareItemSet>(phosg::JSON::parse(*data), s->item_name_index_opt(get_cli_version(args, Version::BB_V4)));
} else if (input_filename_lower.ends_with(".gsl")) {
rs = make_shared<RareItemSet>(GSLArchive(data, false), false);
} else if (input_filename_lower.ends_with(".gslb")) {
rs = make_shared<RareItemSet>(GSLArchive(data, true), true);
} else if (input_filename_lower.ends_with(".afs")) {
rs = make_shared<RareItemSet>(AFSArchive(data), is_v1(get_cli_version(args, Version::DC_V2)));
} else if (input_filename_lower.ends_with(".rel")) {
rs = make_shared<RareItemSet>(*data, true);
} else {
throw runtime_error("cannot determine input format; use a filename ending with .json, .gsl, .gslb, .afs, or .rel");
}
if (rate_factor != 1.0) { if (rate_factor != 1.0) {
rs->multiply_all_rates(rate_factor); rs->multiply_all_rates(rate_factor);
} }
@@ -2289,6 +2294,32 @@ Action a_convert_rare_item_set(
throw runtime_error("cannot determine output format; use a filename ending with .json, .gsl, .gslb, or .afs"); throw runtime_error("cannot determine output format; use a filename ending with .json, .gsl, .gslb, or .afs");
} }
}); });
Action a_compare_rare_item_set(
"compare-rare-item-set", nullptr,
+[](phosg::Arguments& args) {
string input_filename1 = args.get<string>(1, false);
if (input_filename1.empty() || (input_filename1 == "-")) {
throw runtime_error("two input filenames must be given");
}
string input_filename2 = args.get<string>(2, false);
if (input_filename2.empty() || (input_filename2 == "-")) {
throw runtime_error("two input filenames must be given");
}
auto s = make_shared<ServerState>(get_config_filename(args));
s->load_config_early();
s->load_patch_indexes();
s->load_text_index();
s->load_item_definitions();
s->load_item_name_indexes();
s->load_drop_tables();
bool is_v1 = ::is_v1(get_cli_version(args, Version::BB_V4));
auto rs1 = load_rare_item_set(input_filename1, is_v1, s->item_name_index(Version::BB_V4));
auto rs2 = load_rare_item_set(input_filename2, is_v1, s->item_name_index(Version::BB_V4));
rs1->print_diff(stdout, *rs2);
});
static shared_ptr<CommonItemSet> load_common_item_set( static shared_ptr<CommonItemSet> load_common_item_set(
const std::string& filename, const std::string& ct_filename, bool big_endian) { const std::string& filename, const std::string& ct_filename, bool big_endian) {
@@ -2759,26 +2790,26 @@ Action a_generate_ep3_cards_html(
} }
} }
phosg::parallel_range<uint32_t>([&](uint32_t index, size_t) -> bool { phosg::parallel_range(
auto& info = this->card_infos[index]; this->card_infos, [&](CardInfo& info, size_t) -> bool {
if (!info.large_filename.empty()) { if (!info.large_filename.empty()) {
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.large_filename)); auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.large_filename));
img.resize(512, 399); img.resize(512, 399);
info.large_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL); info.large_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
} }
if (!info.medium_filename.empty()) { if (!info.medium_filename.empty()) {
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.medium_filename)); auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.medium_filename));
img.resize(184, 144); img.resize(184, 144);
info.medium_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL); info.medium_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
} }
if (!info.small_filename.empty()) { if (!info.small_filename.empty()) {
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.small_filename)); auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.small_filename));
img.resize(58, 43); img.resize(58, 43);
info.small_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL); info.small_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
} }
return false; return false;
}, },
0, this->card_infos.size(), num_threads); num_threads);
} }
this->num_output_columns = 1 + (!no_disassembly) + this->show_small_column + this->show_medium_column + this->show_large_column; this->num_output_columns = 1 + (!no_disassembly) + this->show_small_column + this->show_medium_column + this->show_large_column;
@@ -3093,8 +3124,7 @@ Action a_check_supermaps(
auto f = phosg::fopen_unique(filename, "wt"); auto f = phosg::fopen_unique(filename, "wt");
phosg::fwrite_fmt(f.get(), "QUEST {} ({})\n", it.first, it.second->meta.name); phosg::fwrite_fmt(f.get(), "QUEST {} ({})\n", it.first, it.second->meta.name);
phosg::fwrite_fmt(f.get(), "ENEMY--------------- DCNTE 11/2K DC-V1 DC-V2 PCNTE PC-V2 GCNTE GC-V3 XB-V3 BB-V4\n"); phosg::fwrite_fmt(f.get(), "ENEMY--------------- DCNTE 11/2K DC-V1 DC-V2 PCNTE PC-V2 GCNTE GC-V3 XB-V3 BB-V4\n");
for (size_t type_ss = 0; type_ss < static_cast<size_t>(EnemyType::MAX_ENEMY_TYPE); type_ss++) { for (auto type : phosg::EnumRange<EnemyType>()) {
EnemyType type = static_cast<EnemyType>(type_ss);
bool any_count_nonzero = false; bool any_count_nonzero = false;
array<size_t, NUM_VERSIONS> counts; array<size_t, NUM_VERSIONS> counts;
for (Version v : ALL_NON_PATCH_VERSIONS) { for (Version v : ALL_NON_PATCH_VERSIONS) {
@@ -3319,7 +3349,7 @@ Action a_optimize_materialized_map(
return false; return false;
}; };
phosg::parallel_range_blocks<uint64_t>(thread_fn, 0, 0x100000000, 0x100, num_threads); phosg::parallel_blocks<uint64_t>(thread_fn, 0, 0x100000000, 0x100, num_threads);
}); });
Action a_print_free_supermap( Action a_print_free_supermap(
@@ -3605,7 +3635,7 @@ Action a_generate_all_dc_serial_numbers(
found_counts[7].load(), serial_numbers[7].size(), found_counts[7].load(), serial_numbers[7].size(),
found_counts[8].load(), serial_numbers[8].size()); found_counts[8].load(), serial_numbers[8].size());
}; };
phosg::parallel_range_blocks<uint64_t>(thread_fn, 0, 0x100000000, 0x1000, num_threads, progress_fn); phosg::parallel_blocks<uint64_t>(thread_fn, 0, 0x100000000, 0x1000, num_threads, progress_fn);
if (num_mismatches > 0) { if (num_mismatches > 0) {
throw logic_error("mismatches occurred during test"); throw logic_error("mismatches occurred during test");
@@ -3749,7 +3779,7 @@ Action a_replay_ep3_battle_commands(
run_replay(base_seed, 0); run_replay(base_seed, 0);
} else { } else {
size_t num_threads = args.get<size_t>("threads", 0); size_t num_threads = args.get<size_t>("threads", 0);
phosg::parallel_range_blocks<int64_t>(run_replay, 0, 0x100000000, 0x1000, num_threads); phosg::parallel_blocks<int64_t>(run_replay, 0, 0x100000000, 0x1000, num_threads);
} }
}); });
@@ -3905,7 +3935,7 @@ Action a_run_server_replay_log(
use_terminal_colors = true; use_terminal_colors = true;
} }
auto state = make_shared<ServerState>(get_config_filename(args)); auto state = make_shared<ServerState>(get_config_filename(args), !replay_log_filename.empty());
if (args.get<bool>("debug")) { if (args.get<bool>("debug")) {
state->is_debug = true; state->is_debug = true;
} }
+54 -12
View File
@@ -866,9 +866,10 @@ static const vector<DATEntityDefinition> dat_object_definitions({
// param5; if the dot product is positive, param2 is used) // param5; if the dot product is positive, param2 is used)
// param3 = room ID to use if the dot product described above is zero or negative // param3 = room ID to use if the dot product described above is zero or negative
// param5 = angle (see param2) // param5 = angle (see param2)
// param6 = if equal to 0x00010000, only the player's room_id field is set, and game flag 0x02000000 is set on // param6 = on v2 and before, this is ignored; on v3 and later, if param6 is equal to 0x00010000, only the
// the player; if not equal to 0x00010000, then both room_id and room_id2 are set and no game flag is set // player's room_id field is set, and player flag 0x02000000 is set on the player; if not equal to 0x00010000,
// (TODO: What are the visible behavior differences due to this parameter?) // then both room_id and room_id_in_custom_area (if in a non-rearrangeable area, like Pioneer 2 or Forest) are
// set and no game flag is set (TODO: What are the visible behavior differences due to this parameter?)
{0x000E, F_V0_V4, 0x00005FFFFFF83FFE, "TObjRoomId"}, {0x000E, F_V0_V4, 0x00005FFFFFF83FFE, "TObjRoomId"},
// Sensor of some kind (TODO). Params: // Sensor of some kind (TODO). Params:
@@ -1372,10 +1373,10 @@ static const vector<DATEntityDefinition> dat_object_definitions({
// Item box. Params: // Item box. Params:
// param1 = if positive, box is specialized to drop a specific item or type of item; if zero or negative, box // param1 = if positive, box is specialized to drop a specific item or type of item; if zero or negative, box
// drops any common item or none at all (and param3-6 are all ignored) // drops any item (including box rares for the current floor), or nothing at all, and param3-6 are all ignored
// param3 = if zero, then only data1[0-1] are used and the rest of the ItemData is cleared, then bonuses, grinds, // param3 = if zero, then only data1[0-1] (the high 2 bytes of param4) are used and the rest of the ItemData is
// etc. are applied to the item; if nonzero, the item is not randomized at all and drops exactly as specified // cleared, then bonuses, grinds, etc. are applied to the item; if nonzero, the item is not randomized at all
// in param4-6 // and drops exactly as specified in param4-6
// param4-6 = item definition (see below) // param4-6 = item definition (see below)
// Not all fields in ItemData can be specified in the item definition here. The field order here does not match the // Not all fields in ItemData can be specified in the item definition here. The field order here does not match the
// field order in ItemData! The item definition is encoded here as follows: // field order in ItemData! The item definition is encoded here as follows:
@@ -2822,7 +2823,8 @@ static const vector<DATEntityDefinition> dat_enemy_definitions({
// param2 = if less than 1, this is a Savage Wolf; otherwise it's a Barbarous Wolf // param2 = if less than 1, this is a Savage Wolf; otherwise it's a Barbarous Wolf
{0x0043, F_V0_V4, 0x0000000000600006, "TObjEneBm5Wolf"}, {0x0043, F_V0_V4, 0x0000000000600006, "TObjEneBm5Wolf"},
// Booma, Gobooma, or Gigobooma. Params: // Booma, Gobooma, or Gigobooma. The activation radius is fixed and cannot be changed: 50 for Hunters, 100 for
// Rangers and Forces; the deactivation radius is 100 for Hunters and 150 for Rangers and Forces. Params:
// param1 = TODO (fraction of max HP; see TObjEnemyV8048ee80_v5A) // param1 = TODO (fraction of max HP; see TObjEnemyV8048ee80_v5A)
// param2 = idle walk radius (when there's no target, it will walk around its spawn location within this radius; // param2 = idle walk radius (when there's no target, it will walk around its spawn location within this radius;
// if this is zero, it stands still instead) // if this is zero, it stands still instead)
@@ -3445,9 +3447,49 @@ void MapFile::RandomState::generate_shuffled_location_table(
} }
const array<uint32_t, 41> MapFile::RAND_ENEMY_BASE_TYPES = { const array<uint32_t, 41> MapFile::RAND_ENEMY_BASE_TYPES = {
0x44, 0x43, 0x41, 0x42, 0x40, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0xA0, 0xA1, 0x0044, /* TObjEneBeast */
0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0x0043, /* TObjEneBm5Wolf */
0xE0, 0xE0, 0xE1}; 0x0041, /* TObjEneLappy */
0x0042, /* TObjEneBm3FlyNest */
0x0040, /* TObjEneMoja */
0x0060, /* TObjGrass */
0x0061, /* TObjEneRe2Flower */
0x0062, /* TObjEneNanoDrago */
0x0063, /* TObjEneShark */
0x0064, /* TObjEneSlime */
0x0065, /* TObjEnePanarms */
0x0080, /* TObjEneDubchik */
0x0081, /* TObjEneGyaranzo */
0x0082, /* TObjEneMe3ShinowaReal */
0x0083, /* TObjEneMe1Canadin */
0x0084, /* TObjEneMe1CanadinLeader */
0x0085, /* TOCtrlDubchik */
0x00A0, /* TObjEneSaver */
0x00A1, /* TObjEneRe4Sorcerer */
0x00A2, /* TObjEneDarkGunner */
0x00A3, /* TObjEneDarkGunCenter */
0x00A4, /* TObjEneDf2Bringer */
0x00A5, /* TObjEneRe7Berura */
0x00A6, /* TObjEneDimedian */
0x00A7, /* TObjEneBalClawBody */
0x00A8, /* TObjEneBalClawClaw */
0x00D4, /* TObjEneMe3StelthReal */
0x00D5, /* TObjEneMerillLia */
0x00D6, /* TObjEneBm9Mericarol */
0x00D7, /* TObjEneBm5GibonU */
0x00D8, /* TObjEneGibbles */
0x00D9, /* TObjEneMe1Gee */
0x00DA, /* TObjEneMe1GiGue */
0x00DB, /* TObjEneDelDepth */
0x00DC, /* TObjEneDellBiter */
0x00DD, /* TObjEneDolmOlm */
0x00DE, /* TObjEneMorfos */
0x00DF, /* TObjEneRecobox */
// This is not a bug; 0x00E0 really does appear twice in this list on the client.
0x00E0, /* TObjEneMe3SinowZoaReal/TObjEneEpsilonBody (depending on area) */
0x00E0, /* TObjEneMe3SinowZoaReal/TObjEneEpsilonBody (depending on area) */
0x00E1, /* TObjEneIllGill */
};
MapFile::MapFile(std::shared_ptr<const std::string> data) { MapFile::MapFile(std::shared_ptr<const std::string> data) {
for (uint8_t z = 0; z < this->sections_for_floor.size(); z++) { for (uint8_t z = 0; z < this->sections_for_floor.size(); z++) {
@@ -6566,7 +6608,7 @@ void MapState::import_enemy_states_from_sync(Version from_version, const SyncEne
// Only set the state if it's not an alias // Only set the state if it's not an alias
if (ene_st->super_ene == ene) { if (ene_st->super_ene == ene) {
if (ene_st->game_flags != entry.flags) { if (ene_st->game_flags != entry.flags) {
this->log.warning_f("({:04X} => E-{:03X}) Flags from client ({:08X}) do not match game flags from map ({:08X})", this->log.warning_f("({:04X} => E-{:03X}) Game flags from client ({:08X}) do not match game flags from map ({:08X})",
enemy_index, ene_st->e_id, entry.flags, ene_st->game_flags); enemy_index, ene_st->e_id, entry.flags, ene_st->game_flags);
ene_st->game_flags = entry.flags; ene_st->game_flags = entry.flags;
} }
+6
View File
@@ -42,6 +42,12 @@ constexpr uint32_t PATCH_SWITCHES = 0x11666611;
constexpr uint32_t PROGRAMS = 0x11777711; constexpr uint32_t PROGRAMS = 0x11777711;
constexpr uint32_t DISCONNECT = 0x11888811; constexpr uint32_t DISCONNECT = 0x11888811;
constexpr uint32_t CLEAR_LICENSE = 0x11999911; constexpr uint32_t CLEAR_LICENSE = 0x11999911;
constexpr uint32_t BB_LIVE_SHIP = 0x11AAAA11;
constexpr uint32_t BB_TEST_SHIP = 0x11BBBB11;
constexpr uint32_t BB_VANILLA_SHIP = 0x11CCCC11;
constexpr uint32_t BB_HARDCORE_SHIP = 0x11F00D11;
constexpr uint32_t BB_DEV_SHIP = 0x11EEEE11;
constexpr uint32_t BLUEBALLZ_PLUS0 = 0x11DDDD11;
} // namespace MainMenuItemID } // namespace MainMenuItemID
namespace ClearLicenseConfirmationMenuItemID { namespace ClearLicenseConfirmationMenuItemID {
+2 -2
View File
@@ -721,7 +721,7 @@ const ChallengeTemplateDefinition& get_challenge_template_definition(Version ver
} }
PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto) PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto)
: unknown_a1(proto.unknown_a1), : expiration_frames(proto.expiration_frames),
unknown_a2(proto.unknown_a2), unknown_a2(proto.unknown_a2),
unknown_a3(0), unknown_a3(0),
trigger_radius2(proto.trigger_radius2), trigger_radius2(proto.trigger_radius2),
@@ -730,7 +730,7 @@ PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto)
PlayerHoldState::operator PlayerHoldState_DCProtos() const { PlayerHoldState::operator PlayerHoldState_DCProtos() const {
PlayerHoldState_DCProtos ret; PlayerHoldState_DCProtos ret;
ret.unknown_a1 = this->unknown_a1; ret.expiration_frames = this->expiration_frames;
ret.unknown_a2 = this->unknown_a2; ret.unknown_a2 = this->unknown_a2;
ret.trigger_radius2 = this->trigger_radius2; ret.trigger_radius2 = this->trigger_radius2;
ret.x = this->x; ret.x = this->x;
+8 -2
View File
@@ -64,6 +64,12 @@ struct PlayerVisualConfigT {
// F = force, R = ranger, H = hunter // F = force, R = ranger, H = hunter
// A = android, N = newman, M = human // A = android, N = newman, M = human
// f = female, m = male // f = female, m = male
// Enemies also have a class_flags field, though it isn't part of PlayerVisualConfig. The bits for enemies are:
// -------- -------- -------- ----DMAN
// D = Dark attribute
// M = Machine attribute
// A = Altered Beast attribute
// N = Native attribute
/* 34 */ U32T<BE> class_flags = 0; /* 34 */ U32T<BE> class_flags = 0;
/* 38 */ U16T<BE> costume = 0; /* 38 */ U16T<BE> costume = 0;
/* 3A */ U16T<BE> skin = 0; /* 3A */ U16T<BE> skin = 0;
@@ -1123,7 +1129,7 @@ struct TelepipeState {
struct PlayerHoldState_DCProtos { struct PlayerHoldState_DCProtos {
// This is used in all versions of this command except DCNTE and 11/2000. // This is used in all versions of this command except DCNTE and 11/2000.
/* 00 */ le_uint16_t unknown_a1 = 0; /* 00 */ le_uint16_t expiration_frames = 0;
/* 02 */ le_uint16_t unknown_a2 = 0; /* 02 */ le_uint16_t unknown_a2 = 0;
// unknown_a3 is missing in this format, unlike the v1+ format below // unknown_a3 is missing in this format, unlike the v1+ format below
/* 04 */ le_float trigger_radius2 = 0.0f; /* 04 */ le_float trigger_radius2 = 0.0f;
@@ -1134,7 +1140,7 @@ struct PlayerHoldState_DCProtos {
struct PlayerHoldState { struct PlayerHoldState {
// This is used in all versions of this command except DCNTE and 11/2000. // This is used in all versions of this command except DCNTE and 11/2000.
/* 00 */ le_uint16_t unknown_a1 = 0; /* 00 */ le_uint16_t expiration_frames = 0;
/* 02 */ le_uint16_t unknown_a2 = 0; /* 02 */ le_uint16_t unknown_a2 = 0;
/* 04 */ le_uint32_t unknown_a3 = 0; /* 04 */ le_uint32_t unknown_a3 = 0;
/* 08 */ le_float trigger_radius2 = 0.0f; /* 08 */ le_float trigger_radius2 = 0.0f;
+20 -6
View File
@@ -960,7 +960,8 @@ static asio::awaitable<HandlerResult> SC_6x60_6xA2(shared_ptr<Client> c, Channel
if (rec.obj_st) { if (rec.obj_st) {
if (rec.ignore_def) { if (rec.ignore_def) {
c->log.info_f("Creating item from box {:04X} (area {:02X})", cmd.entity_index, cmd.effective_area); c->log.info_f("Creating item from box {:04X} (area {:02X})", cmd.entity_index, cmd.effective_area);
res = c->proxy_session->item_creator->on_box_item_drop(cmd.effective_area); res = c->proxy_session->item_creator->on_box_item_drop(
cmd.effective_area, c->check_flag(Client::Flag::ALL_RARES_ENABLED));
} else { } else {
c->log.info_f("Creating item from box {:04X} (area {:02X}; specialized with {:g} {:08X} {:08X} {:08X})", c->log.info_f("Creating item from box {:04X} (area {:02X}; specialized with {:g} {:08X} {:08X} {:08X})",
cmd.entity_index, cmd.effective_area, cmd.entity_index, cmd.effective_area,
@@ -970,7 +971,8 @@ static asio::awaitable<HandlerResult> SC_6x60_6xA2(shared_ptr<Client> c, Channel
} }
} else { } else {
c->log.info_f("Creating item from enemy {:04X} (area {:02X})", cmd.entity_index, cmd.effective_area); c->log.info_f("Creating item from enemy {:04X} (area {:02X})", cmd.entity_index, cmd.effective_area);
res = c->proxy_session->item_creator->on_monster_item_drop(rec.effective_rt_index, cmd.effective_area); res = c->proxy_session->item_creator->on_monster_item_drop(
rec.effective_enemy_type, cmd.effective_area, c->check_flag(Client::Flag::ALL_RARES_ENABLED));
} }
if (res.item.empty()) { if (res.item.empty()) {
@@ -1022,8 +1024,15 @@ static asio::awaitable<HandlerResult> S_6x(shared_ptr<Client> c, Channel::Messag
case 0x17: { case 0x17: {
const auto& cmd = msg.check_size_t<G_SetEntityPositionAndAngle_6x17>(); const auto& cmd = msg.check_size_t<G_SetEntityPositionAndAngle_6x17>();
if (cmd.header.entity_id == c->lobby_client_id) { if (cmd.header.entity_id == c->lobby_client_id) {
c->log.warning_f("Blocking subcommand 6x17 targeting local client"); // Vol Opt phase 1 -> phase 2 uses 6x17 targeting the local client to move
co_return HandlerResult::SUPPRESS; // players into the second arena phase. Allow this only while the proxy-side
// client is already on the Vol Opt floor.
if (c->floor == 0x0D) {
c->log.info_f("Allowing subcommand 6x17 targeting local client on Vol Opt floor");
} else {
c->log.warning_f("Blocking subcommand 6x17 targeting local client outside Vol Opt floor");
co_return HandlerResult::SUPPRESS;
}
} }
break; break;
} }
@@ -1643,7 +1652,7 @@ static asio::awaitable<HandlerResult> S_65_67_68_EB(shared_ptr<Client> c, Channe
c->log.warning_f("Proxied player appears multiple times in lobby"); c->log.warning_f("Proxied player appears multiple times in lobby");
} }
if constexpr (sizeof(cmd.lobby_flags) > sizeof(LobbyFlags_DCNTE)) { if constexpr (sizeof(cmd.lobby_flags) > sizeof(LobbyFlagsDCNTE)) {
c->proxy_session->lobby_event = cmd.lobby_flags.event; c->proxy_session->lobby_event = cmd.lobby_flags.event;
if (c->override_lobby_event != 0xFF) { if (c->override_lobby_event != 0xFF) {
cmd.lobby_flags.event = c->override_lobby_event; cmd.lobby_flags.event = c->override_lobby_event;
@@ -2828,7 +2837,12 @@ asio::awaitable<void> handle_proxy_server_commands(
if (ec == asio::error::eof || ec == asio::error::connection_reset) { if (ec == asio::error::eof || ec == asio::error::connection_reset) {
error_str = "Server channel\ndisconnected"; error_str = "Server channel\ndisconnected";
} else if (ec == asio::error::operation_aborted) { } else if (ec == asio::error::operation_aborted) {
// This happens when the player chooses Change Ship/Change Block, so we don't show an error message // If this is the currently-active backend channel, treat the abort as a backend disconnect.
// Normal Change Ship/Change Block reconnects replace ses->server_channel first; the old
// aborted channel will not match here, so those expected aborts stay silent.
if ((c->proxy_session == ses) && (ses->server_channel == channel)) {
error_str = "Server channel\ndisconnected";
}
} else { } else {
error_str = e.what(); error_str = e.what();
} }
+1 -1
View File
@@ -154,7 +154,7 @@ string find_seed_and_decrypt_download_quest_data_section(
const void* data_section, size_t size, bool skip_checksum, bool is_ep3_trial, size_t num_threads) { const void* data_section, size_t size, bool skip_checksum, bool is_ep3_trial, size_t num_threads) {
mutex result_lock; mutex result_lock;
string result; string result;
uint64_t result_seed = phosg::parallel_range_blocks<uint64_t>([&](uint64_t seed, size_t) { uint64_t result_seed = phosg::parallel_blocks<uint64_t>([&](uint64_t seed, size_t) {
try { try {
string ret = decrypt_download_quest_data_section<BE>(data_section, size, seed, skip_checksum, is_ep3_trial); string ret = decrypt_download_quest_data_section<BE>(data_section, size, seed, skip_checksum, is_ep3_trial);
lock_guard<mutex> g(result_lock); lock_guard<mutex> g(result_lock);
+8 -6
View File
@@ -676,7 +676,7 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
// Sets a player's starting position. // Sets a player's starting position.
// valueA = client ID // valueA = client ID
// regsB[0-2] = position (x, y, z as integers) // regsB[0-2] = position (x, y, z as integers)
// r egsB[3] = angle // regsB[3] = angle
{0x76, "set_player_start_position", "p_setpos", {CLIENT_ID, {R_REG_SET_FIXED, 4}}, F_V0_V4 | F_ARGS}, {0x76, "set_player_start_position", "p_setpos", {CLIENT_ID, {R_REG_SET_FIXED, 4}}, F_V0_V4 | F_ARGS},
// Returns players to the Hunter's Guild counter. // Returns players to the Hunter's Guild counter.
@@ -780,6 +780,8 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
// regsA[0-2] = location (x, y, z as integers) // regsA[0-2] = location (x, y, z as integers)
// regsA[3] = radius // regsA[3] = radius
// regsA[4] = label index where thread should start // regsA[4] = label index where thread should start
// After executing this opcode, regsA[0] is replaced with the object's token, which can be used in del_obj_param,
// move_coords_object, etc.
{0x8C, "at_coords_call", nullptr, {{R_REG_SET_FIXED, 5}}, F_V0_V4}, {0x8C, "at_coords_call", nullptr, {{R_REG_SET_FIXED, 5}}, F_V0_V4},
// Like at_coords_call, but the thread is not started automatically. Instead, the player's primary action button // Like at_coords_call, but the thread is not started automatically. Instead, the player's primary action button
@@ -890,7 +892,7 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
{0xB1, "thread_stg", nullptr, {SCRIPT16}, F_V0_V4}, {0xB1, "thread_stg", nullptr, {SCRIPT16}, F_V0_V4},
// Deletes an interactable object previously created by set_obj_param. valueA is the object's token, as returned by // Deletes an interactable object previously created by set_obj_param. valueA is the object's token, as returned by
// regB from set_obj_param. // regB from set_obj_param, or regsA[0] from e.g. at_coords_call.
{0xB2, "del_obj_param", nullptr, {R_REG}, F_V0_V4}, {0xB2, "del_obj_param", nullptr, {R_REG}, F_V0_V4},
// Creates an item in the player's inventory. If the item is successfully created, this opcode sends 6x2B on all // Creates an item in the player's inventory. If the item is successfully created, this opcode sends 6x2B on all
@@ -2004,7 +2006,7 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
{0xF8CB, "clear_slot_invincible", "set_slot_targetable?", {R_REG}, F_V3_V4}, {0xF8CB, "clear_slot_invincible", "set_slot_targetable?", {R_REG}, F_V3_V4},
// These opcodes inflict various status conditions on a player. In the case of Shifta/Deband/Jellen/Zalure, the // These opcodes inflict various status conditions on a player. In the case of Shifta/Deband/Jellen/Zalure, the
// effective technicuqe level is 21. // effective technique level is 21.
// regA = client ID // regA = client ID
{0xF8CC, "set_slot_poison", nullptr, {R_REG}, F_V3_V4}, {0xF8CC, "set_slot_poison", nullptr, {R_REG}, F_V3_V4},
{0xF8CD, "set_slot_paralyze", nullptr, {R_REG}, F_V3_V4}, {0xF8CD, "set_slot_paralyze", nullptr, {R_REG}, F_V3_V4},
@@ -2089,9 +2091,9 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
// regsB[0-2] = location (x, y, z as integers) // regsB[0-2] = location (x, y, z as integers)
{0xF8E6, "move_coords_object", nullptr, {R_REG, {R_REG_SET_FIXED, 3}}, F_V3_V4}, {0xF8E6, "move_coords_object", nullptr, {R_REG, {R_REG_SET_FIXED, 3}}, F_V3_V4},
// These are the same as their counterparts without _ex, but these return an object token in regB which can be used // These are the same as their counterparts without _ex, but these also return the object ID (which is distinct
// with del_obj_param, move_coords_object, etc. set_obj_param_ex is the same as set_obj_param, since set_obj_param // from the object token) in regB. There is a bug in set_obj_param_ex - the object token is not returned anywhere,
// already returns an object token. // and only the object ID is returned in regB.
{0xF8E7, "at_coords_call_ex", nullptr, {{R_REG_SET_FIXED, 5}, W_REG}, F_V3_V4}, {0xF8E7, "at_coords_call_ex", nullptr, {{R_REG_SET_FIXED, 5}, W_REG}, F_V3_V4},
{0xF8E8, "at_coords_talk_ex", nullptr, {{R_REG_SET_FIXED, 5}, W_REG}, F_V3_V4}, {0xF8E8, "at_coords_talk_ex", nullptr, {{R_REG_SET_FIXED, 5}, W_REG}, F_V3_V4},
{0xF8E9, "npc_coords_call_ex", "walk_to_coord_call_ex", {{R_REG_SET_FIXED, 5}, W_REG}, F_V3_V4}, {0xF8E9, "npc_coords_call_ex", "walk_to_coord_call_ex", {{R_REG_SET_FIXED, 5}, W_REG}, F_V3_V4},
+172 -89
View File
@@ -177,23 +177,31 @@ RareItemSet::ParsedRELData::ParsedRELData(phosg::StringReader r, bool big_endian
} }
RareItemSet::ParsedRELData::ParsedRELData(const SpecCollection& collection) { RareItemSet::ParsedRELData::ParsedRELData(const SpecCollection& collection) {
for (const auto& specs : collection.rt_index_to_specs) { this->monster_rares.resize(NUM_RT_INDEXES_V4);
ExpandedDrop effective_spec;
for (const auto& [enemy_type, specs] : collection.enemy_specs) {
const auto& def = type_definition_for_enemy(enemy_type);
if (def.rt_index == 0xFF) {
throw runtime_error(std::format(
"monster spec for {} has no rt_index and cannot be converted to ItemRT format", def.enum_name));
}
auto& dest_spec = this->monster_rares.at(def.rt_index);
for (const auto& spec : specs) { for (const auto& spec : specs) {
if (effective_spec.data.empty()) { if (dest_spec.data.empty()) {
effective_spec = spec; dest_spec = spec;
} else if ((effective_spec.probability != spec.probability) || (effective_spec.data != spec.data)) { } else if ((dest_spec.probability != spec.probability) || (dest_spec.data != spec.data)) {
throw runtime_error("monster spec cannot be converted to ItemRT format"); throw runtime_error(std::format(
"monster spec for {} contains multiple drops and cannot be converted to ItemRT format", def.enum_name));
} }
} }
this->monster_rares.emplace_back(specs.empty() ? ExpandedDrop() : specs[0]);
} }
if (collection.box_area_norm_to_specs.size() > 0xFF) { if (collection.box_specs.size() > 0xFF) {
throw runtime_error("area_norm value too high"); throw runtime_error("area_norm value too high");
} }
for (uint8_t area_norm = 0; area_norm < collection.box_area_norm_to_specs.size(); area_norm++) { for (uint8_t area_norm = 0; area_norm < collection.box_specs.size(); area_norm++) {
for (const auto& spec : collection.box_area_norm_to_specs[area_norm]) { for (const auto& spec : collection.box_specs[area_norm]) {
uint8_t area_norm_plus_1 = area_norm + 1; uint8_t area_norm_plus_1 = area_norm + 1;
this->box_rares.emplace_back(BoxRare{.area_norm_plus_1 = area_norm_plus_1, .drop = spec}); this->box_rares.emplace_back(BoxRare{.area_norm_plus_1 = area_norm_plus_1, .drop = spec});
} }
@@ -208,27 +216,26 @@ std::string RareItemSet::ParsedRELData::serialize(bool big_endian, bool is_v1) c
} }
} }
RareItemSet::SpecCollection RareItemSet::ParsedRELData::as_collection() const { RareItemSet::SpecCollection RareItemSet::ParsedRELData::as_collection(Episode episode) const {
SpecCollection ret; SpecCollection ret;
for (size_t z = 0; z < this->monster_rares.size(); z++) { for (size_t rt_index = 0; rt_index < this->monster_rares.size(); rt_index++) {
const auto& drop = this->monster_rares[z]; const auto& drop = this->monster_rares[rt_index];
if (drop.data.empty()) { if (drop.data.empty()) {
continue; continue;
} }
if (z >= ret.rt_index_to_specs.size()) { for (auto enemy_type : enemy_types_for_rare_table_index(episode, rt_index)) {
ret.rt_index_to_specs.resize(z + 1); ret.enemy_specs[enemy_type].emplace_back(drop);
} }
ret.rt_index_to_specs[z].emplace_back(drop);
} }
for (const auto& drop : this->box_rares) { for (const auto& drop : this->box_rares) {
if ((drop.area_norm_plus_1 == 0) || drop.drop.data.empty()) { if ((drop.area_norm_plus_1 == 0) || drop.drop.data.empty()) {
continue; continue;
} }
uint8_t area_norm = drop.area_norm_plus_1 - 1; uint8_t area_norm = drop.area_norm_plus_1 - 1;
if (area_norm >= ret.box_area_norm_to_specs.size()) { if (area_norm >= ret.box_specs.size()) {
ret.box_area_norm_to_specs.resize(area_norm + 1); ret.box_specs.resize(area_norm + 1);
} }
ret.box_area_norm_to_specs[area_norm].emplace_back(drop.drop); ret.box_specs[area_norm].emplace_back(drop.drop);
} }
return ret; return ret;
} }
@@ -241,8 +248,7 @@ RareItemSet::RareItemSet(const AFSArchive& afs, bool is_v1) {
size_t index = static_cast<size_t>(difficulty) * 10 + section_id; size_t index = static_cast<size_t>(difficulty) * 10 + section_id;
ParsedRELData rel(afs.get_reader(index), false, is_v1); ParsedRELData rel(afs.get_reader(index), false, is_v1);
this->collections.emplace( this->collections.emplace(
this->key_for_params(mode, Episode::EP1, difficulty, section_id), this->key_for_params(mode, Episode::EP1, difficulty, section_id), rel.as_collection(Episode::EP1));
rel.as_collection());
} catch (const out_of_range&) { } catch (const out_of_range&) {
} }
} }
@@ -250,7 +256,8 @@ RareItemSet::RareItemSet(const AFSArchive& afs, bool is_v1) {
} }
} }
string RareItemSet::gsl_entry_name_for_table(GameMode mode, Episode episode, Difficulty difficulty, uint8_t section_id) { string RareItemSet::gsl_entry_name_for_table(
GameMode mode, Episode episode, Difficulty difficulty, uint8_t section_id) {
return std::format("ItemRT{}{}{}{}.rel", return std::format("ItemRT{}{}{}{}.rel",
((mode == GameMode::CHALLENGE) ? "c" : ""), ((mode == GameMode::CHALLENGE) ? "c" : ""),
((episode == Episode::EP2) ? "l" : ""), ((episode == Episode::EP2) ? "l" : ""),
@@ -259,7 +266,7 @@ string RareItemSet::gsl_entry_name_for_table(GameMode mode, Episode episode, Dif
} }
RareItemSet::RareItemSet(const GSLArchive& gsl, bool is_big_endian) { RareItemSet::RareItemSet(const GSLArchive& gsl, bool is_big_endian) {
for (GameMode mode : ALL_GAME_MODES_V23) { for (GameMode mode : {GameMode::NORMAL, GameMode::CHALLENGE}) {
for (Episode episode : ALL_EPISODES_V3) { for (Episode episode : ALL_EPISODES_V3) {
for (Difficulty difficulty : ALL_DIFFICULTIES_V234) { for (Difficulty difficulty : ALL_DIFFICULTIES_V234) {
for (size_t section_id = 0; section_id < 10; section_id++) { for (size_t section_id = 0; section_id < 10; section_id++) {
@@ -267,7 +274,7 @@ RareItemSet::RareItemSet(const GSLArchive& gsl, bool is_big_endian) {
string filename = this->gsl_entry_name_for_table(mode, episode, difficulty, section_id); string filename = this->gsl_entry_name_for_table(mode, episode, difficulty, section_id);
ParsedRELData rel(gsl.get_reader(filename), is_big_endian, false); ParsedRELData rel(gsl.get_reader(filename), is_big_endian, false);
this->collections.emplace( this->collections.emplace(
this->key_for_params(mode, episode, difficulty, section_id), rel.as_collection()); this->key_for_params(mode, episode, difficulty, section_id), rel.as_collection(episode));
} catch (const out_of_range&) { } catch (const out_of_range&) {
} }
} }
@@ -287,7 +294,7 @@ RareItemSet::RareItemSet(const string& rel_data, bool is_big_endian) {
size_t index = (ep_index * 40) + static_cast<size_t>(difficulty) * 10 + section_id; size_t index = (ep_index * 40) + static_cast<size_t>(difficulty) * 10 + section_id;
ParsedRELData rel(r.sub(0x280 * index, 0x280), is_big_endian, false); ParsedRELData rel(r.sub(0x280 * index, 0x280), is_big_endian, false);
this->collections.emplace( this->collections.emplace(
this->key_for_params(GameMode::NORMAL, episode, difficulty, section_id), rel.as_collection()); this->key_for_params(GameMode::NORMAL, episode, difficulty, section_id), rel.as_collection(episode));
} catch (const out_of_range&) { } catch (const out_of_range&) {
} }
} }
@@ -315,26 +322,19 @@ RareItemSet::RareItemSet(const phosg::JSON& json, shared_ptr<const ItemNameIndex
uint8_t section_id = section_id_for_name(section_id_it.first); uint8_t section_id = section_id_for_name(section_id_it.first);
auto& collection = this->collections[this->key_for_params(mode, episode, difficulty, section_id)]; auto& collection = this->collections[this->key_for_params(mode, episode, difficulty, section_id)];
for (const auto& item_it : section_id_it.second->as_dict()) { for (const auto& [enemy_type_name, specs_json] : section_id_it.second->as_dict()) {
vector<ExpandedDrop>* target; vector<ExpandedDrop>* target;
if (item_it.first.starts_with("Box-")) { if (enemy_type_name.starts_with("Box-")) {
uint8_t area_norm = FloorDefinition::get(episode, item_it.first.substr(4)).drop_area_norm; uint8_t area_norm = FloorDefinition::get(episode, enemy_type_name.substr(4)).drop_area_norm;
if (collection.box_area_norm_to_specs.size() <= area_norm) { if (collection.box_specs.size() <= area_norm) {
collection.box_area_norm_to_specs.resize(area_norm + 1); collection.box_specs.resize(area_norm + 1);
} }
target = &collection.box_area_norm_to_specs[area_norm]; target = &collection.box_specs[area_norm];
} else { } else {
size_t rt_index = type_definition_for_enemy(phosg::enum_for_name<EnemyType>(item_it.first)).rt_index; target = &collection.enemy_specs[phosg::enum_for_name<EnemyType>(enemy_type_name)];
if (rt_index == 0xFF) {
throw runtime_error("enemy type " + item_it.first + " does not have an rt_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()) { for (const auto& spec_json : specs_json->as_list()) {
auto& d = target->emplace_back(); auto& d = target->emplace_back();
auto prob_desc = spec_json->at(0); auto prob_desc = spec_json->at(0);
@@ -702,7 +702,11 @@ string RareItemSet::serialize_html(
std::string exact_token = std::format("Exact rate: {} / {}", frac.first, frac.second); std::string exact_token = std::format("Exact rate: {} / {}", frac.first, frac.second);
if (common_item_set && type_def && type_def->rt_index != 0xFF) { if (common_item_set && type_def && type_def->rt_index != 0xFF) {
auto table = common_item_set->get_table(episode, mode, difficulty, section_id); auto table = common_item_set->get_table(episode, mode, difficulty, section_id);
uint8_t dar = table->enemy_type_drop_probs.at(type_def->rt_index); uint8_t dar = 0;
try {
dar = table->enemy_type_drop_probs.at(type_def->type);
} catch (const out_of_range&) {
}
exact_token += std::format(" (DAR: {}%)", dar); exact_token += std::format(" (DAR: {}%)", dar);
frac.first *= dar; frac.first *= dar;
frac.second *= 100; frac.second *= 100;
@@ -747,13 +751,9 @@ string RareItemSet::serialize_html(
for (const auto& zone_type : zone_types) { for (const auto& zone_type : zone_types) {
add_location_header(zone_type.name); add_location_header(zone_type.name);
for (EnemyType type : zone_type.types) { for (EnemyType type : zone_type.types) {
uint8_t rt_index = type_definition_for_enemy(type).rt_index;
if (rt_index == 0xFF) {
continue;
}
array<vector<ExpandedDrop>, 10> specs_lists; array<vector<ExpandedDrop>, 10> specs_lists;
for (uint8_t section_id = 0; section_id < 10; section_id++) { 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); specs_lists[section_id] = this->get_enemy_specs(mode, episode, difficulty, section_id, type);
} }
const auto& type_def = type_definition_for_enemy(type); const auto& type_def = type_definition_for_enemy(type);
const char* name = (difficulty == Difficulty::ULTIMATE && type_def.ultimate_name) ? type_def.ultimate_name : type_def.in_game_name; const char* name = (difficulty == Difficulty::ULTIMATE && type_def.ultimate_name) ? type_def.ultimate_name : type_def.in_game_name;
@@ -787,13 +787,9 @@ phosg::JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const
auto section_id_dict = phosg::JSON::dict(); auto section_id_dict = phosg::JSON::dict();
for (uint8_t section_id = 0; section_id < 10; section_id++) { for (uint8_t section_id = 0; section_id < 10; section_id++) {
auto collection_dict = phosg::JSON::dict(); auto collection_dict = phosg::JSON::dict();
for (size_t rt_index = 0; rt_index < 0x80; rt_index++) { for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
const auto& enemy_types = enemy_types_for_rare_table_index(episode, rt_index); const auto& specs = this->get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, enemy_type);
if (enemy_types.empty()) { for (const auto& spec : specs) {
continue;
}
for (const auto& spec : this->get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, rt_index)) {
if (spec.data.empty()) { if (spec.data.empty()) {
continue; continue;
} }
@@ -807,12 +803,8 @@ phosg::JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const
if (name_index) { if (name_index) {
spec_json.emplace_back(name_index->describe_item(spec.data)); spec_json.emplace_back(name_index->describe_item(spec.data));
} }
for (const auto& enemy_type : enemy_types) { auto list_emplace_ret = collection_dict.emplace(phosg::name_for_enum(enemy_type), phosg::JSON::list());
if (type_definition_for_enemy(enemy_type).valid_in_episode(episode)) { list_emplace_ret.first->second->emplace_back(std::move(spec_json));
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));
}
}
} }
} }
@@ -858,17 +850,17 @@ phosg::JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const
} }
void RareItemSet::multiply_all_rates(double factor) { void RareItemSet::multiply_all_rates(double factor) {
auto multiply_rates_vec = +[](vector<vector<ExpandedDrop>>& vec, double factor) -> void { for (auto& [_, collection] : this->collections) {
for (auto& vec_it : vec) { for (auto& [_, specs] : collection.enemy_specs) {
for (auto& z_it : vec_it) { for (auto& spec : specs) {
uint64_t new_probability = z_it.probability * factor; spec.probability = min<uint64_t>(spec.probability * factor, 0xFFFFFFFF);
z_it.probability = min<uint64_t>(new_probability, 0xFFFFFFFF); }
}
for (auto& specs : collection.box_specs) {
for (auto& spec : specs) {
spec.probability = min<uint64_t>(spec.probability * factor, 0xFFFFFFFF);
} }
} }
};
for (auto& coll_it : this->collections) {
multiply_rates_vec(coll_it.second.rt_index_to_specs, factor);
multiply_rates_vec(coll_it.second.box_area_norm_to_specs, factor);
} }
} }
@@ -893,28 +885,22 @@ void RareItemSet::print_collection(
name_for_section_id(section_id)); name_for_section_id(section_id));
phosg::fwrite_fmt(stream, " Monster rares:\n"); phosg::fwrite_fmt(stream, " Monster rares:\n");
for (size_t z = 0; z < collection->rt_index_to_specs.size(); z++) { for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
string enemy_types_str; try {
const auto& enemy_types = enemy_types_for_rare_table_index(episode, z); const auto& def = type_definition_for_enemy(enemy_type);
for (EnemyType enemy_type : enemy_types) { for (const auto& spec : collection->enemy_specs.at(enemy_type)) {
enemy_types_str += phosg::name_for_enum(enemy_type); string s = name_index ? spec.str(name_index) : spec.str();
enemy_types_str.push_back(','); phosg::fwrite_fmt(stream, " {:<23} {}\n", def.enum_name, s);
} }
if (!enemy_types_str.empty()) { } catch (const out_of_range&) {
enemy_types_str.resize(enemy_types_str.size() - 1);
}
for (const auto& spec : collection->rt_index_to_specs[z]) {
string s = name_index ? spec.str(name_index) : spec.str();
phosg::fwrite_fmt(stream, " {:02X}: {} ({})\n", z, s, enemy_types_str);
} }
} }
phosg::fwrite_fmt(stream, " Box rares:\n"); phosg::fwrite_fmt(stream, " Box rares:\n");
for (size_t area_norm = 0; area_norm < collection->box_area_norm_to_specs.size(); area_norm++) { for (size_t area_norm = 0; area_norm < collection->box_specs.size(); area_norm++) {
for (const auto& spec : collection->box_area_norm_to_specs[area_norm]) { for (const auto& spec : collection->box_specs[area_norm]) {
string s = name_index ? spec.str(name_index) : spec.str(); string s = name_index ? spec.str(name_index) : spec.str();
phosg::fwrite_fmt(stream, " (area-norm {:02X}) {}\n", area_norm, s); phosg::fwrite_fmt(stream, " (area-norm {:02X}) {}\n", area_norm, s);
} }
} }
} }
@@ -934,10 +920,100 @@ void RareItemSet::print_all_collections(FILE* stream, std::shared_ptr<const Item
} }
} }
void RareItemSet::SpecCollection::print_diff(FILE* stream, const SpecCollection& other) const {
auto format_specs = [](const std::vector<ExpandedDrop>& specs) -> std::string {
std::string ret;
for (const auto& spec : specs) {
if (!ret.empty()) {
ret += ",";
}
ret += std::format("{:08X}:{}", spec.probability, spec.data.short_hex());
}
return ret;
};
const std::vector<ExpandedDrop> empty_specs{};
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
const std::vector<ExpandedDrop>* this_specs = &empty_specs;
const std::vector<ExpandedDrop>* other_specs = &empty_specs;
try {
this_specs = &this->enemy_specs.at(enemy_type);
} catch (const out_of_range&) {
}
try {
other_specs = &other.enemy_specs.at(enemy_type);
} catch (const out_of_range&) {
}
if (*this_specs != *other_specs) {
phosg::fwrite_fmt(stream, " {}: {} -> {}\n",
phosg::name_for_enum(enemy_type), format_specs(*this_specs), format_specs(*other_specs));
}
}
for (size_t area_norm = 0; area_norm < 10; area_norm++) {
const auto& this_specs = (area_norm < this->box_specs.size()) ? this->box_specs[area_norm] : empty_specs;
const auto& other_specs = (area_norm < other.box_specs.size()) ? other.box_specs[area_norm] : empty_specs;
if (this_specs != other_specs) {
phosg::fwrite_fmt(stream, " Box (area_norm {}): {} -> {}\n",
area_norm, format_specs(this_specs), format_specs(other_specs));
}
}
}
void RareItemSet::print_diff(FILE* stream, const RareItemSet& other) const {
bool any_difference_found = false;
for (const auto& episode : ALL_EPISODES_V4) {
for (const auto& mode : ALL_GAME_MODES_V4) {
for (const auto& difficulty : ALL_DIFFICULTIES_V234) {
for (uint8_t section_id = 0; section_id < 10; section_id++) {
const SpecCollection* this_coll = nullptr;
const SpecCollection* other_coll = nullptr;
try {
this_coll = &this->get_collection(mode, episode, difficulty, section_id);
} catch (const out_of_range&) {
}
try {
other_coll = &other.get_collection(mode, episode, difficulty, section_id);
} catch (const out_of_range&) {
}
if (!this_coll && !other_coll) {
continue;
} else if (!this_coll) {
any_difference_found = true;
phosg::fwrite_fmt(stream, "> Collection present in other but not this: {} {} {} {}\n",
name_for_episode(episode),
name_for_mode(mode),
name_for_difficulty(difficulty),
name_for_section_id(section_id));
} else if (!other_coll) {
any_difference_found = true;
phosg::fwrite_fmt(stream, "> Collection present in this but not other: {} {} {} {}\n",
name_for_episode(episode),
name_for_mode(mode),
name_for_difficulty(difficulty),
name_for_section_id(section_id));
} else if (*this_coll != *other_coll) {
any_difference_found = true;
phosg::fwrite_fmt(stream, "> Collections do not match: {} {} {} {}\n",
name_for_episode(episode),
name_for_mode(mode),
name_for_difficulty(difficulty),
name_for_section_id(section_id));
this_coll->print_diff(stream, *other_coll);
}
}
}
}
}
if (!any_difference_found) {
phosg::fwrite_fmt(stream, "> These rare item sets are identical\n");
}
}
std::vector<RareItemSet::ExpandedDrop> RareItemSet::get_enemy_specs( std::vector<RareItemSet::ExpandedDrop> RareItemSet::get_enemy_specs(
GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t rt_index) const { GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, EnemyType enemy_type) const {
try { try {
return this->get_collection(mode, episode, difficulty, secid).rt_index_to_specs.at(rt_index); return this->get_collection(mode, episode, difficulty, secid).enemy_specs.at(enemy_type);
} catch (const out_of_range&) { } catch (const out_of_range&) {
static const std::vector<ExpandedDrop> empty_vector; static const std::vector<ExpandedDrop> empty_vector;
return empty_vector; return empty_vector;
@@ -947,7 +1023,7 @@ std::vector<RareItemSet::ExpandedDrop> RareItemSet::get_enemy_specs(
std::vector<RareItemSet::ExpandedDrop> RareItemSet::get_box_specs( std::vector<RareItemSet::ExpandedDrop> RareItemSet::get_box_specs(
GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t area_norm) const { GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t area_norm) const {
try { try {
return this->get_collection(mode, episode, difficulty, secid).box_area_norm_to_specs.at(area_norm); return this->get_collection(mode, episode, difficulty, secid).box_specs.at(area_norm);
} catch (const out_of_range&) { } catch (const out_of_range&) {
static const std::vector<ExpandedDrop> empty_vector; static const std::vector<ExpandedDrop> empty_vector;
return empty_vector; return empty_vector;
@@ -965,7 +1041,14 @@ bool RareItemSet::has_entries_for_game_config(GameMode mode, Episode episode, Di
const RareItemSet::SpecCollection& RareItemSet::get_collection( const RareItemSet::SpecCollection& RareItemSet::get_collection(
GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid) const { GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid) const {
return this->collections.at(this->key_for_params(mode, episode, difficulty, secid)); try {
return this->collections.at(this->key_for_params(mode, episode, difficulty, secid));
} catch (const out_of_range&) {
if (mode == GameMode::BATTLE || mode == GameMode::SOLO) {
return this->collections.at(this->key_for_params(GameMode::NORMAL, episode, difficulty, secid));
}
throw;
}
} }
uint16_t RareItemSet::key_for_params(GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid) { uint16_t RareItemSet::key_for_params(GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid) {
+15 -6
View File
@@ -22,6 +22,9 @@ public:
uint32_t probability = 0; uint32_t probability = 0;
ItemData data; ItemData data;
bool operator==(const ExpandedDrop& other) const = default;
bool operator!=(const ExpandedDrop& other) const = default;
std::string str() const; std::string str() const;
std::string str(std::shared_ptr<const ItemNameIndex> name_index) const; std::string str(std::shared_ptr<const ItemNameIndex> name_index) const;
}; };
@@ -34,7 +37,7 @@ public:
~RareItemSet() = default; ~RareItemSet() = default;
std::vector<ExpandedDrop> get_enemy_specs( std::vector<ExpandedDrop> get_enemy_specs(
GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t rt_index) const; GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, EnemyType enemy_type) const;
std::vector<ExpandedDrop> get_box_specs( std::vector<ExpandedDrop> get_box_specs(
GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t area_norm) const; GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t area_norm) const;
@@ -60,11 +63,17 @@ public:
uint8_t section_id, uint8_t section_id,
std::shared_ptr<const ItemNameIndex> name_index = nullptr) const; std::shared_ptr<const ItemNameIndex> name_index = nullptr) const;
void print_all_collections(FILE* stream, std::shared_ptr<const ItemNameIndex> name_index = nullptr) const; void print_all_collections(FILE* stream, std::shared_ptr<const ItemNameIndex> name_index = nullptr) const;
void print_diff(FILE* stream, const RareItemSet& other) const;
protected: protected:
struct SpecCollection { struct SpecCollection {
std::vector<std::vector<ExpandedDrop>> rt_index_to_specs; std::unordered_map<EnemyType, std::vector<ExpandedDrop>> enemy_specs;
std::vector<std::vector<ExpandedDrop>> box_area_norm_to_specs; std::vector<std::vector<ExpandedDrop>> box_specs; // Indexed by area_norm
bool operator==(const SpecCollection& other) const = default;
bool operator!=(const SpecCollection& other) const = default;
void print_diff(FILE* stream, const SpecCollection& other) const;
}; };
struct ParsedRELData { struct ParsedRELData {
@@ -95,8 +104,8 @@ protected:
ExpandedDrop drop; ExpandedDrop drop;
}; };
std::vector<ExpandedDrop> monster_rares; std::vector<ExpandedDrop> monster_rares; // Indexed by rt_index
std::vector<BoxRare> box_rares; std::vector<BoxRare> box_rares; // Not indexed (area_norm + 1 is in the struct)
ParsedRELData() = default; ParsedRELData() = default;
ParsedRELData(phosg::StringReader r, bool big_endian, bool is_v1); ParsedRELData(phosg::StringReader r, bool big_endian, bool is_v1);
@@ -108,7 +117,7 @@ protected:
template <bool BE> template <bool BE>
std::string serialize_t(bool is_v1) const; std::string serialize_t(bool is_v1) const;
SpecCollection as_collection() const; SpecCollection as_collection(Episode episode) const;
}; };
std::unordered_map<uint16_t, SpecCollection> collections; std::unordered_map<uint16_t, SpecCollection> collections;
+612 -70
View File
File diff suppressed because it is too large Load Diff
+370 -88
View File
@@ -2,7 +2,9 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <fstream>
#include <memory> #include <memory>
#include <phosg/Random.hh> #include <phosg/Random.hh>
#include <phosg/Strings.hh> #include <phosg/Strings.hh>
@@ -76,6 +78,184 @@ using SDF = SubcommandDefinition::Flag;
extern const vector<SubcommandDefinition> subcommand_definitions; extern const vector<SubcommandDefinition> subcommand_definitions;
static string json_escape_for_hardcore_ledger(const string& text) {
string ret;
ret.reserve(text.size() + 16);
for (char ch : text) {
switch (ch) {
case '\\':
ret += "\\\\";
break;
case '"':
ret += "\\\"";
break;
case '\n':
ret += "\\n";
break;
case '\r':
ret += "\\r";
break;
case '\t':
ret += "\\t";
break;
default:
ret += ch;
}
}
return ret;
}
static string hardcore_death_character_name_for_ledger(shared_ptr<Client> c) {
try {
auto p = c->character_file(false);
if (p) {
string name = p->disp.name.decode(c->language());
if (!name.empty()) {
return name;
}
}
} catch (const exception&) {
}
return "";
}
static string hardcore_death_ledger_filename(shared_ptr<Client> c) {
string char_filename = c->character_filename();
size_t slash_offset = char_filename.find_last_of('/');
if (slash_offset == string::npos) {
return "hardcore-deaths.jsonl";
}
return char_filename.substr(0, slash_offset + 1) + "hardcore-deaths.jsonl";
}
static string hardcore_zone_name(shared_ptr<Client> c) {
// Basic Episode 1 floor names. Unknown Episode 2/4 floors will fall back safely for now.
switch (c->floor) {
case 0:
return "Pioneer 2";
case 1:
return "Forest 1";
case 2:
return "Forest 2";
case 3:
return "Caves 1";
case 4:
return "Caves 2";
case 5:
return "Caves 3";
case 6:
return "Mines 1";
case 7:
return "Mines 2";
case 8:
return "Ruins 1";
case 9:
return "Ruins 2";
case 10:
return "Ruins 3";
case 11:
return "Dragon";
case 12:
return "De Rol Le";
case 13:
return "Vol Opt";
case 14:
return "Dark Falz";
default:
return std::format("unknown zone {}", c->floor);
}
}
static bool append_hardcore_death_ledger(shared_ptr<Client> c, const char* reason) {
string filename = hardcore_death_ledger_filename(c);
ofstream f(filename, ios::out | ios::app);
if (!f.good()) {
return false;
}
uint32_t account_id = 0;
string username;
if (c->login) {
if (c->login->account) {
account_id = c->login->account->account_id;
}
if (c->login->bb_license) {
username = c->login->bb_license->username;
}
}
string character_file = c->character_filename();
string character_name = hardcore_death_character_name_for_ledger(c);
string zone = hardcore_zone_name(c);
f << "{"
<< "\"time_epoch\":" << static_cast<long long>(time(nullptr)) << ","
<< "\"account_id\":" << account_id << ","
<< "\"username\":\"" << json_escape_for_hardcore_ledger(username) << "\","
<< "\"character_file\":\"" << json_escape_for_hardcore_ledger(character_file) << "\","
<< "\"character_name\":\"" << json_escape_for_hardcore_ledger(character_name) << "\","
<< "\"zone\":\"" << json_escape_for_hardcore_ledger(zone) << "\","
<< "\"reason\":\"" << json_escape_for_hardcore_ledger(reason ? reason : "") << "\""
<< "}\n";
return f.good();
}
static string bb_hardcore_dead_filename_for_subcommands(shared_ptr<Client> c) {
return c->character_filename() + ".hardcore-dead";
}
static bool current_ship_is_hardcore_bb(shared_ptr<Client> c) {
try {
auto s = c->require_server_state();
return s->enable_hardcore_mode && (c->version() == Version::BB_V4);
} catch (const exception&) {
return false;
}
}
static bool mark_bb_character_hardcore_dead_for_subcommands(shared_ptr<Client> c, const char* reason) {
string filename = bb_hardcore_dead_filename_for_subcommands(c);
bool already_dead = false;
{
ifstream existing_f(filename);
already_dead = existing_f.good();
}
ofstream f(filename, ios::out | ios::trunc);
if (!f.good()) {
return false;
}
uint32_t account_id = 0;
if (c->login && c->login->account) {
account_id = c->login->account->account_id;
}
f << "status=hardcore-dead\n";
f << "reason=" << reason << "\n";
f << "account_id=" << account_id << "\n";
f << "character_file=" << c->character_filename() << "\n";
bool ok = f.good();
f.close();
if (ok && !already_dead) {
if (append_hardcore_death_ledger(c, reason)) {
c->log.info_f("Hardcore permadeath: appended death ledger entry for {}", c->character_filename());
} else {
c->log.warning_f("Hardcore permadeath: FAILED to append death ledger entry for {}", c->character_filename());
}
}
return ok;
}
const SubcommandDefinition* def_for_subcommand(Version version, uint8_t subcommand) { const SubcommandDefinition* def_for_subcommand(Version version, uint8_t subcommand) {
static bool populated = false; static bool populated = false;
static std::array<const SubcommandDefinition*, 0x100> nte_defs; static std::array<const SubcommandDefinition*, 0x100> nte_defs;
@@ -399,7 +579,7 @@ asio::awaitable<void> forward_subcommand_with_entity_id_transcode_t(shared_ptr<C
template <typename HeaderT> template <typename HeaderT>
asio::awaitable<void> forward_subcommand_with_entity_targets_transcode_and_track_hits_t( asio::awaitable<void> forward_subcommand_with_entity_targets_transcode_and_track_hits_t(
shared_ptr<Client> c, SubcommandMessage& msg) { shared_ptr<Client> c, SubcommandMessage& msg) {
// I'm lazy and this should never happen for item commands (since all players need to stay in sync) // I'm lazy and this should never happen for private commands
if (command_is_private(msg.command)) { if (command_is_private(msg.command)) {
throw runtime_error("entity subcommand sent via private command"); throw runtime_error("entity subcommand sent via private command");
} }
@@ -430,16 +610,12 @@ asio::awaitable<void> forward_subcommand_with_entity_targets_transcode_and_track
if ((res.entity_id >= 0x1000) && (res.entity_id < 0x4000)) { if ((res.entity_id >= 0x1000) && (res.entity_id < 0x4000)) {
auto ene_st = l->map_state->enemy_state_for_index(c->version(), res.entity_id - 0x1000); auto ene_st = l->map_state->enemy_state_for_index(c->version(), res.entity_id - 0x1000);
res.ene_st = ene_st; res.ene_st = ene_st;
// Track hits for all resolved enemies
c->log.info_f("Claiming last hit on E-{:03X}", ene_st->e_id);
ene_st->set_last_hit_by_client_id(c->lobby_client_id); ene_st->set_last_hit_by_client_id(c->lobby_client_id);
l->log.info_f("E-{:03X} last hit claimed", ene_st->e_id);
if (ene_st->alias_target_ene_st) { if (ene_st->alias_target_ene_st) {
c->log.info_f("Claiming last hit on E-{:03X} (alias of E-{:03X})",
ene_st->alias_target_ene_st->e_id, ene_st->e_id);
ene_st->alias_target_ene_st->set_last_hit_by_client_id(c->lobby_client_id); ene_st->alias_target_ene_st->set_last_hit_by_client_id(c->lobby_client_id);
l->log.info_f("Alias target E-{:03X} last hit claimed", ene_st->alias_target_ene_st->e_id);
} }
} else if ((res.entity_id >= 0x4000) && (res.entity_id < 0xFFFF)) { } else if ((res.entity_id >= 0x4000) && (res.entity_id < 0xFFFF)) {
res.obj_st = l->map_state->object_state_for_index(c->version(), res.entity_id - 0x4000); res.obj_st = l->map_state->object_state_for_index(c->version(), res.entity_id - 0x4000);
} }
@@ -803,8 +979,8 @@ Parsed6x70Data::Parsed6x70Data(
death_flags(cmd.death_flags), death_flags(cmd.death_flags),
hold_state(cmd.hold_state), hold_state(cmd.hold_state),
area(cmd.area), area(cmd.area),
game_flags(cmd.game_flags), player_flags(cmd.player_flags),
game_flags_is_v3(false), player_flags_is_v3(false),
visual(cmd.visual), visual(cmd.visual),
stats(cmd.stats), stats(cmd.stats),
num_items(cmd.num_items), num_items(cmd.num_items),
@@ -839,8 +1015,8 @@ Parsed6x70Data::Parsed6x70Data(
death_flags(cmd.death_flags), death_flags(cmd.death_flags),
hold_state(cmd.hold_state), hold_state(cmd.hold_state),
area(cmd.area), area(cmd.area),
game_flags(cmd.game_flags), player_flags(cmd.player_flags),
game_flags_is_v3(false), player_flags_is_v3(false),
visual(cmd.visual), visual(cmd.visual),
stats(cmd.stats), stats(cmd.stats),
num_items(cmd.num_items), num_items(cmd.num_items),
@@ -872,7 +1048,7 @@ Parsed6x70Data::Parsed6x70Data(
Version from_version, Version from_version,
bool from_client_customization) bool from_client_customization)
: Parsed6x70Data(cmd.base, guild_card_number, from_version, from_client_customization) { : Parsed6x70Data(cmd.base, guild_card_number, from_version, from_client_customization) {
this->game_flags_is_v3 = true; this->player_flags_is_v3 = true;
this->stats = cmd.stats; this->stats = cmd.stats;
this->num_items = cmd.num_items; this->num_items = cmd.num_items;
this->items = cmd.items; this->items = cmd.items;
@@ -888,7 +1064,7 @@ Parsed6x70Data::Parsed6x70Data(
Version from_version, Version from_version,
bool from_client_customization) bool from_client_customization)
: Parsed6x70Data(cmd.base, guild_card_number, from_version, from_client_customization) { : Parsed6x70Data(cmd.base, guild_card_number, from_version, from_client_customization) {
this->game_flags_is_v3 = true; this->player_flags_is_v3 = true;
this->stats = cmd.stats; this->stats = cmd.stats;
this->num_items = cmd.num_items; this->num_items = cmd.num_items;
this->items = cmd.items; this->items = cmd.items;
@@ -904,7 +1080,7 @@ Parsed6x70Data::Parsed6x70Data(
Version from_version, Version from_version,
bool from_client_customization) bool from_client_customization)
: Parsed6x70Data(cmd.base, guild_card_number, from_version, from_client_customization) { : Parsed6x70Data(cmd.base, guild_card_number, from_version, from_client_customization) {
this->game_flags_is_v3 = true; this->player_flags_is_v3 = true;
this->stats = cmd.stats; this->stats = cmd.stats;
this->num_items = cmd.num_items; this->num_items = cmd.num_items;
this->items = cmd.items; this->items = cmd.items;
@@ -924,7 +1100,7 @@ G_SyncPlayerDispAndInventory_DCNTE_6x70 Parsed6x70Data::as_dc_nte(shared_ptr<Ser
ret.death_flags = this->death_flags; ret.death_flags = this->death_flags;
ret.hold_state = this->hold_state; ret.hold_state = this->hold_state;
ret.area = this->area; ret.area = this->area;
ret.game_flags = this->get_game_flags(false); ret.player_flags = this->get_player_flags(false);
ret.visual = this->visual; ret.visual = this->visual;
ret.stats = this->stats; ret.stats = this->stats;
ret.num_items = this->num_items; ret.num_items = this->num_items;
@@ -956,7 +1132,7 @@ G_SyncPlayerDispAndInventory_DC112000_6x70 Parsed6x70Data::as_dc_112000(shared_p
ret.death_flags = this->death_flags; ret.death_flags = this->death_flags;
ret.hold_state = this->hold_state; ret.hold_state = this->hold_state;
ret.area = this->area; ret.area = this->area;
ret.game_flags = this->get_game_flags(false); ret.player_flags = this->get_player_flags(false);
ret.visual = this->visual; ret.visual = this->visual;
ret.stats = this->stats; ret.stats = this->stats;
ret.num_items = this->num_items; ret.num_items = this->num_items;
@@ -1112,7 +1288,7 @@ Parsed6x70Data::Parsed6x70Data(
temporary_status_effect(base.temporary_status_effect), temporary_status_effect(base.temporary_status_effect),
attack_status_effect(base.attack_status_effect), attack_status_effect(base.attack_status_effect),
defense_status_effect(base.defense_status_effect), defense_status_effect(base.defense_status_effect),
unused_status_effect(base.unused_status_effect), unknown_a1_status_effect(base.unknown_a1_status_effect),
language(static_cast<Language>(base.language32.load())), language(static_cast<Language>(base.language32.load())),
player_tag(base.player_tag), player_tag(base.player_tag),
guild_card_number(guild_card_number), // Ignore the client's GC# guild_card_number(guild_card_number), // Ignore the client's GC#
@@ -1122,8 +1298,8 @@ Parsed6x70Data::Parsed6x70Data(
death_flags(base.death_flags), death_flags(base.death_flags),
hold_state(base.hold_state), hold_state(base.hold_state),
area(base.area), area(base.area),
game_flags(base.game_flags), player_flags(base.player_flags),
game_flags_is_v3(!is_v1_or_v2(from_version)), player_flags_is_v3(!is_v1_or_v2(from_version)),
technique_levels_v1(base.technique_levels_v1), technique_levels_v1(base.technique_levels_v1),
visual(base.visual) {} visual(base.visual) {}
@@ -1136,7 +1312,7 @@ G_6x70_Base_V1 Parsed6x70Data::base_v1(bool is_v3) const {
ret.temporary_status_effect = this->temporary_status_effect; ret.temporary_status_effect = this->temporary_status_effect;
ret.attack_status_effect = this->attack_status_effect; ret.attack_status_effect = this->attack_status_effect;
ret.defense_status_effect = this->defense_status_effect; ret.defense_status_effect = this->defense_status_effect;
ret.unused_status_effect = this->unused_status_effect; ret.unknown_a1_status_effect = this->unknown_a1_status_effect;
ret.language32 = static_cast<size_t>(this->language); ret.language32 = static_cast<size_t>(this->language);
ret.player_tag = this->player_tag; ret.player_tag = this->player_tag;
ret.guild_card_number = this->guild_card_number; ret.guild_card_number = this->guild_card_number;
@@ -1146,46 +1322,73 @@ G_6x70_Base_V1 Parsed6x70Data::base_v1(bool is_v3) const {
ret.death_flags = this->death_flags; ret.death_flags = this->death_flags;
ret.hold_state = this->hold_state; ret.hold_state = this->hold_state;
ret.area = this->area; ret.area = this->area;
ret.game_flags = this->get_game_flags(is_v3); ret.player_flags = this->get_player_flags(is_v3);
ret.technique_levels_v1 = this->technique_levels_v1; ret.technique_levels_v1 = this->technique_levels_v1;
ret.visual = this->visual; ret.visual = this->visual;
return ret; return ret;
} }
uint32_t Parsed6x70Data::convert_game_flags(uint32_t game_flags, bool to_v3) { uint32_t Parsed6x70Data::convert_player_flags(uint32_t player_flags, bool to_v3) {
// The format of game_flags for players was changed significantly between v2 and v3, and not accounting for this // The format of player_flags was changed significantly between v2 and v3, and not accounting for this results in odd
// results in odd effects like other characters not appearing when joining a game. Unfortunately, some bits were // effects like other characters not appearing when joining a game. Unfortunately, some bits were deleted on v3 and
// deleted on v3 and other bits were added, so it doesn't suffice to simply store the most complete format of this // other bits were added, so it doesn't suffice to simply store the most complete format of this field - we have to
// field - we have to be able to convert between the two. // be able to convert between the two. What's known about these bits (? indicates meaning/behavior is unverified):
// V1/V2 V3/V4
// Bits on v2: JIHCBAzy xwvutsrq ponmlkji hgfedcba // 00000001 00000001 = player hold is set (see notes on 6x2C and 6x2D in CommandFormats.hh)
// Bits on v3: JIHGFEDC BAzyxwvu srqponkj hgfedcba // 00000002 00000002 = player hold is set for the purpose of dropping an item
// The bits ilmt were removed in v3 and the bits to their left were shifted right. The bits DEFG were added in v3 and // 00000004 00000004 = is on a different floor from the local player (or is loading into game)
// do not exist on v2. Known meanings for these bits so far: // 00000008 00000008 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
// o = is dead // 00000010 00000010 = player has sent any update command (position, attack, etc.) this frame
// n = should play hit animation // 00000020 00000020 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
// y = is near enemy // 00000040 00000040 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
// H = is enemy? // 00000080 00000080 = is in windup animation for technique or PB
// I = is object? (some entities have both H and I set though) // 00000100 -------- = unknown (TODO: appears to be entirely unused, at least in v2)
// J = is item // 00000200 00000100 = chat, pause, or quick menu is open (suppresses action palette)
// 00000400 00000200 = is in PB cutscene
// 00000800 -------- = player is standing in water (steps create splash particles)
// 00001000 -------- = player is standing in grass (steps create grass particles)
// 00002000 00000400 = action palette is disabled by p_action_disable or one of the TObjQuestColA* objects
// 00004000 00000800 = is about to return to Pioneer 2 after a death (TODO: also set by p_return_guild)
// 00008000 00001000 = cannot use telepipe / Ryuker (e.g. boss warps set this flag when the player is nearby)
// 00010000 00002000 = unknown (TODO: appears to be entirely unused, at least in v3)
// 00020000 00004000 = is teleporting as a result of 6x24 (set only briefly after appearing at destination)
// 00040000 00008000 = is dead NPC (set by e.g. npc_crptalk_id when regsA[4] == 1)
// 00080000 -------- = unknown (TODO: appears to be entirely unused, at least in v2)
// 00100000 00010000 = has permanent trap vision (e.g. is android)
// 00200000 00020000 = equipped items are invisible / intangible (e.g. in Pioneer 2)
// 00400000 00040000 = is loading / changing floors (set by 6x22 and at game join, cleared by 6x23)
// 00800000 00080000 = player data is in the process of being exported to save file format
// 01000000 00100000 = initial cutscene with the Principal has started in offline free-play single-mode
// 02000000 00200000 = is visible (set shortly after warping into a floor; remains set until next warp)
// 04000000 00400000 = position is valid (therefore player can be rendered)
// 08000000 00800000 = player is invisible if not local, but items are still visible (TODO: what about on BB?)
// 10000000 01000000 = if set, player does not drop weapon on death
// -------- 02000000 = player's room_id_in_custom_area does not match player's room_id (used by TObjRoomId when
// param6 == 0x00010000; TODO: figure out what this does)
// -------- 04000000 = is sitting in lobby chair
// -------- 08000000 = using male animations / poses in lobby chair
// -------- 10000000 = using alternate lobby chair pose (X+B instead of X+A on GC, for example)
// -------- 20000000 = appears to be unused (there is no codepath that sets this flag); if set, the player will
// freeze when attempting any lobby animation
// -------- 40000000 = unknown (TODO: used in offline multi-player Challenge mode; see tree from 3OE1:801BE594)
if (to_v3) { if (to_v3) {
return (game_flags & 0xE00000FF) | return (player_flags & 0x000000FF) |
((game_flags & 0x00000600) >> 1) | ((player_flags & 0x00000600) >> 1) |
((game_flags & 0x0007E000) >> 3) | ((player_flags & 0x0007E000) >> 3) |
((game_flags & 0x1FF00000) >> 4); ((player_flags & 0x1FF00000) >> 4);
} else { } else {
return (game_flags & 0xE00000FF) | return (player_flags & 0x000000FF) |
((game_flags << 1) & 0x00000600) | ((player_flags << 1) & 0x00000600) |
((game_flags << 3) & 0x0007E000) | ((player_flags << 3) & 0x0007E000) |
((game_flags << 4) & 0x1FF00000); ((player_flags << 4) & 0x1FF00000);
} }
} }
uint32_t Parsed6x70Data::get_game_flags(bool is_v3) const { uint32_t Parsed6x70Data::get_player_flags(bool is_v3) const {
return (this->game_flags_is_v3 == is_v3) return (this->player_flags_is_v3 == is_v3)
? this->game_flags ? this->player_flags
: Parsed6x70Data::convert_game_flags(this->game_flags, is_v3); : Parsed6x70Data::convert_player_flags(this->player_flags, is_v3);
} }
static asio::awaitable<void> on_sync_joining_player_disp_and_inventory( static asio::awaitable<void> on_sync_joining_player_disp_and_inventory(
@@ -1636,7 +1839,21 @@ static asio::awaitable<void> on_player_died(shared_ptr<Client> c, SubcommandMess
} catch (const out_of_range&) { } catch (const out_of_range&) {
} }
bool hardcore_death = current_ship_is_hardcore_bb(c);
if (hardcore_death) {
if (mark_bb_character_hardcore_dead_for_subcommands(c, "player-death-subcommand")) {
c->log.warning_f("Hardcore permadeath: marked BB character dead: {}", c->character_filename());
} else {
c->log.error_f("Hardcore permadeath: FAILED to mark BB character dead: {}", c->character_filename());
}
}
forward_subcommand(c, msg); forward_subcommand(c, msg);
if (hardcore_death) {
send_message_box(c, "DADDY FALZ WINS");
c->channel->disconnect();
}
} }
static asio::awaitable<void> on_player_revivable(shared_ptr<Client> c, SubcommandMessage& msg) { static asio::awaitable<void> on_player_revivable(shared_ptr<Client> c, SubcommandMessage& msg) {
@@ -1647,8 +1864,23 @@ static asio::awaitable<void> on_player_revivable(shared_ptr<Client> c, Subcomman
co_return; co_return;
} }
bool hardcore_death = current_ship_is_hardcore_bb(c);
if (hardcore_death) {
if (mark_bb_character_hardcore_dead_for_subcommands(c, "player-revivable-subcommand")) {
c->log.warning_f("Hardcore permadeath: marked BB character dead from revivable state: {}", c->character_filename());
} else {
c->log.error_f("Hardcore permadeath: FAILED to mark BB character dead from revivable state: {}", c->character_filename());
}
}
forward_subcommand(c, msg); forward_subcommand(c, msg);
if (hardcore_death) {
send_message_box(c, "DADDY FALZ WINS");
c->channel->disconnect();
co_return;
}
// Revive if infinite HP is enabled // Revive if infinite HP is enabled
bool player_cheats_enabled = l->check_flag(Lobby::Flag::CHEATS_ENABLED) || bool player_cheats_enabled = l->check_flag(Lobby::Flag::CHEATS_ENABLED) ||
(c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE)); (c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE));
@@ -1671,6 +1903,17 @@ static asio::awaitable<void> on_player_revived(shared_ptr<Client> c, SubcommandM
auto l = c->require_lobby(); auto l = c->require_lobby();
if (l->is_game()) { if (l->is_game()) {
if (current_ship_is_hardcore_bb(c)) {
if (mark_bb_character_hardcore_dead_for_subcommands(c, "player-revived-subcommand")) {
c->log.warning_f("Hardcore permadeath: blocked revive and marked BB character dead: {}", c->character_filename());
} else {
c->log.error_f("Hardcore permadeath: FAILED to mark BB character dead while blocking revive: {}", c->character_filename());
}
send_message_box(c, "DADDY FALZ WINS");
c->channel->disconnect();
co_return;
}
forward_subcommand(c, msg); forward_subcommand(c, msg);
if ((l->check_flag(Lobby::Flag::CHEATS_ENABLED) || (c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE))) && if ((l->check_flag(Lobby::Flag::CHEATS_ENABLED) || (c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE))) &&
c->check_flag(Client::Flag::INFINITE_HP_ENABLED)) { c->check_flag(Client::Flag::INFINITE_HP_ENABLED)) {
@@ -2241,6 +2484,15 @@ static asio::awaitable<void> on_pick_up_item_generic(
co_return; co_return;
} }
// TODO: Figure out what the actual max range is; 30 is an overestimate
double dist2 = fi->pos.dist2(c->pos);
if (dist2 > 900.0) {
l->log.warning_f("Player {} requests to pick up {:08X}, but it is too far away (dist2={})",
client_id, item_id, dist2);
l->add_item(floor, fi);
co_return;
}
try { try {
p->add_item(fi->data, *s->item_stack_limits(c->version())); p->add_item(fi->data, *s->item_stack_limits(c->version()));
} catch (const out_of_range&) { } catch (const out_of_range&) {
@@ -2810,7 +3062,7 @@ DropReconcileResult reconcile_drop_request_with_map(
bool is_box = (cmd.rt_index == 0x30); bool is_box = (cmd.rt_index == 0x30);
DropReconcileResult res; DropReconcileResult res;
res.effective_rt_index = 0xFF; res.effective_enemy_type = EnemyType::UNKNOWN;
res.should_drop = true; res.should_drop = true;
res.ignore_def = (cmd.ignore_def != 0); res.ignore_def = (cmd.ignore_def != 0);
if (!map) { if (!map) {
@@ -2856,22 +3108,22 @@ DropReconcileResult reconcile_drop_request_with_map(
res.ref_ene_st = map->enemy_state_for_index(version, cmd.floor, cmd.entity_index); res.ref_ene_st = map->enemy_state_for_index(version, cmd.floor, cmd.entity_index);
res.target_ene_st = res.ref_ene_st->alias_target_ene_st ? res.ref_ene_st->alias_target_ene_st : res.ref_ene_st; res.target_ene_st = res.ref_ene_st->alias_target_ene_st ? res.ref_ene_st->alias_target_ene_st : res.ref_ene_st;
uint8_t area = map->floor_to_area.at(res.target_ene_st->super_ene->floor); uint8_t area = map->floor_to_area.at(res.target_ene_st->super_ene->floor);
EnemyType type = res.target_ene_st->type(version, area, difficulty, event); res.effective_enemy_type = res.target_ene_st->type(version, area, difficulty, event);
c->log.info_f("Drop check for E-{:03X} (target E-{:03X}, type {})", c->log.info_f("Drop check for E-{:03X} (target E-{:03X}, type {})",
res.ref_ene_st->e_id, res.target_ene_st->e_id, phosg::name_for_enum(type)); res.ref_ene_st->e_id, res.target_ene_st->e_id, phosg::name_for_enum(res.effective_enemy_type));
res.effective_rt_index = type_definition_for_enemy(type).rt_index; uint8_t expected_rt_index = type_definition_for_enemy(res.effective_enemy_type).rt_index;
bool mismatched_rt_index = false; bool mismatched_rt_index = false;
if (cmd.rt_index != res.effective_rt_index) { if (cmd.rt_index != expected_rt_index) {
// Special cases: BULCLAW => BULK and DARK_GUNNER => DEATH_GUNNER // Special cases: BULCLAW => BULK and DARK_GUNNER => DEATH_GUNNER
if (cmd.rt_index == 0x27 && type == EnemyType::BULCLAW) { if ((cmd.rt_index == 0x27) && (res.effective_enemy_type == EnemyType::BULCLAW)) {
c->log.info_f("E-{:03X} killed as BULK instead of BULCLAW", res.target_ene_st->e_id); c->log.info_f("E-{:03X} killed as BULK instead of BULCLAW", res.target_ene_st->e_id);
res.effective_rt_index = 0x27; res.effective_enemy_type = EnemyType::BULK;
} else if (cmd.rt_index == 0x23 && type == EnemyType::DARK_GUNNER) { } else if ((cmd.rt_index == 0x23) && (res.effective_enemy_type == EnemyType::DARK_GUNNER)) {
c->log.info_f("E-{:03X} killed as DEATH_GUNNER instead of DARK_GUNNER", res.target_ene_st->e_id); c->log.info_f("E-{:03X} killed as DEATH_GUNNER instead of DARK_GUNNER", res.target_ene_st->e_id);
res.effective_rt_index = 0x23; res.effective_enemy_type = EnemyType::DEATH_GUNNER;
} else { } else {
c->log.warning_f("rt_index {:02X} from command does not match entity\'s expected index {:02X}", c->log.warning_f("rt_index {:02X} from command does not match entity\'s expected index {:02X}",
cmd.rt_index, res.effective_rt_index); cmd.rt_index, expected_rt_index);
mismatched_rt_index = true; mismatched_rt_index = true;
} }
} }
@@ -2881,9 +3133,10 @@ DropReconcileResult reconcile_drop_request_with_map(
} }
if (c->check_flag(Client::Flag::DEBUG_ENABLED)) { if (c->check_flag(Client::Flag::DEBUG_ENABLED)) {
std::string rt_index_str = mismatched_rt_index std::string rt_index_str = mismatched_rt_index
? std::format(" $C4{:02X}->{:02X}$C5", cmd.rt_index, res.effective_rt_index) ? std::format(" $C4{:02X}->{:02X}$C5", cmd.rt_index, expected_rt_index)
: std::format(" {:02X}", res.effective_rt_index); : std::format(" {:02X}", expected_rt_index);
send_text_message_fmt(c, "$C5E-{:03X}{} {}", res.target_ene_st->e_id, rt_index_str, phosg::name_for_enum(type)); send_text_message_fmt(c, "$C5E-{:03X}{} {}",
res.target_ene_st->e_id, rt_index_str, phosg::name_for_enum(res.effective_enemy_type));
} }
} }
@@ -2947,12 +3200,13 @@ static asio::awaitable<void> on_entity_drop_item_request(shared_ptr<Client> c, S
} }
if (rec.should_drop) { if (rec.should_drop) {
auto generate_item = [&]() -> ItemCreator::DropResult { auto generate_item_for_client = [&](std::shared_ptr<Client> c) -> ItemCreator::DropResult {
bool force_rare = c->check_flag(Client::Flag::ALL_RARES_ENABLED);
if (rec.obj_st) { if (rec.obj_st) {
if (rec.ignore_def) { if (rec.ignore_def) {
l->log.info_f("Creating item from box {:04X} => K-{:03X} (area {:02X})", l->log.info_f("Creating item from box {:04X} => K-{:03X} (area {:02X})",
cmd.entity_index, rec.obj_st->k_id, cmd.effective_area); cmd.entity_index, rec.obj_st->k_id, cmd.effective_area);
return l->item_creator->on_box_item_drop(cmd.effective_area); return l->item_creator->on_box_item_drop(cmd.effective_area, force_rare);
} else { } else {
l->log.info_f( l->log.info_f(
"Creating item from box {:04X} => K-{:03X} (area {:02X}; specialized with {:g} {:08X} {:08X} {:08X})", "Creating item from box {:04X} => K-{:03X} (area {:02X}; specialized with {:g} {:08X} {:08X} {:08X})",
@@ -2963,7 +3217,7 @@ static asio::awaitable<void> on_entity_drop_item_request(shared_ptr<Client> c, S
} else if (rec.target_ene_st) { } else if (rec.target_ene_st) {
l->log.info_f("Creating item from enemy {:04X} => E-{:03X} (area {:02X})", l->log.info_f("Creating item from enemy {:04X} => E-{:03X} (area {:02X})",
cmd.entity_index, rec.target_ene_st->e_id, cmd.effective_area); cmd.entity_index, rec.target_ene_st->e_id, cmd.effective_area);
return l->item_creator->on_monster_item_drop(rec.effective_rt_index, cmd.effective_area); return l->item_creator->on_monster_item_drop(rec.effective_enemy_type, cmd.effective_area, force_rare);
} else { } else {
throw runtime_error("neither object nor enemy were present"); throw runtime_error("neither object nor enemy were present");
} }
@@ -2985,7 +3239,7 @@ static asio::awaitable<void> on_entity_drop_item_request(shared_ptr<Client> c, S
throw logic_error("unhandled simple drop mode"); throw logic_error("unhandled simple drop mode");
case ServerDropMode::SERVER_SHARED: case ServerDropMode::SERVER_SHARED:
case ServerDropMode::SERVER_DUPLICATE: { case ServerDropMode::SERVER_DUPLICATE: {
auto res = generate_item(); auto res = generate_item_for_client(c);
if (res.item.empty()) { if (res.item.empty()) {
l->log.info_f("No item was created"); l->log.info_f("No item was created");
} else { } else {
@@ -3023,7 +3277,7 @@ static asio::awaitable<void> on_entity_drop_item_request(shared_ptr<Client> c, S
case ServerDropMode::SERVER_PRIVATE: { case ServerDropMode::SERVER_PRIVATE: {
for (const auto& lc : l->clients) { for (const auto& lc : l->clients) {
if (lc && (rec.obj_st || (lc->floor == cmd.floor))) { if (lc && (rec.obj_st || (lc->floor == cmd.floor))) {
auto res = generate_item(); auto res = generate_item_for_client(lc);
if (res.item.empty()) { if (res.item.empty()) {
l->log.info_f("No item was created for {}", lc->channel->name); l->log.info_f("No item was created for {}", lc->channel->name);
} else { } else {
@@ -3434,17 +3688,29 @@ static asio::awaitable<void> on_update_enemy_state(shared_ptr<Client> c, Subcomm
} }
auto ene_st = l->map_state->enemy_state_for_index(c->version(), cmd.enemy_index); auto ene_st = l->map_state->enemy_state_for_index(c->version(), cmd.enemy_index);
uint32_t src_flags = is_big_endian(c->version()) ? bswap32(cmd.game_flags) : cmd.game_flags.load(); uint32_t src_flags = is_big_endian(c->version()) ? bswap32(cmd.game_flags) : cmd.game_flags.load();
if (src_flags & 0xD0000000) { // Don't allow player, object, or item flags to be set
throw std::runtime_error("incorrect entity type flags in 6x0A command");
}
if (l->difficulty == Difficulty::ULTIMATE) { if (l->difficulty == Difficulty::ULTIMATE) {
src_flags = (src_flags & 0xFFFFFFC0) | (ene_st->game_flags & 0x0000003F); src_flags = (src_flags & 0xFFFFFFC0) | (ene_st->game_flags & 0x0000003F);
} }
bool should_track_hit = (src_flags & 0x00000200); // "Enemy was hit" flag (see 6x0A comments in CommandFormats.hh)
if (should_track_hit) {
ene_st->set_last_hit_by_client_id(c->lobby_client_id);
}
ene_st->game_flags = src_flags; ene_st->game_flags = src_flags;
ene_st->total_damage = cmd.total_damage; ene_st->total_damage = cmd.total_damage;
l->log.info_f("E-{:03X} updated to damage={} game_flags={:08X}", ene_st->e_id, ene_st->total_damage, ene_st->game_flags); l->log.info_f("E-{:03X} updated to damage={} game_flags={:08X}; last hit {}",
ene_st->e_id, ene_st->total_damage, ene_st->game_flags, should_track_hit ? "claimed" : "not claimed");
if (ene_st->alias_target_ene_st) { if (ene_st->alias_target_ene_st) {
if (should_track_hit) {
ene_st->alias_target_ene_st->set_last_hit_by_client_id(c->lobby_client_id);
}
ene_st->alias_target_ene_st->game_flags = src_flags; ene_st->alias_target_ene_st->game_flags = src_flags;
ene_st->alias_target_ene_st->total_damage = cmd.total_damage; ene_st->alias_target_ene_st->total_damage = cmd.total_damage;
l->log.info_f("Alias target E-{:03X} updated to damage={} game_flags={:08X}", l->log.info_f("Alias target E-{:03X} updated to damage={} game_flags={:08X}; last hit {}",
ene_st->alias_target_ene_st->e_id, ene_st->alias_target_ene_st->total_damage, ene_st->alias_target_ene_st->game_flags); ene_st->alias_target_ene_st->e_id, ene_st->alias_target_ene_st->total_damage, ene_st->alias_target_ene_st->game_flags, should_track_hit ? "claimed" : "not claimed");
} }
// TODO: It'd be nice if this worked on bosses too, but it seems we have to use each boss' specific state-syncing // TODO: It'd be nice if this worked on bosses too, but it seems we have to use each boss' specific state-syncing
@@ -3492,8 +3758,18 @@ static asio::awaitable<void> on_incr_enemy_damage(shared_ptr<Client> c, Subcomma
cmd.total_damage_before_hit.load(), cmd.total_damage_before_hit.load(),
cmd.current_hp_before_hit.load(), cmd.current_hp_before_hit.load(),
cmd.max_hp.load()); cmd.max_hp.load());
if (cmd.hit_amount > 0) {
c->log.info_f("Claiming last hit on E-{:03X}", ene_st->e_id);
ene_st->set_last_hit_by_client_id(c->lobby_client_id);
}
ene_st->total_damage = std::min<uint32_t>(ene_st->total_damage + cmd.hit_amount, cmd.max_hp); ene_st->total_damage = std::min<uint32_t>(ene_st->total_damage + cmd.hit_amount, cmd.max_hp);
if (ene_st->alias_target_ene_st) { if (ene_st->alias_target_ene_st) {
if (cmd.hit_amount > 0) {
c->log.info_f("Claiming last hit on E-{:03X} (alias of E-{:03X})",
ene_st->alias_target_ene_st->e_id, ene_st->e_id);
ene_st->alias_target_ene_st->set_last_hit_by_client_id(c->lobby_client_id);
}
ene_st->alias_target_ene_st->total_damage = std::min<uint32_t>( ene_st->alias_target_ene_st->total_damage = std::min<uint32_t>(
ene_st->alias_target_ene_st->total_damage + cmd.hit_amount, cmd.max_hp); ene_st->alias_target_ene_st->total_damage + cmd.hit_amount, cmd.max_hp);
} }
@@ -3501,13 +3777,13 @@ static asio::awaitable<void> on_incr_enemy_damage(shared_ptr<Client> c, Subcomma
co_await forward_subcommand_with_entity_id_transcode_t<G_IncrementEnemyDamage_Extension_6xE4>(c, msg); co_await forward_subcommand_with_entity_id_transcode_t<G_IncrementEnemyDamage_Extension_6xE4>(c, msg);
} }
static asio::awaitable<void> on_set_enemy_low_game_flags_ultimate(shared_ptr<Client> c, SubcommandMessage& msg) { static asio::awaitable<void> on_set_enemy_status_effect_flags_ultimate(shared_ptr<Client> c, SubcommandMessage& msg) {
auto& cmd = msg.check_size_t<G_SetEnemyLowGameFlagsUltimate_6x9C>(); auto& cmd = msg.check_size_t<G_SetEnemyLowGameFlagsUltimate_6x9C>();
if (command_is_private(msg.command) || if (command_is_private(msg.command) ||
(cmd.header.entity_id < 0x1000) || (cmd.header.entity_id < 0x1000) ||
(cmd.header.entity_id >= 0x4000) || (cmd.header.entity_id >= 0x4000) ||
(cmd.low_game_flags & 0xFFFFFFC0) || (cmd.status_effect_flags & 0xFFFFFFC0) ||
(c->lobby_client_id > 3)) { (c->lobby_client_id > 3)) {
co_return; co_return;
} }
@@ -3517,12 +3793,12 @@ static asio::awaitable<void> on_set_enemy_low_game_flags_ultimate(shared_ptr<Cli
} }
auto ene_st = l->map_state->enemy_state_for_index(c->version(), cmd.header.entity_id - 0x1000); auto ene_st = l->map_state->enemy_state_for_index(c->version(), cmd.header.entity_id - 0x1000);
if (!(ene_st->game_flags & cmd.low_game_flags)) { if (!(ene_st->game_flags & cmd.status_effect_flags)) {
ene_st->game_flags |= cmd.low_game_flags; ene_st->game_flags |= cmd.status_effect_flags;
l->log.info_f("E-{:03X} updated to game_flags={:08X}", ene_st->e_id, ene_st->game_flags); l->log.info_f("E-{:03X} updated to game_flags={:08X}", ene_st->e_id, ene_st->game_flags);
} }
if (ene_st->alias_target_ene_st && !(ene_st->alias_target_ene_st->game_flags & cmd.low_game_flags)) { if (ene_st->alias_target_ene_st && !(ene_st->alias_target_ene_st->game_flags & cmd.status_effect_flags)) {
ene_st->alias_target_ene_st->game_flags |= cmd.low_game_flags; ene_st->alias_target_ene_st->game_flags |= cmd.status_effect_flags;
l->log.info_f("Alias E-{:03X} updated to game_flags={:08X}", l->log.info_f("Alias E-{:03X} updated to game_flags={:08X}",
ene_st->alias_target_ene_st->e_id, ene_st->alias_target_ene_st->game_flags); ene_st->alias_target_ene_st->e_id, ene_st->alias_target_ene_st->game_flags);
} }
@@ -4061,8 +4337,11 @@ static asio::awaitable<void> on_enemy_exp_request_bb(shared_ptr<Client> c, Subco
// If the requesting player never hit this enemy, they are probably cheating; ignore the command. Also, each player // If the requesting player never hit this enemy, they are probably cheating; ignore the command. Also, each player
// sends a 6xC8 if they ever hit the enemy; we only react to the first 6xC8 for each enemy (and give all relevant // sends a 6xC8 if they ever hit the enemy; we only react to the first 6xC8 for each enemy (and give all relevant
// players EXP then, if they deserve it). // players EXP then, if they deserve it).
if (!ene_st->ever_hit_by_client_id(c->lobby_client_id) || if (!ene_st->ever_hit_by_client_id(c->lobby_client_id)) {
(ene_st->server_flags & MapState::EnemyState::Flag::EXP_GIVEN)) { l->log.warning_f("The requesting player did not hit this enemy; ignoring request");
co_return;
}
if (ene_st->server_flags & MapState::EnemyState::Flag::EXP_GIVEN) {
l->log.info_f("EXP already given for this enemy; ignoring request"); l->log.info_f("EXP already given for this enemy; ignoring request");
co_return; co_return;
} }
@@ -4248,9 +4527,6 @@ asio::awaitable<void> on_transfer_item_via_mail_message_bb(shared_ptr<Client> c,
if (!l->is_game()) { if (!l->is_game()) {
throw runtime_error("6xCB command sent in non-game lobby"); throw runtime_error("6xCB command sent in non-game lobby");
} }
if (!l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS) && !l->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) {
throw runtime_error("6xCB command sent during free play");
}
if (cmd.header.client_id != c->lobby_client_id) { if (cmd.header.client_id != c->lobby_client_id) {
throw runtime_error("6xCB command sent by incorrect client"); throw runtime_error("6xCB command sent by incorrect client");
} }
@@ -4439,7 +4715,7 @@ static asio::awaitable<void> on_destroy_floor_item(shared_ptr<Client> c, Subcomm
static asio::awaitable<void> on_identify_item_bb(shared_ptr<Client> c, SubcommandMessage& msg) { static asio::awaitable<void> on_identify_item_bb(shared_ptr<Client> c, SubcommandMessage& msg) {
auto l = c->require_lobby(); auto l = c->require_lobby();
if (!l->is_game()) { if (!l->is_game()) {
throw runtime_error("6xDA command sent in non-game lobby"); throw runtime_error("6xB8 command sent in non-game lobby");
} }
if (c->version() == Version::BB_V4) { if (c->version() == Version::BB_V4) {
@@ -5377,10 +5653,8 @@ static asio::awaitable<void> on_upgrade_weapon_attribute_bb(shared_ptr<Client> c
if (payment_item.stack_size(*s->item_stack_limits(c->version())) < cmd.payment_count) { if (payment_item.stack_size(*s->item_stack_limits(c->version())) < cmd.payment_count) {
throw runtime_error("not enough payment items present"); throw runtime_error("not enough payment items present");
} }
p->remove_item(payment_item.id, cmd.payment_count, *s->item_stack_limits(c->version()));
send_destroy_item_to_lobby(c, payment_item.id, cmd.payment_count);
uint8_t attribute_amount = 0; int8_t attribute_amount = 0;
if (cmd.payment_type == 1 && cmd.payment_count == 1) { if (cmd.payment_type == 1 && cmd.payment_count == 1) {
attribute_amount = 30; attribute_amount = 30;
} else if (cmd.payment_type == 0 && cmd.payment_count == 4) { } else if (cmd.payment_type == 0 && cmd.payment_count == 4) {
@@ -5392,7 +5666,7 @@ static asio::awaitable<void> on_upgrade_weapon_attribute_bb(shared_ptr<Client> c
} }
size_t attribute_index = 0; size_t attribute_index = 0;
for (size_t z = 6; z <= (item.has_kill_count() ? 10 : 8); z += 2) { for (size_t z = 6; z <= (item.has_kill_count() ? 8 : 10); z += 2) {
if ((item.data1[z] == 0) || (!(item.data1[z] & 0x80) && (item.data1[z] == cmd.attribute))) { if ((item.data1[z] == 0) || (!(item.data1[z] & 0x80) && (item.data1[z] == cmd.attribute))) {
attribute_index = z; attribute_index = z;
break; break;
@@ -5401,8 +5675,16 @@ static asio::awaitable<void> on_upgrade_weapon_attribute_bb(shared_ptr<Client> c
if (attribute_index == 0) { if (attribute_index == 0) {
throw runtime_error("no available attribute slots"); throw runtime_error("no available attribute slots");
} }
int8_t new_attr_value = static_cast<int8_t>(item.data1[attribute_index + 1]) + attribute_amount;
if (new_attr_value > 100) {
throw runtime_error("bonus value exceeds 100");
}
p->remove_item(payment_item.id, cmd.payment_count, *s->item_stack_limits(c->version()));
send_destroy_item_to_lobby(c, payment_item.id, cmd.payment_count);
item.data1[attribute_index] = cmd.attribute; item.data1[attribute_index] = cmd.attribute;
item.data1[attribute_index + 1] += attribute_amount; item.data1[attribute_index + 1] += new_attr_value;
send_destroy_item_to_lobby(c, item.id, 1); send_destroy_item_to_lobby(c, item.id, 1);
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item); send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
@@ -5585,7 +5867,7 @@ const vector<SubcommandDefinition> subcommand_definitions{
/* 6x99 */ {NONE, NONE, 0x99, on_forward_check_game}, /* 6x99 */ {NONE, NONE, 0x99, on_forward_check_game},
/* 6x9A */ {NONE, NONE, 0x9A, on_forward_check_game_client}, /* 6x9A */ {NONE, NONE, 0x9A, on_forward_check_game_client},
/* 6x9B */ {NONE, NONE, 0x9B, on_forward_check_game}, /* 6x9B */ {NONE, NONE, 0x9B, on_forward_check_game},
/* 6x9C */ {NONE, NONE, 0x9C, on_set_enemy_low_game_flags_ultimate}, /* 6x9C */ {NONE, NONE, 0x9C, on_set_enemy_status_effect_flags_ultimate},
/* 6x9D */ {NONE, NONE, 0x9D, on_forward_check_game}, /* 6x9D */ {NONE, NONE, 0x9D, on_forward_check_game},
/* 6x9E */ {NONE, NONE, 0x9E, forward_subcommand_m}, /* 6x9E */ {NONE, NONE, 0x9E, forward_subcommand_m},
/* 6x9F */ {NONE, NONE, 0x9F, forward_subcommand_with_entity_id_transcode_t<G_GalGryphonBossActions_6x9F>}, /* 6x9F */ {NONE, NONE, 0x9F, forward_subcommand_with_entity_id_transcode_t<G_GalGryphonBossActions_6x9F>},
+6 -6
View File
@@ -23,7 +23,7 @@ struct DropReconcileResult {
// for drop computation (which may be the result of following an alias from the ref ene_st) // for drop computation (which may be the result of following an alias from the ref ene_st)
std::shared_ptr<MapState::EnemyState> ref_ene_st; std::shared_ptr<MapState::EnemyState> ref_ene_st;
std::shared_ptr<MapState::EnemyState> target_ene_st; std::shared_ptr<MapState::EnemyState> target_ene_st;
uint8_t effective_rt_index; EnemyType effective_enemy_type;
bool should_drop; bool should_drop;
bool ignore_def; bool ignore_def;
}; };
@@ -52,7 +52,7 @@ public:
StatusEffectState temporary_status_effect; StatusEffectState temporary_status_effect;
StatusEffectState attack_status_effect; StatusEffectState attack_status_effect;
StatusEffectState defense_status_effect; StatusEffectState defense_status_effect;
StatusEffectState unused_status_effect; StatusEffectState unknown_a1_status_effect; // De Rol Le uses this?
Language language = Language::JAPANESE; Language language = Language::JAPANESE;
uint32_t player_tag = 0; uint32_t player_tag = 0;
uint32_t guild_card_number = 0; uint32_t guild_card_number = 0;
@@ -62,8 +62,8 @@ public:
uint32_t death_flags = 0; uint32_t death_flags = 0;
PlayerHoldState hold_state; PlayerHoldState hold_state;
uint32_t area = 0; uint32_t area = 0;
uint32_t game_flags = 0; uint32_t player_flags = 0;
bool game_flags_is_v3 = false; bool player_flags_is_v3 = false;
parray<uint8_t, 0x14> technique_levels_v1 = 0xFF; parray<uint8_t, 0x14> technique_levels_v1 = 0xFF;
PlayerVisualConfig visual; PlayerVisualConfig visual;
std::string name; std::string name;
@@ -121,8 +121,8 @@ protected:
Parsed6x70Data( Parsed6x70Data(
const G_6x70_Base_V1& base, uint32_t guild_card_number, Version from_version, bool from_client_customization); const G_6x70_Base_V1& base, uint32_t guild_card_number, Version from_version, bool from_client_customization);
G_6x70_Base_V1 base_v1(bool is_v3) const; G_6x70_Base_V1 base_v1(bool is_v3) const;
static uint32_t convert_game_flags(uint32_t game_flags, bool to_v3); static uint32_t convert_player_flags(uint32_t player_flags, bool to_v3);
uint32_t get_game_flags(bool is_v3) const; uint32_t get_player_flags(bool is_v3) const;
}; };
bool validate_6xBB(G_SyncCardTradeServerState_Ep3_6xBB& cmd); bool validate_6xBB(G_SyncCardTradeServerState_Ep3_6xBB& cmd);
+3
View File
@@ -365,6 +365,9 @@ ReplaySession::ReplaySession(shared_ptr<ServerState> state, FILE* input_log, boo
if (line == "### use psov2 crypt") { if (line == "### use psov2 crypt") {
this->state->use_psov2_rand_crypt = true; this->state->use_psov2_rand_crypt = true;
} }
if (line == "### use legacy item random behavior") {
this->state->use_legacy_item_random_behavior = true;
}
if (line.starts_with("### cc ")) { if (line.starts_with("### cc ")) {
// ### cc $<chat command> // ### cc $<chat command>
if (this->clients.size() != 1) { if (this->clients.size() != 1) {
+6 -6
View File
@@ -324,17 +324,17 @@ void PSOBBGuildCardFile::delete_duplicates() {
{ {
unordered_set<uint32_t> seen; unordered_set<uint32_t> seen;
size_t read_index = 0, write_index = 0; size_t read_index = 0, write_index = 0;
for (read_index = 0; read_index < this->blocked.size(); read_index++) { for (read_index = 0; read_index < this->blocked_senders.size(); read_index++) {
const auto& read_blocked = this->blocked[read_index]; const auto& read_blocked_senders = this->blocked_senders[read_index];
if (seen.emplace(read_blocked.guild_card_number).second) { if (seen.emplace(read_blocked_senders.guild_card_number).second) {
if (write_index != read_index) { if (write_index != read_index) {
this->blocked[write_index] = read_blocked; this->blocked_senders[write_index] = read_blocked_senders;
} }
write_index++; write_index++;
} }
} }
for (; write_index < this->blocked.size(); write_index++) { for (; write_index < this->blocked_senders.size(); write_index++) {
this->blocked[write_index].clear(); this->blocked_senders[write_index].clear();
} }
} }
+1 -1
View File
@@ -994,7 +994,7 @@ struct PSOBBGuildCardFile {
} __packed_ws__(Entry, 0x1BC); } __packed_ws__(Entry, 0x1BC);
/* 0000 */ PSOBBMinimalSystemFile system_file; /* 0000 */ PSOBBMinimalSystemFile system_file;
/* 0114 */ parray<GuildCardBB, 0x1C> blocked; /* 0114 */ parray<GuildCardBB, 0x1C> blocked_senders;
/* 1DF4 */ parray<uint8_t, 0x180> unknown_a2; /* 1DF4 */ parray<uint8_t, 0x180> unknown_a2;
/* 1F74 */ parray<Entry, 0x69> entries; /* 1F74 */ parray<Entry, 0x69> entries;
/* D590 */ /* D590 */
+103 -43
View File
@@ -1,4 +1,5 @@
#include "SendCommands.hh" #include "SendCommands.hh"
#include "BattleParamsIndex.hh"
#include <inttypes.h> #include <inttypes.h>
#include <stdarg.h> #include <stdarg.h>
@@ -690,6 +691,68 @@ void send_guild_card_chunk_bb(shared_ptr<Client> c, size_t chunk_index) {
send_command(c, 0x02DC, 0x00000000, &cmd, sizeof(cmd) - sizeof(cmd.data) + data_size); send_command(c, 0x02DC, 0x00000000, &cmd, sizeof(cmd) - sizeof(cmd.data) + data_size);
} }
static bool is_battle_param_stream_file_for_blueballz(const string& filename) {
return (filename == "BattleParamEntry.dat") ||
(filename == "BattleParamEntry_on.dat") ||
(filename == "BattleParamEntry_lab.dat") ||
(filename == "BattleParamEntry_lab_on.dat") ||
(filename == "BattleParamEntry_ep4.dat") ||
(filename == "BattleParamEntry_ep4_on.dat");
}
static shared_ptr<const string> bb_stream_file_data_for_client(shared_ptr<Client> c, const string& filename) {
auto s = c->require_server_state();
auto raw_data = s->bb_stream_files_cache->get_or_load("system/blueburst/" + filename).file->data;
int64_t effective_blueballz_hp_scale_tier = (c->selected_blueballz_tier >= 0)
? c->selected_blueballz_tier
: s->blueballz_enemy_hp_scale_tier;
if (!is_battle_param_stream_file_for_blueballz(filename) || (effective_blueballz_hp_scale_tier < 0)) {
return raw_data;
}
effective_blueballz_hp_scale_tier = std::min<int64_t>(
s->blueballz_max_tier,
effective_blueballz_hp_scale_tier);
string scaled_data = *raw_data;
if (scaled_data.size() < sizeof(BattleParamsIndex::Table)) {
c->log.warning_f("Blueballz enemy HP scaling skipped for {}; file is too small", filename);
return raw_data;
}
double mult = 1.0 + (static_cast<double>(effective_blueballz_hp_scale_tier) * 0.25);
auto* table = reinterpret_cast<BattleParamsIndex::Table*>(scaled_data.data());
size_t ultimate_index = static_cast<size_t>(Difficulty::ULTIMATE);
auto scale_u16 = [mult](uint32_t v) -> uint16_t {
if (v == 0) {
return 0;
}
uint32_t scaled = static_cast<uint32_t>(static_cast<double>(v) * mult);
if (scaled < 1) {
scaled = 1;
}
if (scaled > 0xFFFF) {
scaled = 0xFFFF;
}
return static_cast<uint16_t>(scaled);
};
for (size_t z = 0; z < 0x60; z++) {
auto& stats = table->stats[ultimate_index][z];
stats.char_stats.hp = scale_u16(stats.char_stats.hp);
}
c->log.info_f("Blueballz enemy HP scaling: serving {} with tier {} ({:g}x Ultimate HP)",
filename, effective_blueballz_hp_scale_tier, mult);
return make_shared<string>(std::move(scaled_data));
}
static const vector<string> stream_file_entries = { static const vector<string> stream_file_entries = {
"ItemMagEdit.prs", "ItemMagEdit.prs",
"ItemPMT.prs", "ItemPMT.prs",
@@ -705,24 +768,15 @@ static const vector<string> stream_file_entries = {
void send_stream_file_index_bb(shared_ptr<Client> c) { void send_stream_file_index_bb(shared_ptr<Client> c) {
auto s = c->require_server_state(); auto s = c->require_server_state();
c->log.info_f("PSO Peeps BBZ stream debug: send_stream_file_index_bb called");
vector<S_StreamFileIndexEntry_BB_01EB> entries; vector<S_StreamFileIndexEntry_BB_01EB> entries;
size_t offset = 0; size_t offset = 0;
for (const string& filename : stream_file_entries) { for (const string& filename : stream_file_entries) {
string key = "system/blueburst/" + filename; auto file_data = bb_stream_file_data_for_client(c, filename);
auto cache_res = s->bb_stream_files_cache->get_or_load(key);
auto& e = entries.emplace_back(); auto& e = entries.emplace_back();
e.size = cache_res.file->data->size(); e.size = file_data->size();
// Computing the checksum can be slow, so we cache it along with the file data. If the cache result was just e.checksum = crc32(file_data->data(), e.size);
// populated, then it may be different, so we always recompute the checksum in that case.
if (cache_res.generate_called) {
e.checksum = crc32(cache_res.file->data->data(), e.size);
s->bb_stream_files_cache->replace_obj<uint32_t>(key + ".crc32", e.checksum);
} else {
auto compute_checksum = [&](const string&) -> uint32_t {
return crc32(cache_res.file->data->data(), e.size);
};
e.checksum = s->bb_stream_files_cache->get_obj<uint32_t>(key + ".crc32", compute_checksum).obj;
}
e.offset = offset; e.offset = offset;
e.filename.encode(filename); e.filename.encode(filename);
offset += e.size; offset += e.size;
@@ -733,30 +787,27 @@ void send_stream_file_index_bb(shared_ptr<Client> c) {
void send_stream_file_chunk_bb(shared_ptr<Client> c, uint32_t chunk_index) { void send_stream_file_chunk_bb(shared_ptr<Client> c, uint32_t chunk_index) {
auto s = c->require_server_state(); auto s = c->require_server_state();
auto cache_result = s->bb_stream_files_cache->get( c->log.info_f("PSO Peeps BBZ stream debug: send_stream_file_chunk_bb called for chunk {}", chunk_index);
"<BB stream file>", [&](const string&) -> string {
size_t bytes = 0;
for (const auto& name : stream_file_entries) {
bytes += s->bb_stream_files_cache->get_or_load("system/blueburst/" + name).file->data->size();
}
string ret; size_t total_bytes = 0;
ret.reserve(bytes); for (const auto& name : stream_file_entries) {
for (const auto& name : stream_file_entries) { total_bytes += bb_stream_file_data_for_client(c, name)->size();
ret += *s->bb_stream_files_cache->get_or_load("system/blueburst/" + name).file->data; }
}
return ret; string contents;
}); contents.reserve(total_bytes);
const auto& contents = cache_result.file->data; for (const auto& name : stream_file_entries) {
contents += *bb_stream_file_data_for_client(c, name);
}
S_StreamFileChunk_BB_02EB chunk_cmd; S_StreamFileChunk_BB_02EB chunk_cmd;
chunk_cmd.chunk_index = chunk_index; chunk_cmd.chunk_index = chunk_index;
size_t offset = sizeof(chunk_cmd.data) * chunk_index; size_t offset = sizeof(chunk_cmd.data) * chunk_index;
if (offset > contents->size()) { if (offset > contents.size()) {
throw runtime_error("client requested chunk beyond end of stream file"); throw runtime_error("client requested chunk beyond end of stream file");
} }
size_t bytes = min<size_t>(contents->size() - offset, sizeof(chunk_cmd.data)); size_t bytes = min<size_t>(contents.size() - offset, sizeof(chunk_cmd.data));
chunk_cmd.data.assign_range(reinterpret_cast<const uint8_t*>(contents->data() + offset), bytes, 0); chunk_cmd.data.assign_range(reinterpret_cast<const uint8_t*>(contents.data() + offset), bytes, 0);
size_t cmd_size = offsetof(S_StreamFileChunk_BB_02EB, data) + bytes; size_t cmd_size = offsetof(S_StreamFileChunk_BB_02EB, data) + bytes;
cmd_size = (cmd_size + 3) & ~3; cmd_size = (cmd_size + 3) & ~3;
@@ -1139,16 +1190,25 @@ void send_simple_mail(shared_ptr<ServerState> s, uint32_t from_guild_card_number
template <TextEncoding NameEncoding, TextEncoding MessageEncoding> template <TextEncoding NameEncoding, TextEncoding MessageEncoding>
void send_info_board_t(shared_ptr<Client> c) { void send_info_board_t(shared_ptr<Client> c) {
vector<S_InfoBoardEntryT_D8<NameEncoding, MessageEncoding>> entries; vector<S_InfoBoardEntryT_D8<NameEncoding, MessageEncoding>> entries;
auto l = c->require_lobby();
for (const auto& other_c : l->clients) { auto add_clients_from_lobby = [&](std::shared_ptr<Lobby> l) -> void {
if (!other_c.get()) { for (const auto& lc : l->clients) {
continue; if (lc) {
auto lp = lc->character_file(true, false);
auto& e = entries.emplace_back();
e.name.encode(lp->disp.name.decode(lp->inventory.language), c->language());
e.message.encode(add_color(lp->info_board.decode(lp->inventory.language)), c->language());
}
} }
auto other_p = other_c->character_file(true, false); };
auto& e = entries.emplace_back();
e.name.encode(other_p->disp.name.decode(other_p->inventory.language), c->language()); auto l = c->require_lobby();
e.message.encode(add_color(other_p->info_board.decode(other_p->inventory.language)), c->language()); auto watched_l = l->watched_lobby.lock();
if (watched_l) {
add_clients_from_lobby(watched_l);
} }
add_clients_from_lobby(l);
send_command_vt(c, 0xD8, entries.size(), entries); send_command_vt(c, 0xD8, entries.size(), entries);
} }
@@ -2654,16 +2714,16 @@ asio::awaitable<void> send_change_player_hp(
} }
asio::awaitable<void> send_remove_negative_conditions(shared_ptr<Client> c) { asio::awaitable<void> send_remove_negative_conditions(shared_ptr<Client> c) {
G_AddStatusEffect_6x0C cmd; G_AddOrRemoveStatusEffect_6x0C_6x0D cmd;
cmd.header = {0x0C, sizeof(G_AddStatusEffect_6x0C) >> 2, c->lobby_client_id}; cmd.header = {0x0C, sizeof(G_AddOrRemoveStatusEffect_6x0C_6x0D) >> 2, c->lobby_client_id};
cmd.effect_type = 7; // Healing ring cmd.effect_type = 7; // Healing ring
cmd.amount = 0; cmd.amount = 0;
co_await send_protected_command(c, &cmd, sizeof(cmd), true); co_await send_protected_command(c, &cmd, sizeof(cmd), true);
} }
void send_remove_negative_conditions(std::shared_ptr<Channel> ch, uint16_t client_id) { void send_remove_negative_conditions(std::shared_ptr<Channel> ch, uint16_t client_id) {
G_AddStatusEffect_6x0C cmd; G_AddOrRemoveStatusEffect_6x0C_6x0D cmd;
cmd.header = {0x0C, sizeof(G_AddStatusEffect_6x0C) >> 2, client_id}; cmd.header = {0x0C, sizeof(G_AddOrRemoveStatusEffect_6x0C_6x0D) >> 2, client_id};
cmd.effect_type = 7; // Healing ring cmd.effect_type = 7; // Healing ring
cmd.amount = 0; cmd.amount = 0;
ch->send(0x60, 0x00, &cmd, sizeof(cmd)); ch->send(0x60, 0x00, &cmd, sizeof(cmd));
+32 -5
View File
@@ -73,10 +73,11 @@ ServerState::QuestF960Result::QuestF960Result(
} }
} }
ServerState::ServerState(const string& config_filename) ServerState::ServerState(const string& config_filename, bool is_replay)
: creation_time(phosg::now()), : creation_time(phosg::now()),
io_context(make_shared<asio::io_context>(1)), io_context(make_shared<asio::io_context>(1)),
config_filename(config_filename), config_filename(config_filename),
is_replay(is_replay),
thread_pool(make_unique<asio::thread_pool>()), thread_pool(make_unique<asio::thread_pool>()),
bb_stream_files_cache(new FileContentsCache(3600000000ULL)), bb_stream_files_cache(new FileContentsCache(3600000000ULL)),
bb_system_cache(new FileContentsCache(3600000000ULL)), bb_system_cache(new FileContentsCache(3600000000ULL)),
@@ -259,7 +260,7 @@ shared_ptr<Client> ServerState::find_client(const string* identifier, uint64_t a
for (auto& other_l : this->all_lobbies()) { for (auto& other_l : this->all_lobbies()) {
if (l == other_l) { if (l == other_l) {
continue; // don't bother looking again continue; // Don't bother looking again
} }
try { try {
return other_l->find_client(identifier, account_id); return other_l->find_client(identifier, account_id);
@@ -319,7 +320,7 @@ uint16_t ServerState::game_server_port_for_version(Version v) const {
case Version::XB_V3: case Version::XB_V3:
return this->name_to_port_config.at("xb")->port; return this->name_to_port_config.at("xb")->port;
case Version::BB_V4: case Version::BB_V4:
return this->name_to_port_config.at("xb")->port; return this->name_to_port_config.at("bb-data1")->port;
default: default:
throw runtime_error("unknown version"); throw runtime_error("unknown version");
} }
@@ -505,7 +506,12 @@ ItemData ServerState::parse_item_description(Version version, const string& desc
shared_ptr<const CommonItemSet> ServerState::common_item_set(Version logic_version, shared_ptr<const Quest> q) const { shared_ptr<const CommonItemSet> ServerState::common_item_set(Version logic_version, shared_ptr<const Quest> q) const {
if (q && !q->meta.common_item_set_name.empty()) { if (q && !q->meta.common_item_set_name.empty()) {
return this->common_item_sets.at(q->meta.common_item_set_name); try {
return this->common_item_sets.at(q->meta.common_item_set_name);
} catch (const std::out_of_range&) {
throw runtime_error(std::format("common item set {} for quest {} does not exist",
q->meta.common_item_set_name, q->meta.name));
}
} else if (is_v1_or_v2(logic_version) && (logic_version != Version::GC_NTE)) { } else if (is_v1_or_v2(logic_version) && (logic_version != Version::GC_NTE)) {
// TODO: We should probably have a v1 common item set at some point too // TODO: We should probably have a v1 common item set at some point too
return this->common_item_sets.at("common-table-v1-v2"); return this->common_item_sets.at("common-table-v1-v2");
@@ -519,7 +525,12 @@ shared_ptr<const CommonItemSet> ServerState::common_item_set(Version logic_versi
shared_ptr<const RareItemSet> ServerState::rare_item_set(Version logic_version, shared_ptr<const Quest> q) const { shared_ptr<const RareItemSet> ServerState::rare_item_set(Version logic_version, shared_ptr<const Quest> q) const {
if (q && !q->meta.rare_item_set_name.empty()) { if (q && !q->meta.rare_item_set_name.empty()) {
return this->rare_item_sets.at(q->meta.rare_item_set_name); try {
return this->rare_item_sets.at(q->meta.rare_item_set_name);
} catch (const std::out_of_range&) {
throw runtime_error(std::format("rare item set {} for quest {} does not exist",
q->meta.rare_item_set_name, q->meta.name));
}
} else if (is_v1(logic_version)) { } else if (is_v1(logic_version)) {
return this->rare_item_sets.at("rare-table-v1"); return this->rare_item_sets.at("rare-table-v1");
} else if (is_v2(logic_version) && (logic_version != Version::GC_NTE)) { } else if (is_v2(logic_version) && (logic_version != Version::GC_NTE)) {
@@ -904,6 +915,22 @@ void ServerState::load_config_early() {
this->cheat_mode_behavior = parse_behavior_switch("CheatModeBehavior", BehaviorSwitch::OFF_BY_DEFAULT); this->cheat_mode_behavior = parse_behavior_switch("CheatModeBehavior", BehaviorSwitch::OFF_BY_DEFAULT);
this->default_switch_assist_enabled = this->config_json->get_bool("EnableSwitchAssistByDefault", false); this->default_switch_assist_enabled = this->config_json->get_bool("EnableSwitchAssistByDefault", false);
this->use_game_creator_section_id = this->config_json->get_bool("UseGameCreatorSectionID", false); this->use_game_creator_section_id = this->config_json->get_bool("UseGameCreatorSectionID", false);
this->enable_bb_ship_selection_menu = this->config_json->get_bool("EnableBBShipSelectionMenu", false);
this->enable_blueballz = this->config_json->get_bool("EnableBlueballz", false);
this->enable_hardcore_mode = this->config_json->get_bool("EnableHardcoreMode", false);
this->blueballz_max_tier = std::min<int64_t>(10, std::max<int64_t>(0, this->config_json->get_int("BlueballzMaxTier", 10)));
this->blueballz_unlocked_tier_v2 = std::min<int64_t>(
this->blueballz_max_tier,
std::max<int64_t>(-1, this->config_json->get_int("BlueballzUnlockedTierV2", -1)));
this->blueballz_unlocked_tier_v3 = std::min<int64_t>(
this->blueballz_max_tier,
std::max<int64_t>(-1, this->config_json->get_int("BlueballzUnlockedTierV3", -1)));
this->blueballz_unlocked_tier_v4 = std::min<int64_t>(
this->blueballz_max_tier,
std::max<int64_t>(-1, this->config_json->get_int("BlueballzUnlockedTierV4", -1)));
this->blueballz_enemy_hp_scale_tier = std::min<int64_t>(
this->blueballz_max_tier,
std::max<int64_t>(-1, this->config_json->get_int("BlueballzEnemyHPScaleTier", -1)));
this->rare_notifs_enabled_for_client_drops = this->config_json->get_bool("RareNotificationsEnabledForClientDrops", false); this->rare_notifs_enabled_for_client_drops = this->config_json->get_bool("RareNotificationsEnabledForClientDrops", false);
this->default_rare_notifs_enabled_v1_v2 = this->config_json->get_bool("RareNotificationsEnabledByDefault", false); this->default_rare_notifs_enabled_v1_v2 = this->config_json->get_bool("RareNotificationsEnabledByDefault", false);
this->default_rare_notifs_enabled_v3_v4 = this->default_rare_notifs_enabled_v1_v2; this->default_rare_notifs_enabled_v3_v4 = this->default_rare_notifs_enabled_v1_v2;
+11 -1
View File
@@ -91,6 +91,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
std::shared_ptr<const phosg::JSON> config_json; std::shared_ptr<const phosg::JSON> config_json;
bool one_time_config_loaded = false; bool one_time_config_loaded = false;
bool default_lobbies_created = false; bool default_lobbies_created = false;
bool is_replay = false;
size_t num_worker_threads = 0; size_t num_worker_threads = 0;
std::unique_ptr<asio::thread_pool> thread_pool; std::unique_ptr<asio::thread_pool> thread_pool;
@@ -155,7 +156,16 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
BehaviorSwitch cheat_mode_behavior = BehaviorSwitch::OFF_BY_DEFAULT; BehaviorSwitch cheat_mode_behavior = BehaviorSwitch::OFF_BY_DEFAULT;
bool default_switch_assist_enabled = false; bool default_switch_assist_enabled = false;
bool use_game_creator_section_id = false; bool use_game_creator_section_id = false;
bool enable_bb_ship_selection_menu = false;
bool use_psov2_rand_crypt = false; // Used in some tests bool use_psov2_rand_crypt = false; // Used in some tests
bool enable_blueballz = false;
int64_t blueballz_enemy_hp_scale_tier = -1; // -1 = disabled; 0..10 = scale BB enemy HP in stream files
bool enable_hardcore_mode = false;
int8_t blueballz_max_tier = 10;
int8_t blueballz_unlocked_tier_v2 = 0;
int8_t blueballz_unlocked_tier_v3 = 0;
int8_t blueballz_unlocked_tier_v4 = 0;
bool use_legacy_item_random_behavior = false; // Used in some tests
bool rare_notifs_enabled_for_client_drops = false; bool rare_notifs_enabled_for_client_drops = false;
bool default_rare_notifs_enabled_v1_v2 = false; bool default_rare_notifs_enabled_v1_v2 = false;
bool default_rare_notifs_enabled_v3_v4 = false; bool default_rare_notifs_enabled_v3_v4 = false;
@@ -308,7 +318,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
std::unordered_map<uint32_t, ProxySession::PersistentConfig> proxy_persistent_configs; std::unordered_map<uint32_t, ProxySession::PersistentConfig> proxy_persistent_configs;
explicit ServerState(const std::string& config_filename = ""); explicit ServerState(const std::string& config_filename = "", bool is_replay = false);
ServerState(const ServerState&) = delete; ServerState(const ServerState&) = delete;
ServerState(ServerState&&) = delete; ServerState(ServerState&&) = delete;
ServerState& operator=(const ServerState&) = delete; ServerState& operator=(const ServerState&) = delete;
+12 -2
View File
@@ -293,8 +293,18 @@ uint8_t npc_for_name(const string& name, Version version) {
const char* name_for_char_class(uint8_t cls) { const char* name_for_char_class(uint8_t cls) {
static const array<const char*, 12> names = { static const array<const char*, 12> names = {
"HUmar", "HUnewearl", "HUcast", "RAmar", "RAcast", "RAcaseal", "FOmarl", "FOnewm", "FOnewearl", "HUcaseal", /* 00 */ "HUmar", // 0
"FOmar", "RAmarl"}; /* 01 */ "HUnewearl", // 0
/* 02 */ "HUcast", // 1
/* 03 */ "RAmar", // 0
/* 04 */ "RAcast", // 2
/* 05 */ "RAcaseal", // 1
/* 06 */ "FOmarl", // 0
/* 07 */ "FOnewm", // 0
/* 08 */ "FOnewearl", // 0
/* 09 */ "HUcaseal", // 1
/* 0A */ "FOmar", // 0
/* 0B */ "RAmarl"}; // 0
try { try {
return names.at(cls); return names.at(cls);
} catch (const out_of_range&) { } catch (const out_of_range&) {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 B

After

Width:  |  Height:  |  Size: 2.8 KiB

@@ -18,6 +18,7 @@ start:
# Tiny Grass Assassins Bug Fix # Tiny Grass Assassins Bug Fix
.data <VERS 0x0016227A 0x0016238A 0x0016232A 0x0016240A 0x0016229A 0x0016242A 0x0016225A> .data <VERS 0x0016227A 0x0016238A 0x0016232A 0x0016240A 0x0016229A 0x0016242A 0x0016225A>
.data 0x00000002 .data 0x00000002
.binary EB0E .binary EB0E
@@ -25,6 +26,7 @@ start:
# Shield DFP/EVP Bug Fix (allows shields to reach true max DFP/EVP values) # Shield DFP/EVP Bug Fix (allows shields to reach true max DFP/EVP values)
.data <VERS 0x00185D8E 0x00185F4E 0x0018600E 0x00185F0E 0x00185F6E 0x00185F2E 0x00185F2E> .data <VERS 0x00185D8E 0x00185F4E 0x0018600E 0x00185F0E 0x00185F6E 0x00185F2E 0x00185F2E>
.data 0x00000001 .data 0x00000001
.binary 16 .binary 16
@@ -35,6 +37,7 @@ start:
# VR Spaceship Item Drop Bug Fix (allows items to drop from enemies above a certain Y position) # VR Spaceship Item Drop Bug Fix (allows items to drop from enemies above a certain Y position)
.data <VERS 0x00175D75 0x00175E55 0x00175F35 0x00175EC5 0x00175ED5 0x00175EE5 0x00175E95> .data <VERS 0x00175D75 0x00175E55 0x00175F35 0x00175EC5 0x00175ED5 0x00175EE5 0x00175E95>
.data 0x00000002 .data 0x00000002
.data 0x435C0000 .data 0x435C0000
@@ -42,6 +45,7 @@ start:
# Gol Dragon Camera Bug Fix (makes the camera after Gol Dragon display "normally") # Gol Dragon Camera Bug Fix (makes the camera after Gol Dragon display "normally")
.data <VERS 0x000A8AE1 0x000A8C51 0x000A8BD1 0x000A89C1 0x000A8961 0x000A89E1 0x000A8921> .data <VERS 0x000A8AE1 0x000A8C51 0x000A8BD1 0x000A89C1 0x000A8961 0x000A89E1 0x000A8921>
.data 0x00000002 .data 0x00000002
.binary 01 .binary 01
@@ -49,6 +53,7 @@ start:
# Rain Drops Color Bug Fix # Rain Drops Color Bug Fix
.data <VERS 0x0054D670 0x0054DD00 0x005557E8 0x00552C68 0x00552508 0x00552C68 0x00553008> .data <VERS 0x0054D670 0x0054DD00 0x005557E8 0x00552C68 0x00552508 0x00552C68 0x00553008>
.data 0x00000008 .data 0x00000008
.binary 7080808060707070 .binary 7080808060707070
@@ -56,6 +61,7 @@ start:
# TP Bar Color Bug Fix # TP Bar Color Bug Fix
.data <VERS 0x002779CE 0x00277C7E 0x0027808E 0x00277DAE 0x00277ECE 0x00277DCE 0x00277F9E> .data <VERS 0x002779CE 0x00277C7E 0x0027808E 0x00277DAE 0x00277ECE 0x00277DCE 0x00277F9E>
.data 0x00000004 .data 0x00000004
.data 0xFF00AAFA .data 0xFF00AAFA
@@ -71,13 +77,116 @@ start:
# Olga Flow Barta Bug Fix
.label g1_hook_call, <VERS 0x000970E0 0x000973F0 0x00097460 0x00097140 0x000970E0 0x00097160 0x00096FE0>
.label g1_hook_loc, <VERS 0x00097124 0x00097434 0x000974A4 0x00097184 0x00097124 0x000971A4 0x00097024>
.data g1_hook_call
.data 6
.address g1_hook_call
mov eax, esi
cmp al, 19
jmp g1_hook_loc
g1_hook_call_end:
.data g1_hook_loc
.deltaof g1_hook_start, g1_hook_end
.address g1_hook_loc
g1_hook_start:
jne g1_hook_skip_replace_value
mov al, 2
g1_hook_skip_replace_value:
cmp eax, [ebx + 0x440] // Original opcode
jmp g1_hook_call_end
g1_hook_end:
# Morfos Frozen Player Bug Fix
.label g2_hook_call, <VERS 0x0012E257 0x0012E387 0x0012E4E7 0x0012E537 0x0012E567 0x0012E557 0x0012E5A7>
.label g2_hook_loc1, <VERS 0x0012E5F4 0x0012E724 0x0012E884 0x0012E8D4 0x0012E904 0x0012E8F4 0x0012E944>
.label g2_hook_loc2, <VERS 0x0012E622 0x0012E752 0x0012E8B2 0x0012E902 0x0012E932 0x0012E922 0x0012E972>
.data g2_hook_call
.data 6
.address g2_hook_call
call g2_hook_loc1
nop
.data g2_hook_loc1
.deltaof g2_hook_start1, g2_hook_end1
.address g2_hook_loc1
g2_hook_start1:
fld1 st0 // st = [1.0, speed]
fld1 st0 // st = [1.0, 1.0, speed]
fadd st0, st1 // st = [2.0, 1.0, speed]
fdivp st1, st0 // st = [0.5, speed]
jmp g2_hook_loc2
g2_hook_end1:
.data g2_hook_loc2
.deltaof g2_hook_start2, g2_hook_end2
.address g2_hook_loc2
g2_hook_start2:
test byte [esi + 0x30], 0x20 // If not set, use 1.5; if set, use 0.5
jnz g2_hook_entity_is_frozen
fld1 st0 // st = [1, 0.5, speed]
faddp st1, st0 // st = [1.5, speed]
g2_hook_entity_is_frozen:
fmulp st1, st0 // st = [((game_flags & 0x20) ? 0.5 : 1.5) * speed]
ret
g2_hook_end2:
# Dropped Mag Color Bug Fix (only needed on beta version)
.only_versions 4OJB
.data 0x001759E6
.data 1
.binary 12
.data 0x00180898
.data 1
.binary 12
.all_versions
# Box/Fence Fadeout Bug Fix
.data <VERS 0x001D229B 0x001D244B 0x001D295B 0x001D241B 0x001D26AB 0x001D243B 0x001D26DB>
.data 2
nop
nop
.data <VERS 0x001DF7C4 0x001DF924 0x001DFD94 0x001DF964 0x001DFB04 0x001DF984 0x001DFA74>
.data 6
nop
nop
nop
nop
nop
nop
# TODO: Port the rest of the patches in the GC version of BugFixes: # TODO: Port the rest of the patches in the GC version of BugFixes:
# Olga Flow Barta Bug Fix
# Morfos Frozen Player Bug Fix
# Bulclaw HP Bug Fix # Bulclaw HP Bug Fix
# Control Tower: Delbiter Death SFX Bug Fix
# Weapon Attributes Patch # Weapon Attributes Patch
# Invalid Items Bug Fix
# Item Removal Maxed Stats Bug Fix
# Unit Present Bug Fix
# Bank Item Stacking Bug Fix
# Meseta Drop System Bug Fix
# Offline Quests Drop Table Bug Fix
# Mag Revival Priority Bug Fix
# Mag Revival Challenge & Quest Mode Bug Fix
# Reverser Target Lock Bug Fix
# Deband/Shifta/Resta Target Bug Fix
# Tech Auto Targeting Bug Fix
# Enable Trap Animations
# Tsumikiri J-Sword special attack + rapid weapon switch bug fix
# Control Tower: Delbiter Death SFX Bug Fix
# Ruins Laser Fence SFX Bug Fix # Ruins Laser Fence SFX Bug Fix
# SFX Cancellation Distance Bug Fix # SFX Cancellation Distance Bug Fix
# Foie SFX Pitch Bug Fix # Foie SFX Pitch Bug Fix
@@ -92,28 +201,12 @@ start:
# Grants SFX Pitch Bug Fix # Grants SFX Pitch Bug Fix
# Megid SFX Pitch Bug Fix # Megid SFX Pitch Bug Fix
# Anti SFX Pitch Bug Fix # Anti SFX Pitch Bug Fix
# Invalid Items Bug Fix
# Item Removal Maxed Stats Bug Fix
# Unit Present Bug Fix
# Bank Item Stacking Bug Fix
# Dropped Mag Color Bug Fix
# Meseta Drop System Bug Fix
# Present Color Bug Fix # Present Color Bug Fix
# Offline Quests Drop Table Bug Fix
# Mag Revival Priority Bug Fix
# Mag Revival Challenge & Quest Mode Bug Fix
# Chat Bubble Window TAB Bug Fix # Chat Bubble Window TAB Bug Fix
# Chat Log Window LF/Tab Bug Fix # Chat Log Window LF/Tab Bug Fix
# Dark/Hell Special GFX Bug Fix # Dark/Hell Special GFX Bug Fix
# Box/Fence Fadeout Bug Fix
# Devil's and Demon's Special Damage Display Bug Fix # Devil's and Demon's Special Damage Display Bug Fix
# Christmas Trees Bug Fix # Christmas Trees Bug Fix
# Reverser Target Lock Bug Fix
# Deband/Shifta/Resta Target Bug Fix
# Tech Auto Targeting Bug Fix
# Enable Trap Animations
# Tsumikiri J-Sword special attack + rapid weapon switch bug fix
.data 0x00000000 .data 0x00000000
@@ -0,0 +1,106 @@
.meta hide_from_patches_menu
.meta name="Player flags"
.meta description=""
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
.label check_controller_button, 0x801A6C68 # [std](ControllerState* st, uint32_t flags) -> bool
.label TFogCtrl_change_fog, 0x800FB10C # [std](TFogCtrl* this, uint32_t fog_num, uint32_t instant_transition) -> void
.label render_debug_printf, 0x803D4E3C # [std](uint32_t coords, const char* fmt, ...) -> void
.label set_debug_text_color, 0x803D4990 # [](uint32_t color_argb) -> void
.label hook_call, 0x80228A38
.label hook_loc, 0x8000A000
# Disable D-pad up + down chat shortcuts
.data 0x80246314
.data 4
li r4, 0
.data 0x80246330
.data 4
li r4, 0
.data hook_call
.data 4
.address hook_call
b hook_loc
.data hook_loc
.deltaof hook_start, hook_end
.address hook_loc
hook_start:
mflr r0
stwu [r1 - 0x20], r1
stw [r1 + 0x24], r0
stw [r1 + 0x08], r30
stw [r1 + 0x0C], r31
lis r30, 0x804F
ori r30, r30, 0xC7A8
lwz r4, [r13 - 0x5280] # local_client_id
rlwinm r4, r4, 2, 0, 29
lwzx r30, [r30 + r4] # r30 = TFogCtrl_for_client_id[local_client_id]
cmpwi r30, 0
beq hook_skip_all
lwz r31, [r30 + 0x0184] # Active slot number
rlwinm r31, r31, 2, 0, 29
addi r31, r31, 0x174
lwzx r31, [r30 + r31] # Active slot pointer
lwz r31, [r31 + 0x40] # Active fog number
# Check for button presses to change fog
lis r3, 0x8050
ori r3, r3, 0x9848
li r4, 0x0010 # D-pad up
bl check_controller_button
cmplwi r3, 0
beq hook_skip_incr_fog
mr r3, r30
addi r4, r31, 1
andi. r4, r4, 0x007F
li r5, 1
bl TFogCtrl_change_fog
hook_skip_incr_fog:
lis r3, 0x8050
ori r3, r3, 0x9848
li r4, 0x0020 # D-pad down
bl check_controller_button
cmplwi r3, 0
beq hook_skip_decr_fog
mr r3, r30
subi r4, r31, 1
andi. r4, r4, 0x007F
li r5, 1
bl TFogCtrl_change_fog
hook_skip_decr_fog:
# Show the current fog number
lis r3, 0xFFFF
ori r3, r3, 0x00FF
bl set_debug_text_color
lis r3, 0x0002
ori r3, r3, 0x000B
bl hook_get_fmt_string
.binary "Fog: %02X"000000
hook_get_fmt_string:
mflr r4
mr r5, r31
bl render_debug_printf
hook_skip_all:
lwz r31, [r1 + 0x0C]
lwz r30, [r1 + 0x08]
lwz r0, [r1 + 0x24]
addi r1, r1, 0x20
mtlr r0
blr
hook_end:
.data 0
.data 0
@@ -0,0 +1,74 @@
.meta hide_from_patches_menu
.meta name="Player flags"
.meta description=""
entry_ptr:
reloc0:
.offsetof start
start:
.include WriteCodeBlocksGC
.label TObjPlayer_for_client_id, 0x801BA59C # [std](uint32_t client_id)
.label render_debug_printf, 0x803D4E3C # [std](uint32_t coords, const char* fmt, ...);
.label set_debug_text_color, 0x803D4990 # [](uint32_t color_argb);
.label hook_call, 0x80228A38
.label hook_loc, 0x8000A000
.data hook_call
.data 4
.address hook_call
b hook_loc
.data hook_loc
.deltaof hook_start, hook_end
.address hook_loc
hook_start:
mflr r0
stwu [r1 - 0x20], r1
stw [r1 + 0x24], r0
stw [r1 + 8], r30
li r30, 0
hook_again:
li r6, 0
mr r3, r30
bl TObjPlayer_for_client_id
cmplwi r3, 0
beq hook_skip_player
lwz r6, [r3 + 0x0334] # player_flags
lwz r4, [r13 - 0x5280] # local_client_id
cmp r4, r30
bne hook_not_local_player
lis r3, 0xFFFF
ori r3, r3, 0x00FF
b hook_player_flags_ok
hook_not_local_player:
lis r3, 0xFFFF
ori r3, r3, 0xFFFF
hook_player_flags_ok:
bl set_debug_text_color
lis r3, 0x0002
ori r3, r3, 0x000B
add r3, r3, r30
bl hook_get_fmt_string
.binary "Player %2d: %08X"00000000
hook_get_fmt_string:
mflr r4
mr r5, r30
bl render_debug_printf
hook_skip_player:
addi r30, r30, 1
cmplwi r30, 0x0C
blt hook_again
lwz r30, [r1 + 8]
lwz r0, [r1 + 0x24]
addi r1, r1, 0x20
mtlr r0
blr
hook_end:
.data 0
.data 0
-1
View File
@@ -1 +0,0 @@
ItemCT-pc-v2.afs
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
ItemPT-pc-v2.afs
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
ItemPT-pc-v2.afs
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
ItemRT-pc-v2.afs
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
ItemCT-pc-v2.afs
+30 -158
View File
@@ -122,8 +122,6 @@
"CHAOS_SORCERER": [145, 200], "CHAOS_SORCERER": [145, 200],
"CLAW": [95, 145], "CLAW": [95, 145],
"DARK_BELRA": [50, 80], "DARK_BELRA": [50, 80],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 122], "DARK_GUNNER": [100, 122],
"DEATH_GUNNER": [100, 122], "DEATH_GUNNER": [100, 122],
"DELSABER": [150, 165], "DELSABER": [150, 165],
@@ -143,7 +141,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 165], "LA_DIMENIAN": [115, 165],
"MIGIUM": [50, 85], "MIGIUM": [50, 85],
"MONEST": 0,
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NANO_DRAGON": [50, 170], "NANO_DRAGON": [50, 170],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -159,7 +156,7 @@
"SO_DIMENIAN": [135, 180], "SO_DIMENIAN": [135, 180],
"VOL_OPT_2": 2000 "VOL_OPT_2": 2000
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 31, "CANADINE_GROUP": 31, "CANANE": 31, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 40, "CLAW": 28, "DARK_BELRA": 40, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 30, "DEATH_GUNNER": 30, "DELSABER": 35, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 50, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 31, "CANADINE_GROUP": 31, "CANANE": 31, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 40, "CLAW": 28, "DARK_BELRA": 40, "DARK_GUNNER": 30, "DEATH_GUNNER": 30, "DELSABER": 35, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 50, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 30, 23, 15], [0, 30, 23, 15],
@@ -485,8 +482,6 @@
"CHAOS_SORCERER": [145, 200], "CHAOS_SORCERER": [145, 200],
"CLAW": [95, 145], "CLAW": [95, 145],
"DARK_BELRA": [50, 80], "DARK_BELRA": [50, 80],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 122], "DARK_GUNNER": [100, 122],
"DEATH_GUNNER": [100, 122], "DEATH_GUNNER": [100, 122],
"DELSABER": [150, 165], "DELSABER": [150, 165],
@@ -506,7 +501,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 165], "LA_DIMENIAN": [115, 165],
"MIGIUM": [50, 85], "MIGIUM": [50, 85],
"MONEST": 0,
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NANO_DRAGON": [50, 170], "NANO_DRAGON": [50, 170],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -579,8 +573,6 @@
"CHAOS_SORCERER": [145, 210], "CHAOS_SORCERER": [145, 210],
"CLAW": [95, 155], "CLAW": [95, 155],
"DARK_BELRA": [50, 90], "DARK_BELRA": [50, 90],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 132], "DARK_GUNNER": [100, 132],
"DEATH_GUNNER": [100, 132], "DEATH_GUNNER": [100, 132],
"DELSABER": [150, 175], "DELSABER": [150, 175],
@@ -600,7 +592,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 175], "LA_DIMENIAN": [115, 175],
"MIGIUM": [50, 95], "MIGIUM": [50, 95],
"MONEST": 0,
"MOTHMANT": [80, 100], "MOTHMANT": [80, 100],
"NANO_DRAGON": [50, 180], "NANO_DRAGON": [50, 180],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -748,8 +739,6 @@
"CHAOS_SORCERER": [115, 135], "CHAOS_SORCERER": [115, 135],
"CLAW": [45, 75], "CLAW": [45, 75],
"DARK_BELRA": 10, "DARK_BELRA": 10,
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [110, 125], "DARK_GUNNER": [110, 125],
"DEATH_GUNNER": [110, 125], "DEATH_GUNNER": [110, 125],
"DELSABER": [95, 100], "DELSABER": [95, 100],
@@ -769,7 +758,6 @@
"HILDEBLUE": [500, 1000], "HILDEBLUE": [500, 1000],
"LA_DIMENIAN": [100, 120], "LA_DIMENIAN": [100, 120],
"MIGIUM": [15, 20], "MIGIUM": [15, 20],
"MONEST": 0,
"MOTHMANT": [3, 6], "MOTHMANT": [3, 6],
"NANO_DRAGON": [60, 70], "NANO_DRAGON": [60, 70],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
@@ -847,8 +835,6 @@
"CHAOS_SORCERER": [120, 135], "CHAOS_SORCERER": [120, 135],
"CLAW": [50, 75], "CLAW": [50, 75],
"DARK_BELRA": 10, "DARK_BELRA": 10,
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [105, 130], "DARK_GUNNER": [105, 130],
"DEATH_GUNNER": [105, 130], "DEATH_GUNNER": [105, 130],
"DELSABER": [95, 100], "DELSABER": [95, 100],
@@ -868,7 +854,6 @@
"HILDEBLUE": [500, 1000], "HILDEBLUE": [500, 1000],
"LA_DIMENIAN": [105, 120], "LA_DIMENIAN": [105, 120],
"MIGIUM": [17, 20], "MIGIUM": [17, 20],
"MONEST": 0,
"MOTHMANT": [5, 6], "MOTHMANT": [5, 6],
"NANO_DRAGON": [65, 70], "NANO_DRAGON": [65, 70],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
@@ -922,8 +907,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -943,7 +926,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -1357,8 +1339,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -1378,7 +1358,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -1441,8 +1420,6 @@
"CHAOS_SORCERER": [200, 425], "CHAOS_SORCERER": [200, 425],
"CLAW": [155, 335], "CLAW": [155, 335],
"DARK_BELRA": [100, 160], "DARK_BELRA": [100, 160],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 285], "DARK_GUNNER": [150, 285],
"DEATH_GUNNER": [150, 275], "DEATH_GUNNER": [150, 275],
"DELSABER": [150, 330], "DELSABER": [150, 330],
@@ -1462,7 +1439,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 165], "MIGIUM": [55, 165],
"MONEST": 0,
"MOTHMANT": [120, 170], "MOTHMANT": [120, 170],
"NANO_DRAGON": [80, 340], "NANO_DRAGON": [80, 340],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -1499,8 +1475,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -1520,7 +1494,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -1602,7 +1575,7 @@
[56, 140], [56, 140],
[58, 145] [58, 145]
], ],
"EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_FALZ_2": 255, "DARK_FALZ_3": 255, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DE_ROL_LE": 255, "DIMENIAN": 0, "DRAGON": 255, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MONEST": 255, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1, "VOL_OPT_2": 255}, "EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DIMENIAN": 0, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"AL_RAPPY": [1500, 2000], "AL_RAPPY": [1500, 2000],
"BARBAROUS_WOLF": [120, 164], "BARBAROUS_WOLF": [120, 164],
@@ -1616,8 +1589,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -1637,7 +1608,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -1653,7 +1623,7 @@
"SO_DIMENIAN": [185, 295], "SO_DIMENIAN": [185, 295],
"VOL_OPT_2": 3500 "VOL_OPT_2": 3500
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 35, 23, 14], [0, 35, 23, 14],
@@ -1979,8 +1949,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -2000,7 +1968,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -2063,8 +2030,6 @@
"CHAOS_SORCERER": [200, 425], "CHAOS_SORCERER": [200, 425],
"CLAW": [155, 335], "CLAW": [155, 335],
"DARK_BELRA": [100, 160], "DARK_BELRA": [100, 160],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 285], "DARK_GUNNER": [150, 285],
"DEATH_GUNNER": [150, 275], "DEATH_GUNNER": [150, 275],
"DELSABER": [150, 330], "DELSABER": [150, 330],
@@ -2084,7 +2049,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 165], "MIGIUM": [55, 165],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -2135,7 +2099,7 @@
[210, 275], [210, 275],
[220, 285] [220, 285]
], ],
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 2, "BOOMA": 7, "BULCLAW": 4, "BULK": 7, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 2, "CHAOS_BRINGER": 4, "CHAOS_SORCERER": 4, "CLAW": 7, "DARK_BELRA": 2, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 2, "DE_ROL_LE": 0, "DIMENIAN": 7, "DRAGON": 0, "DUBCHIC": 7, "EVIL_SHARK": 7, "GARANZ": 4, "GIGOBOOMA": 2, "GILLCHIC": 7, "GOBOOMA": 7, "GRASS_ASSASSIN": 10, "GUIL_SHARK": 7, "HIDOOM": 2, "HILDEBEAR": 10, "HILDEBLUE": 100, "LA_DIMENIAN": 7, "MIGIUM": 4, "MONEST": 0, "MOTHMANT": 7, "NANO_DRAGON": 2, "NAR_LILY": 100, "PAL_SHARK": 7, "PAN_ARMS": 2, "POFUILLY_SLIME": 2, "POISON_LILY": 2, "POUILLY_SLIME": 100, "RAG_RAPPY": 2, "SAVAGE_WOLF": 2, "SINOW_BEAT": 7, "SINOW_GOLD": 4, "SO_DIMENIAN": 2, "VOL_OPT_2": 0}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 2, "BOOMA": 7, "BULCLAW": 4, "BULK": 7, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 2, "CHAOS_BRINGER": 4, "CHAOS_SORCERER": 4, "CLAW": 7, "DARK_BELRA": 2, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 2, "DIMENIAN": 7, "DUBCHIC": 7, "EVIL_SHARK": 7, "GARANZ": 4, "GIGOBOOMA": 2, "GILLCHIC": 7, "GOBOOMA": 7, "GRASS_ASSASSIN": 10, "GUIL_SHARK": 7, "HIDOOM": 2, "HILDEBEAR": 10, "HILDEBLUE": 100, "LA_DIMENIAN": 7, "MIGIUM": 4, "MOTHMANT": 7, "NANO_DRAGON": 2, "NAR_LILY": 100, "PAL_SHARK": 7, "PAN_ARMS": 2, "POFUILLY_SLIME": 2, "POISON_LILY": 2, "POUILLY_SLIME": 100, "RAG_RAPPY": 2, "SAVAGE_WOLF": 2, "SINOW_BEAT": 7, "SINOW_GOLD": 4, "SO_DIMENIAN": 2},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 30, 23, 15], [0, 30, 23, 15],
@@ -2483,8 +2447,8 @@
[130, 165], [130, 165],
[135, 175] [135, 175]
], ],
"EnemyMesetaRanges": {"AL_RAPPY": 0, "BARBAROUS_WOLF": 0, "BOOMA": 0, "BULCLAW": 0, "BULK": 0, "CANADINE": 0, "CANADINE_GROUP": 0, "CANANE": 0, "CHAOS_BRINGER": 0, "CHAOS_SORCERER": 0, "CLAW": 0, "DARK_BELRA": 0, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 0, "DEATH_GUNNER": 0, "DELSABER": 0, "DE_ROL_LE": 0, "DIMENIAN": 0, "DRAGON": 0, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 0, "GIGOBOOMA": 0, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 0, "HIDOOM": 0, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 0, "MONEST": 0, "MOTHMANT": 0, "NANO_DRAGON": 0, "NAR_LILY": 0, "PAL_SHARK": 0, "PAN_ARMS": 0, "POFUILLY_SLIME": 0, "POISON_LILY": 0, "POUILLY_SLIME": 0, "RAG_RAPPY": 0, "SAVAGE_WOLF": 0, "SINOW_BEAT": 0, "SINOW_GOLD": 0, "SO_DIMENIAN": 0, "VOL_OPT_2": 0}, "EnemyMesetaRanges": {},
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 12, "BOOMA": 20, "BULCLAW": 20, "BULK": 20, "CANADINE": 12, "CANADINE_GROUP": 12, "CANANE": 20, "CHAOS_BRINGER": 40, "CHAOS_SORCERER": 30, "CLAW": 20, "DARK_BELRA": 30, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 12, "DEATH_GUNNER": 12, "DELSABER": 25, "DE_ROL_LE": 0, "DIMENIAN": 21, "DRAGON": 0, "DUBCHIC": 20, "EVIL_SHARK": 20, "GARANZ": 25, "GIGOBOOMA": 12, "GILLCHIC": 20, "GOBOOMA": 20, "GRASS_ASSASSIN": 20, "GUIL_SHARK": 12, "HIDOOM": 30, "HILDEBEAR": 30, "HILDEBLUE": 100, "LA_DIMENIAN": 23, "MIGIUM": 30, "MONEST": 0, "MOTHMANT": 20, "NANO_DRAGON": 20, "NAR_LILY": 100, "PAL_SHARK": 20, "PAN_ARMS": 30, "POFUILLY_SLIME": 12, "POISON_LILY": 12, "POUILLY_SLIME": 100, "RAG_RAPPY": 12, "SAVAGE_WOLF": 12, "SINOW_BEAT": 12, "SINOW_GOLD": 20, "SO_DIMENIAN": 25, "VOL_OPT_2": 0}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 12, "BOOMA": 20, "BULCLAW": 20, "BULK": 20, "CANADINE": 12, "CANADINE_GROUP": 12, "CANANE": 20, "CHAOS_BRINGER": 40, "CHAOS_SORCERER": 30, "CLAW": 20, "DARK_BELRA": 30, "DARK_GUNNER": 12, "DEATH_GUNNER": 12, "DELSABER": 25, "DIMENIAN": 21, "DUBCHIC": 20, "EVIL_SHARK": 20, "GARANZ": 25, "GIGOBOOMA": 12, "GILLCHIC": 20, "GOBOOMA": 20, "GRASS_ASSASSIN": 20, "GUIL_SHARK": 12, "HIDOOM": 30, "HILDEBEAR": 30, "HILDEBLUE": 100, "LA_DIMENIAN": 23, "MIGIUM": 30, "MOTHMANT": 20, "NANO_DRAGON": 20, "NAR_LILY": 100, "PAL_SHARK": 20, "PAN_ARMS": 30, "POFUILLY_SLIME": 12, "POISON_LILY": 12, "POUILLY_SLIME": 100, "RAG_RAPPY": 12, "SAVAGE_WOLF": 12, "SINOW_BEAT": 12, "SINOW_GOLD": 20, "SO_DIMENIAN": 25},
"NonRareBonusProbSpec": [ "NonRareBonusProbSpec": [
[0, 0, 0, 1, 1, 1, 2, 2, 2, 3], [0, 0, 0, 1, 1, 1, 2, 2, 2, 3],
[255, 255, 0, 0, 0, 1, 1, 1, 2, 2], [255, 255, 0, 0, 0, 1, 1, 1, 2, 2],
@@ -2773,8 +2737,8 @@
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[44, 43, 42, 42, 41, 41, 41, 39, 38, 38] [44, 43, 42, 42, 41, 41, 41, 39, 38, 38]
], ],
"EnemyMesetaRanges": {"AL_RAPPY": 0, "BARBAROUS_WOLF": 0, "BOOMA": 0, "BULCLAW": 0, "BULK": 0, "CANADINE": 0, "CANADINE_GROUP": 0, "CANANE": 0, "CHAOS_BRINGER": 0, "CHAOS_SORCERER": 0, "CLAW": 0, "DARK_BELRA": 0, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 0, "DEATH_GUNNER": 0, "DELSABER": 0, "DE_ROL_LE": 0, "DIMENIAN": 0, "DRAGON": 0, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 0, "GIGOBOOMA": 0, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 0, "HIDOOM": 0, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 0, "MONEST": 0, "MOTHMANT": 0, "NANO_DRAGON": 0, "NAR_LILY": 0, "PAL_SHARK": 0, "PAN_ARMS": 0, "POFUILLY_SLIME": 0, "POISON_LILY": 0, "POUILLY_SLIME": 0, "RAG_RAPPY": 0, "SAVAGE_WOLF": 0, "SINOW_BEAT": 0, "SINOW_GOLD": 0, "SO_DIMENIAN": 0, "VOL_OPT_2": 0}, "EnemyMesetaRanges": {},
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 2, "BOOMA": 7, "BULCLAW": 4, "BULK": 7, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 2, "CHAOS_BRINGER": 4, "CHAOS_SORCERER": 4, "CLAW": 7, "DARK_BELRA": 2, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 2, "DE_ROL_LE": 0, "DIMENIAN": 7, "DRAGON": 0, "DUBCHIC": 7, "EVIL_SHARK": 7, "GARANZ": 4, "GIGOBOOMA": 2, "GILLCHIC": 7, "GOBOOMA": 7, "GRASS_ASSASSIN": 10, "GUIL_SHARK": 7, "HIDOOM": 2, "HILDEBEAR": 10, "HILDEBLUE": 100, "LA_DIMENIAN": 7, "MIGIUM": 4, "MONEST": 0, "MOTHMANT": 7, "NANO_DRAGON": 2, "NAR_LILY": 100, "PAL_SHARK": 7, "PAN_ARMS": 2, "POFUILLY_SLIME": 2, "POISON_LILY": 2, "POUILLY_SLIME": 100, "RAG_RAPPY": 2, "SAVAGE_WOLF": 2, "SINOW_BEAT": 7, "SINOW_GOLD": 4, "SO_DIMENIAN": 2, "VOL_OPT_2": 0}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 2, "BOOMA": 7, "BULCLAW": 4, "BULK": 7, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 2, "CHAOS_BRINGER": 4, "CHAOS_SORCERER": 4, "CLAW": 7, "DARK_BELRA": 2, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 2, "DIMENIAN": 7, "DUBCHIC": 7, "EVIL_SHARK": 7, "GARANZ": 4, "GIGOBOOMA": 2, "GILLCHIC": 7, "GOBOOMA": 7, "GRASS_ASSASSIN": 10, "GUIL_SHARK": 7, "HIDOOM": 2, "HILDEBEAR": 10, "HILDEBLUE": 100, "LA_DIMENIAN": 7, "MIGIUM": 4, "MOTHMANT": 7, "NANO_DRAGON": 2, "NAR_LILY": 100, "PAL_SHARK": 7, "PAN_ARMS": 2, "POFUILLY_SLIME": 2, "POISON_LILY": 2, "POUILLY_SLIME": 100, "RAG_RAPPY": 2, "SAVAGE_WOLF": 2, "SINOW_BEAT": 7, "SINOW_GOLD": 4, "SO_DIMENIAN": 2},
"TechniqueIndexProbTable": [ "TechniqueIndexProbTable": [
[108, 108, 108, 108, 109, 108, 110, 109, 120, 125], [108, 108, 108, 108, 109, 108, 110, 109, 120, 125],
[80, 80, 80, 80, 84, 85, 84, 100, 104, 112], [80, 80, 80, 80, 84, 85, 84, 100, 104, 112],
@@ -3039,7 +3003,7 @@
[380, 430], [380, 430],
[400, 440] [400, 440]
], ],
"EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_FALZ_2": 255, "DARK_FALZ_3": 255, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DE_ROL_LE": 255, "DIMENIAN": 0, "DRAGON": 255, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MONEST": 255, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1, "VOL_OPT_2": 255}, "EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DIMENIAN": 0, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"AL_RAPPY": [1500, 2000], "AL_RAPPY": [1500, 2000],
"BARBAROUS_WOLF": [120, 164], "BARBAROUS_WOLF": [120, 164],
@@ -3053,8 +3017,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -3074,7 +3036,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -3090,7 +3051,7 @@
"SO_DIMENIAN": [185, 295], "SO_DIMENIAN": [185, 295],
"VOL_OPT_2": 3500 "VOL_OPT_2": 3500
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 35, 23, 14], [0, 35, 23, 14],
@@ -3480,8 +3441,6 @@
"CHAOS_SORCERER": [145, 200], "CHAOS_SORCERER": [145, 200],
"CLAW": [95, 145], "CLAW": [95, 145],
"DARK_BELRA": [50, 80], "DARK_BELRA": [50, 80],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 122], "DARK_GUNNER": [100, 122],
"DEATH_GUNNER": [100, 122], "DEATH_GUNNER": [100, 122],
"DELSABER": [150, 165], "DELSABER": [150, 165],
@@ -3501,7 +3460,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 165], "LA_DIMENIAN": [115, 165],
"MIGIUM": [50, 85], "MIGIUM": [50, 85],
"MONEST": 0,
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NANO_DRAGON": [50, 170], "NANO_DRAGON": [50, 170],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -3517,7 +3475,7 @@
"SO_DIMENIAN": [135, 180], "SO_DIMENIAN": [135, 180],
"VOL_OPT_2": 2000 "VOL_OPT_2": 2000
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 31, "CANADINE_GROUP": 31, "CANANE": 31, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 40, "CLAW": 28, "DARK_BELRA": 40, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 30, "DEATH_GUNNER": 30, "DELSABER": 35, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 50, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 31, "CANADINE_GROUP": 31, "CANANE": 31, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 40, "CLAW": 28, "DARK_BELRA": 40, "DARK_GUNNER": 30, "DEATH_GUNNER": 30, "DELSABER": 35, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 50, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 30, 23, 15], [0, 30, 23, 15],
@@ -3843,8 +3801,6 @@
"CHAOS_SORCERER": [145, 200], "CHAOS_SORCERER": [145, 200],
"CLAW": [95, 145], "CLAW": [95, 145],
"DARK_BELRA": [50, 80], "DARK_BELRA": [50, 80],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 122], "DARK_GUNNER": [100, 122],
"DEATH_GUNNER": [100, 122], "DEATH_GUNNER": [100, 122],
"DELSABER": [150, 165], "DELSABER": [150, 165],
@@ -3864,7 +3820,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 165], "LA_DIMENIAN": [115, 165],
"MIGIUM": [50, 85], "MIGIUM": [50, 85],
"MONEST": 0,
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NANO_DRAGON": [50, 170], "NANO_DRAGON": [50, 170],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -3937,8 +3892,6 @@
"CHAOS_SORCERER": [145, 210], "CHAOS_SORCERER": [145, 210],
"CLAW": [95, 155], "CLAW": [95, 155],
"DARK_BELRA": [50, 90], "DARK_BELRA": [50, 90],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 132], "DARK_GUNNER": [100, 132],
"DEATH_GUNNER": [100, 132], "DEATH_GUNNER": [100, 132],
"DELSABER": [150, 175], "DELSABER": [150, 175],
@@ -3958,7 +3911,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 175], "LA_DIMENIAN": [115, 175],
"MIGIUM": [50, 95], "MIGIUM": [50, 95],
"MONEST": 0,
"MOTHMANT": [80, 100], "MOTHMANT": [80, 100],
"NANO_DRAGON": [50, 180], "NANO_DRAGON": [50, 180],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -4120,7 +4072,7 @@
[19, 50], [19, 50],
[21, 55] [21, 55]
], ],
"EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 0, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_FALZ_2": 255, "DARK_FALZ_3": 255, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DE_ROL_LE": 255, "DIMENIAN": 0, "DRAGON": 255, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 2, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MONEST": 255, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 1, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1, "VOL_OPT_2": 255}, "EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 0, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DIMENIAN": 0, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 2, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 1, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"AL_RAPPY": [500, 1000], "AL_RAPPY": [500, 1000],
"BARBAROUS_WOLF": [15, 30], "BARBAROUS_WOLF": [15, 30],
@@ -4134,8 +4086,6 @@
"CHAOS_SORCERER": [115, 135], "CHAOS_SORCERER": [115, 135],
"CLAW": [45, 75], "CLAW": [45, 75],
"DARK_BELRA": 10, "DARK_BELRA": 10,
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [110, 125], "DARK_GUNNER": [110, 125],
"DEATH_GUNNER": [110, 125], "DEATH_GUNNER": [110, 125],
"DELSABER": [95, 100], "DELSABER": [95, 100],
@@ -4155,7 +4105,6 @@
"HILDEBLUE": [500, 1000], "HILDEBLUE": [500, 1000],
"LA_DIMENIAN": [100, 120], "LA_DIMENIAN": [100, 120],
"MIGIUM": [15, 20], "MIGIUM": [15, 20],
"MONEST": 0,
"MOTHMANT": [3, 6], "MOTHMANT": [3, 6],
"NANO_DRAGON": [60, 70], "NANO_DRAGON": [60, 70],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
@@ -4171,7 +4120,7 @@
"SO_DIMENIAN": [120, 145], "SO_DIMENIAN": [120, 145],
"VOL_OPT_2": 900 "VOL_OPT_2": 900
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 33, "CANADINE_GROUP": 33, "CANANE": 33, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 30, "CLAW": 28, "DARK_BELRA": 40, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 40, "DEATH_GUNNER": 40, "DELSABER": 40, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 55, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 33, "CANADINE_GROUP": 33, "CANANE": 33, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 30, "CLAW": 28, "DARK_BELRA": 40, "DARK_GUNNER": 40, "DEATH_GUNNER": 40, "DELSABER": 40, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 55, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 35, 30, 25], [100, 35, 30, 25],
[0, 25, 20, 15], [0, 25, 20, 15],
@@ -4498,8 +4447,6 @@
"CHAOS_SORCERER": [115, 135], "CHAOS_SORCERER": [115, 135],
"CLAW": [45, 75], "CLAW": [45, 75],
"DARK_BELRA": 10, "DARK_BELRA": 10,
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [110, 125], "DARK_GUNNER": [110, 125],
"DEATH_GUNNER": [110, 125], "DEATH_GUNNER": [110, 125],
"DELSABER": [95, 100], "DELSABER": [95, 100],
@@ -4519,7 +4466,6 @@
"HILDEBLUE": [500, 1000], "HILDEBLUE": [500, 1000],
"LA_DIMENIAN": [100, 120], "LA_DIMENIAN": [100, 120],
"MIGIUM": [15, 20], "MIGIUM": [15, 20],
"MONEST": 0,
"MOTHMANT": [3, 6], "MOTHMANT": [3, 6],
"NANO_DRAGON": [60, 70], "NANO_DRAGON": [60, 70],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
@@ -4597,8 +4543,6 @@
"CHAOS_SORCERER": [120, 135], "CHAOS_SORCERER": [120, 135],
"CLAW": [50, 75], "CLAW": [50, 75],
"DARK_BELRA": 10, "DARK_BELRA": 10,
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [105, 130], "DARK_GUNNER": [105, 130],
"DEATH_GUNNER": [105, 130], "DEATH_GUNNER": [105, 130],
"DELSABER": [95, 100], "DELSABER": [95, 100],
@@ -4618,7 +4562,6 @@
"HILDEBLUE": [500, 1000], "HILDEBLUE": [500, 1000],
"LA_DIMENIAN": [105, 120], "LA_DIMENIAN": [105, 120],
"MIGIUM": [17, 20], "MIGIUM": [17, 20],
"MONEST": 0,
"MOTHMANT": [5, 6], "MOTHMANT": [5, 6],
"NANO_DRAGON": [65, 70], "NANO_DRAGON": [65, 70],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
@@ -4672,8 +4615,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -4693,7 +4634,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -5107,8 +5047,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -5128,7 +5066,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -5191,8 +5128,6 @@
"CHAOS_SORCERER": [200, 425], "CHAOS_SORCERER": [200, 425],
"CLAW": [155, 335], "CLAW": [155, 335],
"DARK_BELRA": [100, 160], "DARK_BELRA": [100, 160],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 285], "DARK_GUNNER": [150, 285],
"DEATH_GUNNER": [150, 275], "DEATH_GUNNER": [150, 275],
"DELSABER": [150, 330], "DELSABER": [150, 330],
@@ -5212,7 +5147,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 165], "MIGIUM": [55, 165],
"MONEST": 0,
"MOTHMANT": [120, 170], "MOTHMANT": [120, 170],
"NANO_DRAGON": [80, 340], "NANO_DRAGON": [80, 340],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -5249,8 +5183,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -5270,7 +5202,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -5352,7 +5283,7 @@
[56, 140], [56, 140],
[58, 145] [58, 145]
], ],
"EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_FALZ_2": 255, "DARK_FALZ_3": 255, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DE_ROL_LE": 255, "DIMENIAN": 0, "DRAGON": 255, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MONEST": 255, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1, "VOL_OPT_2": 255}, "EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DIMENIAN": 0, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"AL_RAPPY": [1500, 2000], "AL_RAPPY": [1500, 2000],
"BARBAROUS_WOLF": [120, 164], "BARBAROUS_WOLF": [120, 164],
@@ -5366,8 +5297,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -5387,7 +5316,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -5403,7 +5331,7 @@
"SO_DIMENIAN": [185, 295], "SO_DIMENIAN": [185, 295],
"VOL_OPT_2": 3500 "VOL_OPT_2": 3500
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 35, 23, 14], [0, 35, 23, 14],
@@ -5729,8 +5657,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -5750,7 +5676,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -5813,8 +5738,6 @@
"CHAOS_SORCERER": [200, 425], "CHAOS_SORCERER": [200, 425],
"CLAW": [155, 335], "CLAW": [155, 335],
"DARK_BELRA": [100, 160], "DARK_BELRA": [100, 160],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 285], "DARK_GUNNER": [150, 285],
"DEATH_GUNNER": [150, 275], "DEATH_GUNNER": [150, 275],
"DELSABER": [150, 330], "DELSABER": [150, 330],
@@ -5834,7 +5757,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 165], "MIGIUM": [55, 165],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -5958,8 +5880,6 @@
"CHAOS_SORCERER": [145, 200], "CHAOS_SORCERER": [145, 200],
"CLAW": [95, 145], "CLAW": [95, 145],
"DARK_BELRA": [50, 80], "DARK_BELRA": [50, 80],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 122], "DARK_GUNNER": [100, 122],
"DEATH_GUNNER": [100, 122], "DEATH_GUNNER": [100, 122],
"DELSABER": [150, 165], "DELSABER": [150, 165],
@@ -5979,7 +5899,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 165], "LA_DIMENIAN": [115, 165],
"MIGIUM": [50, 85], "MIGIUM": [50, 85],
"MONEST": 0,
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NANO_DRAGON": [50, 170], "NANO_DRAGON": [50, 170],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -5995,7 +5914,7 @@
"SO_DIMENIAN": [135, 180], "SO_DIMENIAN": [135, 180],
"VOL_OPT_2": 2000 "VOL_OPT_2": 2000
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 31, "CANADINE_GROUP": 31, "CANANE": 31, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 40, "CLAW": 28, "DARK_BELRA": 40, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 30, "DEATH_GUNNER": 30, "DELSABER": 35, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 50, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 28, "BULCLAW": 40, "BULK": 30, "CANADINE": 31, "CANADINE_GROUP": 31, "CANANE": 31, "CHAOS_BRINGER": 85, "CHAOS_SORCERER": 40, "CLAW": 28, "DARK_BELRA": 40, "DARK_GUNNER": 30, "DEATH_GUNNER": 30, "DELSABER": 35, "DE_ROL_LE": 100, "DIMENIAN": 28, "DRAGON": 100, "DUBCHIC": 28, "EVIL_SHARK": 28, "GARANZ": 80, "GIGOBOOMA": 35, "GILLCHIC": 28, "GOBOOMA": 32, "GRASS_ASSASSIN": 50, "GUIL_SHARK": 15, "HIDOOM": 40, "HILDEBEAR": 80, "HILDEBLUE": 100, "LA_DIMENIAN": 31, "MIGIUM": 40, "MOTHMANT": 25, "NANO_DRAGON": 50, "NAR_LILY": 100, "PAL_SHARK": 32, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 50, "SINOW_GOLD": 50, "SO_DIMENIAN": 33, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 30, 23, 15], [0, 30, 23, 15],
@@ -6321,8 +6240,6 @@
"CHAOS_SORCERER": [145, 200], "CHAOS_SORCERER": [145, 200],
"CLAW": [95, 145], "CLAW": [95, 145],
"DARK_BELRA": [50, 80], "DARK_BELRA": [50, 80],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 122], "DARK_GUNNER": [100, 122],
"DEATH_GUNNER": [100, 122], "DEATH_GUNNER": [100, 122],
"DELSABER": [150, 165], "DELSABER": [150, 165],
@@ -6342,7 +6259,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 165], "LA_DIMENIAN": [115, 165],
"MIGIUM": [50, 85], "MIGIUM": [50, 85],
"MONEST": 0,
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NANO_DRAGON": [50, 170], "NANO_DRAGON": [50, 170],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -6415,8 +6331,6 @@
"CHAOS_SORCERER": [145, 210], "CHAOS_SORCERER": [145, 210],
"CLAW": [95, 155], "CLAW": [95, 155],
"DARK_BELRA": [50, 90], "DARK_BELRA": [50, 90],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [100, 132], "DARK_GUNNER": [100, 132],
"DEATH_GUNNER": [100, 132], "DEATH_GUNNER": [100, 132],
"DELSABER": [150, 175], "DELSABER": [150, 175],
@@ -6436,7 +6350,6 @@
"HILDEBLUE": [1000, 1500], "HILDEBLUE": [1000, 1500],
"LA_DIMENIAN": [115, 175], "LA_DIMENIAN": [115, 175],
"MIGIUM": [50, 95], "MIGIUM": [50, 95],
"MONEST": 0,
"MOTHMANT": [80, 100], "MOTHMANT": [80, 100],
"NANO_DRAGON": [50, 180], "NANO_DRAGON": [50, 180],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
@@ -6584,8 +6497,6 @@
"CHAOS_SORCERER": [115, 135], "CHAOS_SORCERER": [115, 135],
"CLAW": [45, 75], "CLAW": [45, 75],
"DARK_BELRA": 10, "DARK_BELRA": 10,
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [110, 125], "DARK_GUNNER": [110, 125],
"DEATH_GUNNER": [110, 125], "DEATH_GUNNER": [110, 125],
"DELSABER": [95, 100], "DELSABER": [95, 100],
@@ -6605,7 +6516,6 @@
"HILDEBLUE": [500, 1000], "HILDEBLUE": [500, 1000],
"LA_DIMENIAN": [100, 120], "LA_DIMENIAN": [100, 120],
"MIGIUM": [15, 20], "MIGIUM": [15, 20],
"MONEST": 0,
"MOTHMANT": [3, 6], "MOTHMANT": [3, 6],
"NANO_DRAGON": [60, 70], "NANO_DRAGON": [60, 70],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
@@ -6683,8 +6593,6 @@
"CHAOS_SORCERER": [120, 135], "CHAOS_SORCERER": [120, 135],
"CLAW": [50, 75], "CLAW": [50, 75],
"DARK_BELRA": 10, "DARK_BELRA": 10,
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [105, 130], "DARK_GUNNER": [105, 130],
"DEATH_GUNNER": [105, 130], "DEATH_GUNNER": [105, 130],
"DELSABER": [95, 100], "DELSABER": [95, 100],
@@ -6704,7 +6612,6 @@
"HILDEBLUE": [500, 1000], "HILDEBLUE": [500, 1000],
"LA_DIMENIAN": [105, 120], "LA_DIMENIAN": [105, 120],
"MIGIUM": [17, 20], "MIGIUM": [17, 20],
"MONEST": 0,
"MOTHMANT": [5, 6], "MOTHMANT": [5, 6],
"NANO_DRAGON": [65, 70], "NANO_DRAGON": [65, 70],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
@@ -6758,8 +6665,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -6779,7 +6684,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -7193,8 +7097,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -7214,7 +7116,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -7277,8 +7178,6 @@
"CHAOS_SORCERER": [200, 425], "CHAOS_SORCERER": [200, 425],
"CLAW": [155, 335], "CLAW": [155, 335],
"DARK_BELRA": [100, 160], "DARK_BELRA": [100, 160],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 285], "DARK_GUNNER": [150, 285],
"DEATH_GUNNER": [150, 275], "DEATH_GUNNER": [150, 275],
"DELSABER": [150, 330], "DELSABER": [150, 330],
@@ -7298,7 +7197,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 165], "MIGIUM": [55, 165],
"MONEST": 0,
"MOTHMANT": [120, 170], "MOTHMANT": [120, 170],
"NANO_DRAGON": [80, 340], "NANO_DRAGON": [80, 340],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -7335,8 +7233,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -7356,7 +7252,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -7438,7 +7333,7 @@
[56, 140], [56, 140],
[58, 145] [58, 145]
], ],
"EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_FALZ_2": 255, "DARK_FALZ_3": 255, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DE_ROL_LE": 255, "DIMENIAN": 0, "DRAGON": 255, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MONEST": 255, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1, "VOL_OPT_2": 255}, "EnemyItemClasses": {"AL_RAPPY": 2, "BARBAROUS_WOLF": 2, "BOOMA": 0, "BULCLAW": 3, "BULK": 0, "CANADINE": 2, "CANADINE_GROUP": 2, "CANANE": 1, "CHAOS_BRINGER": 3, "CHAOS_SORCERER": 3, "CLAW": 0, "DARK_BELRA": 1, "DARK_GUNNER": 2, "DEATH_GUNNER": 2, "DELSABER": 1, "DIMENIAN": 0, "DUBCHIC": 0, "EVIL_SHARK": 0, "GARANZ": 2, "GIGOBOOMA": 3, "GILLCHIC": 0, "GOBOOMA": 0, "GRASS_ASSASSIN": 0, "GUIL_SHARK": 3, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "LA_DIMENIAN": 0, "MIGIUM": 3, "MOTHMANT": 0, "NANO_DRAGON": 2, "NAR_LILY": 3, "PAL_SHARK": 0, "PAN_ARMS": 2, "POFUILLY_SLIME": 1, "POISON_LILY": 1, "POUILLY_SLIME": 3, "RAG_RAPPY": 2, "SAVAGE_WOLF": 1, "SINOW_BEAT": 0, "SINOW_GOLD": 3, "SO_DIMENIAN": 1},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"AL_RAPPY": [1500, 2000], "AL_RAPPY": [1500, 2000],
"BARBAROUS_WOLF": [120, 164], "BARBAROUS_WOLF": [120, 164],
@@ -7452,8 +7347,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -7473,7 +7366,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -7489,7 +7381,7 @@
"SO_DIMENIAN": [185, 295], "SO_DIMENIAN": [185, 295],
"VOL_OPT_2": 3500 "VOL_OPT_2": 3500
}, },
"EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_FALZ_2": 0, "DARK_FALZ_3": 0, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MONEST": 0, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100}, "EnemyTypeDropProbs": {"AL_RAPPY": 100, "BARBAROUS_WOLF": 45, "BOOMA": 30, "BULCLAW": 45, "BULK": 35, "CANADINE": 35, "CANADINE_GROUP": 35, "CANANE": 35, "CHAOS_BRINGER": 88, "CHAOS_SORCERER": 35, "CLAW": 30, "DARK_BELRA": 45, "DARK_GUNNER": 45, "DEATH_GUNNER": 45, "DELSABER": 45, "DE_ROL_LE": 100, "DIMENIAN": 30, "DRAGON": 100, "DUBCHIC": 30, "EVIL_SHARK": 30, "GARANZ": 85, "GIGOBOOMA": 35, "GILLCHIC": 30, "GOBOOMA": 38, "GRASS_ASSASSIN": 55, "GUIL_SHARK": 15, "HIDOOM": 45, "HILDEBEAR": 85, "HILDEBLUE": 100, "LA_DIMENIAN": 35, "MIGIUM": 45, "MOTHMANT": 25, "NANO_DRAGON": 55, "NAR_LILY": 100, "PAL_SHARK": 35, "PAN_ARMS": 90, "POFUILLY_SLIME": 27, "POISON_LILY": 25, "POUILLY_SLIME": 100, "RAG_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BEAT": 60, "SINOW_GOLD": 55, "SO_DIMENIAN": 35, "VOL_OPT_2": 100},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 35, 23, 14], [0, 35, 23, 14],
@@ -7815,8 +7707,6 @@
"CHAOS_SORCERER": [200, 400], "CHAOS_SORCERER": [200, 400],
"CLAW": [135, 245], "CLAW": [135, 245],
"DARK_BELRA": [100, 130], "DARK_BELRA": [100, 130],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 250], "DARK_GUNNER": [150, 250],
"DEATH_GUNNER": [150, 250], "DEATH_GUNNER": [150, 250],
"DELSABER": [150, 300], "DELSABER": [150, 300],
@@ -7836,7 +7726,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -7899,8 +7788,6 @@
"CHAOS_SORCERER": [200, 425], "CHAOS_SORCERER": [200, 425],
"CLAW": [155, 335], "CLAW": [155, 335],
"DARK_BELRA": [100, 160], "DARK_BELRA": [100, 160],
"DARK_FALZ_2": 0,
"DARK_FALZ_3": 0,
"DARK_GUNNER": [150, 285], "DARK_GUNNER": [150, 285],
"DEATH_GUNNER": [150, 275], "DEATH_GUNNER": [150, 275],
"DELSABER": [150, 330], "DELSABER": [150, 330],
@@ -7920,7 +7807,6 @@
"HILDEBLUE": [1500, 2000], "HILDEBLUE": [1500, 2000],
"LA_DIMENIAN": [165, 275], "LA_DIMENIAN": [165, 275],
"MIGIUM": [55, 165], "MIGIUM": [55, 165],
"MONEST": 0,
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NANO_DRAGON": [80, 310], "NANO_DRAGON": [80, 310],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
@@ -8029,7 +7915,7 @@
[44, 110], [44, 110],
[46, 115] [46, 115]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 0, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 0, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"BARBAROUS_WOLF": [100, 180], "BARBAROUS_WOLF": [100, 180],
"BARBA_RAY": 1300, "BARBA_RAY": 1300,
@@ -8068,11 +7954,9 @@
"MERILLIA": [60, 65], "MERILLIA": [60, 65],
"MERILTAS": [70, 85], "MERILTAS": [70, 85],
"MIGIUM": [120, 185], "MIGIUM": [120, 185],
"MONEST": 0,
"MORFOS": [50, 80], "MORFOS": [50, 80],
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
"OLGA_FLOW_2": 0,
"PAN_ARMS": [50, 85], "PAN_ARMS": [50, 85],
"POISON_LILY": [60, 65], "POISON_LILY": [60, 65],
"RAG_RAPPY": [85, 100], "RAG_RAPPY": [85, 100],
@@ -9127,7 +9011,7 @@
[64, 160], [64, 160],
[66, 165] [66, 165]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 2, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 2, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 2, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 2, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"BARBAROUS_WOLF": [150, 260], "BARBAROUS_WOLF": [150, 260],
"BARBA_RAY": 2800, "BARBA_RAY": 2800,
@@ -9166,11 +9050,9 @@
"MERILLIA": [90, 110], "MERILLIA": [90, 110],
"MERILTAS": [100, 135], "MERILTAS": [100, 135],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MORFOS": [151, 171], "MORFOS": [151, 171],
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
"OLGA_FLOW_2": 0,
"PAN_ARMS": [165, 265], "PAN_ARMS": [165, 265],
"POISON_LILY": [90, 110], "POISON_LILY": [90, 110],
"RAG_RAPPY": [85, 150], "RAG_RAPPY": [85, 150],
@@ -9567,8 +9449,8 @@
[210, 275], [210, 275],
[220, 285] [220, 285]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 0, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 0, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyTypeDropProbs": {"BARBAROUS_WOLF": 2, "BARBA_RAY": 100, "BARBA_RAY_JOINT": 100, "CHAOS_SORCERER": 7, "DARK_BELRA": 7, "DELBITER": 7, "DELDEPTH": 4, "DELSABER": 4, "DEL_LILY": 7, "DIMENIAN": 2, "DOLMDARL": 4, "DOLMOLM": 2, "DUBCHIC": 7, "EGG_RAPPY": 100, "EPSILON": 7, "GAL_GRYPHON": 100, "GARANZ": 7, "GEE": 2, "GIBBLES": 10, "GILLCHIC": 2, "GI_GUE": 10, "GOL_DRAGON": 100, "GRASS_ASSASSIN": 4, "HALLO_RAPPY": 100, "HIDOOM": 10, "HILDEBEAR": 10, "HILDEBLUE": 100, "ILL_GILL": 7, "LA_DIMENIAN": 4, "LOVE_RAPPY": 100, "MERICARAND": 10, "MERICAROL": 10, "MERICUS": 10, "MERIKLE": 10, "MERILLIA": 2, "MERILTAS": 4, "MIGIUM": 10, "MONEST": 0, "MORFOS": 4, "MOTHMANT": 1, "NAR_LILY": 100, "OLGA_FLOW_2": 0, "PAN_ARMS": 10, "POISON_LILY": 2, "RAG_RAPPY": 2, "RECOBOX": 2, "RECON": 1, "SAINT_RAPPY": 100, "SAVAGE_WOLF": 2, "SINOW_BERILL": 2, "SINOW_SPIGELL": 4, "SINOW_ZELE": 4, "SINOW_ZOA": 2, "SO_DIMENIAN": 4, "UL_GIBBON": 2, "ZOL_GIBBON": 4}, "EnemyTypeDropProbs": {"BARBAROUS_WOLF": 2, "BARBA_RAY": 100, "BARBA_RAY_JOINT": 100, "CHAOS_SORCERER": 7, "DARK_BELRA": 7, "DELBITER": 7, "DELDEPTH": 4, "DELSABER": 4, "DEL_LILY": 7, "DIMENIAN": 2, "DOLMDARL": 4, "DOLMOLM": 2, "DUBCHIC": 7, "EGG_RAPPY": 100, "EPSILON": 7, "GAL_GRYPHON": 100, "GARANZ": 7, "GEE": 2, "GIBBLES": 10, "GILLCHIC": 2, "GI_GUE": 10, "GOL_DRAGON": 100, "GRASS_ASSASSIN": 4, "HALLO_RAPPY": 100, "HIDOOM": 10, "HILDEBEAR": 10, "HILDEBLUE": 100, "ILL_GILL": 7, "LA_DIMENIAN": 4, "LOVE_RAPPY": 100, "MERICARAND": 10, "MERICAROL": 10, "MERICUS": 10, "MERIKLE": 10, "MERILLIA": 2, "MERILTAS": 4, "MIGIUM": 10, "MORFOS": 4, "MOTHMANT": 1, "NAR_LILY": 100, "PAN_ARMS": 10, "POISON_LILY": 2, "RAG_RAPPY": 2, "RECOBOX": 2, "RECON": 1, "SAINT_RAPPY": 100, "SAVAGE_WOLF": 2, "SINOW_BERILL": 2, "SINOW_SPIGELL": 4, "SINOW_ZELE": 4, "SINOW_ZOA": 2, "SO_DIMENIAN": 4, "UL_GIBBON": 2, "ZOL_GIBBON": 4},
"GrindProbTable": [ "GrindProbTable": [
[100, 30, 25, 20], [100, 30, 25, 20],
[0, 30, 23, 15], [0, 30, 23, 15],
@@ -9916,8 +9798,8 @@
[130, 165], [130, 165],
[135, 175] [135, 175]
], ],
"EnemyMesetaRanges": {"BARBAROUS_WOLF": 0, "BARBA_RAY": 0, "BARBA_RAY_JOINT": 0, "CHAOS_SORCERER": 0, "DARK_BELRA": 0, "DELBITER": 0, "DELDEPTH": 0, "DELSABER": 0, "DEL_LILY": 0, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 0, "EPSILON": 0, "GAL_GRYPHON": 0, "GARANZ": 0, "GEE": 0, "GIBBLES": 0, "GILLCHIC": 0, "GI_GUE": 0, "GOL_DRAGON": 0, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 0, "HIDOOM": 0, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 0, "MERICARAND": 0, "MERICAROL": 0, "MERICUS": 0, "MERIKLE": 0, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 0, "MONEST": 0, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 0, "OLGA_FLOW_2": 0, "PAN_ARMS": 0, "POISON_LILY": 0, "RAG_RAPPY": 0, "RECOBOX": 0, "RECON": 0, "SAINT_RAPPY": 0, "SAVAGE_WOLF": 0, "SINOW_BERILL": 0, "SINOW_SPIGELL": 0, "SINOW_ZELE": 0, "SINOW_ZOA": 0, "SO_DIMENIAN": 0, "UL_GIBBON": 0, "ZOL_GIBBON": 0}, "EnemyMesetaRanges": {},
"EnemyTypeDropProbs": {"BARBAROUS_WOLF": 20, "BARBA_RAY": 100, "BARBA_RAY_JOINT": 100, "CHAOS_SORCERER": 30, "DARK_BELRA": 30, "DELBITER": 30, "DELDEPTH": 25, "DELSABER": 20, "DEL_LILY": 20, "DIMENIAN": 12, "DOLMDARL": 20, "DOLMOLM": 12, "DUBCHIC": 20, "EGG_RAPPY": 100, "EPSILON": 20, "GAL_GRYPHON": 100, "GARANZ": 30, "GEE": 12, "GIBBLES": 40, "GILLCHIC": 12, "GI_GUE": 40, "GOL_DRAGON": 100, "GRASS_ASSASSIN": 20, "HALLO_RAPPY": 100, "HIDOOM": 40, "HILDEBEAR": 40, "HILDEBLUE": 100, "ILL_GILL": 20, "LA_DIMENIAN": 20, "LOVE_RAPPY": 100, "MERICARAND": 40, "MERICAROL": 40, "MERICUS": 40, "MERIKLE": 40, "MERILLIA": 12, "MERILTAS": 20, "MIGIUM": 40, "MONEST": 0, "MORFOS": 30, "MOTHMANT": 5, "NAR_LILY": 100, "OLGA_FLOW_2": 0, "PAN_ARMS": 40, "POISON_LILY": 12, "RAG_RAPPY": 12, "RECOBOX": 12, "RECON": 5, "SAINT_RAPPY": 100, "SAVAGE_WOLF": 12, "SINOW_BERILL": 20, "SINOW_SPIGELL": 25, "SINOW_ZELE": 20, "SINOW_ZOA": 15, "SO_DIMENIAN": 25, "UL_GIBBON": 12, "ZOL_GIBBON": 20}, "EnemyTypeDropProbs": {"BARBAROUS_WOLF": 20, "BARBA_RAY": 100, "BARBA_RAY_JOINT": 100, "CHAOS_SORCERER": 30, "DARK_BELRA": 30, "DELBITER": 30, "DELDEPTH": 25, "DELSABER": 20, "DEL_LILY": 20, "DIMENIAN": 12, "DOLMDARL": 20, "DOLMOLM": 12, "DUBCHIC": 20, "EGG_RAPPY": 100, "EPSILON": 20, "GAL_GRYPHON": 100, "GARANZ": 30, "GEE": 12, "GIBBLES": 40, "GILLCHIC": 12, "GI_GUE": 40, "GOL_DRAGON": 100, "GRASS_ASSASSIN": 20, "HALLO_RAPPY": 100, "HIDOOM": 40, "HILDEBEAR": 40, "HILDEBLUE": 100, "ILL_GILL": 20, "LA_DIMENIAN": 20, "LOVE_RAPPY": 100, "MERICARAND": 40, "MERICAROL": 40, "MERICUS": 40, "MERIKLE": 40, "MERILLIA": 12, "MERILTAS": 20, "MIGIUM": 40, "MORFOS": 30, "MOTHMANT": 5, "NAR_LILY": 100, "PAN_ARMS": 40, "POISON_LILY": 12, "RAG_RAPPY": 12, "RECOBOX": 12, "RECON": 5, "SAINT_RAPPY": 100, "SAVAGE_WOLF": 12, "SINOW_BERILL": 20, "SINOW_SPIGELL": 25, "SINOW_ZELE": 20, "SINOW_ZOA": 15, "SO_DIMENIAN": 25, "UL_GIBBON": 12, "ZOL_GIBBON": 20},
"NonRareBonusProbSpec": [ "NonRareBonusProbSpec": [
[0, 0, 0, 1, 1, 1, 2, 2, 2, 3], [0, 0, 0, 1, 1, 1, 2, 2, 2, 3],
[255, 255, 0, 0, 0, 1, 1, 1, 2, 2], [255, 255, 0, 0, 0, 1, 1, 1, 2, 2],
@@ -10845,7 +10727,7 @@
[44, 110], [44, 110],
[46, 115] [46, 115]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 0, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 0, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"BARBAROUS_WOLF": [100, 180], "BARBAROUS_WOLF": [100, 180],
"BARBA_RAY": 1300, "BARBA_RAY": 1300,
@@ -10884,11 +10766,9 @@
"MERILLIA": [60, 65], "MERILLIA": [60, 65],
"MERILTAS": [70, 85], "MERILTAS": [70, 85],
"MIGIUM": [120, 185], "MIGIUM": [120, 185],
"MONEST": 0,
"MORFOS": [50, 80], "MORFOS": [50, 80],
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
"OLGA_FLOW_2": 0,
"PAN_ARMS": [50, 85], "PAN_ARMS": [50, 85],
"POISON_LILY": [60, 65], "POISON_LILY": [60, 65],
"RAG_RAPPY": [85, 100], "RAG_RAPPY": [85, 100],
@@ -11416,7 +11296,7 @@
[24, 60], [24, 60],
[26, 65] [26, 65]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 0, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 2, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 0, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 2, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"BARBAROUS_WOLF": [30, 45], "BARBAROUS_WOLF": [30, 45],
"BARBA_RAY": 400, "BARBA_RAY": 400,
@@ -11455,11 +11335,9 @@
"MERILLIA": [40, 50], "MERILLIA": [40, 50],
"MERILTAS": [45, 60], "MERILTAS": [45, 60],
"MIGIUM": [45, 65], "MIGIUM": [45, 65],
"MONEST": 0,
"MORFOS": [100, 130], "MORFOS": [100, 130],
"MOTHMANT": [3, 6], "MOTHMANT": [3, 6],
"NAR_LILY": [500, 1200], "NAR_LILY": [500, 1200],
"OLGA_FLOW_2": 0,
"PAN_ARMS": [24, 44], "PAN_ARMS": [24, 44],
"POISON_LILY": [4, 10], "POISON_LILY": [4, 10],
"RAG_RAPPY": [18, 20], "RAG_RAPPY": [18, 20],
@@ -11475,7 +11353,7 @@
"UL_GIBBON": [37, 55], "UL_GIBBON": [37, 55],
"ZOL_GIBBON": [45, 60] "ZOL_GIBBON": [45, 60]
}, },
"EnemyTypeDropProbs": {"BARBAROUS_WOLF": 30, "BARBA_RAY": 100, "BARBA_RAY_JOINT": 100, "CHAOS_SORCERER": 25, "DARK_BELRA": 35, "DELBITER": 80, "DELDEPTH": 40, "DELSABER": 25, "DEL_LILY": 35, "DIMENIAN": 30, "DOLMDARL": 35, "DOLMOLM": 30, "DUBCHIC": 30, "EGG_RAPPY": 100, "EPSILON": 30, "GAL_GRYPHON": 100, "GARANZ": 50, "GEE": 30, "GIBBLES": 80, "GILLCHIC": 30, "GI_GUE": 80, "GOL_DRAGON": 100, "GRASS_ASSASSIN": 40, "HALLO_RAPPY": 100, "HIDOOM": 45, "HILDEBEAR": 80, "HILDEBLUE": 100, "ILL_GILL": 40, "LA_DIMENIAN": 31, "LOVE_RAPPY": 100, "MERICARAND": 80, "MERICAROL": 80, "MERICUS": 80, "MERIKLE": 80, "MERILLIA": 30, "MERILTAS": 35, "MIGIUM": 45, "MONEST": 0, "MORFOS": 40, "MOTHMANT": 20, "NAR_LILY": 100, "OLGA_FLOW_2": 0, "PAN_ARMS": 50, "POISON_LILY": 30, "RAG_RAPPY": 100, "RECOBOX": 35, "RECON": 10, "SAINT_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BERILL": 40, "SINOW_SPIGELL": 45, "SINOW_ZELE": 35, "SINOW_ZOA": 30, "SO_DIMENIAN": 30, "UL_GIBBON": 30, "ZOL_GIBBON": 35}, "EnemyTypeDropProbs": {"BARBAROUS_WOLF": 30, "BARBA_RAY": 100, "BARBA_RAY_JOINT": 100, "CHAOS_SORCERER": 25, "DARK_BELRA": 35, "DELBITER": 80, "DELDEPTH": 40, "DELSABER": 25, "DEL_LILY": 35, "DIMENIAN": 30, "DOLMDARL": 35, "DOLMOLM": 30, "DUBCHIC": 30, "EGG_RAPPY": 100, "EPSILON": 30, "GAL_GRYPHON": 100, "GARANZ": 50, "GEE": 30, "GIBBLES": 80, "GILLCHIC": 30, "GI_GUE": 80, "GOL_DRAGON": 100, "GRASS_ASSASSIN": 40, "HALLO_RAPPY": 100, "HIDOOM": 45, "HILDEBEAR": 80, "HILDEBLUE": 100, "ILL_GILL": 40, "LA_DIMENIAN": 31, "LOVE_RAPPY": 100, "MERICARAND": 80, "MERICAROL": 80, "MERICUS": 80, "MERIKLE": 80, "MERILLIA": 30, "MERILTAS": 35, "MIGIUM": 45, "MORFOS": 40, "MOTHMANT": 20, "NAR_LILY": 100, "PAN_ARMS": 50, "POISON_LILY": 30, "RAG_RAPPY": 100, "RECOBOX": 35, "RECON": 10, "SAINT_RAPPY": 100, "SAVAGE_WOLF": 30, "SINOW_BERILL": 40, "SINOW_SPIGELL": 45, "SINOW_ZELE": 35, "SINOW_ZOA": 30, "SO_DIMENIAN": 30, "UL_GIBBON": 30, "ZOL_GIBBON": 35},
"GrindProbTable": [ "GrindProbTable": [
[100, 35, 30, 25], [100, 35, 30, 25],
[0, 25, 20, 15], [0, 25, 20, 15],
@@ -12343,7 +12221,7 @@
[64, 160], [64, 160],
[66, 165] [66, 165]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 2, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 2, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 2, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 2, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"BARBAROUS_WOLF": [150, 260], "BARBAROUS_WOLF": [150, 260],
"BARBA_RAY": 2800, "BARBA_RAY": 2800,
@@ -12382,11 +12260,9 @@
"MERILLIA": [90, 110], "MERILLIA": [90, 110],
"MERILTAS": [100, 135], "MERILTAS": [100, 135],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MORFOS": [151, 171], "MORFOS": [151, 171],
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
"OLGA_FLOW_2": 0,
"PAN_ARMS": [165, 265], "PAN_ARMS": [165, 265],
"POISON_LILY": [90, 110], "POISON_LILY": [90, 110],
"RAG_RAPPY": [85, 150], "RAG_RAPPY": [85, 150],
@@ -12841,7 +12717,7 @@
[44, 110], [44, 110],
[46, 115] [46, 115]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 0, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 0, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 2, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 1, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"BARBAROUS_WOLF": [100, 180], "BARBAROUS_WOLF": [100, 180],
"BARBA_RAY": 1300, "BARBA_RAY": 1300,
@@ -12880,11 +12756,9 @@
"MERILLIA": [60, 65], "MERILLIA": [60, 65],
"MERILTAS": [70, 85], "MERILTAS": [70, 85],
"MIGIUM": [120, 185], "MIGIUM": [120, 185],
"MONEST": 0,
"MORFOS": [50, 80], "MORFOS": [50, 80],
"MOTHMANT": [80, 90], "MOTHMANT": [80, 90],
"NAR_LILY": [1000, 2000], "NAR_LILY": [1000, 2000],
"OLGA_FLOW_2": 0,
"PAN_ARMS": [50, 85], "PAN_ARMS": [50, 85],
"POISON_LILY": [60, 65], "POISON_LILY": [60, 65],
"RAG_RAPPY": [85, 100], "RAG_RAPPY": [85, 100],
@@ -13939,7 +13813,7 @@
[64, 160], [64, 160],
[66, 165] [66, 165]
], ],
"EnemyItemClasses": {"BARBAROUS_WOLF": 2, "BARBA_RAY": 255, "BARBA_RAY_JOINT": 255, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EGG_RAPPY": 255, "EPSILON": 3, "GAL_GRYPHON": 255, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GOL_DRAGON": 255, "GRASS_ASSASSIN": 0, "HALLO_RAPPY": 255, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MONEST": 255, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "OLGA_FLOW_2": 255, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 2, "RECOBOX": 3, "RECON": 0, "SAINT_RAPPY": 255, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2}, "EnemyItemClasses": {"BARBAROUS_WOLF": 2, "CHAOS_SORCERER": 3, "DARK_BELRA": 1, "DELBITER": 0, "DELDEPTH": 2, "DELSABER": 1, "DEL_LILY": 1, "DIMENIAN": 0, "DOLMDARL": 0, "DOLMOLM": 0, "DUBCHIC": 0, "EPSILON": 3, "GARANZ": 2, "GEE": 0, "GIBBLES": 3, "GILLCHIC": 0, "GI_GUE": 2, "GRASS_ASSASSIN": 0, "HIDOOM": 1, "HILDEBEAR": 0, "HILDEBLUE": 0, "ILL_GILL": 0, "LA_DIMENIAN": 0, "LOVE_RAPPY": 2, "MERICARAND": 3, "MERICAROL": 3, "MERICUS": 2, "MERIKLE": 1, "MERILLIA": 0, "MERILTAS": 0, "MIGIUM": 3, "MORFOS": 0, "MOTHMANT": 0, "NAR_LILY": 3, "PAN_ARMS": 2, "POISON_LILY": 1, "RAG_RAPPY": 2, "RECOBOX": 3, "RECON": 0, "SAVAGE_WOLF": 1, "SINOW_BERILL": 0, "SINOW_SPIGELL": 1, "SINOW_ZELE": 1, "SINOW_ZOA": 0, "SO_DIMENIAN": 1, "UL_GIBBON": 0, "ZOL_GIBBON": 2},
"EnemyMesetaRanges": { "EnemyMesetaRanges": {
"BARBAROUS_WOLF": [150, 260], "BARBAROUS_WOLF": [150, 260],
"BARBA_RAY": 2800, "BARBA_RAY": 2800,
@@ -13978,11 +13852,9 @@
"MERILLIA": [90, 110], "MERILLIA": [90, 110],
"MERILTAS": [100, 135], "MERILTAS": [100, 135],
"MIGIUM": [55, 135], "MIGIUM": [55, 135],
"MONEST": 0,
"MORFOS": [151, 171], "MORFOS": [151, 171],
"MOTHMANT": [120, 140], "MOTHMANT": [120, 140],
"NAR_LILY": [2000, 2500], "NAR_LILY": [2000, 2500],
"OLGA_FLOW_2": 0,
"PAN_ARMS": [165, 265], "PAN_ARMS": [165, 265],
"POISON_LILY": [90, 110], "POISON_LILY": [90, 110],
"RAG_RAPPY": [85, 150], "RAG_RAPPY": [85, 150],
+138 -83
View File
@@ -49,7 +49,7 @@
["13/4096", 0x000B03] ["13/4096", 0x000B03]
], ],
"CANADINE": [["1/128", 0x000A04]], "CANADINE": [["1/128", 0x000A04]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000A04]],
"CANANE": [["7/256", 0x000B04]], "CANANE": [["7/256", 0x000B04]],
"CHAOS_BRINGER": [["1/64", 0x002C00]], "CHAOS_BRINGER": [["1/64", 0x002C00]],
"CHAOS_SORCERER": [["7/256", 0x000B04]], "CHAOS_SORCERER": [["7/256", 0x000B04]],
@@ -125,7 +125,7 @@
["7/8192", 0x030E18] ["7/8192", 0x030E18]
], ],
"CANADINE": [["1/128", 0x000605]], "CANADINE": [["1/128", 0x000605]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000605]],
"CANANE": [["7/256", 0x000705]], "CANANE": [["7/256", 0x000705]],
"CHAOS_BRINGER": [["1/64", 0x002C00]], "CHAOS_BRINGER": [["1/64", 0x002C00]],
"CHAOS_SORCERER": [["7/256", 0x000705]], "CHAOS_SORCERER": [["7/256", 0x000705]],
@@ -212,7 +212,7 @@
["7/8192", 0x030E18] ["7/8192", 0x030E18]
], ],
"CANADINE": [["1/128", 0x000A04]], "CANADINE": [["1/128", 0x000A04]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000A04]],
"CANANE": [["7/256", 0x000305]], "CANANE": [["7/256", 0x000305]],
"CHAOS_BRINGER": [["1/64", 0x002C00]], "CHAOS_BRINGER": [["1/64", 0x002C00]],
"CHAOS_SORCERER": [["7/256", 0x000305]], "CHAOS_SORCERER": [["7/256", 0x000305]],
@@ -304,7 +304,7 @@
["3/2048", 0x030E24] ["3/2048", 0x030E24]
], ],
"CANADINE": [["1/128", 0x000A04]], "CANADINE": [["1/128", 0x000A04]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000A04]],
"CANANE": [["7/256", 0x000C04]], "CANANE": [["7/256", 0x000C04]],
"CHAOS_BRINGER": [["1/64", 0x002C00]], "CHAOS_BRINGER": [["1/64", 0x002C00]],
"CHAOS_SORCERER": [["7/256", 0x000C04]], "CHAOS_SORCERER": [["7/256", 0x000C04]],
@@ -385,7 +385,7 @@
["7/8192", 0x030E18] ["7/8192", 0x030E18]
], ],
"CANADINE": [["1/128", 0x000A04]], "CANADINE": [["1/128", 0x000A04]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000A04]],
"CANANE": [["7/256", 0x000805]], "CANANE": [["7/256", 0x000805]],
"CHAOS_BRINGER": [["1/64", 0x002C00]], "CHAOS_BRINGER": [["1/64", 0x002C00]],
"CHAOS_SORCERER": [["7/256", 0x000305]], "CHAOS_SORCERER": [["7/256", 0x000305]],
@@ -471,7 +471,7 @@
["7/8192", 0x01024B] ["7/8192", 0x01024B]
], ],
"CANADINE": [["1/128", 0x000605]], "CANADINE": [["1/128", 0x000605]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000605]],
"CANANE": [["7/256", 0x000505]], "CANANE": [["7/256", 0x000505]],
"CHAOS_BRINGER": [["1/64", 0x000506]], "CHAOS_BRINGER": [["1/64", 0x000506]],
"CHAOS_SORCERER": [["7/256", 0x000905]], "CHAOS_SORCERER": [["7/256", 0x000905]],
@@ -551,7 +551,7 @@
["7/8192", 0x01024B] ["7/8192", 0x01024B]
], ],
"CANADINE": [["1/128", 0x000105]], "CANADINE": [["1/128", 0x000105]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000105]],
"CANANE": [["7/256", 0x000705]], "CANANE": [["7/256", 0x000705]],
"CHAOS_BRINGER": [["1/64", 0x000F00]], "CHAOS_BRINGER": [["1/64", 0x000F00]],
"CHAOS_SORCERER": [["7/256", 0x000205]], "CHAOS_SORCERER": [["7/256", 0x000205]],
@@ -594,43 +594,18 @@
"BARBAROUS_WOLF": [["1/128", 0x000605]], "BARBAROUS_WOLF": [["1/128", 0x000605]],
"BOOMA": [["1/128", 0x030D0F]], "BOOMA": [["1/128", 0x030D0F]],
"BULCLAW": [["1/128", 0x000905]], "BULCLAW": [["1/128", 0x000905]],
"Box-Cave1": [ "Box-Forest1": [[0x00380000, 0x030E1D]],
["9/536870912", 0x030E1C], "Box-Forest2": [[0x00380000, 0x030E1A], [0x00380000, 0x030E18]],
["13/134217728", 0x030E16], "Box-Cave1": [[0x00380000, 0x030E16]],
["5/134217728", 0x01024A] "Box-Cave2": [[0x00380000, 0x030F00], [0x00380000, 0x01024D]],
], "Box-Cave3": [[0x00900000, 0x000904], [0x00900000, 0x000404], [0x00380000, 0x030E1B]],
"Box-Cave3": [ "Box-Mine1": [[0x02400000, 0x020000], [0x00240000, 0x01024C], [0x00380000, 0x030E1E]],
["7/1073741824", 0x020000], "Box-Mine2": [[0x01000000, 0x020000], [0x00B00000, 0x000904], [0x00B00000, 0x000404], [0x00240000, 0x01024C], [0x00380000, 0x030E1F], [0x00380000, 0x01024A]],
["7/1073741824", 0x000404], "Box-Ruins1": [[0x00380000, 0x030E1C], [0x00380000, 0x030E19]],
["3/536870912", 0x000404], "Box-Ruins2": [[0x00380000, 0x01024C], [0x00380000, 0x030E17]],
["13/2147483648", 0x030E1B], "Box-Ruins3": [[0x00D00000, 0x000905], [0x00D00000, 0x000405], [0x00380000, 0x01024B]],
["13/2147483648", 0x030E1D],
["13/2147483648", 0x030E1F],
["7/1073741824", 0x030E17],
["7/1073741824", 0x01024B]
],
"Box-DarkFalz": [["1/268435456", 0x01024C]],
"Box-Lobby": [["1/268435456", 0x01024D]],
"Box-Mine1": [["3/536870912", 0x020000]],
"Box-Pioneer2": [
["7/2147483648", 0x000904],
["7/2147483648", 0x000904]
],
"Box-Ruins1": [
["3/536870912", 0x030E1E],
["13/2147483648", 0x030E18],
["13/2147483648", 0x030E19]
],
"Box-VolOpt": [
["5/1073741824", 0x000905],
["7/2147483648", 0x000405],
["7/1073741824", 0x01024C],
["7/2147483648", 0x01024C],
["1/268435456", 0x030F00],
["13/2147483648", 0x030E1A]
],
"CANADINE": [["1/128", 0x000605]], "CANADINE": [["1/128", 0x000605]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000605]],
"CANANE": [["7/256", 0x000405]], "CANANE": [["7/256", 0x000405]],
"CHAOS_BRINGER": [["1/64", 0x001003]], "CHAOS_BRINGER": [["1/64", 0x001003]],
"CHAOS_SORCERER": [["7/256", 0x000905]], "CHAOS_SORCERER": [["7/256", 0x000905]],
@@ -715,7 +690,7 @@
["7/8192", 0x01024B] ["7/8192", 0x01024B]
], ],
"CANADINE": [["1/128", 0x000605]], "CANADINE": [["1/128", 0x000605]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000605]],
"CANANE": [["7/256", 0x030A00]], "CANANE": [["7/256", 0x030A00]],
"CHAOS_BRINGER": [["1/64", 0x000506]], "CHAOS_BRINGER": [["1/64", 0x000506]],
"CHAOS_SORCERER": [["7/256", 0x000505]], "CHAOS_SORCERER": [["7/256", 0x000505]],
@@ -793,7 +768,7 @@
], ],
"Box-Ruins3": [["7/8192", 0x030E24]], "Box-Ruins3": [["7/8192", 0x030E24]],
"CANADINE": [["1/128", 0x000A04]], "CANADINE": [["1/128", 0x000A04]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000A04]],
"CANANE": [["7/256", 0x000C04]], "CANANE": [["7/256", 0x000C04]],
"CHAOS_BRINGER": [["1/64", 0x006800]], "CHAOS_BRINGER": [["1/64", 0x006800]],
"CHAOS_SORCERER": [["7/256", 0x000905]], "CHAOS_SORCERER": [["7/256", 0x000905]],
@@ -860,7 +835,7 @@
["13/16384", 0x000B02] ["13/16384", 0x000B02]
], ],
"CANADINE": [["9/16384", 0x01024E]], "CANADINE": [["9/16384", 0x01024E]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024E]],
"CANANE": [["9/16", 0x030002]], "CANANE": [["9/16", 0x030002]],
"CHAOS_BRINGER": [["9/16", 0x030002]], "CHAOS_BRINGER": [["9/16", 0x030002]],
"CHAOS_SORCERER": [["9/16", 0x030300]], "CHAOS_SORCERER": [["9/16", 0x030300]],
@@ -922,7 +897,7 @@
["7/8192", 0x030E24] ["7/8192", 0x030E24]
], ],
"CANADINE": [["9/16384", 0x01024D]], "CANADINE": [["9/16384", 0x01024D]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024D]],
"CANANE": [["11/8192", 0x030A00]], "CANANE": [["11/8192", 0x030A00]],
"CHAOS_BRINGER": [["9/16", 0x030002]], "CHAOS_BRINGER": [["9/16", 0x030002]],
"CHAOS_SORCERER": [["7/8", 0x030B02]], "CHAOS_SORCERER": [["7/8", 0x030B02]],
@@ -990,7 +965,7 @@
["7/8192", 0x030E24] ["7/8192", 0x030E24]
], ],
"CANADINE": [["9/16384", 0x01024E]], "CANADINE": [["9/16384", 0x01024E]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024E]],
"CANANE": [["9/16", 0x030300]], "CANANE": [["9/16", 0x030300]],
"CHAOS_BRINGER": [["9/16", 0x030002]], "CHAOS_BRINGER": [["9/16", 0x030002]],
"CHAOS_SORCERER": [["9/16", 0x030002]], "CHAOS_SORCERER": [["9/16", 0x030002]],
@@ -1064,7 +1039,7 @@
["7/8192", 0x030E24] ["7/8192", 0x030E24]
], ],
"CANADINE": [["9/16384", 0x01024E]], "CANADINE": [["9/16384", 0x01024E]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024E]],
"CANANE": [["9/16", 0x030300]], "CANANE": [["9/16", 0x030300]],
"CHAOS_BRINGER": [["9/16", 0x030002]], "CHAOS_BRINGER": [["9/16", 0x030002]],
"CHAOS_SORCERER": [["9/16", 0x030002]], "CHAOS_SORCERER": [["9/16", 0x030002]],
@@ -1129,7 +1104,7 @@
["13/16384", 0x000303] ["13/16384", 0x000303]
], ],
"CANADINE": [["9/16384", 0x01024E]], "CANADINE": [["9/16384", 0x01024E]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024E]],
"CANANE": [["9/16", 0x030300]], "CANANE": [["9/16", 0x030300]],
"CHAOS_BRINGER": [["9/16", 0x030300]], "CHAOS_BRINGER": [["9/16", 0x030300]],
"CHAOS_SORCERER": [["9/16", 0x030002]], "CHAOS_SORCERER": [["9/16", 0x030002]],
@@ -1193,7 +1168,7 @@
["7/8192", 0x030E24] ["7/8192", 0x030E24]
], ],
"CANADINE": [["9/16384", 0x01024E]], "CANADINE": [["9/16384", 0x01024E]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024E]],
"CANANE": [["9/16", 0x030300]], "CANANE": [["9/16", 0x030300]],
"CHAOS_BRINGER": [["9/16", 0x030002]], "CHAOS_BRINGER": [["9/16", 0x030002]],
"CHAOS_SORCERER": [["9/16", 0x030002]], "CHAOS_SORCERER": [["9/16", 0x030002]],
@@ -1316,7 +1291,7 @@
["13/16384", 0x000403] ["13/16384", 0x000403]
], ],
"CANADINE": [["9/16384", 0x01024C]], "CANADINE": [["9/16384", 0x01024C]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024C]],
"CANANE": [["9/16", 0x030002]], "CANANE": [["9/16", 0x030002]],
"CHAOS_BRINGER": [["9/16", 0x030002]], "CHAOS_BRINGER": [["9/16", 0x030002]],
"CHAOS_SORCERER": [["9/16", 0x030B01]], "CHAOS_SORCERER": [["9/16", 0x030B01]],
@@ -1429,7 +1404,7 @@
"Box-Ruins2": [["7/8192", 0x030E25]], "Box-Ruins2": [["7/8192", 0x030E25]],
"Box-Ruins3": [["7/8192", 0x030E24]], "Box-Ruins3": [["7/8192", 0x030E24]],
"CANADINE": [["9/16384", 0x01024E]], "CANADINE": [["9/16384", 0x01024E]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["9/16384", 0x01024E]],
"CANANE": [["9/16", 0x030300]], "CANANE": [["9/16", 0x030300]],
"CHAOS_BRINGER": [["9/16", 0x030002]], "CHAOS_BRINGER": [["9/16", 0x030002]],
"CHAOS_SORCERER": [["9/16", 0x030002]], "CHAOS_SORCERER": [["9/16", 0x030002]],
@@ -1515,14 +1490,14 @@
["11/4096", 0x000A06] ["11/4096", 0x000A06]
], ],
"CANADINE": [["1/64", 0x000B06]], "CANADINE": [["1/64", 0x000B06]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/64", 0x000B06]],
"CANANE": [["1/1024", 0x010216]], "CANANE": [["1/1024", 0x010216]],
"CHAOS_BRINGER": [["1/1024", 0x010134]], "CHAOS_BRINGER": [["1/1024", 0x010134]],
"CHAOS_SORCERER": [["13/4096", 0x030D00]], "CHAOS_SORCERER": [["13/4096", 0x030D00]],
"CLAW": [["1/64", 0x000407]], "CLAW": [["1/64", 0x000407]],
"DARK_BELRA": [["13/131072", 0x030E0A]], "DARK_BELRA": [["13/131072", 0x030E0A]],
"DARK_FALZ_2": [["1/64", 0x010232]], "DARK_FALZ_2": [["1/64", 0x010232]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010232]],
"DARK_GUNNER": [["13/4096", 0x004100]], "DARK_GUNNER": [["13/4096", 0x004100]],
"DELSABER": [["13/4096", 0x009400]], "DELSABER": [["13/4096", 0x009400]],
"DE_ROL_LE": [["13/64", 0x000B06]], "DE_ROL_LE": [["13/64", 0x000B06]],
@@ -1606,14 +1581,14 @@
["7/8192", 0x030E24] ["7/8192", 0x030E24]
], ],
"CANADINE": [["1/64", 0x000707]], "CANADINE": [["1/64", 0x000707]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/64", 0x000707]],
"CANANE": [["1/1024", 0x01022B]], "CANANE": [["1/1024", 0x01022B]],
"CHAOS_BRINGER": [["13/4096", 0x030D04]], "CHAOS_BRINGER": [["13/4096", 0x030D04]],
"CHAOS_SORCERER": [["5/524288", 0x001D00]], "CHAOS_SORCERER": [["5/524288", 0x001D00]],
"CLAW": [["1/64", 0x000307]], "CLAW": [["1/64", 0x000307]],
"DARK_BELRA": [["13/4096", 0x030D0B]], "DARK_BELRA": [["13/4096", 0x030D0B]],
"DARK_FALZ_2": [["1/64", 0x010231]], "DARK_FALZ_2": [["1/64", 0x010231]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010231]],
"DARK_GUNNER": [["13/4096", 0x004C00]], "DARK_GUNNER": [["13/4096", 0x004C00]],
"DELSABER": [["13/131072", 0x001001]], "DELSABER": [["13/131072", 0x001001]],
"DE_ROL_LE": [["7/256", 0x001300]], "DE_ROL_LE": [["7/256", 0x001300]],
@@ -1697,14 +1672,14 @@
["11/4096", 0x000A06] ["11/4096", 0x000A06]
], ],
"CANADINE": [["1/64", 0x000207]], "CANADINE": [["1/64", 0x000207]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/64", 0x000207]],
"CANANE": [["13/4096", 0x008902]], "CANANE": [["13/4096", 0x008902]],
"CHAOS_BRINGER": [["13/131072", 0x005A00]], "CHAOS_BRINGER": [["13/131072", 0x005A00]],
"CHAOS_SORCERER": [["13/4096", 0x030D00]], "CHAOS_SORCERER": [["13/4096", 0x030D00]],
"CLAW": [["1/64", 0x000D01]], "CLAW": [["1/64", 0x000D01]],
"DARK_BELRA": [["13/4096", 0x009200]], "DARK_BELRA": [["13/4096", 0x009200]],
"DARK_FALZ_2": [["1/64", 0x010231]], "DARK_FALZ_2": [["1/64", 0x010231]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010231]],
"DARK_GUNNER": [["13/4096", 0x009400]], "DARK_GUNNER": [["13/4096", 0x009400]],
"DELSABER": [["5/1024", 0x030D05]], "DELSABER": [["5/1024", 0x030D05]],
"DE_ROL_LE": [["13/64", 0x000207]], "DE_ROL_LE": [["13/64", 0x000207]],
@@ -1794,14 +1769,14 @@
["11/4096", 0x000A06] ["11/4096", 0x000A06]
], ],
"CANADINE": [["1/64", 0x000C06]], "CANADINE": [["1/64", 0x000C06]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/64", 0x000C06]],
"CANANE": [["1/1024", 0x010134]], "CANANE": [["1/1024", 0x010134]],
"CHAOS_BRINGER": [["13/4096", 0x030D04]], "CHAOS_BRINGER": [["13/4096", 0x030D04]],
"CHAOS_SORCERER": [["13/4096", 0x030D00]], "CHAOS_SORCERER": [["13/4096", 0x030D00]],
"CLAW": [["13/4096", 0x000D01]], "CLAW": [["13/4096", 0x000D01]],
"DARK_BELRA": [["13/4096", 0x009200]], "DARK_BELRA": [["13/4096", 0x009200]],
"DARK_FALZ_2": [["1/64", 0x010231]], "DARK_FALZ_2": [["1/64", 0x010231]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010231]],
"DARK_GUNNER": [["13/4096", 0x009400]], "DARK_GUNNER": [["13/4096", 0x009400]],
"DELSABER": [["5/1024", 0x030D05]], "DELSABER": [["5/1024", 0x030D05]],
"DE_ROL_LE": [["7/256", 0x001300]], "DE_ROL_LE": [["7/256", 0x001300]],
@@ -1883,14 +1858,14 @@
["11/4096", 0x000A06] ["11/4096", 0x000A06]
], ],
"CANADINE": [["1/1024", 0x01022B]], "CANADINE": [["1/1024", 0x01022B]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/1024", 0x01022B]],
"CANANE": [["13/4096", 0x006C00]], "CANANE": [["13/4096", 0x006C00]],
"CHAOS_BRINGER": [["13/4096", 0x030D04]], "CHAOS_BRINGER": [["13/4096", 0x030D04]],
"CHAOS_SORCERER": [["13/131072", 0x030E0A]], "CHAOS_SORCERER": [["13/131072", 0x030E0A]],
"CLAW": [["1/64", 0x008C01]], "CLAW": [["1/64", 0x008C01]],
"DARK_BELRA": [["13/4096", 0x030D0B]], "DARK_BELRA": [["13/4096", 0x030D0B]],
"DARK_FALZ_2": [["1/64", 0x010232]], "DARK_FALZ_2": [["1/64", 0x010232]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010232]],
"DARK_GUNNER": [["1/1024", 0x010216]], "DARK_GUNNER": [["1/1024", 0x010216]],
"DELSABER": [["5/1024", 0x030D05]], "DELSABER": [["5/1024", 0x030D05]],
"DE_ROL_LE": [["13/64", 0x000307]], "DE_ROL_LE": [["13/64", 0x000307]],
@@ -1978,14 +1953,14 @@
["7/8192", 0x030E24] ["7/8192", 0x030E24]
], ],
"CANADINE": [["1/64", 0x009005]], "CANADINE": [["1/64", 0x009005]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/64", 0x009005]],
"CANANE": [["13/4096", 0x030E08]], "CANANE": [["13/4096", 0x030E08]],
"CHAOS_BRINGER": [["13/4096", 0x001200]], "CHAOS_BRINGER": [["13/4096", 0x001200]],
"CHAOS_SORCERER": [["5/524288", 0x001D00]], "CHAOS_SORCERER": [["5/524288", 0x001D00]],
"CLAW": [["13/4096", 0x010117]], "CLAW": [["13/4096", 0x010117]],
"DARK_BELRA": [["13/4096", 0x002E00]], "DARK_BELRA": [["13/4096", 0x002E00]],
"DARK_FALZ_2": [["1/64", 0x010227]], "DARK_FALZ_2": [["1/64", 0x010227]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010227]],
"DARK_GUNNER": [["1/512", 0x010134]], "DARK_GUNNER": [["1/512", 0x010134]],
"DELSABER": [["5/1024", 0x030D05]], "DELSABER": [["5/1024", 0x030D05]],
"DE_ROL_LE": [["13/64", 0x000507]], "DE_ROL_LE": [["13/64", 0x000507]],
@@ -2069,14 +2044,14 @@
["11/4096", 0x000A06] ["11/4096", 0x000A06]
], ],
"CANADINE": [["1/64", 0x000207]], "CANADINE": [["1/64", 0x000207]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/64", 0x000207]],
"CANANE": [["13/4096", 0x008902]], "CANANE": [["13/4096", 0x008902]],
"CHAOS_BRINGER": [["13/4096", 0x002E00]], "CHAOS_BRINGER": [["13/4096", 0x002E00]],
"CHAOS_SORCERER": [["5/524288", 0x001D00]], "CHAOS_SORCERER": [["5/524288", 0x001D00]],
"CLAW": [["1/64", 0x000D01]], "CLAW": [["1/64", 0x000D01]],
"DARK_BELRA": [["1/1024", 0x010133]], "DARK_BELRA": [["1/1024", 0x010133]],
"DARK_FALZ_2": [["1/64", 0x010227]], "DARK_FALZ_2": [["1/64", 0x010227]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010227]],
"DARK_GUNNER": [["13/131072", 0x009302]], "DARK_GUNNER": [["13/131072", 0x009302]],
"DELSABER": [["5/1024", 0x030D05]], "DELSABER": [["5/1024", 0x030D05]],
"DE_ROL_LE": [["13/64", 0x000207]], "DE_ROL_LE": [["13/64", 0x000207]],
@@ -2158,14 +2133,14 @@
["11/4096", 0x000A06] ["11/4096", 0x000A06]
], ],
"CANADINE": [["13/131072", 0x009300]], "CANADINE": [["13/131072", 0x009300]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["13/131072", 0x009300]],
"CANANE": [["5/1024", 0x010226]], "CANANE": [["5/1024", 0x010226]],
"CHAOS_BRINGER": [["13/4096", 0x030D04]], "CHAOS_BRINGER": [["13/4096", 0x030D04]],
"CHAOS_SORCERER": [["13/131072", 0x001F00]], "CHAOS_SORCERER": [["13/131072", 0x001F00]],
"CLAW": [["1/64", 0x000D01]], "CLAW": [["1/64", 0x000D01]],
"DARK_BELRA": [["13/4096", 0x030D0B]], "DARK_BELRA": [["13/4096", 0x030D0B]],
"DARK_FALZ_2": [["1/64", 0x010227]], "DARK_FALZ_2": [["1/64", 0x010227]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010227]],
"DARK_GUNNER": [["1/1024", 0x01012B]], "DARK_GUNNER": [["1/1024", 0x01012B]],
"DELSABER": [["5/1024", 0x030D05]], "DELSABER": [["5/1024", 0x030D05]],
"DE_ROL_LE": [["13/64", 0x000407]], "DE_ROL_LE": [["13/64", 0x000407]],
@@ -2245,14 +2220,14 @@
["11/4096", 0x000A06] ["11/4096", 0x000A06]
], ],
"CANADINE": [["13/131072", 0x009309]], "CANADINE": [["13/131072", 0x009309]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["13/131072", 0x009309]],
"CANANE": [["13/4096", 0x008902]], "CANANE": [["13/4096", 0x008902]],
"CHAOS_BRINGER": [["1/512", 0x010232]], "CHAOS_BRINGER": [["1/512", 0x010232]],
"CHAOS_SORCERER": [["13/131072", 0x004200]], "CHAOS_SORCERER": [["13/131072", 0x004200]],
"CLAW": [["1/512", 0x010332]], "CLAW": [["1/512", 0x010332]],
"DARK_BELRA": [["13/4096", 0x030D0B]], "DARK_BELRA": [["13/4096", 0x030D0B]],
"DARK_FALZ_2": [["7/256", 0x010227]], "DARK_FALZ_2": [["7/256", 0x010227]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["7/256", 0x010227]],
"DARK_GUNNER": [["13/4096", 0x004100]], "DARK_GUNNER": [["13/4096", 0x004100]],
"DELSABER": [["13/4096", 0x009400]], "DELSABER": [["13/4096", 0x009400]],
"DE_ROL_LE": [["13/64", 0x000507]], "DE_ROL_LE": [["13/64", 0x000507]],
@@ -2335,14 +2310,14 @@
["7/8192", 0x030E24] ["7/8192", 0x030E24]
], ],
"CANADINE": [["13/131072", 0x008D00]], "CANADINE": [["13/131072", 0x008D00]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["13/131072", 0x008D00]],
"CANANE": [["13/4096", 0x030E08]], "CANANE": [["13/4096", 0x030E08]],
"CHAOS_BRINGER": [["13/4096", 0x030D04]], "CHAOS_BRINGER": [["13/4096", 0x030D04]],
"CHAOS_SORCERER": [["13/4096", 0x030D00]], "CHAOS_SORCERER": [["13/4096", 0x030D00]],
"CLAW": [["1/64", 0x009007]], "CLAW": [["1/64", 0x009007]],
"DARK_BELRA": [["13/4096", 0x030D0B]], "DARK_BELRA": [["13/4096", 0x030D0B]],
"DARK_FALZ_2": [["1/64", 0x010232]], "DARK_FALZ_2": [["1/64", 0x010232]],
"DARK_FALZ_3": [], "DARK_FALZ_3": [["1/64", 0x010232]],
"DARK_GUNNER": [["13/4096", 0x009200]], "DARK_GUNNER": [["13/4096", 0x009200]],
"DELSABER": [["1/64", 0x030D03]], "DELSABER": [["1/64", 0x030D03]],
"DE_ROL_LE": [["7/256", 0x001300]], "DE_ROL_LE": [["7/256", 0x001300]],
@@ -2428,7 +2403,7 @@
["7/8192", 0x01024B] ["7/8192", 0x01024B]
], ],
"CANADINE": [["1/128", 0x000B05]], "CANADINE": [["1/128", 0x000B05]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000B05]],
"CANANE": [["1/128", 0x010223]], "CANANE": [["1/128", 0x010223]],
"CHAOS_BRINGER": [["7/256", 0x000407]], "CHAOS_BRINGER": [["7/256", 0x000407]],
"CHAOS_SORCERER": [["7/256", 0x008C01]], "CHAOS_SORCERER": [["7/256", 0x008C01]],
@@ -2514,7 +2489,7 @@
["7/8192", 0x030F00] ["7/8192", 0x030F00]
], ],
"CANADINE": [["1/128", 0x000706]], "CANADINE": [["1/128", 0x000706]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000706]],
"CANANE": [["1/128", 0x010223]], "CANANE": [["1/128", 0x010223]],
"CHAOS_BRINGER": [["7/256", 0x030500]], "CHAOS_BRINGER": [["7/256", 0x030500]],
"CHAOS_SORCERER": [["7/256", 0x008C00]], "CHAOS_SORCERER": [["7/256", 0x008C00]],
@@ -2602,7 +2577,7 @@
["13/4096", 0x000A05] ["13/4096", 0x000A05]
], ],
"CANADINE": [["1/128", 0x000306]], "CANADINE": [["1/128", 0x000306]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000306]],
"CANANE": [["1/128", 0x010223]], "CANANE": [["1/128", 0x010223]],
"CHAOS_BRINGER": [["7/256", 0x000307]], "CHAOS_BRINGER": [["7/256", 0x000307]],
"CHAOS_SORCERER": [["7/256", 0x008C01]], "CHAOS_SORCERER": [["7/256", 0x008C01]],
@@ -2688,7 +2663,7 @@
["13/4096", 0x000606] ["13/4096", 0x000606]
], ],
"CANADINE": [["1/128", 0x000C05]], "CANADINE": [["1/128", 0x000C05]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000C05]],
"CANANE": [["1/128", 0x010223]], "CANANE": [["1/128", 0x010223]],
"CHAOS_BRINGER": [["7/256", 0x000C06]], "CHAOS_BRINGER": [["7/256", 0x000C06]],
"CHAOS_SORCERER": [["7/256", 0x008C01]], "CHAOS_SORCERER": [["7/256", 0x008C01]],
@@ -2774,7 +2749,7 @@
["13/4096", 0x000A05] ["13/4096", 0x000A05]
], ],
"CANADINE": [["1/128", 0x000806]], "CANADINE": [["1/128", 0x000806]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000806]],
"CANANE": [["1/128", 0x010223]], "CANANE": [["1/128", 0x010223]],
"CHAOS_BRINGER": [["7/256", 0x000807]], "CHAOS_BRINGER": [["7/256", 0x000807]],
"CHAOS_SORCERER": [["7/256", 0x008C00]], "CHAOS_SORCERER": [["7/256", 0x008C00]],
@@ -2860,7 +2835,7 @@
["7/8192", 0x030E25] ["7/8192", 0x030E25]
], ],
"CANADINE": [["1/128", 0x000506]], "CANADINE": [["1/128", 0x000506]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000506]],
"CANANE": [["1/128", 0x010223]], "CANANE": [["1/128", 0x010223]],
"CHAOS_BRINGER": [["7/256", 0x000506]], "CHAOS_BRINGER": [["7/256", 0x000506]],
"CHAOS_SORCERER": [["7/256", 0x008C00]], "CHAOS_SORCERER": [["7/256", 0x008C00]],
@@ -2944,7 +2919,7 @@
["7/8192", 0x030F00] ["7/8192", 0x030F00]
], ],
"CANADINE": [["1/128", 0x000705]], "CANADINE": [["1/128", 0x000705]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000705]],
"CANANE": [["1/128", 0x010226]], "CANANE": [["1/128", 0x010226]],
"CHAOS_BRINGER": [["7/256", 0x000207]], "CHAOS_BRINGER": [["7/256", 0x000207]],
"CHAOS_SORCERER": [["7/256", 0x008C00]], "CHAOS_SORCERER": [["7/256", 0x008C00]],
@@ -3030,7 +3005,7 @@
["13/4096", 0x000A05] ["13/4096", 0x000A05]
], ],
"CANADINE": [["1/128", 0x000405]], "CANADINE": [["1/128", 0x000405]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000405]],
"CANANE": [["1/1024", 0x010134]], "CANANE": [["1/1024", 0x010134]],
"CHAOS_BRINGER": [["7/256", 0x000907]], "CHAOS_BRINGER": [["7/256", 0x000907]],
"CHAOS_SORCERER": [["7/256", 0x008C00]], "CHAOS_SORCERER": [["7/256", 0x008C00]],
@@ -3116,7 +3091,7 @@
["7/8192", 0x01024B] ["7/8192", 0x01024B]
], ],
"CANADINE": [["1/128", 0x000506]], "CANADINE": [["1/128", 0x000506]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000506]],
"CANANE": [["1/128", 0x010221]], "CANANE": [["1/128", 0x010221]],
"CHAOS_BRINGER": [["7/256", 0x000506]], "CHAOS_BRINGER": [["7/256", 0x000506]],
"CHAOS_SORCERER": [["7/256", 0x008C00]], "CHAOS_SORCERER": [["7/256", 0x008C00]],
@@ -3208,7 +3183,7 @@
["13/4096", 0x000505] ["13/4096", 0x000505]
], ],
"CANADINE": [["1/128", 0x000806]], "CANADINE": [["1/128", 0x000806]],
"CANADINE_GROUP": [], "CANADINE_GROUP": [["1/128", 0x000806]],
"CANANE": [["1/128", 0x010223]], "CANANE": [["1/128", 0x010223]],
"CHAOS_BRINGER": [["7/256", 0x000B05]], "CHAOS_BRINGER": [["7/256", 0x000B05]],
"CHAOS_SORCERER": [["7/256", 0x008C00]], "CHAOS_SORCERER": [["7/256", 0x008C00]],
@@ -3253,6 +3228,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["1/128", 0x000B04]], "BARBAROUS_WOLF": [["1/128", 0x000B04]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000404], ["9/4096", 0x000404],
["9/4096", 0x000B02], ["9/4096", 0x000B02],
@@ -3310,6 +3286,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002600]], "LOVE_RAPPY": [["7/8", 0x002600]],
"MERICAROL": [["7/256", 0x000406]], "MERICAROL": [["7/256", 0x000406]],
"MERICARAND": [["7/256", 0x000406]],
"MERICUS": [["7/256", 0x000406]], "MERICUS": [["7/256", 0x000406]],
"MERIKLE": [["7/256", 0x000406]], "MERIKLE": [["7/256", 0x000406]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3333,6 +3310,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["1/128", 0x000305]], "BARBAROUS_WOLF": [["1/128", 0x000305]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000704], ["9/4096", 0x000704],
["9/4096", 0x000304] ["9/4096", 0x000304]
@@ -3387,6 +3365,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000706]], "MERICAROL": [["7/256", 0x000706]],
"MERICARAND": [["7/256", 0x000706]],
"MERICUS": [["7/256", 0x000706]], "MERICUS": [["7/256", 0x000706]],
"MERIKLE": [["7/256", 0x000706]], "MERIKLE": [["7/256", 0x000706]],
"MERILLIA": [["1/128", 0x000606]], "MERILLIA": [["1/128", 0x000606]],
@@ -3410,6 +3389,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["1/128", 0x000205]], "BARBAROUS_WOLF": [["1/128", 0x000205]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000304], ["9/4096", 0x000304],
["9/4096", 0x000204], ["9/4096", 0x000204],
@@ -3479,6 +3459,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000306]], "MERICAROL": [["7/256", 0x000306]],
"MERICARAND": [["7/256", 0x000306]],
"MERICUS": [["7/256", 0x000306]], "MERICUS": [["7/256", 0x000306]],
"MERIKLE": [["7/256", 0x000306]], "MERIKLE": [["7/256", 0x000306]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3502,6 +3483,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["1/128", 0x000405]], "BARBAROUS_WOLF": [["1/128", 0x000405]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000C03], ["9/4096", 0x000C03],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -3572,6 +3554,7 @@
"LA_DIMENIAN": [["1/128", 0x000A04]], "LA_DIMENIAN": [["1/128", 0x000A04]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000C05]], "MERICAROL": [["7/256", 0x000C05]],
"MERICARAND": [["7/256", 0x000C05]],
"MERICUS": [["7/256", 0x000C05]], "MERICUS": [["7/256", 0x000C05]],
"MERIKLE": [["7/256", 0x000C05]], "MERIKLE": [["7/256", 0x000C05]],
"MERILLIA": [["1/128", 0x000A04]], "MERILLIA": [["1/128", 0x000A04]],
@@ -3595,6 +3578,7 @@
"Purplenum": { "Purplenum": {
"BARBAROUS_WOLF": [["1/128", 0x000305]], "BARBAROUS_WOLF": [["1/128", 0x000305]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000804], ["9/4096", 0x000804],
["9/4096", 0x000304], ["9/4096", 0x000304],
@@ -3656,6 +3640,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x004900]], "LOVE_RAPPY": [["7/8", 0x004900]],
"MERICAROL": [["7/256", 0x000806]], "MERICAROL": [["7/256", 0x000806]],
"MERICARAND": [["7/256", 0x000806]],
"MERICUS": [["7/256", 0x000806]], "MERICUS": [["7/256", 0x000806]],
"MERIKLE": [["7/256", 0x000806]], "MERIKLE": [["7/256", 0x000806]],
"MERILLIA": [["1/128", 0x000605]], "MERILLIA": [["1/128", 0x000605]],
@@ -3679,6 +3664,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["1/128", 0x000905]], "BARBAROUS_WOLF": [["1/128", 0x000905]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000504], ["9/4096", 0x000504],
["9/4096", 0x000904], ["9/4096", 0x000904],
@@ -3751,6 +3737,7 @@
"LA_DIMENIAN": [["1/128", 0x000A04]], "LA_DIMENIAN": [["1/128", 0x000A04]],
"LOVE_RAPPY": [["7/8", 0x002600]], "LOVE_RAPPY": [["7/8", 0x002600]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x000506]], "MERICUS": [["7/256", 0x000506]],
"MERIKLE": [["7/256", 0x000506]], "MERIKLE": [["7/256", 0x000506]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3774,6 +3761,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["1/128", 0x000705]], "BARBAROUS_WOLF": [["1/128", 0x000705]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000204], ["9/4096", 0x000204],
["9/4096", 0x000704], ["9/4096", 0x000704],
@@ -3830,6 +3818,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000206]], "MERICAROL": [["7/256", 0x000206]],
"MERICARAND": [["7/256", 0x000206]],
"MERICUS": [["7/256", 0x000206]], "MERICUS": [["7/256", 0x000206]],
"MERIKLE": [["7/256", 0x000206]], "MERIKLE": [["7/256", 0x000206]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3853,6 +3842,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["1/128", 0x000405]], "BARBAROUS_WOLF": [["1/128", 0x000405]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000904], ["9/4096", 0x000904],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -3914,6 +3904,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002000]], "LOVE_RAPPY": [["7/8", 0x002000]],
"MERICAROL": [["7/256", 0x000906]], "MERICAROL": [["7/256", 0x000906]],
"MERICARAND": [["7/256", 0x000906]],
"MERICUS": [["7/256", 0x000906]], "MERICUS": [["7/256", 0x000906]],
"MERIKLE": [["7/256", 0x000906]], "MERIKLE": [["7/256", 0x000906]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3937,6 +3928,7 @@
"Whitill": { "Whitill": {
"BARBAROUS_WOLF": [["1/128", 0x000805]], "BARBAROUS_WOLF": [["1/128", 0x000805]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000504], ["9/4096", 0x000504],
["9/4096", 0x000804], ["9/4096", 0x000804],
@@ -4002,6 +3994,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x000506]], "MERICUS": [["7/256", 0x000506]],
"MERIKLE": [["7/256", 0x000506]], "MERIKLE": [["7/256", 0x000506]],
"MERILLIA": [["1/128", 0x000605]], "MERILLIA": [["1/128", 0x000605]],
@@ -4025,6 +4018,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["1/128", 0x000205]], "BARBAROUS_WOLF": [["1/128", 0x000205]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [["7/8192", 0x01024C]], "Box-JungleNorth": [["7/8192", 0x01024C]],
"Box-Mountain": [["1/256", 0x020000]], "Box-Mountain": [["1/256", 0x020000]],
"Box-JungleEast": [ "Box-JungleEast": [
@@ -4073,6 +4067,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x000306]], "MERICUS": [["7/256", 0x000306]],
"MERIKLE": [["7/256", 0x000406]], "MERIKLE": [["7/256", 0x000406]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -4098,6 +4093,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["9/16384", 0x030A00]], "BARBAROUS_WOLF": [["9/16384", 0x030A00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000402], ["9/16384", 0x000402],
["9/16384", 0x000B01], ["9/16384", 0x000B01],
@@ -4150,6 +4146,7 @@
"LA_DIMENIAN": [["9/16384", 0x030A00]], "LA_DIMENIAN": [["9/16384", 0x030A00]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["9/16384", 0x030A00]], "MERILLIA": [["9/16384", 0x030A00]],
@@ -4169,6 +4166,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["3/8192", 0x030F00]], "BARBAROUS_WOLF": [["3/8192", 0x030F00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000702], ["9/16384", 0x000702],
["9/16384", 0x000302] ["9/16384", 0x000302]
@@ -4219,6 +4217,7 @@
"LA_DIMENIAN": [["9/16384", 0x030B06]], "LA_DIMENIAN": [["9/16384", 0x030B06]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILTAS": [["9/16384", 0x030A00]], "MERILTAS": [["9/16384", 0x030A00]],
@@ -4238,6 +4237,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["9/16384", 0x030A00]], "BARBAROUS_WOLF": [["9/16384", 0x030A00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000302], ["9/16384", 0x000302],
["9/16384", 0x000202], ["9/16384", 0x000202],
@@ -4288,6 +4288,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B05]], "LA_DIMENIAN": [["11/8192", 0x030B05]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B00]], "MERILLIA": [["11/8192", 0x030B00]],
@@ -4309,6 +4310,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["11/8192", 0x030B01]], "BARBAROUS_WOLF": [["11/8192", 0x030B01]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000C01], ["9/16384", 0x000C01],
["9/16384", 0x000402], ["9/16384", 0x000402],
@@ -4372,6 +4374,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B01]], "LA_DIMENIAN": [["11/8192", 0x030B01]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B00]], "MERILLIA": [["11/8192", 0x030B00]],
@@ -4393,6 +4396,7 @@
}, },
"Purplenum": { "Purplenum": {
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000802], ["9/16384", 0x000802],
["9/16384", 0x000302], ["9/16384", 0x000302],
@@ -4447,6 +4451,7 @@
"LA_DIMENIAN": [["9/16384", 0x030A00]], "LA_DIMENIAN": [["9/16384", 0x030A00]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B03]], "MERILLIA": [["11/8192", 0x030B03]],
@@ -4466,6 +4471,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["11/8192", 0x030B01]], "BARBAROUS_WOLF": [["11/8192", 0x030B01]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000502], ["9/16384", 0x000502],
["9/16384", 0x000902], ["9/16384", 0x000902],
@@ -4523,6 +4529,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B01]], "LA_DIMENIAN": [["11/8192", 0x030B01]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILTAS": [["11/8192", 0x030B03]], "MERILTAS": [["11/8192", 0x030B03]],
@@ -4538,6 +4545,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["9/16384", 0x030B06]], "BARBAROUS_WOLF": [["9/16384", 0x030B06]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000202], ["9/16384", 0x000202],
["9/16384", 0x000702], ["9/16384", 0x000702],
@@ -4591,6 +4599,7 @@
"LA_DIMENIAN": [["9/16384", 0x030A00]], "LA_DIMENIAN": [["9/16384", 0x030A00]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILTAS": [["9/16384", 0x030A00]], "MERILTAS": [["9/16384", 0x030A00]],
@@ -4612,6 +4621,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["11/8192", 0x030B00]], "BARBAROUS_WOLF": [["11/8192", 0x030B00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000902], ["9/16384", 0x000902],
["9/16384", 0x000402], ["9/16384", 0x000402],
@@ -4667,6 +4677,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B01]], "LA_DIMENIAN": [["11/8192", 0x030B01]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["9/16384", 0x030A00]], "MERILLIA": [["9/16384", 0x030A00]],
@@ -4687,6 +4698,7 @@
}, },
"Whitill": { "Whitill": {
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000502], ["9/16384", 0x000502],
["9/16384", 0x000802], ["9/16384", 0x000802],
@@ -4739,6 +4751,7 @@
"ILL_GILL": [["7/32768", 0x010309]], "ILL_GILL": [["7/32768", 0x010309]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B03]], "MERILLIA": [["11/8192", 0x030B03]],
@@ -4760,6 +4773,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["11/8192", 0x030300]], "BARBAROUS_WOLF": [["11/8192", 0x030300]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["7/8192", 0x030F00], ["7/8192", 0x030F00],
["7/8192", 0x01024C] ["7/8192", 0x01024C]
@@ -4807,6 +4821,7 @@
"ILL_GILL": [["7/32768", 0x01030D]], "ILL_GILL": [["7/32768", 0x01030D]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B00]], "MERILLIA": [["11/8192", 0x030B00]],
@@ -4830,6 +4845,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["13/4096", 0x002600]], "BARBAROUS_WOLF": [["13/4096", 0x002600]],
"BARBA_RAY": [["13/64", 0x000407]], "BARBA_RAY": [["13/64", 0x000407]],
"BARBA_RAY_JOINT": [["13/64", 0x000407]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000407], ["13/8192", 0x000407],
["7/4096", 0x000B05], ["7/4096", 0x000B05],
@@ -4902,6 +4918,7 @@
"LA_DIMENIAN": [["1/512", 0x010317]], "LA_DIMENIAN": [["1/512", 0x010317]],
"LOVE_RAPPY": [["1/2", 0x005500]], "LOVE_RAPPY": [["1/2", 0x005500]],
"MERICAROL": [["13/4096", 0x005B00]], "MERICAROL": [["13/4096", 0x005B00]],
"MERICARAND": [["13/4096", 0x005B00]],
"MERICUS": [["13/4096", 0x003D00]], "MERICUS": [["13/4096", 0x003D00]],
"MERIKLE": [["13/4096", 0x009500]], "MERIKLE": [["13/4096", 0x009500]],
"MERILLIA": [["1/64", 0x000407]], "MERILLIA": [["1/64", 0x000407]],
@@ -4928,6 +4945,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["1/512", 0x010335]], "BARBAROUS_WOLF": [["1/512", 0x010335]],
"BARBA_RAY": [["13/64", 0x000E01]], "BARBA_RAY": [["13/64", 0x000E01]],
"BARBA_RAY_JOINT": [["13/64", 0x000E01]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000707], ["13/8192", 0x000707],
["7/4096", 0x000306], ["7/4096", 0x000306],
@@ -4998,6 +5016,7 @@
"LA_DIMENIAN": [["1/1024", 0x010229]], "LA_DIMENIAN": [["1/1024", 0x010229]],
"LOVE_RAPPY": [["7/8", 0x01031D]], "LOVE_RAPPY": [["7/8", 0x01031D]],
"MERICAROL": [["13/4096", 0x005600]], "MERICAROL": [["13/4096", 0x005600]],
"MERICARAND": [["13/4096", 0x005600]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x003D00]], "MERIKLE": [["13/4096", 0x003D00]],
"MERILLIA": [["1/64", 0x000707]], "MERILLIA": [["1/64", 0x000707]],
@@ -5024,6 +5043,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["13/4096", 0x002700]], "BARBAROUS_WOLF": [["13/4096", 0x002700]],
"BARBA_RAY": [["13/64", 0x008B02]], "BARBA_RAY": [["13/64", 0x008B02]],
"BARBA_RAY_JOINT": [["13/64", 0x008B02]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000307], ["13/8192", 0x000307],
["7/4096", 0x000206], ["7/4096", 0x000206],
@@ -5096,6 +5116,7 @@
"LA_DIMENIAN": [["1/512", 0x010313]], "LA_DIMENIAN": [["1/512", 0x010313]],
"LOVE_RAPPY": [["1/2", 0x005B00]], "LOVE_RAPPY": [["1/2", 0x005B00]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x010346]], "MERIKLE": [["13/4096", 0x010346]],
"MERILLIA": [["1/64", 0x000307]], "MERILLIA": [["1/64", 0x000307]],
@@ -5121,6 +5142,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["1/512", 0x010320]], "BARBAROUS_WOLF": [["1/512", 0x010320]],
"BARBA_RAY": [["13/64", 0x008902]], "BARBA_RAY": [["13/64", 0x008902]],
"BARBA_RAY_JOINT": [["13/64", 0x008902]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000C06], ["13/8192", 0x000C06],
["7/4096", 0x000406], ["7/4096", 0x000406],
@@ -5199,6 +5221,7 @@
"LA_DIMENIAN": [["1/64", 0x000C06]], "LA_DIMENIAN": [["1/64", 0x000C06]],
"LOVE_RAPPY": [["1/2", 0x005500]], "LOVE_RAPPY": [["1/2", 0x005500]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x005B00]], "MERIKLE": [["13/4096", 0x005B00]],
"MERILLIA": [["13/131072", 0x009305]], "MERILLIA": [["13/131072", 0x009305]],
@@ -5225,6 +5248,7 @@
"Purplenum": { "Purplenum": {
"BARBAROUS_WOLF": [["1/512", 0x01030F]], "BARBAROUS_WOLF": [["1/512", 0x01030F]],
"BARBA_RAY": [["13/64", 0x000807]], "BARBA_RAY": [["13/64", 0x000807]],
"BARBA_RAY_JOINT": [["13/64", 0x000807]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000807], ["13/8192", 0x000807],
["7/4096", 0x000306], ["7/4096", 0x000306],
@@ -5295,6 +5319,7 @@
"LA_DIMENIAN": [["13/4096", 0x004600]], "LA_DIMENIAN": [["13/4096", 0x004600]],
"LOVE_RAPPY": [["1/2", 0x01031D]], "LOVE_RAPPY": [["1/2", 0x01031D]],
"MERICAROL": [["13/131072", 0x001E00]], "MERICAROL": [["13/131072", 0x001E00]],
"MERICARAND": [["13/131072", 0x001E00]],
"MERICUS": [["1/1024", 0x001001]], "MERICUS": [["1/1024", 0x001001]],
"MERIKLE": [["13/4096", 0x009500]], "MERIKLE": [["13/4096", 0x009500]],
"MERILLIA": [["1/64", 0x000307]], "MERILLIA": [["1/64", 0x000307]],
@@ -5321,6 +5346,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["13/4096", 0x001006]], "BARBAROUS_WOLF": [["13/4096", 0x001006]],
"BARBA_RAY": [["7/256", 0x000E02]], "BARBA_RAY": [["7/256", 0x000E02]],
"BARBA_RAY_JOINT": [["7/256", 0x000E02]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000507], ["13/8192", 0x000507],
["7/4096", 0x000107], ["7/4096", 0x000107],
@@ -5393,6 +5419,7 @@
"LA_DIMENIAN": [["13/4096", 0x01030F]], "LA_DIMENIAN": [["13/4096", 0x01030F]],
"LOVE_RAPPY": [["7/8", 0x01031D]], "LOVE_RAPPY": [["7/8", 0x01031D]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x005E00]], "MERIKLE": [["13/4096", 0x005E00]],
"MERILLIA": [["13/4096", 0x001004]], "MERILLIA": [["13/4096", 0x001004]],
@@ -5418,6 +5445,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["13/4096", 0x002000]], "BARBAROUS_WOLF": [["13/4096", 0x002000]],
"BARBA_RAY": [["13/64", 0x000E02]], "BARBA_RAY": [["13/64", 0x000E02]],
"BARBA_RAY_JOINT": [["13/64", 0x000E02]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000207], ["13/8192", 0x000207],
["7/4096", 0x000706], ["7/4096", 0x000706],
@@ -5490,6 +5518,7 @@
"LA_DIMENIAN": [["13/4096", 0x010224]], "LA_DIMENIAN": [["13/4096", 0x010224]],
"LOVE_RAPPY": [["1/2", 0x006900]], "LOVE_RAPPY": [["1/2", 0x006900]],
"MERICAROL": [["13/4096", 0x002F00]], "MERICAROL": [["13/4096", 0x002F00]],
"MERICARAND": [["13/4096", 0x002F00]],
"MERICUS": [["13/4096", 0x006B00]], "MERICUS": [["13/4096", 0x006B00]],
"MERIKLE": [["13/4096", 0x003D00]], "MERIKLE": [["13/4096", 0x003D00]],
"MERILLIA": [["1/64", 0x000E01]], "MERILLIA": [["1/64", 0x000E01]],
@@ -5516,6 +5545,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["13/4096", 0x010224]], "BARBAROUS_WOLF": [["13/4096", 0x010224]],
"BARBA_RAY": [["13/64", 0x000907]], "BARBA_RAY": [["13/64", 0x000907]],
"BARBA_RAY_JOINT": [["13/64", 0x000907]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000907], ["13/8192", 0x000907],
["7/4096", 0x000406], ["7/4096", 0x000406],
@@ -5594,6 +5624,7 @@
"LA_DIMENIAN": [["13/4096", 0x002000]], "LA_DIMENIAN": [["13/4096", 0x002000]],
"LOVE_RAPPY": [["1/2", 0x001006]], "LOVE_RAPPY": [["1/2", 0x001006]],
"MERICAROL": [["13/4096", 0x003B00]], "MERICAROL": [["13/4096", 0x003B00]],
"MERICARAND": [["13/4096", 0x003B00]],
"MERICUS": [["13/4096", 0x004600]], "MERICUS": [["13/4096", 0x004600]],
"MERIKLE": [["13/4096", 0x001101]], "MERIKLE": [["13/4096", 0x001101]],
"MERILLIA": [["1/512", 0x01011D]], "MERILLIA": [["1/512", 0x01011D]],
@@ -5620,6 +5651,7 @@
"Whitill": { "Whitill": {
"BARBAROUS_WOLF": [["1/64", 0x000807]], "BARBAROUS_WOLF": [["1/64", 0x000807]],
"BARBA_RAY": [["13/64", 0x000507]], "BARBA_RAY": [["13/64", 0x000507]],
"BARBA_RAY_JOINT": [["13/64", 0x000507]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000507], ["13/8192", 0x000507],
["7/4096", 0x000806], ["7/4096", 0x000806],
@@ -5690,6 +5722,7 @@
"LA_DIMENIAN": [["1/64", 0x000D01]], "LA_DIMENIAN": [["1/64", 0x000D01]],
"LOVE_RAPPY": [["1/2", 0x010132]], "LOVE_RAPPY": [["1/2", 0x010132]],
"MERICAROL": [["1/64", 0x008902]], "MERICAROL": [["1/64", 0x008902]],
"MERICARAND": [["1/64", 0x008902]],
"MERICUS": [["1/64", 0x008B02]], "MERICUS": [["1/64", 0x008B02]],
"MERIKLE": [["13/4096", 0x002F00]], "MERIKLE": [["13/4096", 0x002F00]],
"MERILLIA": [["1/64", 0x000807]], "MERILLIA": [["1/64", 0x000807]],
@@ -5716,6 +5749,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["1/512", 0x01030F]], "BARBAROUS_WOLF": [["1/512", 0x01030F]],
"BARBA_RAY": [["7/256", 0x000F02]], "BARBA_RAY": [["7/256", 0x000F02]],
"BARBA_RAY_JOINT": [["7/256", 0x000F02]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["1/1024", 0x000107], ["1/1024", 0x000107],
["1/1024", 0x000607], ["1/1024", 0x000607],
@@ -5785,6 +5819,7 @@
"LA_DIMENIAN": [["13/4096", 0x010225]], "LA_DIMENIAN": [["13/4096", 0x010225]],
"LOVE_RAPPY": [["1/2", 0x005B00]], "LOVE_RAPPY": [["1/2", 0x005B00]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x002F00]], "MERICUS": [["13/4096", 0x002F00]],
"MERIKLE": [["13/4096", 0x005E00]], "MERIKLE": [["13/4096", 0x005E00]],
"MERILLIA": [["1/64", 0x000C06]], "MERILLIA": [["1/64", 0x000C06]],
@@ -5813,6 +5848,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["1/128", 0x000406]], "BARBAROUS_WOLF": [["1/128", 0x000406]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000405], ["9/4096", 0x000405],
["9/4096", 0x000B03], ["9/4096", 0x000B03],
@@ -5881,6 +5917,7 @@
"LA_DIMENIAN": [["1/128", 0x000B05]], "LA_DIMENIAN": [["1/128", 0x000B05]],
"LOVE_RAPPY": [["7/8", 0x000407]], "LOVE_RAPPY": [["7/8", 0x000407]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x010125]], "MERIKLE": [["7/256", 0x010125]],
"MERILLIA": [["1/128", 0x000406]], "MERILLIA": [["1/128", 0x000406]],
@@ -5904,6 +5941,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["1/128", 0x000706]], "BARBAROUS_WOLF": [["1/128", 0x000706]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000705], ["9/4096", 0x000705],
["9/4096", 0x000304], ["9/4096", 0x000304],
@@ -5972,6 +6010,7 @@
"LA_DIMENIAN": [["1/128", 0x000706]], "LA_DIMENIAN": [["1/128", 0x000706]],
"LOVE_RAPPY": [["7/8", 0x000707]], "LOVE_RAPPY": [["7/8", 0x000707]],
"MERICAROL": [["7/256", 0x005600]], "MERICAROL": [["7/256", 0x005600]],
"MERICARAND": [["7/256", 0x005600]],
"MERICUS": [["7/256", 0x008C01]], "MERICUS": [["7/256", 0x008C01]],
"MERIKLE": [["7/256", 0x000707]], "MERIKLE": [["7/256", 0x000707]],
"MERILLIA": [["1/128", 0x000706]], "MERILLIA": [["1/128", 0x000706]],
@@ -5995,6 +6034,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["1/128", 0x000306]], "BARBAROUS_WOLF": [["1/128", 0x000306]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000305], ["9/4096", 0x000305],
["9/4096", 0x000204], ["9/4096", 0x000204],
@@ -6065,6 +6105,7 @@
"LA_DIMENIAN": [["1/128", 0x000306]], "LA_DIMENIAN": [["1/128", 0x000306]],
"LOVE_RAPPY": [["7/8", 0x010219]], "LOVE_RAPPY": [["7/8", 0x010219]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000307]], "MERIKLE": [["7/256", 0x000307]],
"MERILLIA": [["1/128", 0x000306]], "MERILLIA": [["1/128", 0x000306]],
@@ -6088,6 +6129,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["1/128", 0x000C05]], "BARBAROUS_WOLF": [["1/128", 0x000C05]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000C04], ["9/4096", 0x000C04],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -6162,6 +6204,7 @@
"LA_DIMENIAN": [["1/128", 0x000C05]], "LA_DIMENIAN": [["1/128", 0x000C05]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x005600]], "MERIKLE": [["7/256", 0x005600]],
"MERILLIA": [["1/128", 0x000406]], "MERILLIA": [["1/128", 0x000406]],
@@ -6185,6 +6228,7 @@
"Purplenum": { "Purplenum": {
"BARBAROUS_WOLF": [["1/128", 0x000806]], "BARBAROUS_WOLF": [["1/128", 0x000806]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000805], ["9/4096", 0x000805],
["9/4096", 0x000304], ["9/4096", 0x000304],
@@ -6255,6 +6299,7 @@
"LA_DIMENIAN": [["1/128", 0x000E00]], "LA_DIMENIAN": [["1/128", 0x000E00]],
"LOVE_RAPPY": [["7/8", 0x000807]], "LOVE_RAPPY": [["7/8", 0x000807]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000307]], "MERIKLE": [["7/256", 0x000307]],
"MERILLIA": [["1/128", 0x000306]], "MERILLIA": [["1/128", 0x000306]],
@@ -6278,6 +6323,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["1/128", 0x000906]], "BARBAROUS_WOLF": [["1/128", 0x000906]],
"BARBA_RAY": [["3/32", 0x000E01]], "BARBA_RAY": [["3/32", 0x000E01]],
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000504], ["9/4096", 0x000504],
["9/4096", 0x000904], ["9/4096", 0x000904],
@@ -6346,6 +6392,7 @@
"LA_DIMENIAN": [["1/128", 0x000906]], "LA_DIMENIAN": [["1/128", 0x000906]],
"LOVE_RAPPY": [["7/8", 0x01031D]], "LOVE_RAPPY": [["7/8", 0x01031D]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x000F01]], "MERICUS": [["7/256", 0x000F01]],
"MERIKLE": [["7/256", 0x001004]], "MERIKLE": [["7/256", 0x001004]],
"MERILLIA": [["1/128", 0x000506]], "MERILLIA": [["1/128", 0x000506]],
@@ -6369,6 +6416,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["1/128", 0x000206]], "BARBAROUS_WOLF": [["1/128", 0x000206]],
"BARBA_RAY": [["3/32", 0x000E01]], "BARBA_RAY": [["3/32", 0x000E01]],
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000205], ["9/4096", 0x000205],
["9/4096", 0x000704], ["9/4096", 0x000704],
@@ -6439,6 +6487,7 @@
"LA_DIMENIAN": [["1/128", 0x000206]], "LA_DIMENIAN": [["1/128", 0x000206]],
"LOVE_RAPPY": [["7/8", 0x000207]], "LOVE_RAPPY": [["7/8", 0x000207]],
"MERICAROL": [["7/256", 0x005601]], "MERICAROL": [["7/256", 0x005601]],
"MERICARAND": [["7/256", 0x005601]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000207]], "MERIKLE": [["7/256", 0x000207]],
"MERILLIA": [["1/128", 0x000205]], "MERILLIA": [["1/128", 0x000205]],
@@ -6462,6 +6511,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["1/128", 0x010219]], "BARBAROUS_WOLF": [["1/128", 0x010219]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000905], ["9/4096", 0x000905],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -6532,6 +6582,7 @@
"LA_DIMENIAN": [["1/64", 0x000406]], "LA_DIMENIAN": [["1/64", 0x000406]],
"LOVE_RAPPY": [["7/8", 0x000907]], "LOVE_RAPPY": [["7/8", 0x000907]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000407]], "MERIKLE": [["7/256", 0x000407]],
"MERILLIA": [["1/128", 0x000906]], "MERILLIA": [["1/128", 0x000906]],
@@ -6555,6 +6606,7 @@
"Whitill": { "Whitill": {
"BARBAROUS_WOLF": [["1/128", 0x000506]], "BARBAROUS_WOLF": [["1/128", 0x000506]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000505], ["9/4096", 0x000505],
["9/4096", 0x000804], ["9/4096", 0x000804],
@@ -6627,6 +6679,7 @@
"LA_DIMENIAN": [["1/128", 0x000806]], "LA_DIMENIAN": [["1/128", 0x000806]],
"LOVE_RAPPY": [["7/8", 0x010222]], "LOVE_RAPPY": [["7/8", 0x010222]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x005601]], "MERICUS": [["7/256", 0x005601]],
"MERIKLE": [["7/256", 0x008901]], "MERIKLE": [["7/256", 0x008901]],
"MERILLIA": [["1/128", 0x000506]], "MERILLIA": [["1/128", 0x000506]],
@@ -6650,6 +6703,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["1/128", 0x000806]], "BARBAROUS_WOLF": [["1/128", 0x000806]],
"BARBA_RAY": [["3/32", 0x000F01]], "BARBA_RAY": [["3/32", 0x000F01]],
"BARBA_RAY_JOINT": [["3/32", 0x000F01]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000105], ["9/4096", 0x000105],
["9/4096", 0x000605], ["9/4096", 0x000605],
@@ -6722,6 +6776,7 @@
"LA_DIMENIAN": [["1/128", 0x010225]], "LA_DIMENIAN": [["1/128", 0x010225]],
"LOVE_RAPPY": [["7/8", 0x000906]], "LOVE_RAPPY": [["7/8", 0x000906]],
"MERICAROL": [["7/256", 0x003B00]], "MERICAROL": [["7/256", 0x003B00]],
"MERICARAND": [["7/256", 0x003B00]],
"MERICUS": [["7/256", 0x010125]], "MERICUS": [["7/256", 0x010125]],
"MERIKLE": [["7/256", 0x008B01]], "MERIKLE": [["7/256", 0x008B01]],
"MERILLIA": [["1/128", 0x000106]], "MERILLIA": [["1/128", 0x000106]],
+90 -35
View File
@@ -610,41 +610,16 @@
"BARBAROUS_WOLF": [["1/128", 0x000605]], "BARBAROUS_WOLF": [["1/128", 0x000605]],
"BOOMA": [["1/128", 0x030D0F]], "BOOMA": [["1/128", 0x030D0F]],
"BULCLAW": [["1/128", 0x000905]], "BULCLAW": [["1/128", 0x000905]],
"Box-Cave1": [ "Box-Forest1": [[0x00380000, 0x030E1D]],
["9/536870912", 0x030E1C], "Box-Forest2": [[0x00380000, 0x030E1A], [0x00380000, 0x030E18]],
["13/134217728", 0x030E16], "Box-Cave1": [[0x00380000, 0x030E16]],
["5/134217728", 0x01024A] "Box-Cave2": [[0x00380000, 0x030F00], [0x00380000, 0x01024D]],
], "Box-Cave3": [[0x00900000, 0x000904], [0x00900000, 0x000404], [0x00380000, 0x030E1B]],
"Box-Cave3": [ "Box-Mine1": [[0x02400000, 0x020000], [0x00240000, 0x01024C], [0x00380000, 0x030E1E]],
["7/1073741824", 0x020000], "Box-Mine2": [[0x01000000, 0x020000], [0x00B00000, 0x000904], [0x00B00000, 0x000404], [0x00240000, 0x01024C], [0x00380000, 0x030E1F], [0x00380000, 0x01024A]],
["7/1073741824", 0x000404], "Box-Ruins1": [[0x00380000, 0x030E1C], [0x00380000, 0x030E19]],
["3/536870912", 0x000404], "Box-Ruins2": [[0x00380000, 0x01024C], [0x00380000, 0x030E17]],
["13/2147483648", 0x030E1B], "Box-Ruins3": [[0x00D00000, 0x000905], [0x00D00000, 0x000405], [0x00380000, 0x01024B]],
["13/2147483648", 0x030E1D],
["13/2147483648", 0x030E1F],
["7/1073741824", 0x030E17],
["7/1073741824", 0x01024B]
],
"Box-DarkFalz": [["1/268435456", 0x01024C]],
"Box-Lobby": [["1/268435456", 0x01024D]],
"Box-Mine1": [["3/536870912", 0x020000]],
"Box-Pioneer2": [
["7/2147483648", 0x000904],
["7/2147483648", 0x000904]
],
"Box-Ruins1": [
["3/536870912", 0x030E1E],
["13/2147483648", 0x030E18],
["13/2147483648", 0x030E19]
],
"Box-VolOpt": [
["5/1073741824", 0x000905],
["7/2147483648", 0x000405],
["7/1073741824", 0x01024C],
["7/2147483648", 0x01024C],
["1/268435456", 0x030F00],
["13/2147483648", 0x030E1A]
],
"CANADINE": [["1/128", 0x000605]], "CANADINE": [["1/128", 0x000605]],
"CANADINE_GROUP": [["1/128", 0x000605]], "CANADINE_GROUP": [["1/128", 0x000605]],
"CANANE": [["7/256", 0x000405]], "CANANE": [["7/256", 0x000405]],
@@ -3269,6 +3244,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["1/128", 0x000B04]], "BARBAROUS_WOLF": [["1/128", 0x000B04]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000404], ["9/4096", 0x000404],
["9/4096", 0x000B02], ["9/4096", 0x000B02],
@@ -3326,6 +3302,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002600]], "LOVE_RAPPY": [["7/8", 0x002600]],
"MERICAROL": [["7/256", 0x000406]], "MERICAROL": [["7/256", 0x000406]],
"MERICARAND": [["7/256", 0x000406]],
"MERICUS": [["7/256", 0x000406]], "MERICUS": [["7/256", 0x000406]],
"MERIKLE": [["7/256", 0x000406]], "MERIKLE": [["7/256", 0x000406]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3349,6 +3326,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["1/128", 0x000305]], "BARBAROUS_WOLF": [["1/128", 0x000305]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000704], ["9/4096", 0x000704],
["9/4096", 0x000304] ["9/4096", 0x000304]
@@ -3403,6 +3381,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000706]], "MERICAROL": [["7/256", 0x000706]],
"MERICARAND": [["7/256", 0x000706]],
"MERICUS": [["7/256", 0x000706]], "MERICUS": [["7/256", 0x000706]],
"MERIKLE": [["7/256", 0x000706]], "MERIKLE": [["7/256", 0x000706]],
"MERILLIA": [["1/128", 0x000606]], "MERILLIA": [["1/128", 0x000606]],
@@ -3426,6 +3405,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["1/128", 0x000205]], "BARBAROUS_WOLF": [["1/128", 0x000205]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000304], ["9/4096", 0x000304],
["9/4096", 0x000204], ["9/4096", 0x000204],
@@ -3495,6 +3475,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000306]], "MERICAROL": [["7/256", 0x000306]],
"MERICARAND": [["7/256", 0x000306]],
"MERICUS": [["7/256", 0x000306]], "MERICUS": [["7/256", 0x000306]],
"MERIKLE": [["7/256", 0x000306]], "MERIKLE": [["7/256", 0x000306]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3518,6 +3499,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["1/128", 0x000405]], "BARBAROUS_WOLF": [["1/128", 0x000405]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000C03], ["9/4096", 0x000C03],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -3588,6 +3570,7 @@
"LA_DIMENIAN": [["1/128", 0x000A04]], "LA_DIMENIAN": [["1/128", 0x000A04]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000C05]], "MERICAROL": [["7/256", 0x000C05]],
"MERICARAND": [["7/256", 0x000C05]],
"MERICUS": [["7/256", 0x000C05]], "MERICUS": [["7/256", 0x000C05]],
"MERIKLE": [["7/256", 0x000C05]], "MERIKLE": [["7/256", 0x000C05]],
"MERILLIA": [["1/128", 0x000A04]], "MERILLIA": [["1/128", 0x000A04]],
@@ -3611,6 +3594,7 @@
"Purplenum": { "Purplenum": {
"BARBAROUS_WOLF": [["1/128", 0x000305]], "BARBAROUS_WOLF": [["1/128", 0x000305]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000804], ["9/4096", 0x000804],
["9/4096", 0x000304], ["9/4096", 0x000304],
@@ -3672,6 +3656,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x004900]], "LOVE_RAPPY": [["7/8", 0x004900]],
"MERICAROL": [["7/256", 0x000806]], "MERICAROL": [["7/256", 0x000806]],
"MERICARAND": [["7/256", 0x000806]],
"MERICUS": [["7/256", 0x000806]], "MERICUS": [["7/256", 0x000806]],
"MERIKLE": [["7/256", 0x000806]], "MERIKLE": [["7/256", 0x000806]],
"MERILLIA": [["1/128", 0x000605]], "MERILLIA": [["1/128", 0x000605]],
@@ -3695,6 +3680,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["1/128", 0x000905]], "BARBAROUS_WOLF": [["1/128", 0x000905]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000504], ["9/4096", 0x000504],
["9/4096", 0x000904], ["9/4096", 0x000904],
@@ -3767,6 +3753,7 @@
"LA_DIMENIAN": [["1/128", 0x000A04]], "LA_DIMENIAN": [["1/128", 0x000A04]],
"LOVE_RAPPY": [["7/8", 0x002600]], "LOVE_RAPPY": [["7/8", 0x002600]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x000506]], "MERICUS": [["7/256", 0x000506]],
"MERIKLE": [["7/256", 0x000506]], "MERIKLE": [["7/256", 0x000506]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3790,6 +3777,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["1/128", 0x000705]], "BARBAROUS_WOLF": [["1/128", 0x000705]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000204], ["9/4096", 0x000204],
["9/4096", 0x000704], ["9/4096", 0x000704],
@@ -3846,6 +3834,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x000206]], "MERICAROL": [["7/256", 0x000206]],
"MERICARAND": [["7/256", 0x000206]],
"MERICUS": [["7/256", 0x000206]], "MERICUS": [["7/256", 0x000206]],
"MERIKLE": [["7/256", 0x000206]], "MERIKLE": [["7/256", 0x000206]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3869,6 +3858,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["1/128", 0x000405]], "BARBAROUS_WOLF": [["1/128", 0x000405]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000904], ["9/4096", 0x000904],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -3930,6 +3920,7 @@
"LA_DIMENIAN": [["1/128", 0x000105]], "LA_DIMENIAN": [["1/128", 0x000105]],
"LOVE_RAPPY": [["7/8", 0x002000]], "LOVE_RAPPY": [["7/8", 0x002000]],
"MERICAROL": [["7/256", 0x000906]], "MERICAROL": [["7/256", 0x000906]],
"MERICARAND": [["7/256", 0x000906]],
"MERICUS": [["7/256", 0x000906]], "MERICUS": [["7/256", 0x000906]],
"MERIKLE": [["7/256", 0x000906]], "MERIKLE": [["7/256", 0x000906]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -3953,6 +3944,7 @@
"Whitill": { "Whitill": {
"BARBAROUS_WOLF": [["1/128", 0x000805]], "BARBAROUS_WOLF": [["1/128", 0x000805]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000504], ["9/4096", 0x000504],
["9/4096", 0x000804], ["9/4096", 0x000804],
@@ -4018,6 +4010,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x000506]], "MERICUS": [["7/256", 0x000506]],
"MERIKLE": [["7/256", 0x000506]], "MERIKLE": [["7/256", 0x000506]],
"MERILLIA": [["1/128", 0x000605]], "MERILLIA": [["1/128", 0x000605]],
@@ -4041,6 +4034,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["1/128", 0x000205]], "BARBAROUS_WOLF": [["1/128", 0x000205]],
"BARBA_RAY": [["1/16", 0x000E00]], "BARBA_RAY": [["1/16", 0x000E00]],
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
"Box-JungleNorth": [["7/8192", 0x01024C]], "Box-JungleNorth": [["7/8192", 0x01024C]],
"Box-Mountain": [["1/256", 0x020000]], "Box-Mountain": [["1/256", 0x020000]],
"Box-JungleEast": [ "Box-JungleEast": [
@@ -4089,6 +4083,7 @@
"LA_DIMENIAN": [["1/128", 0x000605]], "LA_DIMENIAN": [["1/128", 0x000605]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x000306]], "MERICUS": [["7/256", 0x000306]],
"MERIKLE": [["7/256", 0x000406]], "MERIKLE": [["7/256", 0x000406]],
"MERILLIA": [["1/128", 0x000105]], "MERILLIA": [["1/128", 0x000105]],
@@ -4114,6 +4109,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["9/16384", 0x030A00]], "BARBAROUS_WOLF": [["9/16384", 0x030A00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000402], ["9/16384", 0x000402],
["9/16384", 0x000B01], ["9/16384", 0x000B01],
@@ -4166,6 +4162,7 @@
"LA_DIMENIAN": [["9/16384", 0x030A00]], "LA_DIMENIAN": [["9/16384", 0x030A00]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["9/16384", 0x030A00]], "MERILLIA": [["9/16384", 0x030A00]],
@@ -4185,6 +4182,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["3/8192", 0x030F00]], "BARBAROUS_WOLF": [["3/8192", 0x030F00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000702], ["9/16384", 0x000702],
["9/16384", 0x000302] ["9/16384", 0x000302]
@@ -4235,6 +4233,7 @@
"LA_DIMENIAN": [["9/16384", 0x030B06]], "LA_DIMENIAN": [["9/16384", 0x030B06]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILTAS": [["9/16384", 0x030A00]], "MERILTAS": [["9/16384", 0x030A00]],
@@ -4254,6 +4253,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["9/16384", 0x030A00]], "BARBAROUS_WOLF": [["9/16384", 0x030A00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000302], ["9/16384", 0x000302],
["9/16384", 0x000202], ["9/16384", 0x000202],
@@ -4304,6 +4304,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B05]], "LA_DIMENIAN": [["11/8192", 0x030B05]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B00]], "MERILLIA": [["11/8192", 0x030B00]],
@@ -4325,6 +4326,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["11/8192", 0x030B01]], "BARBAROUS_WOLF": [["11/8192", 0x030B01]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000C01], ["9/16384", 0x000C01],
["9/16384", 0x000402], ["9/16384", 0x000402],
@@ -4388,6 +4390,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B01]], "LA_DIMENIAN": [["11/8192", 0x030B01]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B00]], "MERILLIA": [["11/8192", 0x030B00]],
@@ -4409,6 +4412,7 @@
}, },
"Purplenum": { "Purplenum": {
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000802], ["9/16384", 0x000802],
["9/16384", 0x000302], ["9/16384", 0x000302],
@@ -4463,6 +4467,7 @@
"LA_DIMENIAN": [["9/16384", 0x030A00]], "LA_DIMENIAN": [["9/16384", 0x030A00]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B03]], "MERILLIA": [["11/8192", 0x030B03]],
@@ -4482,6 +4487,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["11/8192", 0x030B01]], "BARBAROUS_WOLF": [["11/8192", 0x030B01]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000502], ["9/16384", 0x000502],
["9/16384", 0x000902], ["9/16384", 0x000902],
@@ -4539,6 +4545,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B01]], "LA_DIMENIAN": [["11/8192", 0x030B01]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILTAS": [["11/8192", 0x030B03]], "MERILTAS": [["11/8192", 0x030B03]],
@@ -4554,6 +4561,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["9/16384", 0x030B06]], "BARBAROUS_WOLF": [["9/16384", 0x030B06]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000202], ["9/16384", 0x000202],
["9/16384", 0x000702], ["9/16384", 0x000702],
@@ -4607,6 +4615,7 @@
"LA_DIMENIAN": [["9/16384", 0x030A00]], "LA_DIMENIAN": [["9/16384", 0x030A00]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILTAS": [["9/16384", 0x030A00]], "MERILTAS": [["9/16384", 0x030A00]],
@@ -4628,6 +4637,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["11/8192", 0x030B00]], "BARBAROUS_WOLF": [["11/8192", 0x030B00]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000902], ["9/16384", 0x000902],
["9/16384", 0x000402], ["9/16384", 0x000402],
@@ -4683,6 +4693,7 @@
"LA_DIMENIAN": [["11/8192", 0x030B01]], "LA_DIMENIAN": [["11/8192", 0x030B01]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["9/16384", 0x030A00]], "MERILLIA": [["9/16384", 0x030A00]],
@@ -4703,6 +4714,7 @@
}, },
"Whitill": { "Whitill": {
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/16384", 0x000502], ["9/16384", 0x000502],
["9/16384", 0x000802], ["9/16384", 0x000802],
@@ -4755,6 +4767,7 @@
"ILL_GILL": [["7/32768", 0x010309]], "ILL_GILL": [["7/32768", 0x010309]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B03]], "MERILLIA": [["11/8192", 0x030B03]],
@@ -4776,6 +4789,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["11/8192", 0x030300]], "BARBAROUS_WOLF": [["11/8192", 0x030300]],
"BARBA_RAY": [["7/8", 0x030500]], "BARBA_RAY": [["7/8", 0x030500]],
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["7/8192", 0x030F00], ["7/8192", 0x030F00],
["7/8192", 0x01024C] ["7/8192", 0x01024C]
@@ -4823,6 +4837,7 @@
"ILL_GILL": [["7/32768", 0x01030D]], "ILL_GILL": [["7/32768", 0x01030D]],
"LOVE_RAPPY": [["7/8", 0x01031C]], "LOVE_RAPPY": [["7/8", 0x01031C]],
"MERICAROL": [["7/8", 0x030500]], "MERICAROL": [["7/8", 0x030500]],
"MERICARAND": [["7/8", 0x030500]],
"MERICUS": [["7/8", 0x030500]], "MERICUS": [["7/8", 0x030500]],
"MERIKLE": [["7/8", 0x030500]], "MERIKLE": [["7/8", 0x030500]],
"MERILLIA": [["11/8192", 0x030B00]], "MERILLIA": [["11/8192", 0x030B00]],
@@ -4846,6 +4861,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["13/4096", 0x002600]], "BARBAROUS_WOLF": [["13/4096", 0x002600]],
"BARBA_RAY": [["7/256", 0x030D15]], "BARBA_RAY": [["7/256", 0x030D15]],
"BARBA_RAY_JOINT": [["7/256", 0x030D15]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000407], ["13/8192", 0x000407],
["7/4096", 0x000B05], ["7/4096", 0x000B05],
@@ -4918,6 +4934,7 @@
"LA_DIMENIAN": [["1/512", 0x010317]], "LA_DIMENIAN": [["1/512", 0x010317]],
"LOVE_RAPPY": [["1/2", 0x005500]], "LOVE_RAPPY": [["1/2", 0x005500]],
"MERICAROL": [["13/4096", 0x005B00]], "MERICAROL": [["13/4096", 0x005B00]],
"MERICARAND": [["13/4096", 0x005B00]],
"MERICUS": [["13/4096", 0x003D00]], "MERICUS": [["13/4096", 0x003D00]],
"MERIKLE": [["13/4096", 0x009500]], "MERIKLE": [["13/4096", 0x009500]],
"MERILLIA": [["1/64", 0x000407]], "MERILLIA": [["1/64", 0x000407]],
@@ -4944,6 +4961,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["1/512", 0x010335]], "BARBAROUS_WOLF": [["1/512", 0x010335]],
"BARBA_RAY": [["7/256", 0x01035F]], "BARBA_RAY": [["7/256", 0x01035F]],
"BARBA_RAY_JOINT": [["7/256", 0x01035F]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000707], ["13/8192", 0x000707],
["7/4096", 0x000306], ["7/4096", 0x000306],
@@ -5014,6 +5032,7 @@
"LA_DIMENIAN": [["1/1024", 0x010229]], "LA_DIMENIAN": [["1/1024", 0x010229]],
"LOVE_RAPPY": [["7/8", 0x01031D]], "LOVE_RAPPY": [["7/8", 0x01031D]],
"MERICAROL": [["13/4096", 0x005600]], "MERICAROL": [["13/4096", 0x005600]],
"MERICARAND": [["13/4096", 0x005600]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x003D00]], "MERIKLE": [["13/4096", 0x003D00]],
"MERILLIA": [["1/64", 0x000707]], "MERILLIA": [["1/64", 0x000707]],
@@ -5040,6 +5059,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["13/4096", 0x002700]], "BARBAROUS_WOLF": [["13/4096", 0x002700]],
"BARBA_RAY": [["7/256", 0x01035E]], "BARBA_RAY": [["7/256", 0x01035E]],
"BARBA_RAY_JOINT": [["7/256", 0x01035E]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000307], ["13/8192", 0x000307],
["7/4096", 0x000206], ["7/4096", 0x000206],
@@ -5112,6 +5132,7 @@
"LA_DIMENIAN": [["1/512", 0x010313]], "LA_DIMENIAN": [["1/512", 0x010313]],
"LOVE_RAPPY": [["1/2", 0x005B00]], "LOVE_RAPPY": [["1/2", 0x005B00]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x010346]], "MERIKLE": [["13/4096", 0x010346]],
"MERILLIA": [["1/64", 0x000307]], "MERILLIA": [["1/64", 0x000307]],
@@ -5137,6 +5158,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["1/512", 0x010320]], "BARBAROUS_WOLF": [["1/512", 0x010320]],
"BARBA_RAY": [["7/256", 0x030D15]], "BARBA_RAY": [["7/256", 0x030D15]],
"BARBA_RAY_JOINT": [["7/256", 0x030D15]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000C06], ["13/8192", 0x000C06],
["7/4096", 0x000406], ["7/4096", 0x000406],
@@ -5215,6 +5237,7 @@
"LA_DIMENIAN": [["1/64", 0x000C06]], "LA_DIMENIAN": [["1/64", 0x000C06]],
"LOVE_RAPPY": [["1/2", 0x005500]], "LOVE_RAPPY": [["1/2", 0x005500]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x005B00]], "MERIKLE": [["13/4096", 0x005B00]],
"MERILLIA": [["13/131072", 0x009305]], "MERILLIA": [["13/131072", 0x009305]],
@@ -5241,6 +5264,7 @@
"Purplenum": { "Purplenum": {
"BARBAROUS_WOLF": [["1/512", 0x01030F]], "BARBAROUS_WOLF": [["1/512", 0x01030F]],
"BARBA_RAY": [["7/256", 0x01035E]], "BARBA_RAY": [["7/256", 0x01035E]],
"BARBA_RAY_JOINT": [["7/256", 0x01035E]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000807], ["13/8192", 0x000807],
["7/4096", 0x000306], ["7/4096", 0x000306],
@@ -5311,6 +5335,7 @@
"LA_DIMENIAN": [["13/4096", 0x004600]], "LA_DIMENIAN": [["13/4096", 0x004600]],
"LOVE_RAPPY": [["1/2", 0x01031D]], "LOVE_RAPPY": [["1/2", 0x01031D]],
"MERICAROL": [["13/131072", 0x001E00]], "MERICAROL": [["13/131072", 0x001E00]],
"MERICARAND": [["13/131072", 0x001E00]],
"MERICUS": [["1/1024", 0x001001]], "MERICUS": [["1/1024", 0x001001]],
"MERIKLE": [["13/4096", 0x009500]], "MERIKLE": [["13/4096", 0x009500]],
"MERILLIA": [["1/64", 0x000307]], "MERILLIA": [["1/64", 0x000307]],
@@ -5337,6 +5362,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["13/4096", 0x001006]], "BARBAROUS_WOLF": [["13/4096", 0x001006]],
"BARBA_RAY": [["7/256", 0x000E02]], "BARBA_RAY": [["7/256", 0x000E02]],
"BARBA_RAY_JOINT": [["7/256", 0x000E02]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000507], ["13/8192", 0x000507],
["7/4096", 0x000107], ["7/4096", 0x000107],
@@ -5409,6 +5435,7 @@
"LA_DIMENIAN": [["13/4096", 0x01030F]], "LA_DIMENIAN": [["13/4096", 0x01030F]],
"LOVE_RAPPY": [["7/8", 0x01031D]], "LOVE_RAPPY": [["7/8", 0x01031D]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x008B02]], "MERICUS": [["13/4096", 0x008B02]],
"MERIKLE": [["13/4096", 0x005E00]], "MERIKLE": [["13/4096", 0x005E00]],
"MERILLIA": [["13/4096", 0x001004]], "MERILLIA": [["13/4096", 0x001004]],
@@ -5434,6 +5461,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["13/4096", 0x002000]], "BARBAROUS_WOLF": [["13/4096", 0x002000]],
"BARBA_RAY": [["11/256", 0x000E02]], "BARBA_RAY": [["11/256", 0x000E02]],
"BARBA_RAY_JOINT": [["11/256", 0x000E02]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000207], ["13/8192", 0x000207],
["7/4096", 0x000706], ["7/4096", 0x000706],
@@ -5506,6 +5534,7 @@
"LA_DIMENIAN": [["13/4096", 0x010224]], "LA_DIMENIAN": [["13/4096", 0x010224]],
"LOVE_RAPPY": [["1/2", 0x006900]], "LOVE_RAPPY": [["1/2", 0x006900]],
"MERICAROL": [["13/4096", 0x002F00]], "MERICAROL": [["13/4096", 0x002F00]],
"MERICARAND": [["13/4096", 0x002F00]],
"MERICUS": [["13/4096", 0x006B00]], "MERICUS": [["13/4096", 0x006B00]],
"MERIKLE": [["13/4096", 0x003D00]], "MERIKLE": [["13/4096", 0x003D00]],
"MERILLIA": [["1/64", 0x000E01]], "MERILLIA": [["1/64", 0x000E01]],
@@ -5532,6 +5561,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["13/4096", 0x010224]], "BARBAROUS_WOLF": [["13/4096", 0x010224]],
"BARBA_RAY": [["7/256", 0x001402]], "BARBA_RAY": [["7/256", 0x001402]],
"BARBA_RAY_JOINT": [["7/256", 0x001402]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000907], ["13/8192", 0x000907],
["7/4096", 0x000406], ["7/4096", 0x000406],
@@ -5610,6 +5640,7 @@
"LA_DIMENIAN": [["13/4096", 0x002000]], "LA_DIMENIAN": [["13/4096", 0x002000]],
"LOVE_RAPPY": [["1/2", 0x001006]], "LOVE_RAPPY": [["1/2", 0x001006]],
"MERICAROL": [["13/4096", 0x003B00]], "MERICAROL": [["13/4096", 0x003B00]],
"MERICARAND": [["13/4096", 0x003B00]],
"MERICUS": [["13/4096", 0x004600]], "MERICUS": [["13/4096", 0x004600]],
"MERIKLE": [["13/4096", 0x001101]], "MERIKLE": [["13/4096", 0x001101]],
"MERILLIA": [["1/512", 0x01011D]], "MERILLIA": [["1/512", 0x01011D]],
@@ -5636,6 +5667,7 @@
"Whitill": { "Whitill": {
"BARBAROUS_WOLF": [["1/64", 0x000807]], "BARBAROUS_WOLF": [["1/64", 0x000807]],
"BARBA_RAY": [["13/512", 0x01035E]], // Schtserv's original table has ["7/256", 0x01035D]] (Heavenly/HP) here "BARBA_RAY": [["13/512", 0x01035E]], // Schtserv's original table has ["7/256", 0x01035D]] (Heavenly/HP) here
"BARBA_RAY_JOINT": [["13/512", 0x01035E]], // Schtserv's original table has ["7/256", 0x01035D]] (Heavenly/HP) here
"Box-JungleNorth": [ "Box-JungleNorth": [
["13/8192", 0x000507], ["13/8192", 0x000507],
["7/4096", 0x000806], ["7/4096", 0x000806],
@@ -5706,6 +5738,7 @@
"LA_DIMENIAN": [["1/64", 0x000D01]], "LA_DIMENIAN": [["1/64", 0x000D01]],
"LOVE_RAPPY": [["1/2", 0x010132]], "LOVE_RAPPY": [["1/2", 0x010132]],
"MERICAROL": [["1/64", 0x008902]], "MERICAROL": [["1/64", 0x008902]],
"MERICARAND": [["1/64", 0x008902]],
"MERICUS": [["1/64", 0x008B02]], "MERICUS": [["1/64", 0x008B02]],
"MERIKLE": [["13/4096", 0x002F00]], "MERIKLE": [["13/4096", 0x002F00]],
"MERILLIA": [["1/64", 0x000807]], "MERILLIA": [["1/64", 0x000807]],
@@ -5732,6 +5765,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["1/512", 0x01030F]], "BARBAROUS_WOLF": [["1/512", 0x01030F]],
"BARBA_RAY": [["7/256", 0x000F02]], "BARBA_RAY": [["7/256", 0x000F02]],
"BARBA_RAY_JOINT": [["7/256", 0x000F02]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["1/1024", 0x000107], ["1/1024", 0x000107],
["1/1024", 0x000607], ["1/1024", 0x000607],
@@ -5801,6 +5835,7 @@
"LA_DIMENIAN": [["13/4096", 0x010225]], "LA_DIMENIAN": [["13/4096", 0x010225]],
"LOVE_RAPPY": [["1/2", 0x005B00]], "LOVE_RAPPY": [["1/2", 0x005B00]],
"MERICAROL": [["13/4096", 0x008902]], "MERICAROL": [["13/4096", 0x008902]],
"MERICARAND": [["13/4096", 0x008902]],
"MERICUS": [["13/4096", 0x002F00]], "MERICUS": [["13/4096", 0x002F00]],
"MERIKLE": [["13/4096", 0x005E00]], "MERIKLE": [["13/4096", 0x005E00]],
"MERILLIA": [["1/64", 0x000C06]], "MERILLIA": [["1/64", 0x000C06]],
@@ -5829,6 +5864,7 @@
"Bluefull": { "Bluefull": {
"BARBAROUS_WOLF": [["1/128", 0x000406]], "BARBAROUS_WOLF": [["1/128", 0x000406]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000405], ["9/4096", 0x000405],
["9/4096", 0x000B03], ["9/4096", 0x000B03],
@@ -5897,6 +5933,7 @@
"LA_DIMENIAN": [["1/128", 0x000B05]], "LA_DIMENIAN": [["1/128", 0x000B05]],
"LOVE_RAPPY": [["7/8", 0x000407]], "LOVE_RAPPY": [["7/8", 0x000407]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x010125]], "MERIKLE": [["7/256", 0x010125]],
"MERILLIA": [["1/128", 0x000406]], "MERILLIA": [["1/128", 0x000406]],
@@ -5920,6 +5957,7 @@
"Greennill": { "Greennill": {
"BARBAROUS_WOLF": [["1/128", 0x000706]], "BARBAROUS_WOLF": [["1/128", 0x000706]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000705], ["9/4096", 0x000705],
["9/4096", 0x000304], ["9/4096", 0x000304],
@@ -5988,6 +6026,7 @@
"LA_DIMENIAN": [["1/128", 0x000706]], "LA_DIMENIAN": [["1/128", 0x000706]],
"LOVE_RAPPY": [["7/8", 0x000707]], "LOVE_RAPPY": [["7/8", 0x000707]],
"MERICAROL": [["7/256", 0x005600]], "MERICAROL": [["7/256", 0x005600]],
"MERICARAND": [["7/256", 0x005600]],
"MERICUS": [["7/256", 0x008C01]], "MERICUS": [["7/256", 0x008C01]],
"MERIKLE": [["7/256", 0x000707]], "MERIKLE": [["7/256", 0x000707]],
"MERILLIA": [["1/128", 0x000706]], "MERILLIA": [["1/128", 0x000706]],
@@ -6011,6 +6050,7 @@
"Oran": { "Oran": {
"BARBAROUS_WOLF": [["1/128", 0x000306]], "BARBAROUS_WOLF": [["1/128", 0x000306]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000305], ["9/4096", 0x000305],
["9/4096", 0x000204], ["9/4096", 0x000204],
@@ -6081,6 +6121,7 @@
"LA_DIMENIAN": [["1/128", 0x000306]], "LA_DIMENIAN": [["1/128", 0x000306]],
"LOVE_RAPPY": [["7/8", 0x010219]], "LOVE_RAPPY": [["7/8", 0x010219]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000307]], "MERIKLE": [["7/256", 0x000307]],
"MERILLIA": [["1/128", 0x000306]], "MERILLIA": [["1/128", 0x000306]],
@@ -6104,6 +6145,7 @@
"Pinkal": { "Pinkal": {
"BARBAROUS_WOLF": [["1/128", 0x000C05]], "BARBAROUS_WOLF": [["1/128", 0x000C05]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000C04], ["9/4096", 0x000C04],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -6178,6 +6220,7 @@
"LA_DIMENIAN": [["1/128", 0x000C05]], "LA_DIMENIAN": [["1/128", 0x000C05]],
"LOVE_RAPPY": [["7/8", 0x002300]], "LOVE_RAPPY": [["7/8", 0x002300]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x005600]], "MERIKLE": [["7/256", 0x005600]],
"MERILLIA": [["1/128", 0x000406]], "MERILLIA": [["1/128", 0x000406]],
@@ -6201,6 +6244,7 @@
"Purplenum": { "Purplenum": {
"BARBAROUS_WOLF": [["1/128", 0x000806]], "BARBAROUS_WOLF": [["1/128", 0x000806]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000805], ["9/4096", 0x000805],
["9/4096", 0x000304], ["9/4096", 0x000304],
@@ -6271,6 +6315,7 @@
"LA_DIMENIAN": [["1/128", 0x000E00]], "LA_DIMENIAN": [["1/128", 0x000E00]],
"LOVE_RAPPY": [["7/8", 0x000807]], "LOVE_RAPPY": [["7/8", 0x000807]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000307]], "MERIKLE": [["7/256", 0x000307]],
"MERILLIA": [["1/128", 0x000306]], "MERILLIA": [["1/128", 0x000306]],
@@ -6294,6 +6339,7 @@
"Redria": { "Redria": {
"BARBAROUS_WOLF": [["1/128", 0x000906]], "BARBAROUS_WOLF": [["1/128", 0x000906]],
"BARBA_RAY": [["3/32", 0x000E01]], "BARBA_RAY": [["3/32", 0x000E01]],
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000504], ["9/4096", 0x000504],
["9/4096", 0x000904], ["9/4096", 0x000904],
@@ -6362,6 +6408,7 @@
"LA_DIMENIAN": [["1/128", 0x000906]], "LA_DIMENIAN": [["1/128", 0x000906]],
"LOVE_RAPPY": [["7/8", 0x01031D]], "LOVE_RAPPY": [["7/8", 0x01031D]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x000F01]], "MERICUS": [["7/256", 0x000F01]],
"MERIKLE": [["7/256", 0x001004]], "MERIKLE": [["7/256", 0x001004]],
"MERILLIA": [["1/128", 0x000506]], "MERILLIA": [["1/128", 0x000506]],
@@ -6385,6 +6432,7 @@
"Skyly": { "Skyly": {
"BARBAROUS_WOLF": [["1/128", 0x000206]], "BARBAROUS_WOLF": [["1/128", 0x000206]],
"BARBA_RAY": [["3/32", 0x000E01]], "BARBA_RAY": [["3/32", 0x000E01]],
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000205], ["9/4096", 0x000205],
["9/4096", 0x000704], ["9/4096", 0x000704],
@@ -6455,6 +6503,7 @@
"LA_DIMENIAN": [["1/128", 0x000206]], "LA_DIMENIAN": [["1/128", 0x000206]],
"LOVE_RAPPY": [["7/8", 0x000207]], "LOVE_RAPPY": [["7/8", 0x000207]],
"MERICAROL": [["7/256", 0x005601]], "MERICAROL": [["7/256", 0x005601]],
"MERICARAND": [["7/256", 0x005601]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000207]], "MERIKLE": [["7/256", 0x000207]],
"MERILLIA": [["1/128", 0x000205]], "MERILLIA": [["1/128", 0x000205]],
@@ -6478,6 +6527,7 @@
"Viridia": { "Viridia": {
"BARBAROUS_WOLF": [["1/128", 0x010219]], "BARBAROUS_WOLF": [["1/128", 0x010219]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000905], ["9/4096", 0x000905],
["9/4096", 0x000404], ["9/4096", 0x000404],
@@ -6548,6 +6598,7 @@
"LA_DIMENIAN": [["1/64", 0x000406]], "LA_DIMENIAN": [["1/64", 0x000406]],
"LOVE_RAPPY": [["7/8", 0x000907]], "LOVE_RAPPY": [["7/8", 0x000907]],
"MERICAROL": [["7/256", 0x008901]], "MERICAROL": [["7/256", 0x008901]],
"MERICARAND": [["7/256", 0x008901]],
"MERICUS": [["7/256", 0x008B01]], "MERICUS": [["7/256", 0x008B01]],
"MERIKLE": [["7/256", 0x000407]], "MERIKLE": [["7/256", 0x000407]],
"MERILLIA": [["1/128", 0x000906]], "MERILLIA": [["1/128", 0x000906]],
@@ -6571,6 +6622,7 @@
"Whitill": { "Whitill": {
"BARBAROUS_WOLF": [["1/128", 0x000506]], "BARBAROUS_WOLF": [["1/128", 0x000506]],
"BARBA_RAY": [["3/32", 0x008901]], "BARBA_RAY": [["3/32", 0x008901]],
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000505], ["9/4096", 0x000505],
["9/4096", 0x000804], ["9/4096", 0x000804],
@@ -6643,6 +6695,7 @@
"LA_DIMENIAN": [["1/128", 0x000806]], "LA_DIMENIAN": [["1/128", 0x000806]],
"LOVE_RAPPY": [["7/8", 0x010222]], "LOVE_RAPPY": [["7/8", 0x010222]],
"MERICAROL": [["7/256", 0x000506]], "MERICAROL": [["7/256", 0x000506]],
"MERICARAND": [["7/256", 0x000506]],
"MERICUS": [["7/256", 0x005601]], "MERICUS": [["7/256", 0x005601]],
"MERIKLE": [["7/256", 0x008901]], "MERIKLE": [["7/256", 0x008901]],
"MERILLIA": [["1/128", 0x000506]], "MERILLIA": [["1/128", 0x000506]],
@@ -6666,6 +6719,7 @@
"Yellowboze": { "Yellowboze": {
"BARBAROUS_WOLF": [["1/128", 0x000806]], "BARBAROUS_WOLF": [["1/128", 0x000806]],
"BARBA_RAY": [["3/32", 0x000F01]], "BARBA_RAY": [["3/32", 0x000F01]],
"BARBA_RAY_JOINT": [["3/32", 0x000F01]],
"Box-JungleNorth": [ "Box-JungleNorth": [
["9/4096", 0x000105], ["9/4096", 0x000105],
["9/4096", 0x000605], ["9/4096", 0x000605],
@@ -6738,6 +6792,7 @@
"LA_DIMENIAN": [["1/128", 0x010225]], "LA_DIMENIAN": [["1/128", 0x010225]],
"LOVE_RAPPY": [["7/8", 0x000906]], "LOVE_RAPPY": [["7/8", 0x000906]],
"MERICAROL": [["7/256", 0x003B00]], "MERICAROL": [["7/256", 0x003B00]],
"MERICARAND": [["7/256", 0x003B00]],
"MERICUS": [["7/256", 0x010125]], "MERICUS": [["7/256", 0x010125]],
"MERIKLE": [["7/256", 0x008B01]], "MERIKLE": [["7/256", 0x008B01]],
"MERILLIA": [["1/128", 0x000106]], "MERILLIA": [["1/128", 0x000106]],
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1,3 +1,2 @@
{ {
"EnabledIf": "!F_0065 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-1
View File
@@ -1,3 +1,2 @@
{ {
"EnabledIf": "!F_0067 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9",
"EnabledIf": "!F_0069 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-1
View File
@@ -1,3 +1,2 @@
{ {
"EnabledIf": "!F_006B || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B",
"EnabledIf": "!F_006D || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B",
"EnabledIf": "!F_006F || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B",
"EnabledIf": "!F_0071 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0071",
"EnabledIf": "!F_0073 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B",
"EnabledIf": "!F_0075 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9",
"EnabledIf": "!F_0077 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9",
"EnabledIf": "!F_0079 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0077 && F_0079 && F_007F && F_0085",
"EnabledIf": "!F_007B || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_007B",
"EnabledIf": "!F_007D || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9",
"EnabledIf": "!F_007F || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0077 && F_0079 && F_007F && F_0085",
"EnabledIf": "!F_0081 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_0201",
"EnabledIf": "!F_0083 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_01F9",
"EnabledIf": "!F_0085 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_0201",
"EnabledIf": "!F_0087 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_0209",
"EnabledIf": "!F_0089 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_0201",
"EnabledIf": "!F_008B || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_008B",
"EnabledIf": "!F_008D || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_008D && F_0209",
"EnabledIf": "!F_008F || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_006F && F_0209",
"EnabledIf": "!F_0091 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_0209",
"EnabledIf": "!F_0093 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-2
View File
@@ -1,4 +1,2 @@
{ {
"AvailableIf": "F_0065 && F_0067 && F_006B && F_008D && F_0209",
"EnabledIf": "!F_0095 || (F_0065 && F_0067 && F_0069 && F_006B && F_006D && F_006F && F_0071 && F_0073 && F_0075 && F_0077 && F_0079 && F_007B && F_007D && F_007F && F_0081 && F_0083 && F_0085 && F_0087 && F_0089 && F_008B && F_008D && F_008F && F_0091 && F_0093 && F_0095)",
} }
-1
View File
@@ -1,3 +1,2 @@
{ {
"AvailableIf": "F_0073 && (V_NumPlayers == 1)",
} }
@@ -1,4 +1,5 @@
### use psov2 crypt ### use psov2 crypt
### use legacy item random behavior
I 35932 2025-05-22 21:56:44 - [C-1] Channel name updated: C-1 @ ip:10.37.129.2:49620 I 35932 2025-05-22 21:56:44 - [C-1] Channel name updated: C-1 @ ip:10.37.129.2:49620
I 35932 2025-05-22 21:56:44 - [C-1] Created I 35932 2025-05-22 21:56:44 - [C-1] Created
I 35932 2025-05-22 21:56:44 - [GameServer] Client connected: C-1 via TG-9300-PC_V2-pc-game_server I 35932 2025-05-22 21:56:44 - [GameServer] Client connected: C-1 via TG-9300-PC_V2-pc-game_server
+1
View File
@@ -1,4 +1,5 @@
### use psov2 crypt ### use psov2 crypt
### use legacy item random behavior
I 39471 2025-05-21 23:39:20 - [IPStackSimulator] Virtual network N-2 connected via T-IPS-5059 I 39471 2025-05-21 23:39:20 - [IPStackSimulator] Virtual network N-2 connected via T-IPS-5059
I 39471 2025-05-21 23:39:20 - [IPStackSimulator] Client opened TCP connection 23232323238C062D (10.0.1.535:1581 -> 35.35.35.35:9100) (acked_server_seq=BD656BE7, next_client_seq=4F6748DF) I 39471 2025-05-21 23:39:20 - [IPStackSimulator] Client opened TCP connection 23232323238C062D (10.0.1.535:1581 -> 35.35.35.35:9100) (acked_server_seq=BD656BE7, next_client_seq=4F6748DF)
I 39471 2025-05-21 23:39:20 - [C-9] Channel name updated: C-9 @ ipss:N-2:127.0.0.1:57072 I 39471 2025-05-21 23:39:20 - [C-9] Channel name updated: C-9 @ ipss:N-2:127.0.0.1:57072
File diff suppressed because it is too large Load Diff