Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
f05e68492d
|
|||
| 7f68d41bac | |||
| 75e7232096 | |||
| 7a29b39771 | |||
| cfcb56b13f | |||
| 9e6740b778 | |||
| 590f937959 | |||
| 31abc24e81 | |||
| 507fbf0451 | |||
| 1fa660129d | |||
| 67082f7b6b | |||
| b34c9a7c88 | |||
| 87e85932a4 | |||
| b704d827ed | |||
| 598ecf88e3 | |||
| a05971017d | |||
| b7819413b0 | |||
| 80e4b0e6fe | |||
| daee47b722 | |||
| 5724fb9a12 | |||
| 983753f840 | |||
| 53d2318873 | |||
| 83291d5501 | |||
| 55be92a56f | |||
| 6a23e5da0a | |||
| 4571cf7fdc | |||
| 4e3549ba6b | |||
| 3cbf64dda2 | |||
| 382bc6b7ce | |||
| e05991ffb3 | |||
| ffda97222d | |||
| 8f21604367 | |||
| 4045504b61 | |||
| 4aad1514c2 |
+12
-1
@@ -3,6 +3,7 @@
|
||||
|
||||
# Build products
|
||||
newserv
|
||||
newserv.exe
|
||||
src/Revision.cc
|
||||
|
||||
# CMake files
|
||||
@@ -37,12 +38,22 @@ system/teams/*.json
|
||||
# Files fuzziqersoftware uses that don't make sense to be committed to the main
|
||||
# repository
|
||||
*.dec
|
||||
*.WIP-s
|
||||
files
|
||||
make_release.py
|
||||
notes-private
|
||||
old-khyller
|
||||
old-newserv
|
||||
release
|
||||
release.zip
|
||||
all-quests
|
||||
system/dol
|
||||
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
@@ -134,11 +134,12 @@ set(SOURCES
|
||||
|
||||
add_executable(newserv ${SOURCES})
|
||||
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)
|
||||
target_compile_definitions(newserv PUBLIC -DWINVER=0x0A00 -D_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)
|
||||
target_compile_definitions(newserv PUBLIC WINVER=0x0A00 _WIN32_WINNT=0x0A00)
|
||||
target_compile_options(newserv PRIVATE -Wa,-mbig-obj -Wno-mismatched-new-delete)
|
||||
target_link_options(newserv PRIVATE -static -static-libgcc -static-libstdc++)
|
||||
target_link_libraries(newserv ws2_32 mswsock bcrypt iphlpapi)
|
||||
endif()
|
||||
add_dependencies(newserv newserv-Revision-cc)
|
||||
|
||||
|
||||
@@ -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.
|
||||
* `$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.
|
||||
* `$allrare`: Make all enemies and boxes drop their rare items every time.
|
||||
* `$gc` (non-proxy only): Send your own Guild Card 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.
|
||||
* `$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.
|
||||
|
||||
Executable
+67
@@ -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())
|
||||
@@ -1074,3 +1074,37 @@ Enable quest board menu in free play (for use with the above code)
|
||||
3OJ3 => 04262E44 38600001
|
||||
3OJ4 => 04263EB8 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)
|
||||
|
||||
@@ -538,8 +538,8 @@ fparam4 = TODO: 3OE1:802D7490; NNF: Jump cooldown time (Higher value = less wait
|
||||
iparam1 = TODO: 3OE1:802D7484
|
||||
|
||||
MOVEMENT DATA 40 (MORFOS)
|
||||
fparam1 = TODO: 3OE1:80335A98, 3OE1:80335DBC; NNF: Laser speed (also affects hitbox property - needs retest with others for opinion).
|
||||
fparam2 = TODO: 3OE1:80335ADC; NNF: Laser damage.
|
||||
fparam1 = laser speed; hitbox radius is fparam1 * 1.5
|
||||
fparam2 = laser damage
|
||||
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.
|
||||
iparam3 = TODO: 3OE1:80331F04; NNF: Interval in frames of attacks
|
||||
|
||||
+24
-5
@@ -2227,6 +2227,15 @@ ChatCommandDefinition cc_fastkill(
|
||||
}
|
||||
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(
|
||||
{"$rand"},
|
||||
@@ -2349,14 +2358,18 @@ ChatCommandDefinition cc_saverec(
|
||||
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) {
|
||||
a.check_debug_enabled();
|
||||
}
|
||||
string data = phosg::parse_data_string(a.text);
|
||||
data.resize((data.size() + 3) & (~3));
|
||||
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 (a.c->proxy_session) {
|
||||
@@ -2371,13 +2384,19 @@ static asio::awaitable<void> command_send_command(const Args& a, bool to_client,
|
||||
ChatCommandDefinition cc_sb(
|
||||
{"$sb"},
|
||||
+[](const Args& a) -> asio::awaitable<void> {
|
||||
return command_send_command(a, true, true);
|
||||
return command_send_command(a, true, true, false);
|
||||
});
|
||||
|
||||
ChatCommandDefinition cc_sc(
|
||||
{"$sc"},
|
||||
+[](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(
|
||||
@@ -2571,7 +2590,7 @@ ChatCommandDefinition cc_spec(
|
||||
ChatCommandDefinition cc_ss(
|
||||
{"$ss"},
|
||||
+[](const Args& a) -> asio::awaitable<void> {
|
||||
return command_send_command(a, false, true);
|
||||
return command_send_command(a, false, true, false);
|
||||
});
|
||||
|
||||
ChatCommandDefinition cc_stat(
|
||||
|
||||
+3
-3
@@ -1008,9 +1008,9 @@ void Client::load_all_files() {
|
||||
auto stack_limits = s->item_stack_limits(this->version());
|
||||
|
||||
this->blocked_senders.clear();
|
||||
for (size_t z = 0; z < this->guild_card_data->blocked.size(); z++) {
|
||||
if (this->guild_card_data->blocked[z].present) {
|
||||
this->blocked_senders.emplace(this->guild_card_data->blocked[z].guild_card_number);
|
||||
for (size_t z = 0; z < this->guild_card_data->blocked_senders.size(); z++) {
|
||||
if (this->guild_card_data->blocked_senders[z].present) {
|
||||
this->blocked_senders.emplace(this->guild_card_data->blocked_senders[z].guild_card_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ public:
|
||||
INFINITE_HP_ENABLED = 0x0000000040000000,
|
||||
INFINITE_TP_ENABLED = 0x0000000080000000,
|
||||
FAST_KILLS_ENABLED = 0x0000000100000000,
|
||||
ALL_RARES_ENABLED = 0x0000100000000000,
|
||||
DEBUG_ENABLED = 0x0000000200000000,
|
||||
ITEM_DROP_NOTIFICATIONS_1 = 0x0000000400000000,
|
||||
ITEM_DROP_NOTIFICATIONS_2 = 0x0000000800000000,
|
||||
@@ -139,6 +140,7 @@ public:
|
||||
std::shared_ptr<Channel> channel;
|
||||
std::shared_ptr<PSOBBMultiKeyDetectorEncryption> bb_detector_crypt;
|
||||
ServerBehavior server_behavior;
|
||||
uint16_t listener_port = 0;
|
||||
std::unordered_map<std::string, std::function<void()>> disconnect_hooks;
|
||||
uint64_t ping_start_time = 0;
|
||||
|
||||
@@ -149,6 +151,7 @@ public:
|
||||
uint8_t override_lobby_event = 0xFF; // FF = no override
|
||||
uint8_t override_lobby_number = 0x80; // 80 = no override
|
||||
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;
|
||||
VectorXYZF pos;
|
||||
uint32_t floor = 0x0F;
|
||||
|
||||
+243
-191
@@ -144,7 +144,7 @@ struct S_ServerInit_Patch_02 {
|
||||
} __packed_ws__(S_ServerInit_Patch_02, 0x48);
|
||||
|
||||
// 02 (C->S): Encryption started
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 03: Invalid command
|
||||
|
||||
@@ -163,7 +163,7 @@ struct C_Login_Patch_04 {
|
||||
} __packed_ws__(C_Login_Patch_04, 0x6C);
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
|
||||
// 0A (S->C): Exit directory
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 0B (S->C): Start patch session and go to patch root directory
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 0C (S->C): File checksum request
|
||||
|
||||
@@ -216,7 +216,7 @@ struct S_FileChecksumRequest_Patch_0C {
|
||||
} __packed_ws__(S_FileChecksumRequest_Patch_0C, 0x24);
|
||||
|
||||
// 0D (S->C): End of file checksum requests
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 0E: Invalid command
|
||||
|
||||
@@ -229,7 +229,7 @@ struct C_FileInformation_Patch_0F {
|
||||
} __packed_ws__(C_FileInformation_Patch_0F, 0x0C);
|
||||
|
||||
// 10 (C->S): End of file information command list
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 11 (S->C): Start file downloads
|
||||
|
||||
@@ -239,7 +239,7 @@ struct S_StartFileDownloads_Patch_11 {
|
||||
} __packed_ws__(S_StartFileDownloads_Patch_11, 0x08);
|
||||
|
||||
// 12 (S->C): End patch session successfully
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 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
|
||||
@@ -293,10 +293,10 @@ struct SC_TextHeader_01_06_11_B0_EE {
|
||||
// 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
|
||||
// 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 11/2000 and DCv1 clients will respond with 93.
|
||||
// - DCv2, PCv2, and GC NTE clients will respond with an 9A, 9D, or 9E.
|
||||
// - V3 clients will respond with 9A or 9E command.
|
||||
// - DC NTE clients will respond with an 8B command.
|
||||
// - DC 11/2000 and DCv1 clients will respond with a 93 command.
|
||||
// - DCv2, PCv2, and GC NTE clients will respond with a 9A, 9D, 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 above text is required on all versions that use this command, including those versions that don't run on the
|
||||
// DreamCast.)
|
||||
@@ -494,16 +494,16 @@ struct S_MenuItemT {
|
||||
// - On BB, 0x40/0x41 mean Episodes 1/2 as on GC, and 0x43 means Episode 4.
|
||||
uint8_t episode = 0;
|
||||
// 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)
|
||||
// 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 = Disabled (BB only; used for solo games)
|
||||
// 10 = Is battle mode
|
||||
// 20 = Is challenge mode
|
||||
// 40 = Is v2 only (DCv2/PC); game name renders in orange
|
||||
// 40 = Is Episode 1 (V3/BB)
|
||||
// 80 = Is Episode 2 (V3/BB)
|
||||
// C0 = Is Episode 4 (BB)
|
||||
// 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)
|
||||
// 04 = In battle (Episode 3 only; a sword icon appears in the menu)
|
||||
// 04 = Disabled (BB only; used for solo games)
|
||||
// 10 = Is battle mode
|
||||
// 20 = Is challenge mode
|
||||
// 40 = Is v2 only (DCv2/PC); game name renders in orange
|
||||
// 40 = Is Episode 1 (V3/BB)
|
||||
// 80 = Is Episode 2 (V3/BB)
|
||||
// C0 = Is Episode 4 (BB)
|
||||
uint8_t flags = 0;
|
||||
} __attribute__((packed));
|
||||
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
|
||||
// Internal name: SndGameList
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 08 (S->C): Game list
|
||||
// Internal name: RcvGameList
|
||||
@@ -530,6 +530,7 @@ struct C_MenuItemInfoRequest_09 {
|
||||
le_uint32_t item_id = 0;
|
||||
} __packed_ws__(C_MenuItemInfoRequest_09, 8);
|
||||
|
||||
// 0A: Invalid command
|
||||
// 0B: Invalid command
|
||||
|
||||
// 0C (C->S): Create game (DCv1)
|
||||
@@ -709,10 +710,10 @@ struct C_WriteFileConfirmation_V3_BB_13_A7 {
|
||||
// Internal name: RcvPsoRegistConnectV2
|
||||
// Same format as 02 command, but a different copyright: "DreamCast Port Map. Copyright SEGA Enterprises. 1999"
|
||||
// The response depends on the client's version:
|
||||
// - DC NTE will respond with 8B.
|
||||
// - DC 11/2000 and DCv1 will respond with 90.
|
||||
// - DCv2, PCv2, and GC NTE clients will respond with 9A or 9D.
|
||||
// - V3 (GC/Xbox) clients will respond with a DB command when they receive a 17 command in any online
|
||||
// - DC NTE will respond with an 8B command.
|
||||
// - DC 11/2000 and DCv1 will respond with a 90 command.
|
||||
// - DCv2, PCv2, and GC NTE clients will respond with a 9A or 9D command.
|
||||
// - 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)
|
||||
// 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
|
||||
// 2E: 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
|
||||
// 32: 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
|
||||
// 1D until loading is done.
|
||||
|
||||
struct LobbyFlags_DCNTE {
|
||||
struct LobbyFlagsDCNTE {
|
||||
uint8_t client_id = 0;
|
||||
uint8_t leader_id = 0;
|
||||
uint8_t disable_udp = 1;
|
||||
uint8_t unused = 0;
|
||||
} __packed_ws__(LobbyFlags_DCNTE, 4);
|
||||
} __packed_ws__(LobbyFlagsDCNTE, 4);
|
||||
|
||||
struct LobbyFlags {
|
||||
uint8_t client_id = 0;
|
||||
@@ -1273,7 +1274,7 @@ struct S_JoinLobbyT {
|
||||
return offsetof(S_JoinLobbyT, entries) + used_entries * sizeof(Entry);
|
||||
}
|
||||
} __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_DC_GC_65_67_68_Ep3_EB = S_JoinLobbyT<LobbyFlags, PlayerLobbyDataDCGC, PlayerDispDataDCPCV3>;
|
||||
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.
|
||||
|
||||
// 8A (C->S): Request lobby/game name (except DC NTE)
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 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
|
||||
@@ -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.
|
||||
} __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.
|
||||
|
||||
// 91 (S->C): Start encryption at login server (legacy; non-BB only)
|
||||
@@ -1604,7 +1605,7 @@ struct C_RegisterV1_DC_92 {
|
||||
// Internal name: RcvPsoRegist
|
||||
// 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 {
|
||||
/* 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;
|
||||
} __packed_ws__(C_LoginExtendedV1_DC_93, 0x110);
|
||||
|
||||
// 93 (C->S): Log in (BB)
|
||||
|
||||
struct C_LoginBase_BB_93 {
|
||||
/* 00 */ le_uint32_t player_tag = 0x00010000;
|
||||
/* 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
|
||||
// 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
|
||||
// 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.
|
||||
@@ -1698,7 +1697,7 @@ struct C_CharSaveInfo_DCv2_PC_V3_BB_96 {
|
||||
|
||||
// 97 (S->C): Save to memory card
|
||||
// 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
|
||||
// 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
|
||||
@@ -1718,7 +1717,7 @@ struct C_CharSaveInfo_DCv2_PC_V3_BB_96 {
|
||||
|
||||
// 99 (C->S): Server time accepted
|
||||
// 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
|
||||
// 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.
|
||||
@@ -1763,14 +1762,13 @@ struct C_Login_DC_PC_V3_9A {
|
||||
// 13 = servers under maintenance (118)
|
||||
// Seems like most (all?) of the rest of the codes are "network error" (119).
|
||||
|
||||
// 9B (S->C): Secondary server init (non-BB, non-DCv1)
|
||||
// Behaves exactly the same as 17 (S->C).
|
||||
|
||||
// 9B (S->C): Secondary server init (BB)
|
||||
// Format is the same as 03 (and the client uses the same encryption afterward). The only differences:
|
||||
// 9B (S->C): Secondary server init (DCv2 and later)
|
||||
// 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
|
||||
// differences are:
|
||||
// - 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.".
|
||||
// - 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
|
||||
// Internal name: SndPsoRegist
|
||||
@@ -1826,13 +1824,13 @@ struct C_Login_DC_PC_GC_9D {
|
||||
/* 08 */ be_uint64_t hardware_id;
|
||||
/* 10 */ le_uint32_t sub_version = 0;
|
||||
/* 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
|
||||
/* 18 */ pstring<TextEncoding::ASCII, 0x10> v1_serial_number;
|
||||
/* 28 */ pstring<TextEncoding::ASCII, 0x10> v1_access_key;
|
||||
/* 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
|
||||
/* 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
|
||||
/* B8 */ pstring<TextEncoding::ASCII, 0x10> login_character_name;
|
||||
/* C8 */
|
||||
@@ -1936,7 +1934,7 @@ struct C_ChangeShipOrBlock_A0_A1 {
|
||||
// Same as 07 command.
|
||||
|
||||
// A2 (C->S): Request quest menu
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 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
|
||||
@@ -2014,7 +2012,7 @@ struct S_QuestMenuEntry_BB_A2_A4 {
|
||||
|
||||
// A9 (C->S): Quest menu closed (canceled)
|
||||
// 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
|
||||
// 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.
|
||||
@@ -2148,7 +2146,7 @@ struct S_RankUpdate_Ep3_B7 {
|
||||
} __packed_ws__(S_RankUpdate_Ep3_B7, 0x1C);
|
||||
|
||||
// B7 (C->S): Confirm rank update (Episode 3)
|
||||
// No arguments
|
||||
// No arguments.
|
||||
// The client sends this after it receives a B7 from the server.
|
||||
|
||||
// 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.
|
||||
|
||||
// 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.
|
||||
|
||||
// B8 (C->S): Valid but ignored (BB)
|
||||
@@ -2457,21 +2455,33 @@ struct S_ConfirmTournamentEntry_Ep3_CC {
|
||||
// CF: Invalid command
|
||||
|
||||
// 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
|
||||
// - When both have confirmed, one client (the initiator) sends D0
|
||||
// - The server sends D1 to the other client (the responder)
|
||||
// - The responder sends D0
|
||||
// - When both have confirmed, one client (the initiator) sends D0 with the items it intends to give to the other
|
||||
// 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 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
|
||||
// - 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
|
||||
// - Both clients send the appropriate subcommand to create inventory items
|
||||
// On BB, the flow is similar, except after both D2 commands are received, the server instead handles the rest of the
|
||||
// process - it sends 6x29 commands to delete the inventory items and 6xBE to create the traded items.
|
||||
// At any point if an error occurs, either client may send a D4 00, which cancels the entire sequence. The server
|
||||
// should then send D4 00 to both clients.
|
||||
// - Both clients send the appropriate subcommands to create inventory items (6x5E)
|
||||
// On BB, the sequence is:
|
||||
// - Clients sync trade state with 6xA6 commands
|
||||
// - When both have confirmed, one client (the initiator) sends D0 with the items it intends to give to the other
|
||||
// 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
|
||||
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
|
||||
// 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.
|
||||
|
||||
// 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.
|
||||
|
||||
// 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
|
||||
// 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)
|
||||
// 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
|
||||
// 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
|
||||
@@ -2523,7 +2534,7 @@ struct C_GBAGameRequest_V3_D7 {
|
||||
} __packed_ws__(C_GBAGameRequest_V3_D7, 0x10);
|
||||
|
||||
// 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 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).
|
||||
@@ -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.
|
||||
|
||||
// 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 {
|
||||
pstring<TextEncoding::ASCII, 0x10> v1_serial_number; // Unused
|
||||
@@ -3161,7 +3175,7 @@ struct SC_TeamChat_BB_07EA {
|
||||
} __packed_ws__(SC_TeamChat_BB_07EA, 0x20);
|
||||
|
||||
// 08EA (C->S): Get team member list
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 09EA (S->C): Team member list
|
||||
|
||||
@@ -3188,7 +3202,7 @@ struct S_Unknown_BB_0CEA {
|
||||
} __packed_ws__(S_Unknown_BB_0CEA, 0x20);
|
||||
|
||||
// 0DEA (C->S): Get team name
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// 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.
|
||||
|
||||
// 18EA: Intra-team ranking information
|
||||
// No arguments (C->S)
|
||||
// No arguments (C->S).
|
||||
|
||||
struct S_IntraTeamRanking_BB_18EA {
|
||||
/* 0000 */ le_uint32_t ranking_points = 0;
|
||||
@@ -3271,7 +3285,7 @@ struct S_IntraTeamRanking_BB_18EA {
|
||||
} __packed_ws__(S_IntraTeamRanking_BB_18EA, 0x10);
|
||||
|
||||
// 19EA: Team reward list
|
||||
// No arguments (C->S)
|
||||
// No arguments (C->S).
|
||||
|
||||
struct S_TeamRewardList_BB_19EA_1AEA {
|
||||
le_uint32_t num_entries;
|
||||
@@ -3434,7 +3448,7 @@ struct S_AdvanceCardTradeState_Ep3_EE_FlagD1 {
|
||||
} __packed_ws__(S_AdvanceCardTradeState_Ep3_EE_FlagD1, 4);
|
||||
|
||||
// EE D2 (C->S): Trade can proceed
|
||||
// No arguments
|
||||
// No arguments.
|
||||
|
||||
// EE D3 (S->C): Execute trade
|
||||
// Same format as EE D0
|
||||
@@ -3710,6 +3724,49 @@ struct G_UpdateEnemyStateT_6x0A {
|
||||
G_EntityIDHeader header;
|
||||
le_uint16_t enemy_index = 0; // [0, 0xB50)
|
||||
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;
|
||||
} __attribute__((packed));
|
||||
using G_UpdateEnemyState_GC_6x0A = G_UpdateEnemyStateT_6x0A<true>;
|
||||
@@ -3726,13 +3783,14 @@ struct G_UpdateObjectState_6x0B {
|
||||
} __packed_ws__(G_UpdateObjectState_6x0B, 0x0C);
|
||||
|
||||
// 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;
|
||||
// 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
|
||||
// status effect is replaced. Non-technique status effects have fixed or indefinite durations; technique-based
|
||||
// effects have durations based on the technique's level.
|
||||
// last slot, slot 4, may be used by certain boss effects; this is unconfirmed.) If a new status effect is added to a
|
||||
// slot that already contains one, the existing status effect is replaced. Non-technique status effects have fixed or
|
||||
// indefinite durations; technique-based effects have durations based on the technique's level.
|
||||
// Values for effect_type:
|
||||
// 02 = Freeze (slot 1; 5 seconds)
|
||||
// 03 = Shock (slot 1; 10 seconds)
|
||||
@@ -3747,16 +3805,8 @@ struct G_AddStatusEffect_6x0C {
|
||||
// 12 = Confuse (slot 1; 10 seconds)
|
||||
// Anything else = command is ignored
|
||||
le_uint32_t effect_type = 0;
|
||||
le_float amount = 0; // Only used for Shifta/Deband/Jellen/Zalure
|
||||
} __packed_ws__(G_AddStatusEffect_6x0C, 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);
|
||||
le_float amount = 0; // Only used in 6x0C for Shifta/Deband/Jellen/Zalure; unused in 6x0D
|
||||
} __packed_ws__(G_AddOrRemoveStatusEffect_6x0C_6x0D, 0x0C);
|
||||
|
||||
// 6x0E: Clear all negative status effects (protected on V3/V4)
|
||||
// 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)
|
||||
// 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
|
||||
// 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 {
|
||||
G_UnusedHeader header;
|
||||
@@ -4045,8 +4095,8 @@ struct G_ChangePlayerHP_6x2F {
|
||||
} __packed_ws__(G_ChangePlayerHP_6x2F, 0x0C);
|
||||
|
||||
// 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,
|
||||
// this is not the case.
|
||||
// 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
|
||||
// versions, this is not the case.
|
||||
|
||||
struct G_ChangePlayerLevel_DCNTE_6x30 {
|
||||
G_ClientIDHeader header;
|
||||
@@ -4112,7 +4162,7 @@ struct G_Unknown_6x36 {
|
||||
|
||||
struct G_PhotonBlast_6x37 {
|
||||
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;
|
||||
} __packed_ws__(G_PhotonBlast_6x37, 8);
|
||||
|
||||
@@ -4199,7 +4249,9 @@ struct G_SetPosition_6x3F {
|
||||
struct G_WalkToPosition_6x40 {
|
||||
G_ClientIDHeader header;
|
||||
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);
|
||||
|
||||
// 6x41: Move to position (v1)
|
||||
@@ -4277,8 +4329,8 @@ struct G_ShieldAttack_6x4A {
|
||||
G_ClientIDHeader header;
|
||||
} __packed_ws__(G_ShieldAttack_6x4A, 4);
|
||||
|
||||
// 6x4B: Hit by enemy (protected on GC NTE/V3/V4)
|
||||
// 6x4C: 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: Major hit by enemy (> 25% of max HP; protected on GC NTE/V3/V4)
|
||||
|
||||
struct G_HitByEnemy_6x4B_6x4C {
|
||||
G_ClientIDHeader header;
|
||||
@@ -4380,7 +4432,7 @@ struct G_Unknown_6x57 {
|
||||
struct G_LobbyAnimation_6x58 {
|
||||
G_ClientIDHeader header;
|
||||
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);
|
||||
|
||||
// 6x59: Pick up item
|
||||
@@ -4675,7 +4727,7 @@ struct G_6x70_Sub_Telepipe {
|
||||
struct G_6x70_Base_DCNTE {
|
||||
/* 0000 */ le_uint16_t client_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;
|
||||
/* 0014 */ VectorXYZI angle;
|
||||
/* 0020 */ le_uint16_t phase = 0;
|
||||
@@ -4683,41 +4735,39 @@ struct G_6x70_Base_DCNTE {
|
||||
} __packed_ws__(G_6x70_Base_DCNTE, 0x24);
|
||||
|
||||
struct G_SyncPlayerDispAndInventory_DCNTE_6x70 {
|
||||
// Offsets in this struct are relative to the overall command header
|
||||
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x60, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DCNTE_6x70)};
|
||||
/* 000C */ G_6x70_Base_DCNTE base;
|
||||
/* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x60, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DCNTE_6x70)};
|
||||
/* 0008 */ G_6x70_Base_DCNTE base;
|
||||
// The following two fields appear to contain uninitialized data
|
||||
/* 0030 */ le_uint32_t unknown_a5 = 0;
|
||||
/* 0034 */ le_uint32_t unknown_a6 = 0;
|
||||
/* 0038 */ G_6x70_Sub_Telepipe telepipe;
|
||||
/* 0054 */ le_uint32_t death_flags = 0;
|
||||
/* 0058 */ PlayerHoldState_DCProtos hold_state;
|
||||
/* 0068 */ le_uint32_t area = 0;
|
||||
/* 006C */ le_uint32_t game_flags = 0;
|
||||
/* 0070 */ PlayerVisualConfig visual;
|
||||
/* 00C0 */ PlayerStats stats;
|
||||
/* 00E4 */ le_uint32_t num_items = 0;
|
||||
/* 00E8 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0430 */
|
||||
/* 002C */ le_uint32_t unknown_a5 = 0;
|
||||
/* 0030 */ le_uint32_t unknown_a6 = 0;
|
||||
/* 0034 */ G_6x70_Sub_Telepipe telepipe;
|
||||
/* 0050 */ le_uint32_t death_flags = 0;
|
||||
/* 0054 */ PlayerHoldState_DCProtos hold_state;
|
||||
/* 0064 */ le_uint32_t area = 0;
|
||||
/* 0068 */ le_uint32_t player_flags = 0;
|
||||
/* 006C */ PlayerVisualConfig visual;
|
||||
/* 00BC */ PlayerStats stats;
|
||||
/* 00E0 */ le_uint32_t num_items = 0;
|
||||
/* 00E4 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 042C */
|
||||
} __packed_ws__(G_SyncPlayerDispAndInventory_DCNTE_6x70, 0x42C);
|
||||
|
||||
struct G_SyncPlayerDispAndInventory_DC112000_6x70 {
|
||||
// Offsets in this struct are relative to the overall command header
|
||||
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x67, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC112000_6x70)};
|
||||
/* 000C */ G_6x70_Base_DCNTE base;
|
||||
/* 0030 */ le_uint16_t bonus_hp_from_materials = 0;
|
||||
/* 0032 */ le_uint16_t bonus_tp_from_materials = 0;
|
||||
/* 0034 */ parray<uint8_t, 0x10> unknown_a5;
|
||||
/* 0044 */ G_6x70_Sub_Telepipe telepipe;
|
||||
/* 0060 */ le_uint32_t death_flags = 0;
|
||||
/* 0064 */ PlayerHoldState_DCProtos hold_state;
|
||||
/* 0074 */ le_uint32_t area = 0;
|
||||
/* 0078 */ le_uint32_t game_flags = 0;
|
||||
/* 007C */ PlayerVisualConfig visual;
|
||||
/* 00CC */ PlayerStats stats;
|
||||
/* 00F0 */ le_uint32_t num_items = 0;
|
||||
/* 00F4 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 043C */
|
||||
/* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x67, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC112000_6x70)};
|
||||
/* 0008 */ G_6x70_Base_DCNTE base;
|
||||
/* 002C */ le_uint16_t bonus_hp_from_materials = 0;
|
||||
/* 002E */ le_uint16_t bonus_tp_from_materials = 0;
|
||||
/* 0030 */ parray<uint8_t, 0x10> unknown_a5;
|
||||
/* 0040 */ G_6x70_Sub_Telepipe telepipe;
|
||||
/* 005C */ le_uint32_t death_flags = 0;
|
||||
/* 0060 */ PlayerHoldState_DCProtos hold_state;
|
||||
/* 0070 */ le_uint32_t area = 0;
|
||||
/* 0074 */ le_uint32_t player_flags = 0;
|
||||
/* 0078 */ PlayerVisualConfig visual;
|
||||
/* 00C8 */ PlayerStats stats;
|
||||
/* 00EC */ le_uint32_t num_items = 0;
|
||||
/* 00F0 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0438 */
|
||||
} __packed_ws__(G_SyncPlayerDispAndInventory_DC112000_6x70, 0x438);
|
||||
|
||||
struct G_6x70_Base_V1 {
|
||||
@@ -4728,71 +4778,71 @@ struct G_6x70_Base_V1 {
|
||||
/* 0034 */ StatusEffectState temporary_status_effect;
|
||||
/* 0040 */ StatusEffectState attack_status_effect;
|
||||
/* 004C */ StatusEffectState defense_status_effect;
|
||||
/* 0058 */ StatusEffectState unused_status_effect;
|
||||
/* 0058 */ StatusEffectState unknown_a1_status_effect;
|
||||
/* 0064 */ le_uint32_t language32 = 0;
|
||||
/* 0068 */ le_uint32_t player_tag = 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)
|
||||
/* 0074 */ le_uint32_t battle_team_number = 0;
|
||||
/* 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;
|
||||
/* 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
|
||||
/* 00C8 */ PlayerVisualConfig visual;
|
||||
/* 0118 */
|
||||
} __packed_ws__(G_6x70_Base_V1, 0x118);
|
||||
|
||||
struct G_SyncPlayerDispAndInventory_DC_PC_6x70 {
|
||||
// Offsets in this struct are relative to the overall command header
|
||||
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC_PC_6x70)};
|
||||
/* 000C */ G_6x70_Base_V1 base;
|
||||
/* 0124 */ PlayerStats stats;
|
||||
/* 0148 */ le_uint32_t num_items = 0;
|
||||
/* 014C */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0494 */
|
||||
/* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_DC_PC_6x70)};
|
||||
/* 0008 */ G_6x70_Base_V1 base;
|
||||
/* 0120 */ PlayerStats stats;
|
||||
/* 0144 */ le_uint32_t num_items = 0;
|
||||
/* 0148 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0490 */
|
||||
} __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 {
|
||||
// Offsets in this struct are relative to the overall command header
|
||||
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_GC_6x70)};
|
||||
/* 000C */ G_6x70_Base_V1 base;
|
||||
/* 0124 */ PlayerStats stats;
|
||||
/* 0148 */ le_uint32_t num_items = 0;
|
||||
/* 014C */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0494 */ le_uint32_t floor = 0;
|
||||
/* 0498 */
|
||||
/* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_GC_6x70)};
|
||||
/* 0008 */ G_6x70_Base_V1 base;
|
||||
/* 0120 */ PlayerStats stats;
|
||||
/* 0144 */ le_uint32_t num_items = 0;
|
||||
/* 0148 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0490 */ le_uint32_t floor = 0;
|
||||
/* 0494 */
|
||||
} __packed_ws__(G_SyncPlayerDispAndInventory_GC_6x70, 0x494);
|
||||
|
||||
struct G_SyncPlayerDispAndInventory_XB_6x70 {
|
||||
// Offsets in this struct are relative to the overall command header
|
||||
/* 0004 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_XB_6x70)};
|
||||
/* 000C */ G_6x70_Base_V1 base;
|
||||
/* 0124 */ PlayerStats stats;
|
||||
/* 0148 */ le_uint32_t num_items = 0;
|
||||
/* 014C */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0494 */ le_uint32_t floor = 0;
|
||||
/* 0498 */ le_uint32_t xb_user_id_high = 0;
|
||||
/* 049C */ le_uint32_t xb_user_id_low = 0;
|
||||
/* 04A0 */ le_uint32_t unknown_a16 = 0;
|
||||
/* 04A4 */
|
||||
/* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_XB_6x70)};
|
||||
/* 0008 */ G_6x70_Base_V1 base;
|
||||
/* 0120 */ PlayerStats stats;
|
||||
/* 0144 */ le_uint32_t num_items = 0;
|
||||
/* 0148 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 0490 */ le_uint32_t floor = 0;
|
||||
/* 0494 */ le_uint32_t xb_user_id_high = 0;
|
||||
/* 0498 */ le_uint32_t xb_user_id_low = 0;
|
||||
/* 049C */ le_uint32_t unknown_a16 = 0;
|
||||
/* 04A0 */
|
||||
} __packed_ws__(G_SyncPlayerDispAndInventory_XB_6x70, 0x4A0);
|
||||
|
||||
struct G_SyncPlayerDispAndInventory_BB_6x70 {
|
||||
// Offsets in this struct are relative to the overall command header
|
||||
/* 0008 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_BB_6x70)};
|
||||
/* 0010 */ G_6x70_Base_V1 base;
|
||||
/* 0128 */ pstring<TextEncoding::UTF16_ALWAYS_MARKED, 0x10> name;
|
||||
/* 0148 */ PlayerStats stats;
|
||||
/* 016C */ le_uint32_t num_items = 0;
|
||||
/* 0170 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 04B8 */ le_uint32_t floor = 0;
|
||||
/* 04BC */ le_uint32_t xb_user_id_high = 0;
|
||||
/* 04C0 */ le_uint32_t xb_user_id_low = 0;
|
||||
/* 04C4 */ le_uint32_t unknown_a16 = 0;
|
||||
/* 04C8 */
|
||||
/* 0000 */ G_ExtendedHeaderT<G_ClientIDHeader> header = {{0x70, 0x00, 0x0000}, sizeof(G_SyncPlayerDispAndInventory_BB_6x70)};
|
||||
/* 0008 */ G_6x70_Base_V1 base;
|
||||
/* 0120 */ pstring<TextEncoding::UTF16_ALWAYS_MARKED, 0x10> name;
|
||||
/* 0140 */ PlayerStats stats;
|
||||
/* 0164 */ le_uint32_t num_items = 0;
|
||||
/* 0168 */ parray<PlayerInventoryItem, 0x1E> items;
|
||||
/* 04B0 */ le_uint32_t floor = 0;
|
||||
/* 04B4 */ le_uint32_t xb_user_id_high = 0;
|
||||
/* 04B8 */ le_uint32_t xb_user_id_low = 0;
|
||||
/* 04BC */ le_uint32_t unknown_a16 = 0;
|
||||
/* 04C0 */
|
||||
} __packed_ws__(G_SyncPlayerDispAndInventory_BB_6x70, 0x4C0);
|
||||
|
||||
// 6x71: Unblock game join (used while loading into game)
|
||||
@@ -4994,6 +5044,8 @@ struct G_EnableDropWeaponOnDeath_6x82 {
|
||||
struct G_PlaceTrap_6x83 {
|
||||
G_ClientIDHeader header;
|
||||
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;
|
||||
} __packed_ws__(G_PlaceTrap_6x83, 8);
|
||||
|
||||
@@ -5192,13 +5244,18 @@ struct G_LevelUpAllTechniques_6x9B {
|
||||
parray<uint8_t, 3> unused;
|
||||
} __packed_ws__(G_LevelUpAllTechniques_6x9B, 8);
|
||||
|
||||
// 6x9C: Set enemy low game 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).
|
||||
// 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
|
||||
// essentially separates status effects from the 6x0A command. It's not clear why Sega did this only in Ultimate mode.
|
||||
|
||||
struct G_SetEnemyLowGameFlagsUltimate_6x9C {
|
||||
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.
|
||||
le_uint32_t low_game_flags = 0;
|
||||
// This field is expected to have one of these values (it should not actually be treated as a bit field):
|
||||
// 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);
|
||||
|
||||
// 6x9D: Set dead flag (Challenge mode; not valid on Episode 3)
|
||||
@@ -5389,25 +5446,20 @@ struct G_SetAnimationState_6xAE {
|
||||
G_ClientIDHeader header;
|
||||
le_uint16_t animation_number = 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,
|
||||
// then (flags & 1C000000) is or'ed into the TObjPlayer's flags field. All other bits are ignored.
|
||||
le_uint32_t flags = 0;
|
||||
// This field contains the player_flags field on the sender's TObjPlayer object. If the bit 04000000 is set in this
|
||||
// field, then (flags & 1C000000) is or'ed into the TObjPlayer's player_flags field on the receiver's end; all other
|
||||
// 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;
|
||||
} __packed_ws__(G_SetAnimationState_6xAE, 0x10);
|
||||
|
||||
// 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)
|
||||
|
||||
struct G_MoveLobbyChair_6xB0 {
|
||||
struct G_TurnOrMoveLobbyChair_6xAF_6xB0 {
|
||||
G_ClientIDHeader header;
|
||||
le_uint32_t unknown_a1 = 0;
|
||||
} __packed_ws__(G_MoveLobbyChair_6xB0, 8);
|
||||
le_uint32_t angle = 0; // In range [0x0000, 0xFFFF]
|
||||
} __packed_ws__(G_TurnOrMoveLobbyChair_6xAF_6xB0, 8);
|
||||
|
||||
// 6xB1: Unknown (not valid on pre-V3 or GC Trial Edition)
|
||||
// This subcommand is completely ignored.
|
||||
@@ -5673,7 +5725,7 @@ struct G_BankAction_BB_6xBD {
|
||||
G_UnusedHeader header;
|
||||
le_uint32_t item_id = 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;
|
||||
le_uint16_t item_index = 0; // 0xFFFF = meseta
|
||||
} __packed_ws__(G_BankAction_BB_6xBD, 0x10);
|
||||
@@ -6059,7 +6111,7 @@ struct G_SetMesetaSlotPrizeResult_BB_6xE3 {
|
||||
ItemData item;
|
||||
} __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
|
||||
// 6xE6: Invalid subcommand
|
||||
// 6xE7: Invalid subcommand
|
||||
@@ -6325,7 +6377,7 @@ struct G_SetPlayerDeck_Ep3_CAx14 {
|
||||
|
||||
struct G_HardResetServerState_Ep3_CAx15 {
|
||||
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);
|
||||
|
||||
// 6xB5x17: Unknown
|
||||
@@ -6333,7 +6385,7 @@ struct G_HardResetServerState_Ep3_CAx15 {
|
||||
|
||||
struct G_Unknown_Ep3_6xB5x17 {
|
||||
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);
|
||||
|
||||
// 6xB5x1A: Force disconnect
|
||||
@@ -6343,7 +6395,7 @@ struct G_Unknown_Ep3_6xB5x17 {
|
||||
|
||||
struct G_ForceDisconnect_Ep3_6xB5x1A {
|
||||
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);
|
||||
|
||||
// 6xB3x1B / CAx1B: Set player name
|
||||
@@ -6416,7 +6468,7 @@ struct G_EndBattle_Ep3_CAx21 {
|
||||
|
||||
struct G_Unknown_Ep3_6xB4x22 {
|
||||
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);
|
||||
|
||||
// 6xB4x23: Unknown
|
||||
@@ -6559,7 +6611,7 @@ struct G_SetDeckInBattleSetupMenu_Ep3_6xB5x2F {
|
||||
|
||||
struct G_Unused_Ep3_6xB5x30 {
|
||||
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);
|
||||
|
||||
// 6xB5x31: Confirm deck selection
|
||||
@@ -7064,7 +7116,7 @@ struct G_RejectBattleStartRequest_Ep3_6xB4x53 {
|
||||
// 30 (C->S): Extended player info
|
||||
// Requested with the GetExtendedPlayerInfo patch. Format depends on version:
|
||||
// DC v2: PSODCV2CharacterFile
|
||||
// GC v3: PSOGCCharacterFile::Character
|
||||
// GC v3: PSOGCCharacterFile::Character (including big-endian fields, unlike 61)
|
||||
// XB v3: PSOXBCharacterFile::Character
|
||||
|
||||
// 6xE4: Increment enemy damage
|
||||
|
||||
@@ -37,6 +37,14 @@ struct VectorXZF {
|
||||
inline double norm2() const {
|
||||
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 {
|
||||
double s = sin(angle);
|
||||
|
||||
+150
-130
@@ -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("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;
|
||||
const auto* enemy_type_drop_probs_json = json.count("EnemyTypeDropProbs") ? &json.at("EnemyTypeDropProbs").as_dict() : nullptr;
|
||||
const auto* enemy_item_classes_json = json.count("EnemyItemClasses") ? &json.at("EnemyItemClasses").as_dict() : nullptr;
|
||||
if (enemy_item_classes_json) {
|
||||
// Unspecified is 0xFF, not 0, unlike the other enemy-indexed arrays (except for [0], apparently... sigh)
|
||||
this->enemy_item_classes[0] = 0;
|
||||
this->enemy_item_classes.clear_after(1, 0xFF);
|
||||
if (json.count("EnemyMesetaRanges")) {
|
||||
const auto& dict = json.at("EnemyMesetaRanges").as_dict();
|
||||
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
|
||||
try {
|
||||
from_json_into(*dict.at(phosg::name_for_enum(enemy_type)), this->enemy_type_meseta_ranges[enemy_type]);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
vector<string> names;
|
||||
if (types.empty()) {
|
||||
names.emplace_back(std::format("!{:02X}", z));
|
||||
} else {
|
||||
for (auto type : types) {
|
||||
names.emplace_back(phosg::name_for_enum(type));
|
||||
|
||||
if (json.count("EnemyTypeDropProbs")) {
|
||||
const auto& dict = json.at("EnemyTypeDropProbs").as_dict();
|
||||
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
|
||||
try {
|
||||
this->enemy_type_drop_probs[enemy_type] = dict.at(phosg::name_for_enum(enemy_type))->as_int();
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
for (const auto& name : names) {
|
||||
if (enemy_meseta_ranges_json) {
|
||||
try {
|
||||
from_json_into(*enemy_meseta_ranges_json->at(name), this->enemy_meseta_ranges[z]);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
} else if (prev_table) {
|
||||
this->enemy_meseta_ranges = prev_table->enemy_meseta_ranges;
|
||||
}
|
||||
if (enemy_type_drop_probs_json) {
|
||||
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_drop_probs = prev_table->enemy_type_drop_probs;
|
||||
}
|
||||
|
||||
if (json.count("EnemyItemClasses")) {
|
||||
const auto& dict = json.at("EnemyItemClasses").as_dict();
|
||||
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
|
||||
try {
|
||||
this->enemy_type_item_classes[enemy_type] = dict.at(phosg::name_for_enum(enemy_type))->as_int();
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->enemy_type_item_classes = prev_table->enemy_type_item_classes;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* name_for_common_item_class(uint8_t item_class) {
|
||||
switch (item_class) {
|
||||
case 0x00:
|
||||
return "WEAPON ";
|
||||
return "WEAPON";
|
||||
case 0x01:
|
||||
return "ARMOR ";
|
||||
return "ARMOR";
|
||||
case 0x02:
|
||||
return "SHIELD ";
|
||||
return "SHIELD";
|
||||
case 0x03:
|
||||
return "UNIT ";
|
||||
return "UNIT";
|
||||
case 0x04:
|
||||
return "TOOL ";
|
||||
return "TOOL";
|
||||
case 0x05:
|
||||
return "MESETA ";
|
||||
return "MESETA";
|
||||
case 0x06:
|
||||
return "NOTHING";
|
||||
default:
|
||||
@@ -203,42 +193,29 @@ static const char* name_for_common_item_class(uint8_t item_class) {
|
||||
}
|
||||
|
||||
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& 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, " ## $LOW $HIGH DAR% ITEM ENEMIES\n");
|
||||
for (size_t z = 0; z < NUM_RT_INDEXES_V4; z++) {
|
||||
string enemies_str;
|
||||
for (EnemyType enemy_type : enemy_types_for_rare_table_index(this->episode, z)) {
|
||||
if (!enemies_str.empty()) {
|
||||
enemies_str += ", ";
|
||||
}
|
||||
enemies_str += phosg::name_for_enum(enemy_type);
|
||||
}
|
||||
if (drop_probs[z] || !enemies_str.empty()) {
|
||||
phosg::fwrite_fmt(stream, " {:02X} {:5} {:5} {:3}% {:02X}:{} {}\n",
|
||||
z, meseta_ranges[z].min, meseta_ranges[z].max, drop_probs[z], item_classes[z],
|
||||
name_for_common_item_class(item_classes[z]), enemies_str);
|
||||
} else {
|
||||
phosg::fwrite_fmt(stream, " {:02X} ----- ----- 0% --\n", z);
|
||||
phosg::fwrite_fmt(stream, " ##:ENEMY $LOW $HIGH DAR% ITEM\n");
|
||||
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
|
||||
const auto& def = type_definition_for_enemy(enemy_type);
|
||||
try {
|
||||
const auto& meseta_range = meseta_ranges.at(enemy_type);
|
||||
const auto& drop_prob = drop_probs.at(enemy_type);
|
||||
const auto& item_class = item_classes.at(enemy_type);
|
||||
phosg::fwrite_fmt(stream, " {:02X}:{:<23} {:5} {:5} {:3}% {:02X}:{:<7}\n",
|
||||
def.rt_index, phosg::name_for_enum(enemy_type),
|
||||
meseta_range.min, meseta_range.max, drop_prob, item_class,
|
||||
name_for_common_item_class(item_class));
|
||||
} catch (const out_of_range&) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}:{:<23} ----- ----- ---- --:-------\n",
|
||||
def.rt_index, phosg::name_for_enum(enemy_type));
|
||||
}
|
||||
}
|
||||
|
||||
static const array<const char*, 12> base_weapon_type_names = {
|
||||
"SABER ",
|
||||
"SWORD ",
|
||||
"DAGGER ",
|
||||
"PARTISAN",
|
||||
"SLICER ",
|
||||
"HANDGUN ",
|
||||
"RIFLE ",
|
||||
"MECHGUN ",
|
||||
"SHOT ",
|
||||
"CANE ",
|
||||
"ROD ",
|
||||
"WAND ",
|
||||
};
|
||||
"SABER", "SWORD", "DAGGER", "PARTISAN", "SLICER", "HANDGUN", "RIFLE", "MECHGUN", "SHOT", "CANE", "ROD", "WAND"};
|
||||
phosg::fwrite_fmt(stream, "Base weapon config:\n");
|
||||
phosg::fwrite_fmt(stream, " TYPE PROB [SB AL] FLOORS\n");
|
||||
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]);
|
||||
}
|
||||
}
|
||||
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],
|
||||
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],
|
||||
@@ -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(&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",
|
||||
phosg::format_data_string(&this->enemy_meseta_ranges, sizeof(this->enemy_meseta_ranges)),
|
||||
phosg::format_data_string(&other.enemy_meseta_ranges, sizeof(other.enemy_meseta_ranges)));
|
||||
|
||||
auto format_enemy_range_table = [&](const std::unordered_map<EnemyType, Range<uint16_t>>& table) -> std::string {
|
||||
string ret = "";
|
||||
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) {
|
||||
phosg::fwrite_fmt(stream, "> enemy_type_drop_probs: {} -> {}\n",
|
||||
phosg::format_data_string(&this->enemy_type_drop_probs, sizeof(this->enemy_type_drop_probs)),
|
||||
phosg::format_data_string(&other.enemy_type_drop_probs, sizeof(other.enemy_type_drop_probs)));
|
||||
format_enemy_u8_table(this->enemy_type_drop_probs),
|
||||
format_enemy_u8_table(other.enemy_type_drop_probs));
|
||||
}
|
||||
if (this->enemy_item_classes != other.enemy_item_classes) {
|
||||
phosg::fwrite_fmt(stream, "> enemy_item_classes: {} -> {}\n",
|
||||
phosg::format_data_string(&this->enemy_item_classes, sizeof(this->enemy_item_classes)),
|
||||
phosg::format_data_string(&other.enemy_item_classes, sizeof(other.enemy_item_classes)));
|
||||
if (this->enemy_type_item_classes != other.enemy_type_item_classes) {
|
||||
phosg::fwrite_fmt(stream, "> enemy_type_item_classes: {} -> {}\n",
|
||||
format_enemy_u8_table(this->enemy_type_item_classes),
|
||||
format_enemy_u8_table(other.enemy_type_item_classes));
|
||||
}
|
||||
if (this->box_meseta_ranges != other.box_meseta_ranges) {
|
||||
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));
|
||||
}
|
||||
|
||||
bool needs_enemy_meseta_ranges = (!prev_table || (this->enemy_meseta_ranges != prev_table->enemy_meseta_ranges));
|
||||
bool needs_enemy_type_drop_probs = (!prev_table || (this->enemy_type_drop_probs != prev_table->enemy_type_drop_probs));
|
||||
bool needs_enemy_item_classes = (!prev_table || (this->enemy_item_classes != prev_table->enemy_item_classes));
|
||||
if (needs_enemy_meseta_ranges || needs_enemy_type_drop_probs || needs_enemy_item_classes) {
|
||||
phosg::JSON enemy_meseta_ranges_json = phosg::JSON::dict();
|
||||
bool needs_enemy_type_meseta_ranges = (!prev_table ||
|
||||
(this->enemy_type_meseta_ranges != prev_table->enemy_type_meseta_ranges));
|
||||
bool needs_enemy_type_drop_probs = (!prev_table ||
|
||||
(this->enemy_type_drop_probs != prev_table->enemy_type_drop_probs));
|
||||
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_item_classes_json = phosg::JSON::dict();
|
||||
for (size_t z = 0; z < NUM_RT_INDEXES_V4; z++) {
|
||||
auto types = enemy_types_for_rare_table_index(this->episode, z);
|
||||
vector<string> names;
|
||||
if (types.empty()) {
|
||||
names.emplace_back(std::format("!{:02X}", z));
|
||||
} else {
|
||||
for (auto type : types) {
|
||||
names.emplace_back(phosg::name_for_enum(type));
|
||||
phosg::JSON enemy_type_item_classes_json = phosg::JSON::dict();
|
||||
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
|
||||
auto name = phosg::name_for_enum(enemy_type);
|
||||
if (needs_enemy_type_meseta_ranges) {
|
||||
try {
|
||||
enemy_type_meseta_ranges_json.emplace(name, to_json(this->enemy_type_meseta_ranges.at(enemy_type)));
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
for (const auto& name : names) {
|
||||
if (needs_enemy_meseta_ranges && (!types.empty() || !this->enemy_meseta_ranges[z].empty())) {
|
||||
enemy_meseta_ranges_json.emplace(name, to_json(this->enemy_meseta_ranges[z]));
|
||||
if (needs_enemy_type_drop_probs) {
|
||||
try {
|
||||
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_item_classes && (!types.empty() || (this->enemy_item_classes[z] != ((z == 0) ? 0x00 : 0xFF)))) {
|
||||
enemy_item_classes_json.emplace(name, this->enemy_item_classes[z]);
|
||||
}
|
||||
if (needs_enemy_type_item_classes) {
|
||||
try {
|
||||
enemy_type_item_classes_json.emplace(name, this->enemy_type_item_classes.at(enemy_type));
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_enemy_meseta_ranges) {
|
||||
ret.emplace("EnemyMesetaRanges", std::move(enemy_meseta_ranges_json));
|
||||
if (needs_enemy_type_meseta_ranges) {
|
||||
ret.emplace("EnemyMesetaRanges", std::move(enemy_type_meseta_ranges_json));
|
||||
}
|
||||
if (needs_enemy_type_drop_probs) {
|
||||
ret.emplace("EnemyTypeDropProbs", std::move(enemy_type_drop_probs_json));
|
||||
}
|
||||
if (needs_enemy_item_classes) {
|
||||
ret.emplace("EnemyItemClasses", std::move(enemy_item_classes_json));
|
||||
if (needs_enemy_type_item_classes) {
|
||||
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->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);
|
||||
const auto& data = r.pget<parray<Range<U16T<BE>>, NUM_RT_INDEXES_V3>>(offsets.enemy_meseta_ranges_offset);
|
||||
for (size_t z = 0; z < data.size(); z++) {
|
||||
this->enemy_meseta_ranges[z] = Range<uint16_t>{data[z].min, data[z].max};
|
||||
const auto& enemy_rt_index_meseta_ranges = r.pget<parray<Range<U16T<BE>>, NUM_RT_INDEXES_V3>>(
|
||||
offsets.enemy_rt_index_meseta_ranges_offset);
|
||||
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);
|
||||
for (size_t z = 0; z < data.size(); z++) {
|
||||
@@ -873,7 +895,7 @@ GSLV3V4CommonItemSet::GSLV3V4CommonItemSet(std::shared_ptr<const std::string> gs
|
||||
section_id);
|
||||
};
|
||||
|
||||
for (Episode episode : ALL_EPISODES_V4) {
|
||||
for (Episode episode : ALL_EPISODES_V3) {
|
||||
for (Difficulty difficulty : ALL_DIFFICULTIES_V234) {
|
||||
for (size_t section_id = 0; section_id < 10; section_id++) {
|
||||
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) {
|
||||
try {
|
||||
auto r = gsl.get_reader(filename_for_table(episode, difficulty, 0, true));
|
||||
auto table = make_shared<Table>(r, is_big_endian, true, episode);
|
||||
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);
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
// GC NTE doesn't have Ep2 challenge; just skip adding the table
|
||||
for (Difficulty difficulty : ALL_DIFFICULTIES_V234) {
|
||||
try {
|
||||
auto r = gsl.get_reader(filename_for_table(episode, difficulty, 0, true));
|
||||
auto table = make_shared<Table>(r, is_big_endian, true, episode);
|
||||
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);
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
// GC NTE doesn't have Ep2 challenge; just skip adding the table
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-10
@@ -42,9 +42,10 @@ public:
|
||||
parray<parray<uint8_t, 4>, 9> grind_prob_table;
|
||||
parray<uint8_t, 0x05> armor_shield_type_index_prob_table;
|
||||
parray<uint8_t, 0x05> armor_slot_count_prob_table;
|
||||
parray<Range<uint16_t>, NUM_RT_INDEXES_V4> enemy_meseta_ranges;
|
||||
parray<uint8_t, NUM_RT_INDEXES_V4> enemy_type_drop_probs;
|
||||
parray<uint8_t, NUM_RT_INDEXES_V4> enemy_item_classes;
|
||||
// Note: PSO originally uses arrays indexed by rt_index here, but we index enemies by the EnemyType enum instead
|
||||
std::unordered_map<EnemyType, Range<uint16_t>> enemy_type_meseta_ranges;
|
||||
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;
|
||||
bool has_rare_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>
|
||||
/* 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>
|
||||
/* 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
|
||||
// essentially this probability multiplied by the rare drop rate.)
|
||||
// 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
|
||||
// 01 = armor
|
||||
// 02 = shield
|
||||
@@ -145,7 +146,7 @@ public:
|
||||
// 05 = meseta
|
||||
// Anything else = no item
|
||||
// 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.
|
||||
// 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
|
||||
// [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
|
||||
// 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:
|
||||
// [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
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ static constexpr size_t NUM_RT_INDEXES_V3 = 0x64;
|
||||
static constexpr size_t NUM_RT_INDEXES_V4 = 0x70;
|
||||
|
||||
enum class EnemyType : uint8_t {
|
||||
MIN_VALUE = 0,
|
||||
UNKNOWN = 0,
|
||||
NONE,
|
||||
NON_ENEMY_NPC,
|
||||
@@ -146,7 +147,7 @@ enum class EnemyType : uint8_t {
|
||||
ZOL_GIBBON,
|
||||
ZU_CRATER,
|
||||
ZU_DESERT,
|
||||
MAX_ENEMY_TYPE,
|
||||
MAX_VALUE,
|
||||
};
|
||||
|
||||
struct EnemyTypeDefinition {
|
||||
|
||||
+24
-22
@@ -675,8 +675,8 @@ struct CardDefinition {
|
||||
// - (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
|
||||
// (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,
|
||||
// 9], and affects how likely the card is to appear based on the player's level. See below for details.
|
||||
// - (rate / 1000) % 10 (the thousands decimal place) specifies the rarity class. This can be any number in the range
|
||||
// [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
|
||||
// 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
|
||||
// for a card apply, the card ID is added twice.) The player's level class is then computed according to the
|
||||
// following table:
|
||||
// 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+
|
||||
// CLvOn 1-2 3-4 5-10 11-16 17-23 24-32 33-39 40-49 50-99 100+
|
||||
// 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+
|
||||
// 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
|
||||
// override it - see win_level_override and loss_level_override in MapDefinition. This specifies which row in the
|
||||
// following tables will be used.
|
||||
//
|
||||
// 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):
|
||||
// Offline:
|
||||
// Offline ---------------------------------------------------------------
|
||||
// LC | RC = 0 1 2 3 4 5 6 7 8 9
|
||||
// 1 | 8000 2000 50
|
||||
// 2 | 6000 3500 500 20
|
||||
@@ -705,7 +705,7 @@ struct CardDefinition {
|
||||
// 8 | 1789 2100 2100 2100 1100 800 10 1
|
||||
// 9 | 14620 20000 21000 22000 13000 9000 300 80
|
||||
// 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
|
||||
// 1 | 8000 2000 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 red pack, the restricted cards must be item 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
|
||||
// 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
|
||||
// first 1 or 2 cards, it applies the restriction described above and re-draws if the card is the wrong type. After
|
||||
// sampling the N card IDs, it sorts them and presents them to the player.
|
||||
// The game then samples N card IDs from the appropriate buckets (where N is the number chosen above based on the
|
||||
// post-battle rank), but for the first 1 or 2 cards, it applies the restriction described above and re-draws if the
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// transforming into a rarer card is P(activate) * P(rare).
|
||||
// ======== Card rank N4-N1 ======== ======== Card rank R4-R1 ========
|
||||
// Count P(activate) P(rare) P(vip) P(activate) P(rare) P(vip)
|
||||
// 0-4 0% 0% 0% 0% 0% 0%
|
||||
// 5-10 1.923077% 55% 0.5% 2.0408163% 55% 0.5%
|
||||
// 11-16 2.1276595% 60% 0.45454544% 2.2727273% 60% 0.4761905%
|
||||
// 17-24 2.3809524% 70% 0.4347826% 2.5641026% 70% 0.45454544%
|
||||
// 25-32 2.7027028% 70% 0.4% 2.9411765% 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%
|
||||
// 53-99 5% 90% 0.33333334% 5.263158% 90% 0.4347826%
|
||||
// ========= Card rank N4-N1 ========= ========= Card rank R4-R1 =========
|
||||
// Count P(activate) P(rare) P(vip) P(activate) P(rare) P(vip)
|
||||
// 0-4 0% 0% 0% 0% 0% 0%
|
||||
// 5-10 1.923077% 55% 0.5% 2.0408163% 55% 0.5%
|
||||
// 11-16 2.1276595% 60% 0.45454544% 2.2727273% 60% 0.4761905%
|
||||
// 17-24 2.3809524% 70% 0.4347826% 2.5641026% 70% 0.45454544%
|
||||
// 25-32 2.7027028% 70% 0.4% 2.9411765% 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%
|
||||
// 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
|
||||
// following table to determine the rank of the resulting card (original card's rank on the left, new card's rank
|
||||
|
||||
@@ -44,6 +44,7 @@ void GameServer::listen(
|
||||
|
||||
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);
|
||||
c->listener_port = port;
|
||||
|
||||
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));
|
||||
@@ -133,6 +134,7 @@ shared_ptr<Client> GameServer::create_client(
|
||||
phosg::TerminalFormat::FG_YELLOW,
|
||||
phosg::TerminalFormat::FG_GREEN);
|
||||
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);
|
||||
|
||||
return c;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <phosg/Network.hh>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "GameServer.hh"
|
||||
@@ -54,6 +55,156 @@ HTTPServer::HTTPServer(shared_ptr<ServerState> state)
|
||||
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 {
|
||||
auto res = make_shared<phosg::JSON>(phosg::JSON::list());
|
||||
for (const auto& c : this->state->game_server->all_clients()) {
|
||||
|
||||
+110
-92
@@ -38,6 +38,7 @@ ItemCreator::ItemCreator(
|
||||
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),
|
||||
logic_version(stack_limits->version),
|
||||
is_legacy_replay(false),
|
||||
stack_limits(stack_limits),
|
||||
mode(mode),
|
||||
difficulty(difficulty),
|
||||
@@ -136,13 +137,13 @@ uint8_t ItemCreator::table_index_for_area(uint8_t area) const {
|
||||
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 {
|
||||
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);
|
||||
|
||||
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()) {
|
||||
res.is_from_rare_table = true;
|
||||
} 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 {
|
||||
// Note: The original GC implementation uses (enemy_type > 0x58) here; we extend it to the full array size for BB
|
||||
if (enemy_type >= NUM_RT_INDEXES_V4) {
|
||||
this->log.warning_f("Invalid enemy type: {:X}", enemy_type);
|
||||
return DropResult();
|
||||
}
|
||||
this->log.info_f("Enemy type: {:X}", enemy_type);
|
||||
// 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) {
|
||||
// this->log.warning_f("Invalid enemy type: {:X}", enemy_type);
|
||||
// return DropResult();
|
||||
// }
|
||||
this->log.info_f("Enemy type: {}", phosg::name_for_enum(enemy_type));
|
||||
|
||||
auto pt = this->pt(area);
|
||||
uint8_t type_drop_prob = pt->enemy_type_drop_probs.at(enemy_type);
|
||||
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);
|
||||
uint8_t type_drop_prob = 0;
|
||||
try {
|
||||
type_drop_prob = pt->enemy_type_drop_probs.at(enemy_type);
|
||||
} catch (const std::out_of_range&) {
|
||||
this->log.info_f("No drop probability is set for this enemy type");
|
||||
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;
|
||||
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()) {
|
||||
res.is_from_rare_table = true;
|
||||
} else {
|
||||
uint32_t item_class_determinant =
|
||||
this->should_allow_meseta_drops() ? this->rand_int(3) : (this->rand_int(2) + 1);
|
||||
|
||||
uint32_t item_class;
|
||||
uint8_t item_class_determinant = this->should_allow_meseta_drops() ? this->rand_int(3) : (this->rand_int(2) + 1);
|
||||
uint8_t item_class;
|
||||
switch (item_class_determinant) {
|
||||
case 0:
|
||||
item_class = 5;
|
||||
@@ -224,7 +231,12 @@ ItemCreator::DropResult ItemCreator::on_monster_item_drop(uint32_t enemy_type, u
|
||||
item_class = 4;
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
throw logic_error("invalid item class determinant");
|
||||
@@ -251,7 +263,12 @@ ItemCreator::DropResult ItemCreator::on_monster_item_drop(uint32_t enemy_type, u
|
||||
break;
|
||||
case 5: // Meseta
|
||||
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;
|
||||
default:
|
||||
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 item;
|
||||
ItemData ItemCreator::check_rare_specs_and_create_rare_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()) {
|
||||
return item;
|
||||
return ItemData();
|
||||
}
|
||||
|
||||
uint8_t table_index = this->table_index_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);
|
||||
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("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;
|
||||
auto specs = this->rare_item_set->get_box_specs(this->mode, episode, this->difficulty, this->section_id, table_index);
|
||||
return this->check_rare_specs_and_create_rare_item(specs, area, force_rare);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <size_t NumRanges>
|
||||
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;
|
||||
|
||||
uint32_t ItemCreator::choose_meseta_amount(const CommonItemSet::Table::Range<uint16_t>& range) {
|
||||
// Note: The original code returns 0xFF here if either limit is equal to 0xFF (despite them being 16-bit integers!)
|
||||
uint16_t ret;
|
||||
if (min == max) {
|
||||
ret = min;
|
||||
} else if (max < min) {
|
||||
ret = this->rand_int((min - max) + 1) + max;
|
||||
if (range.min == range.max) {
|
||||
ret = range.min;
|
||||
} else if (range.max < range.min) {
|
||||
ret = this->rand_int((range.min - range.max) + 1) + range.max;
|
||||
} 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;
|
||||
}
|
||||
|
||||
@@ -330,45 +367,24 @@ bool ItemCreator::should_allow_meseta_drops() const {
|
||||
return (this->mode != GameMode::CHALLENGE);
|
||||
}
|
||||
|
||||
ItemData ItemCreator::check_rare_spec_and_create_rare_enemy_item(uint32_t enemy_type, uint8_t area) {
|
||||
ItemData item;
|
||||
if (this->are_rare_drops_allowed() && (enemy_type > 0) && (enemy_type < NUM_RT_INDEXES_V4)) {
|
||||
// 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 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);
|
||||
}
|
||||
}
|
||||
ItemData ItemCreator::check_rare_spec_and_create_rare_enemy_item(EnemyType enemy_type, uint8_t area, bool force_rare) {
|
||||
// Note: The original implementation has a bounds check for enemy_type here, since it uses rt_index instead.
|
||||
// if ((enemy_type <= 0) || (enemy_type >= NUM_RT_INDEXES_V4)) return ItemData{};
|
||||
if (!this->are_rare_drops_allowed()) {
|
||||
return ItemData{};
|
||||
}
|
||||
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) {
|
||||
if (drop.probability == 0) {
|
||||
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;
|
||||
ItemData ItemCreator::create_rare_item(const ItemData& drop_item, uint8_t area) {
|
||||
ItemData item = drop_item;
|
||||
if (item.can_be_encoded_in_rel_rare_table()) {
|
||||
switch (item.data1[0]) {
|
||||
case 0:
|
||||
@@ -617,9 +633,11 @@ void ItemCreator::generate_common_item_variances(ItemData& item, uint8_t area) {
|
||||
case 3:
|
||||
this->generate_common_tool_variances(item, area);
|
||||
break;
|
||||
case 4:
|
||||
item.data2d = this->choose_meseta_amount(this->pt(area)->box_meseta_ranges, this->table_index_for_area(area)) & 0xFFFF;
|
||||
case 4: {
|
||||
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;
|
||||
}
|
||||
default:
|
||||
// Note: The original code does the following here:
|
||||
// item.clear();
|
||||
|
||||
+19
-8
@@ -37,10 +37,18 @@ public:
|
||||
bool is_from_rare_table = false;
|
||||
};
|
||||
|
||||
DropResult on_monster_item_drop(uint32_t enemy_type, uint8_t area);
|
||||
DropResult on_box_item_drop(uint8_t area);
|
||||
inline void set_legacy_replay() {
|
||||
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
|
||||
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;
|
||||
|
||||
std::vector<ItemData> generate_armor_shop_contents(Episode episode, size_t player_level);
|
||||
@@ -69,6 +77,8 @@ private:
|
||||
|
||||
phosg::PrefixedLogger log;
|
||||
Version logic_version;
|
||||
bool is_legacy_replay;
|
||||
double rare_drop_rate_multiplier = 1.0;
|
||||
std::shared_ptr<const ItemData::StackLimits> stack_limits;
|
||||
GameMode mode;
|
||||
Difficulty difficulty;
|
||||
@@ -116,14 +126,15 @@ private:
|
||||
uint32_t rand_int(uint64_t max);
|
||||
float rand_float_0_1_from_crypt();
|
||||
|
||||
template <size_t NumRanges>
|
||||
uint32_t choose_meseta_amount(const parray<CommonItemSet::Table::Range<uint16_t>, NumRanges> ranges, size_t table_index);
|
||||
uint32_t choose_meseta_amount(const CommonItemSet::Table::Range<uint16_t>& range);
|
||||
|
||||
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_specs_and_create_rare_box_item(uint8_t area);
|
||||
ItemData check_rate_and_create_rare_item(const RareItemSet::ExpandedDrop& drop, 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, bool force_rare);
|
||||
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 deduplicate_weapon_bonuses(ItemData& item) const;
|
||||
|
||||
@@ -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)
|
||||
: server_state(s),
|
||||
log(std::format("[{}:{:X}] ", is_game ? "Game" : "Lobby", id), lobby_log.min_level),
|
||||
creation_time(phosg::now()),
|
||||
lobby_id(id),
|
||||
random_seed(phosg::random_object<uint32_t>()),
|
||||
rand_crypt(make_shared<DisabledRandomGenerator>()),
|
||||
@@ -229,6 +230,14 @@ void Lobby::create_item_creator(Version logic_version) {
|
||||
effective_section_id,
|
||||
rand_crypt,
|
||||
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 {
|
||||
|
||||
@@ -81,6 +81,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
START_BATTLE_PLAYER_IMMEDIATELY = 0x00010000,
|
||||
CANNOT_CHANGE_CHEAT_MODE = 0x00020000,
|
||||
USE_CREATOR_SECTION_ID = 0x00040000,
|
||||
BLUEBALLZ_PLUS0 = 0x00080000,
|
||||
// Flags used only for lobbies
|
||||
PUBLIC = 0x01000000,
|
||||
DEFAULT = 0x02000000,
|
||||
@@ -91,6 +92,8 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
std::weak_ptr<ServerState> server_state;
|
||||
phosg::PrefixedLogger log;
|
||||
|
||||
uint64_t creation_time;
|
||||
|
||||
uint32_t lobby_id;
|
||||
|
||||
uint32_t min_level = 0;
|
||||
@@ -116,6 +119,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
Episode episode = Episode::NONE;
|
||||
GameMode mode = GameMode::NORMAL;
|
||||
Difficulty difficulty = Difficulty::NORMAL;
|
||||
int8_t blueballz_tier = -1; // -1 = disabled; 0..10 = Blueballz +0..+10
|
||||
float base_exp_multiplier = 1.0f;
|
||||
float exp_share_multiplier = 0.5f;
|
||||
float challenge_exp_multiplier = 1.0f;
|
||||
|
||||
+99
-69
@@ -464,7 +464,7 @@ Action a_psov2_encrypt_single_test(
|
||||
current_value, num_mismatches, phosg::format_duration(crypt_time), phosg::format_duration(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);
|
||||
});
|
||||
@@ -813,7 +813,7 @@ static void a_encrypt_decrypt_vms_save_fn(phosg::Arguments& args) {
|
||||
}
|
||||
|
||||
} 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 {
|
||||
auto decrypted = decrypt_fixed_size_data_section_t<StructT, false, ChecksumLength>(
|
||||
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\
|
||||
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\
|
||||
If --simple is given, uses the simpler encryption method used in some\n\
|
||||
community modifications of the game (Enhancement Pack, for example). In\n\
|
||||
this case, --seed is not required; if not given, finds the seed\n\
|
||||
If --simple is given, uses the encryption method used in Ives\' Enhancement\n\
|
||||
Pack. In 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\
|
||||
re-encrypting.\n",
|
||||
+[](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\
|
||||
fixup table (KATSUO.SEA). The output is written to EXEC.enc and\n\
|
||||
INDEXES.enc.\n\
|
||||
If --simple is given, uses the simpler encryption method used in some\n\
|
||||
community modifications of the game. In this case, --seed is required.\n",
|
||||
If --simple is given, uses the simpler encryption method used in Ives\'\n\
|
||||
Enhancement Pack. In this case, --seed is required.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
string executable_filename = args.get<string>("executable", true);
|
||||
string executable_data = phosg::load_file(executable_filename);
|
||||
@@ -1188,7 +1187,7 @@ Action a_encrypt_dcv2_executable(
|
||||
Action a_decode_gci_snapshot(
|
||||
"decode-gci-snapshot", "\
|
||||
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) {
|
||||
auto data = read_input_data(args);
|
||||
phosg::StringReader r(data);
|
||||
@@ -1366,7 +1365,7 @@ Action a_salvage_gci(
|
||||
};
|
||||
|
||||
if (!round2) {
|
||||
phosg::parallel_range_blocks<uint64_t>(
|
||||
phosg::parallel_blocks<uint64_t>(
|
||||
[&](uint64_t seed, size_t thread_num) -> bool {
|
||||
auto decrypted = decrypt_fixed_size_data_section_t<StructT, 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
|
||||
// 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.
|
||||
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);
|
||||
if (intermediate_top_seeds.empty()) {
|
||||
throw logic_error("no intermediate seeds were found");
|
||||
@@ -1397,7 +1396,7 @@ Action a_salvage_gci(
|
||||
for (auto& top_seeds : top_seeds_by_thread) {
|
||||
top_seeds.clear();
|
||||
}
|
||||
phosg::parallel_range_blocks<uint64_t>(
|
||||
phosg::parallel_blocks<uint64_t>(
|
||||
[&](uint64_t seed, size_t thread_num) -> bool {
|
||||
return try_round2_seed((seed << 16) | round2_lower_half, thread_num);
|
||||
},
|
||||
@@ -1405,7 +1404,7 @@ Action a_salvage_gci(
|
||||
|
||||
} else {
|
||||
// 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));
|
||||
@@ -1474,7 +1473,7 @@ Action a_find_decryption_seed(
|
||||
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 le_decrypt_buf = ciphertext.substr(0, max_plaintext_size);
|
||||
if (uses_v3_encryption(version)) {
|
||||
@@ -1622,13 +1621,17 @@ Action a_disassemble_quest_script(
|
||||
disassemble-quest-script [OPTIONS] [INPUT-FILENAME [OUTPUT-FILENAME]]\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\
|
||||
with one of the --dc-nte, --dc-v1, --dc-v2, --pc, --gc-nte, --gc, --gc-ep3,\n\
|
||||
--xb, or --bb options. newserv uses more descriptive opcode mnemonics by\n\
|
||||
default; the --qedit option will result in names matching those used by\n\
|
||||
QEdit. If you intend to reassemble the script, after editing it, use the\n\
|
||||
--reassembly option to add explicit label numbers and remove offsets and\n\
|
||||
data in code sections. To include script references from the map, use the\n\
|
||||
--map-file=FILENAME option.\n",
|
||||
with one of the --dc-nte, --dc-v1, --dc-v2, --pc, --gc-nte, --gc,\n\
|
||||
--gc-ep3, --xb, or --bb options. Other options:\n\
|
||||
--qedit: newserv uses more descriptive opcode mnemonics by default; this\n\
|
||||
option will result in names matching those used by QEdit.\n\
|
||||
--reassembly: If you intend to reassemble the script after editing it,\n\
|
||||
use this option to add explicit label numbers and remove offsets and\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) {
|
||||
string data = read_input_data(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)));
|
||||
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 use_qedit_names = args.get<bool>("qedit");
|
||||
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",
|
||||
a_extract_archive_fn);
|
||||
|
||||
Action a_encode_sjis(
|
||||
"transcode-text", nullptr, +[](phosg::Arguments& args) {
|
||||
Action a_transcode_text("transcode-text", nullptr, +[](phosg::Arguments& args) {
|
||||
TextTranscoder* tt_from = nullptr;
|
||||
{
|
||||
std::string from_name = args.get<std::string>("from");
|
||||
@@ -1958,8 +1961,7 @@ Action a_encode_sjis(
|
||||
if (tt_to) {
|
||||
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(
|
||||
"decode-text-archive", "\
|
||||
@@ -2199,6 +2201,25 @@ Action a_download_files(
|
||||
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(
|
||||
"convert-rare-item-set", "\
|
||||
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 == "-")) {
|
||||
throw runtime_error("input filename must be given");
|
||||
}
|
||||
|
||||
string input_filename_lower = phosg::tolower(input_filename);
|
||||
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");
|
||||
}
|
||||
|
||||
auto rs = load_rare_item_set(
|
||||
input_filename, is_v1(get_cli_version(args, Version::BB_V4)), s->item_name_index(Version::BB_V4));
|
||||
if (rate_factor != 1.0) {
|
||||
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");
|
||||
}
|
||||
});
|
||||
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(
|
||||
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 {
|
||||
auto& info = this->card_infos[index];
|
||||
if (!info.large_filename.empty()) {
|
||||
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.large_filename));
|
||||
img.resize(512, 399);
|
||||
info.large_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
if (!info.medium_filename.empty()) {
|
||||
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.medium_filename));
|
||||
img.resize(184, 144);
|
||||
info.medium_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
if (!info.small_filename.empty()) {
|
||||
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.small_filename));
|
||||
img.resize(58, 43);
|
||||
info.small_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
0, this->card_infos.size(), num_threads);
|
||||
phosg::parallel_range(
|
||||
this->card_infos, [&](CardInfo& info, size_t) -> bool {
|
||||
if (!info.large_filename.empty()) {
|
||||
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.large_filename));
|
||||
img.resize(512, 399);
|
||||
info.large_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
if (!info.medium_filename.empty()) {
|
||||
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.medium_filename));
|
||||
img.resize(184, 144);
|
||||
info.medium_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
if (!info.small_filename.empty()) {
|
||||
auto img = phosg::ImageRGBA8888N::from_file_data(phosg::load_file(info.small_filename));
|
||||
img.resize(58, 43);
|
||||
info.small_data_url = img.serialize(phosg::ImageFormat::PNG_DATA_URL);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
num_threads);
|
||||
}
|
||||
|
||||
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");
|
||||
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");
|
||||
for (size_t type_ss = 0; type_ss < static_cast<size_t>(EnemyType::MAX_ENEMY_TYPE); type_ss++) {
|
||||
EnemyType type = static_cast<EnemyType>(type_ss);
|
||||
for (auto type : phosg::EnumRange<EnemyType>()) {
|
||||
bool any_count_nonzero = false;
|
||||
array<size_t, NUM_VERSIONS> counts;
|
||||
for (Version v : ALL_NON_PATCH_VERSIONS) {
|
||||
@@ -3319,7 +3349,7 @@ Action a_optimize_materialized_map(
|
||||
|
||||
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(
|
||||
@@ -3605,7 +3635,7 @@ Action a_generate_all_dc_serial_numbers(
|
||||
found_counts[7].load(), serial_numbers[7].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) {
|
||||
throw logic_error("mismatches occurred during test");
|
||||
@@ -3749,7 +3779,7 @@ Action a_replay_ep3_battle_commands(
|
||||
run_replay(base_seed, 0);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
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")) {
|
||||
state->is_debug = true;
|
||||
}
|
||||
|
||||
+54
-12
@@ -866,9 +866,10 @@ static const vector<DATEntityDefinition> dat_object_definitions({
|
||||
// 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
|
||||
// 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
|
||||
// the player; if not equal to 0x00010000, then both room_id and room_id2 are set and no game flag is set
|
||||
// (TODO: What are the visible behavior differences due to this parameter?)
|
||||
// param6 = on v2 and before, this is ignored; on v3 and later, if param6 is equal to 0x00010000, only the
|
||||
// player's room_id field is set, and player flag 0x02000000 is set on the player; if not equal to 0x00010000,
|
||||
// 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"},
|
||||
|
||||
// Sensor of some kind (TODO). Params:
|
||||
@@ -1372,10 +1373,10 @@ static const vector<DATEntityDefinition> dat_object_definitions({
|
||||
|
||||
// Item box. Params:
|
||||
// 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)
|
||||
// param3 = if zero, then only data1[0-1] are used and the rest of the ItemData is cleared, then bonuses, grinds,
|
||||
// etc. are applied to the item; if nonzero, the item is not randomized at all and drops exactly as specified
|
||||
// in param4-6
|
||||
// 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] (the high 2 bytes of param4) are used and the rest of the ItemData is
|
||||
// cleared, then bonuses, grinds, etc. are applied to the item; if nonzero, the item is not randomized at all
|
||||
// and drops exactly as specified in param4-6
|
||||
// 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
|
||||
// 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
|
||||
{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)
|
||||
// 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)
|
||||
@@ -3445,9 +3447,49 @@ void MapFile::RandomState::generate_shuffled_location_table(
|
||||
}
|
||||
|
||||
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,
|
||||
0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE0, 0xE1};
|
||||
0x0044, /* TObjEneBeast */
|
||||
0x0043, /* TObjEneBm5Wolf */
|
||||
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) {
|
||||
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
|
||||
if (ene_st->super_ene == ene) {
|
||||
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);
|
||||
ene_st->game_flags = entry.flags;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@ constexpr uint32_t PATCH_SWITCHES = 0x11666611;
|
||||
constexpr uint32_t PROGRAMS = 0x11777711;
|
||||
constexpr uint32_t DISCONNECT = 0x11888811;
|
||||
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 ClearLicenseConfirmationMenuItemID {
|
||||
|
||||
@@ -721,7 +721,7 @@ const ChallengeTemplateDefinition& get_challenge_template_definition(Version ver
|
||||
}
|
||||
|
||||
PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto)
|
||||
: unknown_a1(proto.unknown_a1),
|
||||
: expiration_frames(proto.expiration_frames),
|
||||
unknown_a2(proto.unknown_a2),
|
||||
unknown_a3(0),
|
||||
trigger_radius2(proto.trigger_radius2),
|
||||
@@ -730,7 +730,7 @@ PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto)
|
||||
|
||||
PlayerHoldState::operator PlayerHoldState_DCProtos() const {
|
||||
PlayerHoldState_DCProtos ret;
|
||||
ret.unknown_a1 = this->unknown_a1;
|
||||
ret.expiration_frames = this->expiration_frames;
|
||||
ret.unknown_a2 = this->unknown_a2;
|
||||
ret.trigger_radius2 = this->trigger_radius2;
|
||||
ret.x = this->x;
|
||||
|
||||
@@ -64,6 +64,12 @@ struct PlayerVisualConfigT {
|
||||
// F = force, R = ranger, H = hunter
|
||||
// A = android, N = newman, M = human
|
||||
// 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;
|
||||
/* 38 */ U16T<BE> costume = 0;
|
||||
/* 3A */ U16T<BE> skin = 0;
|
||||
@@ -1123,7 +1129,7 @@ struct TelepipeState {
|
||||
|
||||
struct PlayerHoldState_DCProtos {
|
||||
// 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;
|
||||
// unknown_a3 is missing in this format, unlike the v1+ format below
|
||||
/* 04 */ le_float trigger_radius2 = 0.0f;
|
||||
@@ -1134,7 +1140,7 @@ struct PlayerHoldState_DCProtos {
|
||||
|
||||
struct PlayerHoldState {
|
||||
// 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;
|
||||
/* 04 */ le_uint32_t unknown_a3 = 0;
|
||||
/* 08 */ le_float trigger_radius2 = 0.0f;
|
||||
|
||||
+20
-6
@@ -960,7 +960,8 @@ static asio::awaitable<HandlerResult> SC_6x60_6xA2(shared_ptr<Client> c, Channel
|
||||
if (rec.obj_st) {
|
||||
if (rec.ignore_def) {
|
||||
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 {
|
||||
c->log.info_f("Creating item from box {:04X} (area {:02X}; specialized with {:g} {:08X} {:08X} {:08X})",
|
||||
cmd.entity_index, cmd.effective_area,
|
||||
@@ -970,7 +971,8 @@ static asio::awaitable<HandlerResult> SC_6x60_6xA2(shared_ptr<Client> c, Channel
|
||||
}
|
||||
} else {
|
||||
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()) {
|
||||
@@ -1022,8 +1024,15 @@ static asio::awaitable<HandlerResult> S_6x(shared_ptr<Client> c, Channel::Messag
|
||||
case 0x17: {
|
||||
const auto& cmd = msg.check_size_t<G_SetEntityPositionAndAngle_6x17>();
|
||||
if (cmd.header.entity_id == c->lobby_client_id) {
|
||||
c->log.warning_f("Blocking subcommand 6x17 targeting local client");
|
||||
co_return HandlerResult::SUPPRESS;
|
||||
// Vol Opt phase 1 -> phase 2 uses 6x17 targeting the local client to move
|
||||
// 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;
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
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;
|
||||
if (c->override_lobby_event != 0xFF) {
|
||||
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) {
|
||||
error_str = "Server channel\ndisconnected";
|
||||
} 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 {
|
||||
error_str = e.what();
|
||||
}
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
mutex result_lock;
|
||||
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 {
|
||||
string ret = decrypt_download_quest_data_section<BE>(data_section, size, seed, skip_checksum, is_ep3_trial);
|
||||
lock_guard<mutex> g(result_lock);
|
||||
|
||||
+8
-6
@@ -676,7 +676,7 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
|
||||
// Sets a player's starting position.
|
||||
// valueA = client ID
|
||||
// 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},
|
||||
|
||||
// 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[3] = radius
|
||||
// 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},
|
||||
|
||||
// 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},
|
||||
|
||||
// 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},
|
||||
|
||||
// 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},
|
||||
|
||||
// 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
|
||||
{0xF8CC, "set_slot_poison", 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)
|
||||
{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
|
||||
// with del_obj_param, move_coords_object, etc. set_obj_param_ex is the same as set_obj_param, since set_obj_param
|
||||
// already returns an object token.
|
||||
// These are the same as their counterparts without _ex, but these also return the object ID (which is distinct
|
||||
// from the object token) in regB. There is a bug in set_obj_param_ex - the object token is not returned anywhere,
|
||||
// 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},
|
||||
{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},
|
||||
|
||||
+172
-89
@@ -177,23 +177,31 @@ RareItemSet::ParsedRELData::ParsedRELData(phosg::StringReader r, bool big_endian
|
||||
}
|
||||
|
||||
RareItemSet::ParsedRELData::ParsedRELData(const SpecCollection& collection) {
|
||||
for (const auto& specs : collection.rt_index_to_specs) {
|
||||
ExpandedDrop effective_spec;
|
||||
this->monster_rares.resize(NUM_RT_INDEXES_V4);
|
||||
|
||||
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) {
|
||||
if (effective_spec.data.empty()) {
|
||||
effective_spec = spec;
|
||||
} else if ((effective_spec.probability != spec.probability) || (effective_spec.data != spec.data)) {
|
||||
throw runtime_error("monster spec cannot be converted to ItemRT format");
|
||||
if (dest_spec.data.empty()) {
|
||||
dest_spec = spec;
|
||||
} else if ((dest_spec.probability != spec.probability) || (dest_spec.data != spec.data)) {
|
||||
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");
|
||||
}
|
||||
for (uint8_t area_norm = 0; area_norm < collection.box_area_norm_to_specs.size(); area_norm++) {
|
||||
for (const auto& spec : collection.box_area_norm_to_specs[area_norm]) {
|
||||
for (uint8_t area_norm = 0; area_norm < collection.box_specs.size(); area_norm++) {
|
||||
for (const auto& spec : collection.box_specs[area_norm]) {
|
||||
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});
|
||||
}
|
||||
@@ -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;
|
||||
for (size_t z = 0; z < this->monster_rares.size(); z++) {
|
||||
const auto& drop = this->monster_rares[z];
|
||||
for (size_t rt_index = 0; rt_index < this->monster_rares.size(); rt_index++) {
|
||||
const auto& drop = this->monster_rares[rt_index];
|
||||
if (drop.data.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (z >= ret.rt_index_to_specs.size()) {
|
||||
ret.rt_index_to_specs.resize(z + 1);
|
||||
for (auto enemy_type : enemy_types_for_rare_table_index(episode, rt_index)) {
|
||||
ret.enemy_specs[enemy_type].emplace_back(drop);
|
||||
}
|
||||
ret.rt_index_to_specs[z].emplace_back(drop);
|
||||
}
|
||||
for (const auto& drop : this->box_rares) {
|
||||
if ((drop.area_norm_plus_1 == 0) || drop.drop.data.empty()) {
|
||||
continue;
|
||||
}
|
||||
uint8_t area_norm = drop.area_norm_plus_1 - 1;
|
||||
if (area_norm >= ret.box_area_norm_to_specs.size()) {
|
||||
ret.box_area_norm_to_specs.resize(area_norm + 1);
|
||||
if (area_norm >= ret.box_specs.size()) {
|
||||
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;
|
||||
}
|
||||
@@ -241,8 +248,7 @@ RareItemSet::RareItemSet(const AFSArchive& afs, bool is_v1) {
|
||||
size_t index = static_cast<size_t>(difficulty) * 10 + section_id;
|
||||
ParsedRELData rel(afs.get_reader(index), false, is_v1);
|
||||
this->collections.emplace(
|
||||
this->key_for_params(mode, Episode::EP1, difficulty, section_id),
|
||||
rel.as_collection());
|
||||
this->key_for_params(mode, Episode::EP1, difficulty, section_id), rel.as_collection(Episode::EP1));
|
||||
} 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",
|
||||
((mode == GameMode::CHALLENGE) ? "c" : ""),
|
||||
((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) {
|
||||
for (GameMode mode : ALL_GAME_MODES_V23) {
|
||||
for (GameMode mode : {GameMode::NORMAL, GameMode::CHALLENGE}) {
|
||||
for (Episode episode : ALL_EPISODES_V3) {
|
||||
for (Difficulty difficulty : ALL_DIFFICULTIES_V234) {
|
||||
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);
|
||||
ParsedRELData rel(gsl.get_reader(filename), is_big_endian, false);
|
||||
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&) {
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
ParsedRELData rel(r.sub(0x280 * index, 0x280), is_big_endian, false);
|
||||
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&) {
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
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;
|
||||
if (item_it.first.starts_with("Box-")) {
|
||||
uint8_t area_norm = FloorDefinition::get(episode, item_it.first.substr(4)).drop_area_norm;
|
||||
if (collection.box_area_norm_to_specs.size() <= area_norm) {
|
||||
collection.box_area_norm_to_specs.resize(area_norm + 1);
|
||||
if (enemy_type_name.starts_with("Box-")) {
|
||||
uint8_t area_norm = FloorDefinition::get(episode, enemy_type_name.substr(4)).drop_area_norm;
|
||||
if (collection.box_specs.size() <= area_norm) {
|
||||
collection.box_specs.resize(area_norm + 1);
|
||||
}
|
||||
target = &collection.box_area_norm_to_specs[area_norm];
|
||||
target = &collection.box_specs[area_norm];
|
||||
} else {
|
||||
size_t rt_index = type_definition_for_enemy(phosg::enum_for_name<EnemyType>(item_it.first)).rt_index;
|
||||
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];
|
||||
target = &collection.enemy_specs[phosg::enum_for_name<EnemyType>(enemy_type_name)];
|
||||
}
|
||||
|
||||
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 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);
|
||||
if (common_item_set && type_def && type_def->rt_index != 0xFF) {
|
||||
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);
|
||||
frac.first *= dar;
|
||||
frac.second *= 100;
|
||||
@@ -747,13 +751,9 @@ string RareItemSet::serialize_html(
|
||||
for (const auto& zone_type : zone_types) {
|
||||
add_location_header(zone_type.name);
|
||||
for (EnemyType type : zone_type.types) {
|
||||
uint8_t rt_index = type_definition_for_enemy(type).rt_index;
|
||||
if (rt_index == 0xFF) {
|
||||
continue;
|
||||
}
|
||||
array<vector<ExpandedDrop>, 10> specs_lists;
|
||||
for (uint8_t section_id = 0; section_id < 10; section_id++) {
|
||||
specs_lists[section_id] = this->get_enemy_specs(mode, episode, difficulty, section_id, rt_index);
|
||||
specs_lists[section_id] = this->get_enemy_specs(mode, episode, difficulty, section_id, 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;
|
||||
@@ -787,13 +787,9 @@ phosg::JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const
|
||||
auto section_id_dict = phosg::JSON::dict();
|
||||
for (uint8_t section_id = 0; section_id < 10; section_id++) {
|
||||
auto collection_dict = phosg::JSON::dict();
|
||||
for (size_t rt_index = 0; rt_index < 0x80; rt_index++) {
|
||||
const auto& enemy_types = enemy_types_for_rare_table_index(episode, rt_index);
|
||||
if (enemy_types.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& spec : this->get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, rt_index)) {
|
||||
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
|
||||
const auto& specs = this->get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, enemy_type);
|
||||
for (const auto& spec : specs) {
|
||||
if (spec.data.empty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -807,12 +803,8 @@ phosg::JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const
|
||||
if (name_index) {
|
||||
spec_json.emplace_back(name_index->describe_item(spec.data));
|
||||
}
|
||||
for (const auto& enemy_type : enemy_types) {
|
||||
if (type_definition_for_enemy(enemy_type).valid_in_episode(episode)) {
|
||||
phosg::JSON this_spec_json = spec_json;
|
||||
collection_dict.emplace(phosg::name_for_enum(enemy_type), phosg::JSON::list()).first->second->emplace_back(std::move(this_spec_json));
|
||||
}
|
||||
}
|
||||
auto list_emplace_ret = collection_dict.emplace(phosg::name_for_enum(enemy_type), phosg::JSON::list());
|
||||
list_emplace_ret.first->second->emplace_back(std::move(spec_json));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -858,17 +850,17 @@ phosg::JSON RareItemSet::json(shared_ptr<const ItemNameIndex> name_index) const
|
||||
}
|
||||
|
||||
void RareItemSet::multiply_all_rates(double factor) {
|
||||
auto multiply_rates_vec = +[](vector<vector<ExpandedDrop>>& vec, double factor) -> void {
|
||||
for (auto& vec_it : vec) {
|
||||
for (auto& z_it : vec_it) {
|
||||
uint64_t new_probability = z_it.probability * factor;
|
||||
z_it.probability = min<uint64_t>(new_probability, 0xFFFFFFFF);
|
||||
for (auto& [_, collection] : this->collections) {
|
||||
for (auto& [_, specs] : collection.enemy_specs) {
|
||||
for (auto& spec : specs) {
|
||||
spec.probability = min<uint64_t>(spec.probability * factor, 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));
|
||||
|
||||
phosg::fwrite_fmt(stream, " Monster rares:\n");
|
||||
for (size_t z = 0; z < collection->rt_index_to_specs.size(); z++) {
|
||||
string enemy_types_str;
|
||||
const auto& enemy_types = enemy_types_for_rare_table_index(episode, z);
|
||||
for (EnemyType enemy_type : enemy_types) {
|
||||
enemy_types_str += phosg::name_for_enum(enemy_type);
|
||||
enemy_types_str.push_back(',');
|
||||
}
|
||||
if (!enemy_types_str.empty()) {
|
||||
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);
|
||||
for (auto enemy_type : phosg::EnumRange<EnemyType>()) {
|
||||
try {
|
||||
const auto& def = type_definition_for_enemy(enemy_type);
|
||||
for (const auto& spec : collection->enemy_specs.at(enemy_type)) {
|
||||
string s = name_index ? spec.str(name_index) : spec.str();
|
||||
phosg::fwrite_fmt(stream, " {:<23} {}\n", def.enum_name, s);
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
|
||||
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 (const auto& spec : collection->box_area_norm_to_specs[area_norm]) {
|
||||
for (size_t area_norm = 0; area_norm < collection->box_specs.size(); area_norm++) {
|
||||
for (const auto& spec : collection->box_specs[area_norm]) {
|
||||
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(
|
||||
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 {
|
||||
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&) {
|
||||
static const std::vector<ExpandedDrop> 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(
|
||||
GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t area_norm) const {
|
||||
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&) {
|
||||
static const std::vector<ExpandedDrop> 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(
|
||||
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) {
|
||||
|
||||
+15
-6
@@ -22,6 +22,9 @@ public:
|
||||
uint32_t probability = 0;
|
||||
ItemData data;
|
||||
|
||||
bool operator==(const ExpandedDrop& other) const = default;
|
||||
bool operator!=(const ExpandedDrop& other) const = default;
|
||||
|
||||
std::string str() const;
|
||||
std::string str(std::shared_ptr<const ItemNameIndex> name_index) const;
|
||||
};
|
||||
@@ -34,7 +37,7 @@ public:
|
||||
~RareItemSet() = default;
|
||||
|
||||
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(
|
||||
GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t area_norm) const;
|
||||
|
||||
@@ -60,11 +63,17 @@ public:
|
||||
uint8_t section_id,
|
||||
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:
|
||||
struct SpecCollection {
|
||||
std::vector<std::vector<ExpandedDrop>> rt_index_to_specs;
|
||||
std::vector<std::vector<ExpandedDrop>> box_area_norm_to_specs;
|
||||
std::unordered_map<EnemyType, std::vector<ExpandedDrop>> enemy_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 {
|
||||
@@ -95,8 +104,8 @@ protected:
|
||||
ExpandedDrop drop;
|
||||
};
|
||||
|
||||
std::vector<ExpandedDrop> monster_rares;
|
||||
std::vector<BoxRare> box_rares;
|
||||
std::vector<ExpandedDrop> monster_rares; // Indexed by rt_index
|
||||
std::vector<BoxRare> box_rares; // Not indexed (area_norm + 1 is in the struct)
|
||||
|
||||
ParsedRELData() = default;
|
||||
ParsedRELData(phosg::StringReader r, bool big_endian, bool is_v1);
|
||||
@@ -108,7 +117,7 @@ protected:
|
||||
template <bool BE>
|
||||
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;
|
||||
|
||||
+612
-70
File diff suppressed because it is too large
Load Diff
+370
-88
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <phosg/Random.hh>
|
||||
#include <phosg/Strings.hh>
|
||||
@@ -76,6 +78,184 @@ using SDF = SubcommandDefinition::Flag;
|
||||
|
||||
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) {
|
||||
static bool populated = false;
|
||||
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>
|
||||
asio::awaitable<void> forward_subcommand_with_entity_targets_transcode_and_track_hits_t(
|
||||
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)) {
|
||||
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)) {
|
||||
auto ene_st = l->map_state->enemy_state_for_index(c->version(), res.entity_id - 0x1000);
|
||||
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);
|
||||
l->log.info_f("E-{:03X} last hit claimed", ene_st->e_id);
|
||||
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);
|
||||
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)) {
|
||||
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),
|
||||
hold_state(cmd.hold_state),
|
||||
area(cmd.area),
|
||||
game_flags(cmd.game_flags),
|
||||
game_flags_is_v3(false),
|
||||
player_flags(cmd.player_flags),
|
||||
player_flags_is_v3(false),
|
||||
visual(cmd.visual),
|
||||
stats(cmd.stats),
|
||||
num_items(cmd.num_items),
|
||||
@@ -839,8 +1015,8 @@ Parsed6x70Data::Parsed6x70Data(
|
||||
death_flags(cmd.death_flags),
|
||||
hold_state(cmd.hold_state),
|
||||
area(cmd.area),
|
||||
game_flags(cmd.game_flags),
|
||||
game_flags_is_v3(false),
|
||||
player_flags(cmd.player_flags),
|
||||
player_flags_is_v3(false),
|
||||
visual(cmd.visual),
|
||||
stats(cmd.stats),
|
||||
num_items(cmd.num_items),
|
||||
@@ -872,7 +1048,7 @@ Parsed6x70Data::Parsed6x70Data(
|
||||
Version from_version,
|
||||
bool 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->num_items = cmd.num_items;
|
||||
this->items = cmd.items;
|
||||
@@ -888,7 +1064,7 @@ Parsed6x70Data::Parsed6x70Data(
|
||||
Version from_version,
|
||||
bool 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->num_items = cmd.num_items;
|
||||
this->items = cmd.items;
|
||||
@@ -904,7 +1080,7 @@ Parsed6x70Data::Parsed6x70Data(
|
||||
Version from_version,
|
||||
bool 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->num_items = cmd.num_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.hold_state = this->hold_state;
|
||||
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.stats = this->stats;
|
||||
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.hold_state = this->hold_state;
|
||||
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.stats = this->stats;
|
||||
ret.num_items = this->num_items;
|
||||
@@ -1112,7 +1288,7 @@ Parsed6x70Data::Parsed6x70Data(
|
||||
temporary_status_effect(base.temporary_status_effect),
|
||||
attack_status_effect(base.attack_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())),
|
||||
player_tag(base.player_tag),
|
||||
guild_card_number(guild_card_number), // Ignore the client's GC#
|
||||
@@ -1122,8 +1298,8 @@ Parsed6x70Data::Parsed6x70Data(
|
||||
death_flags(base.death_flags),
|
||||
hold_state(base.hold_state),
|
||||
area(base.area),
|
||||
game_flags(base.game_flags),
|
||||
game_flags_is_v3(!is_v1_or_v2(from_version)),
|
||||
player_flags(base.player_flags),
|
||||
player_flags_is_v3(!is_v1_or_v2(from_version)),
|
||||
technique_levels_v1(base.technique_levels_v1),
|
||||
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.attack_status_effect = this->attack_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.player_tag = this->player_tag;
|
||||
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.hold_state = this->hold_state;
|
||||
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.visual = this->visual;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t Parsed6x70Data::convert_game_flags(uint32_t game_flags, bool to_v3) {
|
||||
// The format of game_flags for players was changed significantly between v2 and v3, and not accounting for this
|
||||
// results in odd effects like other characters not appearing when joining a game. Unfortunately, some bits were
|
||||
// deleted on v3 and other bits were added, so it doesn't suffice to simply store the most complete format of this
|
||||
// field - we have to be able to convert between the two.
|
||||
|
||||
// Bits on v2: JIHCBAzy xwvutsrq ponmlkji hgfedcba
|
||||
// Bits on v3: JIHGFEDC BAzyxwvu srqponkj hgfedcba
|
||||
// The bits ilmt were removed in v3 and the bits to their left were shifted right. The bits DEFG were added in v3 and
|
||||
// do not exist on v2. Known meanings for these bits so far:
|
||||
// o = is dead
|
||||
// n = should play hit animation
|
||||
// y = is near enemy
|
||||
// H = is enemy?
|
||||
// I = is object? (some entities have both H and I set though)
|
||||
// J = is item
|
||||
uint32_t Parsed6x70Data::convert_player_flags(uint32_t player_flags, bool to_v3) {
|
||||
// The format of player_flags was changed significantly between v2 and v3, and not accounting for this results in odd
|
||||
// effects like other characters not appearing when joining a game. Unfortunately, some bits were deleted on v3 and
|
||||
// other bits were added, so it doesn't suffice to simply store the most complete format of this field - we have to
|
||||
// be able to convert between the two. What's known about these bits (? indicates meaning/behavior is unverified):
|
||||
// V1/V2 V3/V4
|
||||
// 00000001 00000001 = player hold is set (see notes on 6x2C and 6x2D in CommandFormats.hh)
|
||||
// 00000002 00000002 = player hold is set for the purpose of dropping an item
|
||||
// 00000004 00000004 = is on a different floor from the local player (or is loading into game)
|
||||
// 00000008 00000008 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
|
||||
// 00000010 00000010 = player has sent any update command (position, attack, etc.) this frame
|
||||
// 00000020 00000020 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
|
||||
// 00000040 00000040 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
|
||||
// 00000080 00000080 = is in windup animation for technique or PB
|
||||
// 00000100 -------- = unknown (TODO: appears to be entirely unused, at least in v2)
|
||||
// 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) {
|
||||
return (game_flags & 0xE00000FF) |
|
||||
((game_flags & 0x00000600) >> 1) |
|
||||
((game_flags & 0x0007E000) >> 3) |
|
||||
((game_flags & 0x1FF00000) >> 4);
|
||||
return (player_flags & 0x000000FF) |
|
||||
((player_flags & 0x00000600) >> 1) |
|
||||
((player_flags & 0x0007E000) >> 3) |
|
||||
((player_flags & 0x1FF00000) >> 4);
|
||||
} else {
|
||||
return (game_flags & 0xE00000FF) |
|
||||
((game_flags << 1) & 0x00000600) |
|
||||
((game_flags << 3) & 0x0007E000) |
|
||||
((game_flags << 4) & 0x1FF00000);
|
||||
return (player_flags & 0x000000FF) |
|
||||
((player_flags << 1) & 0x00000600) |
|
||||
((player_flags << 3) & 0x0007E000) |
|
||||
((player_flags << 4) & 0x1FF00000);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Parsed6x70Data::get_game_flags(bool is_v3) const {
|
||||
return (this->game_flags_is_v3 == is_v3)
|
||||
? this->game_flags
|
||||
: Parsed6x70Data::convert_game_flags(this->game_flags, is_v3);
|
||||
uint32_t Parsed6x70Data::get_player_flags(bool is_v3) const {
|
||||
return (this->player_flags_is_v3 == is_v3)
|
||||
? this->player_flags
|
||||
: Parsed6x70Data::convert_player_flags(this->player_flags, is_v3);
|
||||
}
|
||||
|
||||
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&) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
@@ -1647,8 +1864,23 @@ static asio::awaitable<void> on_player_revivable(shared_ptr<Client> c, Subcomman
|
||||
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);
|
||||
|
||||
if (hardcore_death) {
|
||||
send_message_box(c, "DADDY FALZ WINS");
|
||||
c->channel->disconnect();
|
||||
co_return;
|
||||
}
|
||||
|
||||
// Revive if infinite HP is enabled
|
||||
bool player_cheats_enabled = l->check_flag(Lobby::Flag::CHEATS_ENABLED) ||
|
||||
(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();
|
||||
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);
|
||||
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)) {
|
||||
@@ -2241,6 +2484,15 @@ static asio::awaitable<void> on_pick_up_item_generic(
|
||||
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 {
|
||||
p->add_item(fi->data, *s->item_stack_limits(c->version()));
|
||||
} catch (const out_of_range&) {
|
||||
@@ -2810,7 +3062,7 @@ DropReconcileResult reconcile_drop_request_with_map(
|
||||
bool is_box = (cmd.rt_index == 0x30);
|
||||
|
||||
DropReconcileResult res;
|
||||
res.effective_rt_index = 0xFF;
|
||||
res.effective_enemy_type = EnemyType::UNKNOWN;
|
||||
res.should_drop = true;
|
||||
res.ignore_def = (cmd.ignore_def != 0);
|
||||
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.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);
|
||||
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 {})",
|
||||
res.ref_ene_st->e_id, res.target_ene_st->e_id, phosg::name_for_enum(type));
|
||||
res.effective_rt_index = type_definition_for_enemy(type).rt_index;
|
||||
res.ref_ene_st->e_id, res.target_ene_st->e_id, phosg::name_for_enum(res.effective_enemy_type));
|
||||
uint8_t expected_rt_index = type_definition_for_enemy(res.effective_enemy_type).rt_index;
|
||||
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
|
||||
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);
|
||||
res.effective_rt_index = 0x27;
|
||||
} else if (cmd.rt_index == 0x23 && type == EnemyType::DARK_GUNNER) {
|
||||
res.effective_enemy_type = EnemyType::BULK;
|
||||
} 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);
|
||||
res.effective_rt_index = 0x23;
|
||||
res.effective_enemy_type = EnemyType::DEATH_GUNNER;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -2881,9 +3133,10 @@ DropReconcileResult reconcile_drop_request_with_map(
|
||||
}
|
||||
if (c->check_flag(Client::Flag::DEBUG_ENABLED)) {
|
||||
std::string rt_index_str = mismatched_rt_index
|
||||
? std::format(" $C4{:02X}->{:02X}$C5", cmd.rt_index, res.effective_rt_index)
|
||||
: std::format(" {:02X}", res.effective_rt_index);
|
||||
send_text_message_fmt(c, "$C5E-{:03X}{} {}", res.target_ene_st->e_id, rt_index_str, phosg::name_for_enum(type));
|
||||
? std::format(" $C4{:02X}->{:02X}$C5", cmd.rt_index, expected_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(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) {
|
||||
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.ignore_def) {
|
||||
l->log.info_f("Creating item from box {:04X} => K-{:03X} (area {:02X})",
|
||||
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 {
|
||||
l->log.info_f(
|
||||
"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) {
|
||||
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);
|
||||
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 {
|
||||
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");
|
||||
case ServerDropMode::SERVER_SHARED:
|
||||
case ServerDropMode::SERVER_DUPLICATE: {
|
||||
auto res = generate_item();
|
||||
auto res = generate_item_for_client(c);
|
||||
if (res.item.empty()) {
|
||||
l->log.info_f("No item was created");
|
||||
} else {
|
||||
@@ -3023,7 +3277,7 @@ static asio::awaitable<void> on_entity_drop_item_request(shared_ptr<Client> c, S
|
||||
case ServerDropMode::SERVER_PRIVATE: {
|
||||
for (const auto& lc : l->clients) {
|
||||
if (lc && (rec.obj_st || (lc->floor == cmd.floor))) {
|
||||
auto res = generate_item();
|
||||
auto res = generate_item_for_client(lc);
|
||||
if (res.item.empty()) {
|
||||
l->log.info_f("No item was created for {}", lc->channel->name);
|
||||
} 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);
|
||||
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) {
|
||||
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->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 (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->total_damage = cmd.total_damage;
|
||||
l->log.info_f("Alias target E-{:03X} updated to damage={} game_flags={:08X}",
|
||||
ene_st->alias_target_ene_st->e_id, ene_st->alias_target_ene_st->total_damage, ene_st->alias_target_ene_st->game_flags);
|
||||
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, 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
|
||||
@@ -3492,8 +3758,18 @@ static asio::awaitable<void> on_incr_enemy_damage(shared_ptr<Client> c, Subcomma
|
||||
cmd.total_damage_before_hit.load(),
|
||||
cmd.current_hp_before_hit.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);
|
||||
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 + 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);
|
||||
}
|
||||
|
||||
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>();
|
||||
|
||||
if (command_is_private(msg.command) ||
|
||||
(cmd.header.entity_id < 0x1000) ||
|
||||
(cmd.header.entity_id >= 0x4000) ||
|
||||
(cmd.low_game_flags & 0xFFFFFFC0) ||
|
||||
(cmd.status_effect_flags & 0xFFFFFFC0) ||
|
||||
(c->lobby_client_id > 3)) {
|
||||
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);
|
||||
if (!(ene_st->game_flags & cmd.low_game_flags)) {
|
||||
ene_st->game_flags |= cmd.low_game_flags;
|
||||
if (!(ene_st->game_flags & cmd.status_effect_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);
|
||||
}
|
||||
if (ene_st->alias_target_ene_st && !(ene_st->alias_target_ene_st->game_flags & cmd.low_game_flags)) {
|
||||
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.status_effect_flags;
|
||||
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);
|
||||
}
|
||||
@@ -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
|
||||
// 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).
|
||||
if (!ene_st->ever_hit_by_client_id(c->lobby_client_id) ||
|
||||
(ene_st->server_flags & MapState::EnemyState::Flag::EXP_GIVEN)) {
|
||||
if (!ene_st->ever_hit_by_client_id(c->lobby_client_id)) {
|
||||
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");
|
||||
co_return;
|
||||
}
|
||||
@@ -4248,9 +4527,6 @@ asio::awaitable<void> on_transfer_item_via_mail_message_bb(shared_ptr<Client> c,
|
||||
if (!l->is_game()) {
|
||||
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) {
|
||||
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) {
|
||||
auto l = c->require_lobby();
|
||||
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) {
|
||||
@@ -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) {
|
||||
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) {
|
||||
attribute_amount = 30;
|
||||
} 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;
|
||||
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))) {
|
||||
attribute_index = z;
|
||||
break;
|
||||
@@ -5401,8 +5675,16 @@ static asio::awaitable<void> on_upgrade_weapon_attribute_bb(shared_ptr<Client> c
|
||||
if (attribute_index == 0) {
|
||||
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 + 1] += attribute_amount;
|
||||
item.data1[attribute_index + 1] += new_attr_value;
|
||||
|
||||
send_destroy_item_to_lobby(c, item.id, 1);
|
||||
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},
|
||||
/* 6x9A */ {NONE, NONE, 0x9A, on_forward_check_game_client},
|
||||
/* 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},
|
||||
/* 6x9E */ {NONE, NONE, 0x9E, forward_subcommand_m},
|
||||
/* 6x9F */ {NONE, NONE, 0x9F, forward_subcommand_with_entity_id_transcode_t<G_GalGryphonBossActions_6x9F>},
|
||||
|
||||
@@ -23,7 +23,7 @@ struct DropReconcileResult {
|
||||
// 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> target_ene_st;
|
||||
uint8_t effective_rt_index;
|
||||
EnemyType effective_enemy_type;
|
||||
bool should_drop;
|
||||
bool ignore_def;
|
||||
};
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
StatusEffectState temporary_status_effect;
|
||||
StatusEffectState attack_status_effect;
|
||||
StatusEffectState defense_status_effect;
|
||||
StatusEffectState unused_status_effect;
|
||||
StatusEffectState unknown_a1_status_effect; // De Rol Le uses this?
|
||||
Language language = Language::JAPANESE;
|
||||
uint32_t player_tag = 0;
|
||||
uint32_t guild_card_number = 0;
|
||||
@@ -62,8 +62,8 @@ public:
|
||||
uint32_t death_flags = 0;
|
||||
PlayerHoldState hold_state;
|
||||
uint32_t area = 0;
|
||||
uint32_t game_flags = 0;
|
||||
bool game_flags_is_v3 = false;
|
||||
uint32_t player_flags = 0;
|
||||
bool player_flags_is_v3 = false;
|
||||
parray<uint8_t, 0x14> technique_levels_v1 = 0xFF;
|
||||
PlayerVisualConfig visual;
|
||||
std::string name;
|
||||
@@ -121,8 +121,8 @@ protected:
|
||||
Parsed6x70Data(
|
||||
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;
|
||||
static uint32_t convert_game_flags(uint32_t game_flags, bool to_v3);
|
||||
uint32_t get_game_flags(bool is_v3) const;
|
||||
static uint32_t convert_player_flags(uint32_t player_flags, bool to_v3);
|
||||
uint32_t get_player_flags(bool is_v3) const;
|
||||
};
|
||||
|
||||
bool validate_6xBB(G_SyncCardTradeServerState_Ep3_6xBB& cmd);
|
||||
|
||||
@@ -365,6 +365,9 @@ ReplaySession::ReplaySession(shared_ptr<ServerState> state, FILE* input_log, boo
|
||||
if (line == "### use psov2 crypt") {
|
||||
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 ")) {
|
||||
// ### cc $<chat command>
|
||||
if (this->clients.size() != 1) {
|
||||
|
||||
@@ -324,17 +324,17 @@ void PSOBBGuildCardFile::delete_duplicates() {
|
||||
{
|
||||
unordered_set<uint32_t> seen;
|
||||
size_t read_index = 0, write_index = 0;
|
||||
for (read_index = 0; read_index < this->blocked.size(); read_index++) {
|
||||
const auto& read_blocked = this->blocked[read_index];
|
||||
if (seen.emplace(read_blocked.guild_card_number).second) {
|
||||
for (read_index = 0; read_index < this->blocked_senders.size(); read_index++) {
|
||||
const auto& read_blocked_senders = this->blocked_senders[read_index];
|
||||
if (seen.emplace(read_blocked_senders.guild_card_number).second) {
|
||||
if (write_index != read_index) {
|
||||
this->blocked[write_index] = read_blocked;
|
||||
this->blocked_senders[write_index] = read_blocked_senders;
|
||||
}
|
||||
write_index++;
|
||||
}
|
||||
}
|
||||
for (; write_index < this->blocked.size(); write_index++) {
|
||||
this->blocked[write_index].clear();
|
||||
for (; write_index < this->blocked_senders.size(); write_index++) {
|
||||
this->blocked_senders[write_index].clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -994,7 +994,7 @@ struct PSOBBGuildCardFile {
|
||||
} __packed_ws__(Entry, 0x1BC);
|
||||
|
||||
/* 0000 */ PSOBBMinimalSystemFile system_file;
|
||||
/* 0114 */ parray<GuildCardBB, 0x1C> blocked;
|
||||
/* 0114 */ parray<GuildCardBB, 0x1C> blocked_senders;
|
||||
/* 1DF4 */ parray<uint8_t, 0x180> unknown_a2;
|
||||
/* 1F74 */ parray<Entry, 0x69> entries;
|
||||
/* D590 */
|
||||
|
||||
+103
-43
@@ -1,4 +1,5 @@
|
||||
#include "SendCommands.hh"
|
||||
#include "BattleParamsIndex.hh"
|
||||
|
||||
#include <inttypes.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);
|
||||
}
|
||||
|
||||
|
||||
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 = {
|
||||
"ItemMagEdit.prs",
|
||||
"ItemPMT.prs",
|
||||
@@ -705,24 +768,15 @@ static const vector<string> stream_file_entries = {
|
||||
void send_stream_file_index_bb(shared_ptr<Client> c) {
|
||||
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;
|
||||
size_t offset = 0;
|
||||
for (const string& filename : stream_file_entries) {
|
||||
string key = "system/blueburst/" + filename;
|
||||
auto cache_res = s->bb_stream_files_cache->get_or_load(key);
|
||||
auto file_data = bb_stream_file_data_for_client(c, filename);
|
||||
auto& e = entries.emplace_back();
|
||||
e.size = cache_res.file->data->size();
|
||||
// Computing the checksum can be slow, so we cache it along with the file data. If the cache result was just
|
||||
// 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.size = file_data->size();
|
||||
e.checksum = crc32(file_data->data(), e.size);
|
||||
e.offset = offset;
|
||||
e.filename.encode(filename);
|
||||
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) {
|
||||
auto s = c->require_server_state();
|
||||
|
||||
auto cache_result = s->bb_stream_files_cache->get(
|
||||
"<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();
|
||||
}
|
||||
c->log.info_f("PSO Peeps BBZ stream debug: send_stream_file_chunk_bb called for chunk {}", chunk_index);
|
||||
|
||||
string ret;
|
||||
ret.reserve(bytes);
|
||||
for (const auto& name : stream_file_entries) {
|
||||
ret += *s->bb_stream_files_cache->get_or_load("system/blueburst/" + name).file->data;
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
const auto& contents = cache_result.file->data;
|
||||
size_t total_bytes = 0;
|
||||
for (const auto& name : stream_file_entries) {
|
||||
total_bytes += bb_stream_file_data_for_client(c, name)->size();
|
||||
}
|
||||
|
||||
string contents;
|
||||
contents.reserve(total_bytes);
|
||||
for (const auto& name : stream_file_entries) {
|
||||
contents += *bb_stream_file_data_for_client(c, name);
|
||||
}
|
||||
|
||||
S_StreamFileChunk_BB_02EB chunk_cmd;
|
||||
chunk_cmd.chunk_index = 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");
|
||||
}
|
||||
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);
|
||||
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);
|
||||
|
||||
size_t cmd_size = offsetof(S_StreamFileChunk_BB_02EB, data) + bytes;
|
||||
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>
|
||||
void send_info_board_t(shared_ptr<Client> c) {
|
||||
vector<S_InfoBoardEntryT_D8<NameEncoding, MessageEncoding>> entries;
|
||||
auto l = c->require_lobby();
|
||||
for (const auto& other_c : l->clients) {
|
||||
if (!other_c.get()) {
|
||||
continue;
|
||||
|
||||
auto add_clients_from_lobby = [&](std::shared_ptr<Lobby> l) -> void {
|
||||
for (const auto& lc : l->clients) {
|
||||
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());
|
||||
e.message.encode(add_color(other_p->info_board.decode(other_p->inventory.language)), c->language());
|
||||
};
|
||||
|
||||
auto l = c->require_lobby();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2654,16 +2714,16 @@ asio::awaitable<void> send_change_player_hp(
|
||||
}
|
||||
|
||||
asio::awaitable<void> send_remove_negative_conditions(shared_ptr<Client> c) {
|
||||
G_AddStatusEffect_6x0C cmd;
|
||||
cmd.header = {0x0C, sizeof(G_AddStatusEffect_6x0C) >> 2, c->lobby_client_id};
|
||||
G_AddOrRemoveStatusEffect_6x0C_6x0D cmd;
|
||||
cmd.header = {0x0C, sizeof(G_AddOrRemoveStatusEffect_6x0C_6x0D) >> 2, c->lobby_client_id};
|
||||
cmd.effect_type = 7; // Healing ring
|
||||
cmd.amount = 0;
|
||||
co_await send_protected_command(c, &cmd, sizeof(cmd), true);
|
||||
}
|
||||
|
||||
void send_remove_negative_conditions(std::shared_ptr<Channel> ch, uint16_t client_id) {
|
||||
G_AddStatusEffect_6x0C cmd;
|
||||
cmd.header = {0x0C, sizeof(G_AddStatusEffect_6x0C) >> 2, client_id};
|
||||
G_AddOrRemoveStatusEffect_6x0C_6x0D cmd;
|
||||
cmd.header = {0x0C, sizeof(G_AddOrRemoveStatusEffect_6x0C_6x0D) >> 2, client_id};
|
||||
cmd.effect_type = 7; // Healing ring
|
||||
cmd.amount = 0;
|
||||
ch->send(0x60, 0x00, &cmd, sizeof(cmd));
|
||||
|
||||
+32
-5
@@ -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()),
|
||||
io_context(make_shared<asio::io_context>(1)),
|
||||
config_filename(config_filename),
|
||||
is_replay(is_replay),
|
||||
thread_pool(make_unique<asio::thread_pool>()),
|
||||
bb_stream_files_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()) {
|
||||
if (l == other_l) {
|
||||
continue; // don't bother looking again
|
||||
continue; // Don't bother looking again
|
||||
}
|
||||
try {
|
||||
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:
|
||||
return this->name_to_port_config.at("xb")->port;
|
||||
case Version::BB_V4:
|
||||
return this->name_to_port_config.at("xb")->port;
|
||||
return this->name_to_port_config.at("bb-data1")->port;
|
||||
default:
|
||||
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 {
|
||||
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)) {
|
||||
// TODO: We should probably have a v1 common item set at some point too
|
||||
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 {
|
||||
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)) {
|
||||
return this->rare_item_sets.at("rare-table-v1");
|
||||
} 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->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->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->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;
|
||||
|
||||
+11
-1
@@ -91,6 +91,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
||||
std::shared_ptr<const phosg::JSON> config_json;
|
||||
bool one_time_config_loaded = false;
|
||||
bool default_lobbies_created = false;
|
||||
bool is_replay = false;
|
||||
|
||||
size_t num_worker_threads = 0;
|
||||
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;
|
||||
bool default_switch_assist_enabled = 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 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 default_rare_notifs_enabled_v1_v2 = 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;
|
||||
|
||||
explicit ServerState(const std::string& config_filename = "");
|
||||
explicit ServerState(const std::string& config_filename = "", bool is_replay = false);
|
||||
ServerState(const ServerState&) = delete;
|
||||
ServerState(ServerState&&) = delete;
|
||||
ServerState& operator=(const ServerState&) = delete;
|
||||
|
||||
+12
-2
@@ -293,8 +293,18 @@ uint8_t npc_for_name(const string& name, Version version) {
|
||||
|
||||
const char* name_for_char_class(uint8_t cls) {
|
||||
static const array<const char*, 12> names = {
|
||||
"HUmar", "HUnewearl", "HUcast", "RAmar", "RAcast", "RAcaseal", "FOmarl", "FOnewm", "FOnewearl", "HUcaseal",
|
||||
"FOmar", "RAmarl"};
|
||||
/* 00 */ "HUmar", // 0
|
||||
/* 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 {
|
||||
return names.at(cls);
|
||||
} 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
|
||||
|
||||
.data <VERS 0x0016227A 0x0016238A 0x0016232A 0x0016240A 0x0016229A 0x0016242A 0x0016225A>
|
||||
.data 0x00000002
|
||||
.binary EB0E
|
||||
@@ -25,6 +26,7 @@ start:
|
||||
|
||||
|
||||
# Shield DFP/EVP Bug Fix (allows shields to reach true max DFP/EVP values)
|
||||
|
||||
.data <VERS 0x00185D8E 0x00185F4E 0x0018600E 0x00185F0E 0x00185F6E 0x00185F2E 0x00185F2E>
|
||||
.data 0x00000001
|
||||
.binary 16
|
||||
@@ -35,6 +37,7 @@ start:
|
||||
|
||||
|
||||
# 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 0x00000002
|
||||
.data 0x435C0000
|
||||
@@ -42,6 +45,7 @@ start:
|
||||
|
||||
|
||||
# Gol Dragon Camera Bug Fix (makes the camera after Gol Dragon display "normally")
|
||||
|
||||
.data <VERS 0x000A8AE1 0x000A8C51 0x000A8BD1 0x000A89C1 0x000A8961 0x000A89E1 0x000A8921>
|
||||
.data 0x00000002
|
||||
.binary 01
|
||||
@@ -49,6 +53,7 @@ start:
|
||||
|
||||
|
||||
# Rain Drops Color Bug Fix
|
||||
|
||||
.data <VERS 0x0054D670 0x0054DD00 0x005557E8 0x00552C68 0x00552508 0x00552C68 0x00553008>
|
||||
.data 0x00000008
|
||||
.binary 7080808060707070
|
||||
@@ -56,6 +61,7 @@ start:
|
||||
|
||||
|
||||
# TP Bar Color Bug Fix
|
||||
|
||||
.data <VERS 0x002779CE 0x00277C7E 0x0027808E 0x00277DAE 0x00277ECE 0x00277DCE 0x00277F9E>
|
||||
.data 0x00000004
|
||||
.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:
|
||||
|
||||
# Olga Flow Barta Bug Fix
|
||||
# Morfos Frozen Player Bug Fix
|
||||
# Bulclaw HP Bug Fix
|
||||
# Control Tower: Delbiter Death SFX Bug Fix
|
||||
# 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
|
||||
# SFX Cancellation Distance Bug Fix
|
||||
# Foie SFX Pitch Bug Fix
|
||||
@@ -92,28 +201,12 @@ start:
|
||||
# Grants SFX Pitch Bug Fix
|
||||
# Megid 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
|
||||
# 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 Log Window LF/Tab Bug Fix
|
||||
# Dark/Hell Special GFX Bug Fix
|
||||
# Box/Fence Fadeout Bug Fix
|
||||
# Devil's and Demon's Special Damage Display 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
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
ItemCT-pc-v2.afs
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
ItemPT-pc-v2.afs
|
||||
Binary file not shown.
Binary file not shown.
@@ -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 +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
|
||||
@@ -122,8 +122,6 @@
|
||||
"CHAOS_SORCERER": [145, 200],
|
||||
"CLAW": [95, 145],
|
||||
"DARK_BELRA": [50, 80],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 122],
|
||||
"DEATH_GUNNER": [100, 122],
|
||||
"DELSABER": [150, 165],
|
||||
@@ -143,7 +141,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 165],
|
||||
"MIGIUM": [50, 85],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 90],
|
||||
"NANO_DRAGON": [50, 170],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -159,7 +156,7 @@
|
||||
"SO_DIMENIAN": [135, 180],
|
||||
"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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 30, 23, 15],
|
||||
@@ -485,8 +482,6 @@
|
||||
"CHAOS_SORCERER": [145, 200],
|
||||
"CLAW": [95, 145],
|
||||
"DARK_BELRA": [50, 80],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 122],
|
||||
"DEATH_GUNNER": [100, 122],
|
||||
"DELSABER": [150, 165],
|
||||
@@ -506,7 +501,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 165],
|
||||
"MIGIUM": [50, 85],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 90],
|
||||
"NANO_DRAGON": [50, 170],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -579,8 +573,6 @@
|
||||
"CHAOS_SORCERER": [145, 210],
|
||||
"CLAW": [95, 155],
|
||||
"DARK_BELRA": [50, 90],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 132],
|
||||
"DEATH_GUNNER": [100, 132],
|
||||
"DELSABER": [150, 175],
|
||||
@@ -600,7 +592,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 175],
|
||||
"MIGIUM": [50, 95],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 100],
|
||||
"NANO_DRAGON": [50, 180],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -748,8 +739,6 @@
|
||||
"CHAOS_SORCERER": [115, 135],
|
||||
"CLAW": [45, 75],
|
||||
"DARK_BELRA": 10,
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [110, 125],
|
||||
"DEATH_GUNNER": [110, 125],
|
||||
"DELSABER": [95, 100],
|
||||
@@ -769,7 +758,6 @@
|
||||
"HILDEBLUE": [500, 1000],
|
||||
"LA_DIMENIAN": [100, 120],
|
||||
"MIGIUM": [15, 20],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [3, 6],
|
||||
"NANO_DRAGON": [60, 70],
|
||||
"NAR_LILY": [500, 1200],
|
||||
@@ -847,8 +835,6 @@
|
||||
"CHAOS_SORCERER": [120, 135],
|
||||
"CLAW": [50, 75],
|
||||
"DARK_BELRA": 10,
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [105, 130],
|
||||
"DEATH_GUNNER": [105, 130],
|
||||
"DELSABER": [95, 100],
|
||||
@@ -868,7 +854,6 @@
|
||||
"HILDEBLUE": [500, 1000],
|
||||
"LA_DIMENIAN": [105, 120],
|
||||
"MIGIUM": [17, 20],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [5, 6],
|
||||
"NANO_DRAGON": [65, 70],
|
||||
"NAR_LILY": [500, 1200],
|
||||
@@ -922,8 +907,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -943,7 +926,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -1357,8 +1339,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -1378,7 +1358,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -1441,8 +1420,6 @@
|
||||
"CHAOS_SORCERER": [200, 425],
|
||||
"CLAW": [155, 335],
|
||||
"DARK_BELRA": [100, 160],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 285],
|
||||
"DEATH_GUNNER": [150, 275],
|
||||
"DELSABER": [150, 330],
|
||||
@@ -1462,7 +1439,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 165],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 170],
|
||||
"NANO_DRAGON": [80, 340],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -1499,8 +1475,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -1520,7 +1494,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -1602,7 +1575,7 @@
|
||||
[56, 140],
|
||||
[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": {
|
||||
"AL_RAPPY": [1500, 2000],
|
||||
"BARBAROUS_WOLF": [120, 164],
|
||||
@@ -1616,8 +1589,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -1637,7 +1608,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -1653,7 +1623,7 @@
|
||||
"SO_DIMENIAN": [185, 295],
|
||||
"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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 35, 23, 14],
|
||||
@@ -1979,8 +1949,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -2000,7 +1968,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -2063,8 +2030,6 @@
|
||||
"CHAOS_SORCERER": [200, 425],
|
||||
"CLAW": [155, 335],
|
||||
"DARK_BELRA": [100, 160],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 285],
|
||||
"DEATH_GUNNER": [150, 275],
|
||||
"DELSABER": [150, 330],
|
||||
@@ -2084,7 +2049,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 165],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -2135,7 +2099,7 @@
|
||||
[210, 275],
|
||||
[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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 30, 23, 15],
|
||||
@@ -2483,8 +2447,8 @@
|
||||
[130, 165],
|
||||
[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},
|
||||
"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},
|
||||
"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_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": [
|
||||
[0, 0, 0, 1, 1, 1, 2, 2, 2, 3],
|
||||
[255, 255, 0, 0, 0, 1, 1, 1, 2, 2],
|
||||
@@ -2773,8 +2737,8 @@
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[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},
|
||||
"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},
|
||||
"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_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": [
|
||||
[108, 108, 108, 108, 109, 108, 110, 109, 120, 125],
|
||||
[80, 80, 80, 80, 84, 85, 84, 100, 104, 112],
|
||||
@@ -3039,7 +3003,7 @@
|
||||
[380, 430],
|
||||
[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": {
|
||||
"AL_RAPPY": [1500, 2000],
|
||||
"BARBAROUS_WOLF": [120, 164],
|
||||
@@ -3053,8 +3017,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -3074,7 +3036,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -3090,7 +3051,7 @@
|
||||
"SO_DIMENIAN": [185, 295],
|
||||
"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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 35, 23, 14],
|
||||
@@ -3480,8 +3441,6 @@
|
||||
"CHAOS_SORCERER": [145, 200],
|
||||
"CLAW": [95, 145],
|
||||
"DARK_BELRA": [50, 80],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 122],
|
||||
"DEATH_GUNNER": [100, 122],
|
||||
"DELSABER": [150, 165],
|
||||
@@ -3501,7 +3460,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 165],
|
||||
"MIGIUM": [50, 85],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 90],
|
||||
"NANO_DRAGON": [50, 170],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -3517,7 +3475,7 @@
|
||||
"SO_DIMENIAN": [135, 180],
|
||||
"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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 30, 23, 15],
|
||||
@@ -3843,8 +3801,6 @@
|
||||
"CHAOS_SORCERER": [145, 200],
|
||||
"CLAW": [95, 145],
|
||||
"DARK_BELRA": [50, 80],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 122],
|
||||
"DEATH_GUNNER": [100, 122],
|
||||
"DELSABER": [150, 165],
|
||||
@@ -3864,7 +3820,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 165],
|
||||
"MIGIUM": [50, 85],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 90],
|
||||
"NANO_DRAGON": [50, 170],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -3937,8 +3892,6 @@
|
||||
"CHAOS_SORCERER": [145, 210],
|
||||
"CLAW": [95, 155],
|
||||
"DARK_BELRA": [50, 90],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 132],
|
||||
"DEATH_GUNNER": [100, 132],
|
||||
"DELSABER": [150, 175],
|
||||
@@ -3958,7 +3911,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 175],
|
||||
"MIGIUM": [50, 95],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 100],
|
||||
"NANO_DRAGON": [50, 180],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -4120,7 +4072,7 @@
|
||||
[19, 50],
|
||||
[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": {
|
||||
"AL_RAPPY": [500, 1000],
|
||||
"BARBAROUS_WOLF": [15, 30],
|
||||
@@ -4134,8 +4086,6 @@
|
||||
"CHAOS_SORCERER": [115, 135],
|
||||
"CLAW": [45, 75],
|
||||
"DARK_BELRA": 10,
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [110, 125],
|
||||
"DEATH_GUNNER": [110, 125],
|
||||
"DELSABER": [95, 100],
|
||||
@@ -4155,7 +4105,6 @@
|
||||
"HILDEBLUE": [500, 1000],
|
||||
"LA_DIMENIAN": [100, 120],
|
||||
"MIGIUM": [15, 20],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [3, 6],
|
||||
"NANO_DRAGON": [60, 70],
|
||||
"NAR_LILY": [500, 1200],
|
||||
@@ -4171,7 +4120,7 @@
|
||||
"SO_DIMENIAN": [120, 145],
|
||||
"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": [
|
||||
[100, 35, 30, 25],
|
||||
[0, 25, 20, 15],
|
||||
@@ -4498,8 +4447,6 @@
|
||||
"CHAOS_SORCERER": [115, 135],
|
||||
"CLAW": [45, 75],
|
||||
"DARK_BELRA": 10,
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [110, 125],
|
||||
"DEATH_GUNNER": [110, 125],
|
||||
"DELSABER": [95, 100],
|
||||
@@ -4519,7 +4466,6 @@
|
||||
"HILDEBLUE": [500, 1000],
|
||||
"LA_DIMENIAN": [100, 120],
|
||||
"MIGIUM": [15, 20],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [3, 6],
|
||||
"NANO_DRAGON": [60, 70],
|
||||
"NAR_LILY": [500, 1200],
|
||||
@@ -4597,8 +4543,6 @@
|
||||
"CHAOS_SORCERER": [120, 135],
|
||||
"CLAW": [50, 75],
|
||||
"DARK_BELRA": 10,
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [105, 130],
|
||||
"DEATH_GUNNER": [105, 130],
|
||||
"DELSABER": [95, 100],
|
||||
@@ -4618,7 +4562,6 @@
|
||||
"HILDEBLUE": [500, 1000],
|
||||
"LA_DIMENIAN": [105, 120],
|
||||
"MIGIUM": [17, 20],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [5, 6],
|
||||
"NANO_DRAGON": [65, 70],
|
||||
"NAR_LILY": [500, 1200],
|
||||
@@ -4672,8 +4615,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -4693,7 +4634,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -5107,8 +5047,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -5128,7 +5066,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -5191,8 +5128,6 @@
|
||||
"CHAOS_SORCERER": [200, 425],
|
||||
"CLAW": [155, 335],
|
||||
"DARK_BELRA": [100, 160],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 285],
|
||||
"DEATH_GUNNER": [150, 275],
|
||||
"DELSABER": [150, 330],
|
||||
@@ -5212,7 +5147,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 165],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 170],
|
||||
"NANO_DRAGON": [80, 340],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -5249,8 +5183,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -5270,7 +5202,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -5352,7 +5283,7 @@
|
||||
[56, 140],
|
||||
[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": {
|
||||
"AL_RAPPY": [1500, 2000],
|
||||
"BARBAROUS_WOLF": [120, 164],
|
||||
@@ -5366,8 +5297,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -5387,7 +5316,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -5403,7 +5331,7 @@
|
||||
"SO_DIMENIAN": [185, 295],
|
||||
"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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 35, 23, 14],
|
||||
@@ -5729,8 +5657,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -5750,7 +5676,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -5813,8 +5738,6 @@
|
||||
"CHAOS_SORCERER": [200, 425],
|
||||
"CLAW": [155, 335],
|
||||
"DARK_BELRA": [100, 160],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 285],
|
||||
"DEATH_GUNNER": [150, 275],
|
||||
"DELSABER": [150, 330],
|
||||
@@ -5834,7 +5757,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 165],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -5958,8 +5880,6 @@
|
||||
"CHAOS_SORCERER": [145, 200],
|
||||
"CLAW": [95, 145],
|
||||
"DARK_BELRA": [50, 80],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 122],
|
||||
"DEATH_GUNNER": [100, 122],
|
||||
"DELSABER": [150, 165],
|
||||
@@ -5979,7 +5899,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 165],
|
||||
"MIGIUM": [50, 85],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 90],
|
||||
"NANO_DRAGON": [50, 170],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -5995,7 +5914,7 @@
|
||||
"SO_DIMENIAN": [135, 180],
|
||||
"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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 30, 23, 15],
|
||||
@@ -6321,8 +6240,6 @@
|
||||
"CHAOS_SORCERER": [145, 200],
|
||||
"CLAW": [95, 145],
|
||||
"DARK_BELRA": [50, 80],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 122],
|
||||
"DEATH_GUNNER": [100, 122],
|
||||
"DELSABER": [150, 165],
|
||||
@@ -6342,7 +6259,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 165],
|
||||
"MIGIUM": [50, 85],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 90],
|
||||
"NANO_DRAGON": [50, 170],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -6415,8 +6331,6 @@
|
||||
"CHAOS_SORCERER": [145, 210],
|
||||
"CLAW": [95, 155],
|
||||
"DARK_BELRA": [50, 90],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [100, 132],
|
||||
"DEATH_GUNNER": [100, 132],
|
||||
"DELSABER": [150, 175],
|
||||
@@ -6436,7 +6350,6 @@
|
||||
"HILDEBLUE": [1000, 1500],
|
||||
"LA_DIMENIAN": [115, 175],
|
||||
"MIGIUM": [50, 95],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [80, 100],
|
||||
"NANO_DRAGON": [50, 180],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
@@ -6584,8 +6497,6 @@
|
||||
"CHAOS_SORCERER": [115, 135],
|
||||
"CLAW": [45, 75],
|
||||
"DARK_BELRA": 10,
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [110, 125],
|
||||
"DEATH_GUNNER": [110, 125],
|
||||
"DELSABER": [95, 100],
|
||||
@@ -6605,7 +6516,6 @@
|
||||
"HILDEBLUE": [500, 1000],
|
||||
"LA_DIMENIAN": [100, 120],
|
||||
"MIGIUM": [15, 20],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [3, 6],
|
||||
"NANO_DRAGON": [60, 70],
|
||||
"NAR_LILY": [500, 1200],
|
||||
@@ -6683,8 +6593,6 @@
|
||||
"CHAOS_SORCERER": [120, 135],
|
||||
"CLAW": [50, 75],
|
||||
"DARK_BELRA": 10,
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [105, 130],
|
||||
"DEATH_GUNNER": [105, 130],
|
||||
"DELSABER": [95, 100],
|
||||
@@ -6704,7 +6612,6 @@
|
||||
"HILDEBLUE": [500, 1000],
|
||||
"LA_DIMENIAN": [105, 120],
|
||||
"MIGIUM": [17, 20],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [5, 6],
|
||||
"NANO_DRAGON": [65, 70],
|
||||
"NAR_LILY": [500, 1200],
|
||||
@@ -6758,8 +6665,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -6779,7 +6684,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -7193,8 +7097,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -7214,7 +7116,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -7277,8 +7178,6 @@
|
||||
"CHAOS_SORCERER": [200, 425],
|
||||
"CLAW": [155, 335],
|
||||
"DARK_BELRA": [100, 160],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 285],
|
||||
"DEATH_GUNNER": [150, 275],
|
||||
"DELSABER": [150, 330],
|
||||
@@ -7298,7 +7197,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 165],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 170],
|
||||
"NANO_DRAGON": [80, 340],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -7335,8 +7233,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -7356,7 +7252,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -7438,7 +7333,7 @@
|
||||
[56, 140],
|
||||
[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": {
|
||||
"AL_RAPPY": [1500, 2000],
|
||||
"BARBAROUS_WOLF": [120, 164],
|
||||
@@ -7452,8 +7347,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -7473,7 +7366,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -7489,7 +7381,7 @@
|
||||
"SO_DIMENIAN": [185, 295],
|
||||
"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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 35, 23, 14],
|
||||
@@ -7815,8 +7707,6 @@
|
||||
"CHAOS_SORCERER": [200, 400],
|
||||
"CLAW": [135, 245],
|
||||
"DARK_BELRA": [100, 130],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 250],
|
||||
"DEATH_GUNNER": [150, 250],
|
||||
"DELSABER": [150, 300],
|
||||
@@ -7836,7 +7726,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -7899,8 +7788,6 @@
|
||||
"CHAOS_SORCERER": [200, 425],
|
||||
"CLAW": [155, 335],
|
||||
"DARK_BELRA": [100, 160],
|
||||
"DARK_FALZ_2": 0,
|
||||
"DARK_FALZ_3": 0,
|
||||
"DARK_GUNNER": [150, 285],
|
||||
"DEATH_GUNNER": [150, 275],
|
||||
"DELSABER": [150, 330],
|
||||
@@ -7920,7 +7807,6 @@
|
||||
"HILDEBLUE": [1500, 2000],
|
||||
"LA_DIMENIAN": [165, 275],
|
||||
"MIGIUM": [55, 165],
|
||||
"MONEST": 0,
|
||||
"MOTHMANT": [120, 140],
|
||||
"NANO_DRAGON": [80, 310],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
@@ -8029,7 +7915,7 @@
|
||||
[44, 110],
|
||||
[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": {
|
||||
"BARBAROUS_WOLF": [100, 180],
|
||||
"BARBA_RAY": 1300,
|
||||
@@ -8068,11 +7954,9 @@
|
||||
"MERILLIA": [60, 65],
|
||||
"MERILTAS": [70, 85],
|
||||
"MIGIUM": [120, 185],
|
||||
"MONEST": 0,
|
||||
"MORFOS": [50, 80],
|
||||
"MOTHMANT": [80, 90],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
"OLGA_FLOW_2": 0,
|
||||
"PAN_ARMS": [50, 85],
|
||||
"POISON_LILY": [60, 65],
|
||||
"RAG_RAPPY": [85, 100],
|
||||
@@ -9127,7 +9011,7 @@
|
||||
[64, 160],
|
||||
[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": {
|
||||
"BARBAROUS_WOLF": [150, 260],
|
||||
"BARBA_RAY": 2800,
|
||||
@@ -9166,11 +9050,9 @@
|
||||
"MERILLIA": [90, 110],
|
||||
"MERILTAS": [100, 135],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MORFOS": [151, 171],
|
||||
"MOTHMANT": [120, 140],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
"OLGA_FLOW_2": 0,
|
||||
"PAN_ARMS": [165, 265],
|
||||
"POISON_LILY": [90, 110],
|
||||
"RAG_RAPPY": [85, 150],
|
||||
@@ -9567,8 +9449,8 @@
|
||||
[210, 275],
|
||||
[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},
|
||||
"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},
|
||||
"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, "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": [
|
||||
[100, 30, 25, 20],
|
||||
[0, 30, 23, 15],
|
||||
@@ -9916,8 +9798,8 @@
|
||||
[130, 165],
|
||||
[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},
|
||||
"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},
|
||||
"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, "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": [
|
||||
[0, 0, 0, 1, 1, 1, 2, 2, 2, 3],
|
||||
[255, 255, 0, 0, 0, 1, 1, 1, 2, 2],
|
||||
@@ -10845,7 +10727,7 @@
|
||||
[44, 110],
|
||||
[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": {
|
||||
"BARBAROUS_WOLF": [100, 180],
|
||||
"BARBA_RAY": 1300,
|
||||
@@ -10884,11 +10766,9 @@
|
||||
"MERILLIA": [60, 65],
|
||||
"MERILTAS": [70, 85],
|
||||
"MIGIUM": [120, 185],
|
||||
"MONEST": 0,
|
||||
"MORFOS": [50, 80],
|
||||
"MOTHMANT": [80, 90],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
"OLGA_FLOW_2": 0,
|
||||
"PAN_ARMS": [50, 85],
|
||||
"POISON_LILY": [60, 65],
|
||||
"RAG_RAPPY": [85, 100],
|
||||
@@ -11416,7 +11296,7 @@
|
||||
[24, 60],
|
||||
[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": {
|
||||
"BARBAROUS_WOLF": [30, 45],
|
||||
"BARBA_RAY": 400,
|
||||
@@ -11455,11 +11335,9 @@
|
||||
"MERILLIA": [40, 50],
|
||||
"MERILTAS": [45, 60],
|
||||
"MIGIUM": [45, 65],
|
||||
"MONEST": 0,
|
||||
"MORFOS": [100, 130],
|
||||
"MOTHMANT": [3, 6],
|
||||
"NAR_LILY": [500, 1200],
|
||||
"OLGA_FLOW_2": 0,
|
||||
"PAN_ARMS": [24, 44],
|
||||
"POISON_LILY": [4, 10],
|
||||
"RAG_RAPPY": [18, 20],
|
||||
@@ -11475,7 +11353,7 @@
|
||||
"UL_GIBBON": [37, 55],
|
||||
"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": [
|
||||
[100, 35, 30, 25],
|
||||
[0, 25, 20, 15],
|
||||
@@ -12343,7 +12221,7 @@
|
||||
[64, 160],
|
||||
[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": {
|
||||
"BARBAROUS_WOLF": [150, 260],
|
||||
"BARBA_RAY": 2800,
|
||||
@@ -12382,11 +12260,9 @@
|
||||
"MERILLIA": [90, 110],
|
||||
"MERILTAS": [100, 135],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MORFOS": [151, 171],
|
||||
"MOTHMANT": [120, 140],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
"OLGA_FLOW_2": 0,
|
||||
"PAN_ARMS": [165, 265],
|
||||
"POISON_LILY": [90, 110],
|
||||
"RAG_RAPPY": [85, 150],
|
||||
@@ -12841,7 +12717,7 @@
|
||||
[44, 110],
|
||||
[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": {
|
||||
"BARBAROUS_WOLF": [100, 180],
|
||||
"BARBA_RAY": 1300,
|
||||
@@ -12880,11 +12756,9 @@
|
||||
"MERILLIA": [60, 65],
|
||||
"MERILTAS": [70, 85],
|
||||
"MIGIUM": [120, 185],
|
||||
"MONEST": 0,
|
||||
"MORFOS": [50, 80],
|
||||
"MOTHMANT": [80, 90],
|
||||
"NAR_LILY": [1000, 2000],
|
||||
"OLGA_FLOW_2": 0,
|
||||
"PAN_ARMS": [50, 85],
|
||||
"POISON_LILY": [60, 65],
|
||||
"RAG_RAPPY": [85, 100],
|
||||
@@ -13939,7 +13813,7 @@
|
||||
[64, 160],
|
||||
[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": {
|
||||
"BARBAROUS_WOLF": [150, 260],
|
||||
"BARBA_RAY": 2800,
|
||||
@@ -13978,11 +13852,9 @@
|
||||
"MERILLIA": [90, 110],
|
||||
"MERILTAS": [100, 135],
|
||||
"MIGIUM": [55, 135],
|
||||
"MONEST": 0,
|
||||
"MORFOS": [151, 171],
|
||||
"MOTHMANT": [120, 140],
|
||||
"NAR_LILY": [2000, 2500],
|
||||
"OLGA_FLOW_2": 0,
|
||||
"PAN_ARMS": [165, 265],
|
||||
"POISON_LILY": [90, 110],
|
||||
"RAG_RAPPY": [85, 150],
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
["13/4096", 0x000B03]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000A04]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000A04]],
|
||||
"CANANE": [["7/256", 0x000B04]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x002C00]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000B04]],
|
||||
@@ -125,7 +125,7 @@
|
||||
["7/8192", 0x030E18]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000605]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000605]],
|
||||
"CANANE": [["7/256", 0x000705]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x002C00]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000705]],
|
||||
@@ -212,7 +212,7 @@
|
||||
["7/8192", 0x030E18]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000A04]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000A04]],
|
||||
"CANANE": [["7/256", 0x000305]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x002C00]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000305]],
|
||||
@@ -304,7 +304,7 @@
|
||||
["3/2048", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000A04]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000A04]],
|
||||
"CANANE": [["7/256", 0x000C04]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x002C00]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000C04]],
|
||||
@@ -385,7 +385,7 @@
|
||||
["7/8192", 0x030E18]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000A04]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000A04]],
|
||||
"CANANE": [["7/256", 0x000805]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x002C00]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000305]],
|
||||
@@ -471,7 +471,7 @@
|
||||
["7/8192", 0x01024B]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000605]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000605]],
|
||||
"CANANE": [["7/256", 0x000505]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x000506]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000905]],
|
||||
@@ -551,7 +551,7 @@
|
||||
["7/8192", 0x01024B]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000105]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000105]],
|
||||
"CANANE": [["7/256", 0x000705]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x000F00]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000205]],
|
||||
@@ -594,43 +594,18 @@
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000605]],
|
||||
"BOOMA": [["1/128", 0x030D0F]],
|
||||
"BULCLAW": [["1/128", 0x000905]],
|
||||
"Box-Cave1": [
|
||||
["9/536870912", 0x030E1C],
|
||||
["13/134217728", 0x030E16],
|
||||
["5/134217728", 0x01024A]
|
||||
],
|
||||
"Box-Cave3": [
|
||||
["7/1073741824", 0x020000],
|
||||
["7/1073741824", 0x000404],
|
||||
["3/536870912", 0x000404],
|
||||
["13/2147483648", 0x030E1B],
|
||||
["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]
|
||||
],
|
||||
"Box-Forest1": [[0x00380000, 0x030E1D]],
|
||||
"Box-Forest2": [[0x00380000, 0x030E1A], [0x00380000, 0x030E18]],
|
||||
"Box-Cave1": [[0x00380000, 0x030E16]],
|
||||
"Box-Cave2": [[0x00380000, 0x030F00], [0x00380000, 0x01024D]],
|
||||
"Box-Cave3": [[0x00900000, 0x000904], [0x00900000, 0x000404], [0x00380000, 0x030E1B]],
|
||||
"Box-Mine1": [[0x02400000, 0x020000], [0x00240000, 0x01024C], [0x00380000, 0x030E1E]],
|
||||
"Box-Mine2": [[0x01000000, 0x020000], [0x00B00000, 0x000904], [0x00B00000, 0x000404], [0x00240000, 0x01024C], [0x00380000, 0x030E1F], [0x00380000, 0x01024A]],
|
||||
"Box-Ruins1": [[0x00380000, 0x030E1C], [0x00380000, 0x030E19]],
|
||||
"Box-Ruins2": [[0x00380000, 0x01024C], [0x00380000, 0x030E17]],
|
||||
"Box-Ruins3": [[0x00D00000, 0x000905], [0x00D00000, 0x000405], [0x00380000, 0x01024B]],
|
||||
"CANADINE": [["1/128", 0x000605]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000605]],
|
||||
"CANANE": [["7/256", 0x000405]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x001003]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000905]],
|
||||
@@ -715,7 +690,7 @@
|
||||
["7/8192", 0x01024B]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000605]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000605]],
|
||||
"CANANE": [["7/256", 0x030A00]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x000506]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000505]],
|
||||
@@ -793,7 +768,7 @@
|
||||
],
|
||||
"Box-Ruins3": [["7/8192", 0x030E24]],
|
||||
"CANADINE": [["1/128", 0x000A04]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000A04]],
|
||||
"CANANE": [["7/256", 0x000C04]],
|
||||
"CHAOS_BRINGER": [["1/64", 0x006800]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x000905]],
|
||||
@@ -860,7 +835,7 @@
|
||||
["13/16384", 0x000B02]
|
||||
],
|
||||
"CANADINE": [["9/16384", 0x01024E]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024E]],
|
||||
"CANANE": [["9/16", 0x030002]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030002]],
|
||||
"CHAOS_SORCERER": [["9/16", 0x030300]],
|
||||
@@ -922,7 +897,7 @@
|
||||
["7/8192", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["9/16384", 0x01024D]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024D]],
|
||||
"CANANE": [["11/8192", 0x030A00]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030002]],
|
||||
"CHAOS_SORCERER": [["7/8", 0x030B02]],
|
||||
@@ -990,7 +965,7 @@
|
||||
["7/8192", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["9/16384", 0x01024E]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024E]],
|
||||
"CANANE": [["9/16", 0x030300]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030002]],
|
||||
"CHAOS_SORCERER": [["9/16", 0x030002]],
|
||||
@@ -1064,7 +1039,7 @@
|
||||
["7/8192", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["9/16384", 0x01024E]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024E]],
|
||||
"CANANE": [["9/16", 0x030300]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030002]],
|
||||
"CHAOS_SORCERER": [["9/16", 0x030002]],
|
||||
@@ -1129,7 +1104,7 @@
|
||||
["13/16384", 0x000303]
|
||||
],
|
||||
"CANADINE": [["9/16384", 0x01024E]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024E]],
|
||||
"CANANE": [["9/16", 0x030300]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030300]],
|
||||
"CHAOS_SORCERER": [["9/16", 0x030002]],
|
||||
@@ -1193,7 +1168,7 @@
|
||||
["7/8192", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["9/16384", 0x01024E]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024E]],
|
||||
"CANANE": [["9/16", 0x030300]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030002]],
|
||||
"CHAOS_SORCERER": [["9/16", 0x030002]],
|
||||
@@ -1316,7 +1291,7 @@
|
||||
["13/16384", 0x000403]
|
||||
],
|
||||
"CANADINE": [["9/16384", 0x01024C]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024C]],
|
||||
"CANANE": [["9/16", 0x030002]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030002]],
|
||||
"CHAOS_SORCERER": [["9/16", 0x030B01]],
|
||||
@@ -1429,7 +1404,7 @@
|
||||
"Box-Ruins2": [["7/8192", 0x030E25]],
|
||||
"Box-Ruins3": [["7/8192", 0x030E24]],
|
||||
"CANADINE": [["9/16384", 0x01024E]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["9/16384", 0x01024E]],
|
||||
"CANANE": [["9/16", 0x030300]],
|
||||
"CHAOS_BRINGER": [["9/16", 0x030002]],
|
||||
"CHAOS_SORCERER": [["9/16", 0x030002]],
|
||||
@@ -1515,14 +1490,14 @@
|
||||
["11/4096", 0x000A06]
|
||||
],
|
||||
"CANADINE": [["1/64", 0x000B06]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/64", 0x000B06]],
|
||||
"CANANE": [["1/1024", 0x010216]],
|
||||
"CHAOS_BRINGER": [["1/1024", 0x010134]],
|
||||
"CHAOS_SORCERER": [["13/4096", 0x030D00]],
|
||||
"CLAW": [["1/64", 0x000407]],
|
||||
"DARK_BELRA": [["13/131072", 0x030E0A]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010232]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010232]],
|
||||
"DARK_GUNNER": [["13/4096", 0x004100]],
|
||||
"DELSABER": [["13/4096", 0x009400]],
|
||||
"DE_ROL_LE": [["13/64", 0x000B06]],
|
||||
@@ -1606,14 +1581,14 @@
|
||||
["7/8192", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["1/64", 0x000707]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/64", 0x000707]],
|
||||
"CANANE": [["1/1024", 0x01022B]],
|
||||
"CHAOS_BRINGER": [["13/4096", 0x030D04]],
|
||||
"CHAOS_SORCERER": [["5/524288", 0x001D00]],
|
||||
"CLAW": [["1/64", 0x000307]],
|
||||
"DARK_BELRA": [["13/4096", 0x030D0B]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010231]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010231]],
|
||||
"DARK_GUNNER": [["13/4096", 0x004C00]],
|
||||
"DELSABER": [["13/131072", 0x001001]],
|
||||
"DE_ROL_LE": [["7/256", 0x001300]],
|
||||
@@ -1697,14 +1672,14 @@
|
||||
["11/4096", 0x000A06]
|
||||
],
|
||||
"CANADINE": [["1/64", 0x000207]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/64", 0x000207]],
|
||||
"CANANE": [["13/4096", 0x008902]],
|
||||
"CHAOS_BRINGER": [["13/131072", 0x005A00]],
|
||||
"CHAOS_SORCERER": [["13/4096", 0x030D00]],
|
||||
"CLAW": [["1/64", 0x000D01]],
|
||||
"DARK_BELRA": [["13/4096", 0x009200]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010231]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010231]],
|
||||
"DARK_GUNNER": [["13/4096", 0x009400]],
|
||||
"DELSABER": [["5/1024", 0x030D05]],
|
||||
"DE_ROL_LE": [["13/64", 0x000207]],
|
||||
@@ -1794,14 +1769,14 @@
|
||||
["11/4096", 0x000A06]
|
||||
],
|
||||
"CANADINE": [["1/64", 0x000C06]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/64", 0x000C06]],
|
||||
"CANANE": [["1/1024", 0x010134]],
|
||||
"CHAOS_BRINGER": [["13/4096", 0x030D04]],
|
||||
"CHAOS_SORCERER": [["13/4096", 0x030D00]],
|
||||
"CLAW": [["13/4096", 0x000D01]],
|
||||
"DARK_BELRA": [["13/4096", 0x009200]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010231]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010231]],
|
||||
"DARK_GUNNER": [["13/4096", 0x009400]],
|
||||
"DELSABER": [["5/1024", 0x030D05]],
|
||||
"DE_ROL_LE": [["7/256", 0x001300]],
|
||||
@@ -1883,14 +1858,14 @@
|
||||
["11/4096", 0x000A06]
|
||||
],
|
||||
"CANADINE": [["1/1024", 0x01022B]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/1024", 0x01022B]],
|
||||
"CANANE": [["13/4096", 0x006C00]],
|
||||
"CHAOS_BRINGER": [["13/4096", 0x030D04]],
|
||||
"CHAOS_SORCERER": [["13/131072", 0x030E0A]],
|
||||
"CLAW": [["1/64", 0x008C01]],
|
||||
"DARK_BELRA": [["13/4096", 0x030D0B]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010232]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010232]],
|
||||
"DARK_GUNNER": [["1/1024", 0x010216]],
|
||||
"DELSABER": [["5/1024", 0x030D05]],
|
||||
"DE_ROL_LE": [["13/64", 0x000307]],
|
||||
@@ -1978,14 +1953,14 @@
|
||||
["7/8192", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["1/64", 0x009005]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/64", 0x009005]],
|
||||
"CANANE": [["13/4096", 0x030E08]],
|
||||
"CHAOS_BRINGER": [["13/4096", 0x001200]],
|
||||
"CHAOS_SORCERER": [["5/524288", 0x001D00]],
|
||||
"CLAW": [["13/4096", 0x010117]],
|
||||
"DARK_BELRA": [["13/4096", 0x002E00]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010227]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010227]],
|
||||
"DARK_GUNNER": [["1/512", 0x010134]],
|
||||
"DELSABER": [["5/1024", 0x030D05]],
|
||||
"DE_ROL_LE": [["13/64", 0x000507]],
|
||||
@@ -2069,14 +2044,14 @@
|
||||
["11/4096", 0x000A06]
|
||||
],
|
||||
"CANADINE": [["1/64", 0x000207]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/64", 0x000207]],
|
||||
"CANANE": [["13/4096", 0x008902]],
|
||||
"CHAOS_BRINGER": [["13/4096", 0x002E00]],
|
||||
"CHAOS_SORCERER": [["5/524288", 0x001D00]],
|
||||
"CLAW": [["1/64", 0x000D01]],
|
||||
"DARK_BELRA": [["1/1024", 0x010133]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010227]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010227]],
|
||||
"DARK_GUNNER": [["13/131072", 0x009302]],
|
||||
"DELSABER": [["5/1024", 0x030D05]],
|
||||
"DE_ROL_LE": [["13/64", 0x000207]],
|
||||
@@ -2158,14 +2133,14 @@
|
||||
["11/4096", 0x000A06]
|
||||
],
|
||||
"CANADINE": [["13/131072", 0x009300]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["13/131072", 0x009300]],
|
||||
"CANANE": [["5/1024", 0x010226]],
|
||||
"CHAOS_BRINGER": [["13/4096", 0x030D04]],
|
||||
"CHAOS_SORCERER": [["13/131072", 0x001F00]],
|
||||
"CLAW": [["1/64", 0x000D01]],
|
||||
"DARK_BELRA": [["13/4096", 0x030D0B]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010227]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010227]],
|
||||
"DARK_GUNNER": [["1/1024", 0x01012B]],
|
||||
"DELSABER": [["5/1024", 0x030D05]],
|
||||
"DE_ROL_LE": [["13/64", 0x000407]],
|
||||
@@ -2245,14 +2220,14 @@
|
||||
["11/4096", 0x000A06]
|
||||
],
|
||||
"CANADINE": [["13/131072", 0x009309]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["13/131072", 0x009309]],
|
||||
"CANANE": [["13/4096", 0x008902]],
|
||||
"CHAOS_BRINGER": [["1/512", 0x010232]],
|
||||
"CHAOS_SORCERER": [["13/131072", 0x004200]],
|
||||
"CLAW": [["1/512", 0x010332]],
|
||||
"DARK_BELRA": [["13/4096", 0x030D0B]],
|
||||
"DARK_FALZ_2": [["7/256", 0x010227]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["7/256", 0x010227]],
|
||||
"DARK_GUNNER": [["13/4096", 0x004100]],
|
||||
"DELSABER": [["13/4096", 0x009400]],
|
||||
"DE_ROL_LE": [["13/64", 0x000507]],
|
||||
@@ -2335,14 +2310,14 @@
|
||||
["7/8192", 0x030E24]
|
||||
],
|
||||
"CANADINE": [["13/131072", 0x008D00]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["13/131072", 0x008D00]],
|
||||
"CANANE": [["13/4096", 0x030E08]],
|
||||
"CHAOS_BRINGER": [["13/4096", 0x030D04]],
|
||||
"CHAOS_SORCERER": [["13/4096", 0x030D00]],
|
||||
"CLAW": [["1/64", 0x009007]],
|
||||
"DARK_BELRA": [["13/4096", 0x030D0B]],
|
||||
"DARK_FALZ_2": [["1/64", 0x010232]],
|
||||
"DARK_FALZ_3": [],
|
||||
"DARK_FALZ_3": [["1/64", 0x010232]],
|
||||
"DARK_GUNNER": [["13/4096", 0x009200]],
|
||||
"DELSABER": [["1/64", 0x030D03]],
|
||||
"DE_ROL_LE": [["7/256", 0x001300]],
|
||||
@@ -2428,7 +2403,7 @@
|
||||
["7/8192", 0x01024B]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000B05]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000B05]],
|
||||
"CANANE": [["1/128", 0x010223]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000407]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C01]],
|
||||
@@ -2514,7 +2489,7 @@
|
||||
["7/8192", 0x030F00]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000706]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000706]],
|
||||
"CANANE": [["1/128", 0x010223]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x030500]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C00]],
|
||||
@@ -2602,7 +2577,7 @@
|
||||
["13/4096", 0x000A05]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000306]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000306]],
|
||||
"CANANE": [["1/128", 0x010223]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000307]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C01]],
|
||||
@@ -2688,7 +2663,7 @@
|
||||
["13/4096", 0x000606]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000C05]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000C05]],
|
||||
"CANANE": [["1/128", 0x010223]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000C06]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C01]],
|
||||
@@ -2774,7 +2749,7 @@
|
||||
["13/4096", 0x000A05]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000806]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000806]],
|
||||
"CANANE": [["1/128", 0x010223]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000807]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C00]],
|
||||
@@ -2860,7 +2835,7 @@
|
||||
["7/8192", 0x030E25]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000506]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000506]],
|
||||
"CANANE": [["1/128", 0x010223]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000506]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C00]],
|
||||
@@ -2944,7 +2919,7 @@
|
||||
["7/8192", 0x030F00]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000705]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000705]],
|
||||
"CANANE": [["1/128", 0x010226]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000207]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C00]],
|
||||
@@ -3030,7 +3005,7 @@
|
||||
["13/4096", 0x000A05]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000405]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000405]],
|
||||
"CANANE": [["1/1024", 0x010134]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000907]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C00]],
|
||||
@@ -3116,7 +3091,7 @@
|
||||
["7/8192", 0x01024B]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000506]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000506]],
|
||||
"CANANE": [["1/128", 0x010221]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000506]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C00]],
|
||||
@@ -3208,7 +3183,7 @@
|
||||
["13/4096", 0x000505]
|
||||
],
|
||||
"CANADINE": [["1/128", 0x000806]],
|
||||
"CANADINE_GROUP": [],
|
||||
"CANADINE_GROUP": [["1/128", 0x000806]],
|
||||
"CANANE": [["1/128", 0x010223]],
|
||||
"CHAOS_BRINGER": [["7/256", 0x000B05]],
|
||||
"CHAOS_SORCERER": [["7/256", 0x008C00]],
|
||||
@@ -3253,6 +3228,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000B04]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000404],
|
||||
["9/4096", 0x000B02],
|
||||
@@ -3310,6 +3286,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002600]],
|
||||
"MERICAROL": [["7/256", 0x000406]],
|
||||
"MERICARAND": [["7/256", 0x000406]],
|
||||
"MERICUS": [["7/256", 0x000406]],
|
||||
"MERIKLE": [["7/256", 0x000406]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3333,6 +3310,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000305]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000704],
|
||||
["9/4096", 0x000304]
|
||||
@@ -3387,6 +3365,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000706]],
|
||||
"MERICARAND": [["7/256", 0x000706]],
|
||||
"MERICUS": [["7/256", 0x000706]],
|
||||
"MERIKLE": [["7/256", 0x000706]],
|
||||
"MERILLIA": [["1/128", 0x000606]],
|
||||
@@ -3410,6 +3389,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000205]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000304],
|
||||
["9/4096", 0x000204],
|
||||
@@ -3479,6 +3459,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000306]],
|
||||
"MERICARAND": [["7/256", 0x000306]],
|
||||
"MERICUS": [["7/256", 0x000306]],
|
||||
"MERIKLE": [["7/256", 0x000306]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3502,6 +3483,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000405]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000C03],
|
||||
["9/4096", 0x000404],
|
||||
@@ -3572,6 +3554,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000A04]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000C05]],
|
||||
"MERICARAND": [["7/256", 0x000C05]],
|
||||
"MERICUS": [["7/256", 0x000C05]],
|
||||
"MERIKLE": [["7/256", 0x000C05]],
|
||||
"MERILLIA": [["1/128", 0x000A04]],
|
||||
@@ -3595,6 +3578,7 @@
|
||||
"Purplenum": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000305]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000804],
|
||||
["9/4096", 0x000304],
|
||||
@@ -3656,6 +3640,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x004900]],
|
||||
"MERICAROL": [["7/256", 0x000806]],
|
||||
"MERICARAND": [["7/256", 0x000806]],
|
||||
"MERICUS": [["7/256", 0x000806]],
|
||||
"MERIKLE": [["7/256", 0x000806]],
|
||||
"MERILLIA": [["1/128", 0x000605]],
|
||||
@@ -3679,6 +3664,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000905]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000504],
|
||||
["9/4096", 0x000904],
|
||||
@@ -3751,6 +3737,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000A04]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002600]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x000506]],
|
||||
"MERIKLE": [["7/256", 0x000506]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3774,6 +3761,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000705]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000204],
|
||||
["9/4096", 0x000704],
|
||||
@@ -3830,6 +3818,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000206]],
|
||||
"MERICARAND": [["7/256", 0x000206]],
|
||||
"MERICUS": [["7/256", 0x000206]],
|
||||
"MERIKLE": [["7/256", 0x000206]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3853,6 +3842,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000405]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000904],
|
||||
["9/4096", 0x000404],
|
||||
@@ -3914,6 +3904,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002000]],
|
||||
"MERICAROL": [["7/256", 0x000906]],
|
||||
"MERICARAND": [["7/256", 0x000906]],
|
||||
"MERICUS": [["7/256", 0x000906]],
|
||||
"MERIKLE": [["7/256", 0x000906]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3937,6 +3928,7 @@
|
||||
"Whitill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000805]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000504],
|
||||
["9/4096", 0x000804],
|
||||
@@ -4002,6 +3994,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x000506]],
|
||||
"MERIKLE": [["7/256", 0x000506]],
|
||||
"MERILLIA": [["1/128", 0x000605]],
|
||||
@@ -4025,6 +4018,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000205]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [["7/8192", 0x01024C]],
|
||||
"Box-Mountain": [["1/256", 0x020000]],
|
||||
"Box-JungleEast": [
|
||||
@@ -4073,6 +4067,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x000306]],
|
||||
"MERIKLE": [["7/256", 0x000406]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -4098,6 +4093,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["9/16384", 0x030A00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000402],
|
||||
["9/16384", 0x000B01],
|
||||
@@ -4150,6 +4146,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030A00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["9/16384", 0x030A00]],
|
||||
@@ -4169,6 +4166,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["3/8192", 0x030F00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000702],
|
||||
["9/16384", 0x000302]
|
||||
@@ -4219,6 +4217,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030B06]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILTAS": [["9/16384", 0x030A00]],
|
||||
@@ -4238,6 +4237,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["9/16384", 0x030A00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000302],
|
||||
["9/16384", 0x000202],
|
||||
@@ -4288,6 +4288,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B05]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B00]],
|
||||
@@ -4309,6 +4310,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030B01]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000C01],
|
||||
["9/16384", 0x000402],
|
||||
@@ -4372,6 +4374,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B01]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B00]],
|
||||
@@ -4393,6 +4396,7 @@
|
||||
},
|
||||
"Purplenum": {
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000802],
|
||||
["9/16384", 0x000302],
|
||||
@@ -4447,6 +4451,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030A00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B03]],
|
||||
@@ -4466,6 +4471,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030B01]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000502],
|
||||
["9/16384", 0x000902],
|
||||
@@ -4523,6 +4529,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B01]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILTAS": [["11/8192", 0x030B03]],
|
||||
@@ -4538,6 +4545,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["9/16384", 0x030B06]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000202],
|
||||
["9/16384", 0x000702],
|
||||
@@ -4591,6 +4599,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030A00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILTAS": [["9/16384", 0x030A00]],
|
||||
@@ -4612,6 +4621,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030B00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000902],
|
||||
["9/16384", 0x000402],
|
||||
@@ -4667,6 +4677,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B01]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["9/16384", 0x030A00]],
|
||||
@@ -4687,6 +4698,7 @@
|
||||
},
|
||||
"Whitill": {
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000502],
|
||||
["9/16384", 0x000802],
|
||||
@@ -4739,6 +4751,7 @@
|
||||
"ILL_GILL": [["7/32768", 0x010309]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B03]],
|
||||
@@ -4760,6 +4773,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030300]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["7/8192", 0x030F00],
|
||||
["7/8192", 0x01024C]
|
||||
@@ -4807,6 +4821,7 @@
|
||||
"ILL_GILL": [["7/32768", 0x01030D]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B00]],
|
||||
@@ -4830,6 +4845,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x002600]],
|
||||
"BARBA_RAY": [["13/64", 0x000407]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x000407]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000407],
|
||||
["7/4096", 0x000B05],
|
||||
@@ -4902,6 +4918,7 @@
|
||||
"LA_DIMENIAN": [["1/512", 0x010317]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005500]],
|
||||
"MERICAROL": [["13/4096", 0x005B00]],
|
||||
"MERICARAND": [["13/4096", 0x005B00]],
|
||||
"MERICUS": [["13/4096", 0x003D00]],
|
||||
"MERIKLE": [["13/4096", 0x009500]],
|
||||
"MERILLIA": [["1/64", 0x000407]],
|
||||
@@ -4928,6 +4945,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x010335]],
|
||||
"BARBA_RAY": [["13/64", 0x000E01]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x000E01]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000707],
|
||||
["7/4096", 0x000306],
|
||||
@@ -4998,6 +5016,7 @@
|
||||
"LA_DIMENIAN": [["1/1024", 0x010229]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031D]],
|
||||
"MERICAROL": [["13/4096", 0x005600]],
|
||||
"MERICARAND": [["13/4096", 0x005600]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x003D00]],
|
||||
"MERILLIA": [["1/64", 0x000707]],
|
||||
@@ -5024,6 +5043,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x002700]],
|
||||
"BARBA_RAY": [["13/64", 0x008B02]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x008B02]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000307],
|
||||
["7/4096", 0x000206],
|
||||
@@ -5096,6 +5116,7 @@
|
||||
"LA_DIMENIAN": [["1/512", 0x010313]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005B00]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x010346]],
|
||||
"MERILLIA": [["1/64", 0x000307]],
|
||||
@@ -5121,6 +5142,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x010320]],
|
||||
"BARBA_RAY": [["13/64", 0x008902]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x008902]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000C06],
|
||||
["7/4096", 0x000406],
|
||||
@@ -5199,6 +5221,7 @@
|
||||
"LA_DIMENIAN": [["1/64", 0x000C06]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005500]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x005B00]],
|
||||
"MERILLIA": [["13/131072", 0x009305]],
|
||||
@@ -5225,6 +5248,7 @@
|
||||
"Purplenum": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x01030F]],
|
||||
"BARBA_RAY": [["13/64", 0x000807]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x000807]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000807],
|
||||
["7/4096", 0x000306],
|
||||
@@ -5295,6 +5319,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x004600]],
|
||||
"LOVE_RAPPY": [["1/2", 0x01031D]],
|
||||
"MERICAROL": [["13/131072", 0x001E00]],
|
||||
"MERICARAND": [["13/131072", 0x001E00]],
|
||||
"MERICUS": [["1/1024", 0x001001]],
|
||||
"MERIKLE": [["13/4096", 0x009500]],
|
||||
"MERILLIA": [["1/64", 0x000307]],
|
||||
@@ -5321,6 +5346,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x001006]],
|
||||
"BARBA_RAY": [["7/256", 0x000E02]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x000E02]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000507],
|
||||
["7/4096", 0x000107],
|
||||
@@ -5393,6 +5419,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x01030F]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031D]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x005E00]],
|
||||
"MERILLIA": [["13/4096", 0x001004]],
|
||||
@@ -5418,6 +5445,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x002000]],
|
||||
"BARBA_RAY": [["13/64", 0x000E02]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x000E02]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000207],
|
||||
["7/4096", 0x000706],
|
||||
@@ -5490,6 +5518,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x010224]],
|
||||
"LOVE_RAPPY": [["1/2", 0x006900]],
|
||||
"MERICAROL": [["13/4096", 0x002F00]],
|
||||
"MERICARAND": [["13/4096", 0x002F00]],
|
||||
"MERICUS": [["13/4096", 0x006B00]],
|
||||
"MERIKLE": [["13/4096", 0x003D00]],
|
||||
"MERILLIA": [["1/64", 0x000E01]],
|
||||
@@ -5516,6 +5545,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x010224]],
|
||||
"BARBA_RAY": [["13/64", 0x000907]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x000907]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000907],
|
||||
["7/4096", 0x000406],
|
||||
@@ -5594,6 +5624,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x002000]],
|
||||
"LOVE_RAPPY": [["1/2", 0x001006]],
|
||||
"MERICAROL": [["13/4096", 0x003B00]],
|
||||
"MERICARAND": [["13/4096", 0x003B00]],
|
||||
"MERICUS": [["13/4096", 0x004600]],
|
||||
"MERIKLE": [["13/4096", 0x001101]],
|
||||
"MERILLIA": [["1/512", 0x01011D]],
|
||||
@@ -5620,6 +5651,7 @@
|
||||
"Whitill": {
|
||||
"BARBAROUS_WOLF": [["1/64", 0x000807]],
|
||||
"BARBA_RAY": [["13/64", 0x000507]],
|
||||
"BARBA_RAY_JOINT": [["13/64", 0x000507]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000507],
|
||||
["7/4096", 0x000806],
|
||||
@@ -5690,6 +5722,7 @@
|
||||
"LA_DIMENIAN": [["1/64", 0x000D01]],
|
||||
"LOVE_RAPPY": [["1/2", 0x010132]],
|
||||
"MERICAROL": [["1/64", 0x008902]],
|
||||
"MERICARAND": [["1/64", 0x008902]],
|
||||
"MERICUS": [["1/64", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x002F00]],
|
||||
"MERILLIA": [["1/64", 0x000807]],
|
||||
@@ -5716,6 +5749,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x01030F]],
|
||||
"BARBA_RAY": [["7/256", 0x000F02]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x000F02]],
|
||||
"Box-JungleNorth": [
|
||||
["1/1024", 0x000107],
|
||||
["1/1024", 0x000607],
|
||||
@@ -5785,6 +5819,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x010225]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005B00]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x002F00]],
|
||||
"MERIKLE": [["13/4096", 0x005E00]],
|
||||
"MERILLIA": [["1/64", 0x000C06]],
|
||||
@@ -5813,6 +5848,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000406]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000405],
|
||||
["9/4096", 0x000B03],
|
||||
@@ -5881,6 +5917,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000B05]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000407]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x010125]],
|
||||
"MERILLIA": [["1/128", 0x000406]],
|
||||
@@ -5904,6 +5941,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000706]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000705],
|
||||
["9/4096", 0x000304],
|
||||
@@ -5972,6 +6010,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000706]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000707]],
|
||||
"MERICAROL": [["7/256", 0x005600]],
|
||||
"MERICARAND": [["7/256", 0x005600]],
|
||||
"MERICUS": [["7/256", 0x008C01]],
|
||||
"MERIKLE": [["7/256", 0x000707]],
|
||||
"MERILLIA": [["1/128", 0x000706]],
|
||||
@@ -5995,6 +6034,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000306]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000305],
|
||||
["9/4096", 0x000204],
|
||||
@@ -6065,6 +6105,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000306]],
|
||||
"LOVE_RAPPY": [["7/8", 0x010219]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000307]],
|
||||
"MERILLIA": [["1/128", 0x000306]],
|
||||
@@ -6088,6 +6129,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000C05]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000C04],
|
||||
["9/4096", 0x000404],
|
||||
@@ -6162,6 +6204,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000C05]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x005600]],
|
||||
"MERILLIA": [["1/128", 0x000406]],
|
||||
@@ -6185,6 +6228,7 @@
|
||||
"Purplenum": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000806]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000805],
|
||||
["9/4096", 0x000304],
|
||||
@@ -6255,6 +6299,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000E00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000807]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000307]],
|
||||
"MERILLIA": [["1/128", 0x000306]],
|
||||
@@ -6278,6 +6323,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000906]],
|
||||
"BARBA_RAY": [["3/32", 0x000E01]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000504],
|
||||
["9/4096", 0x000904],
|
||||
@@ -6346,6 +6392,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000906]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031D]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x000F01]],
|
||||
"MERIKLE": [["7/256", 0x001004]],
|
||||
"MERILLIA": [["1/128", 0x000506]],
|
||||
@@ -6369,6 +6416,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000206]],
|
||||
"BARBA_RAY": [["3/32", 0x000E01]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000205],
|
||||
["9/4096", 0x000704],
|
||||
@@ -6439,6 +6487,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000206]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000207]],
|
||||
"MERICAROL": [["7/256", 0x005601]],
|
||||
"MERICARAND": [["7/256", 0x005601]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000207]],
|
||||
"MERILLIA": [["1/128", 0x000205]],
|
||||
@@ -6462,6 +6511,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x010219]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000905],
|
||||
["9/4096", 0x000404],
|
||||
@@ -6532,6 +6582,7 @@
|
||||
"LA_DIMENIAN": [["1/64", 0x000406]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000907]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000407]],
|
||||
"MERILLIA": [["1/128", 0x000906]],
|
||||
@@ -6555,6 +6606,7 @@
|
||||
"Whitill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000506]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000505],
|
||||
["9/4096", 0x000804],
|
||||
@@ -6627,6 +6679,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000806]],
|
||||
"LOVE_RAPPY": [["7/8", 0x010222]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x005601]],
|
||||
"MERIKLE": [["7/256", 0x008901]],
|
||||
"MERILLIA": [["1/128", 0x000506]],
|
||||
@@ -6650,6 +6703,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000806]],
|
||||
"BARBA_RAY": [["3/32", 0x000F01]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x000F01]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000105],
|
||||
["9/4096", 0x000605],
|
||||
@@ -6722,6 +6776,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x010225]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000906]],
|
||||
"MERICAROL": [["7/256", 0x003B00]],
|
||||
"MERICARAND": [["7/256", 0x003B00]],
|
||||
"MERICUS": [["7/256", 0x010125]],
|
||||
"MERIKLE": [["7/256", 0x008B01]],
|
||||
"MERILLIA": [["1/128", 0x000106]],
|
||||
|
||||
@@ -610,41 +610,16 @@
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000605]],
|
||||
"BOOMA": [["1/128", 0x030D0F]],
|
||||
"BULCLAW": [["1/128", 0x000905]],
|
||||
"Box-Cave1": [
|
||||
["9/536870912", 0x030E1C],
|
||||
["13/134217728", 0x030E16],
|
||||
["5/134217728", 0x01024A]
|
||||
],
|
||||
"Box-Cave3": [
|
||||
["7/1073741824", 0x020000],
|
||||
["7/1073741824", 0x000404],
|
||||
["3/536870912", 0x000404],
|
||||
["13/2147483648", 0x030E1B],
|
||||
["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]
|
||||
],
|
||||
"Box-Forest1": [[0x00380000, 0x030E1D]],
|
||||
"Box-Forest2": [[0x00380000, 0x030E1A], [0x00380000, 0x030E18]],
|
||||
"Box-Cave1": [[0x00380000, 0x030E16]],
|
||||
"Box-Cave2": [[0x00380000, 0x030F00], [0x00380000, 0x01024D]],
|
||||
"Box-Cave3": [[0x00900000, 0x000904], [0x00900000, 0x000404], [0x00380000, 0x030E1B]],
|
||||
"Box-Mine1": [[0x02400000, 0x020000], [0x00240000, 0x01024C], [0x00380000, 0x030E1E]],
|
||||
"Box-Mine2": [[0x01000000, 0x020000], [0x00B00000, 0x000904], [0x00B00000, 0x000404], [0x00240000, 0x01024C], [0x00380000, 0x030E1F], [0x00380000, 0x01024A]],
|
||||
"Box-Ruins1": [[0x00380000, 0x030E1C], [0x00380000, 0x030E19]],
|
||||
"Box-Ruins2": [[0x00380000, 0x01024C], [0x00380000, 0x030E17]],
|
||||
"Box-Ruins3": [[0x00D00000, 0x000905], [0x00D00000, 0x000405], [0x00380000, 0x01024B]],
|
||||
"CANADINE": [["1/128", 0x000605]],
|
||||
"CANADINE_GROUP": [["1/128", 0x000605]],
|
||||
"CANANE": [["7/256", 0x000405]],
|
||||
@@ -3269,6 +3244,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000B04]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000404],
|
||||
["9/4096", 0x000B02],
|
||||
@@ -3326,6 +3302,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002600]],
|
||||
"MERICAROL": [["7/256", 0x000406]],
|
||||
"MERICARAND": [["7/256", 0x000406]],
|
||||
"MERICUS": [["7/256", 0x000406]],
|
||||
"MERIKLE": [["7/256", 0x000406]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3349,6 +3326,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000305]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000704],
|
||||
["9/4096", 0x000304]
|
||||
@@ -3403,6 +3381,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000706]],
|
||||
"MERICARAND": [["7/256", 0x000706]],
|
||||
"MERICUS": [["7/256", 0x000706]],
|
||||
"MERIKLE": [["7/256", 0x000706]],
|
||||
"MERILLIA": [["1/128", 0x000606]],
|
||||
@@ -3426,6 +3405,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000205]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000304],
|
||||
["9/4096", 0x000204],
|
||||
@@ -3495,6 +3475,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000306]],
|
||||
"MERICARAND": [["7/256", 0x000306]],
|
||||
"MERICUS": [["7/256", 0x000306]],
|
||||
"MERIKLE": [["7/256", 0x000306]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3518,6 +3499,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000405]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000C03],
|
||||
["9/4096", 0x000404],
|
||||
@@ -3588,6 +3570,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000A04]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000C05]],
|
||||
"MERICARAND": [["7/256", 0x000C05]],
|
||||
"MERICUS": [["7/256", 0x000C05]],
|
||||
"MERIKLE": [["7/256", 0x000C05]],
|
||||
"MERILLIA": [["1/128", 0x000A04]],
|
||||
@@ -3611,6 +3594,7 @@
|
||||
"Purplenum": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000305]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000804],
|
||||
["9/4096", 0x000304],
|
||||
@@ -3672,6 +3656,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x004900]],
|
||||
"MERICAROL": [["7/256", 0x000806]],
|
||||
"MERICARAND": [["7/256", 0x000806]],
|
||||
"MERICUS": [["7/256", 0x000806]],
|
||||
"MERIKLE": [["7/256", 0x000806]],
|
||||
"MERILLIA": [["1/128", 0x000605]],
|
||||
@@ -3695,6 +3680,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000905]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000504],
|
||||
["9/4096", 0x000904],
|
||||
@@ -3767,6 +3753,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000A04]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002600]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x000506]],
|
||||
"MERIKLE": [["7/256", 0x000506]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3790,6 +3777,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000705]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000204],
|
||||
["9/4096", 0x000704],
|
||||
@@ -3846,6 +3834,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x000206]],
|
||||
"MERICARAND": [["7/256", 0x000206]],
|
||||
"MERICUS": [["7/256", 0x000206]],
|
||||
"MERIKLE": [["7/256", 0x000206]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3869,6 +3858,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000405]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000904],
|
||||
["9/4096", 0x000404],
|
||||
@@ -3930,6 +3920,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000105]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002000]],
|
||||
"MERICAROL": [["7/256", 0x000906]],
|
||||
"MERICARAND": [["7/256", 0x000906]],
|
||||
"MERICUS": [["7/256", 0x000906]],
|
||||
"MERIKLE": [["7/256", 0x000906]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -3953,6 +3944,7 @@
|
||||
"Whitill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000805]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000504],
|
||||
["9/4096", 0x000804],
|
||||
@@ -4018,6 +4010,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x000506]],
|
||||
"MERIKLE": [["7/256", 0x000506]],
|
||||
"MERILLIA": [["1/128", 0x000605]],
|
||||
@@ -4041,6 +4034,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000205]],
|
||||
"BARBA_RAY": [["1/16", 0x000E00]],
|
||||
"BARBA_RAY_JOINT": [["1/16", 0x000E00]],
|
||||
"Box-JungleNorth": [["7/8192", 0x01024C]],
|
||||
"Box-Mountain": [["1/256", 0x020000]],
|
||||
"Box-JungleEast": [
|
||||
@@ -4089,6 +4083,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000605]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x000306]],
|
||||
"MERIKLE": [["7/256", 0x000406]],
|
||||
"MERILLIA": [["1/128", 0x000105]],
|
||||
@@ -4114,6 +4109,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["9/16384", 0x030A00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000402],
|
||||
["9/16384", 0x000B01],
|
||||
@@ -4166,6 +4162,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030A00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["9/16384", 0x030A00]],
|
||||
@@ -4185,6 +4182,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["3/8192", 0x030F00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000702],
|
||||
["9/16384", 0x000302]
|
||||
@@ -4235,6 +4233,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030B06]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILTAS": [["9/16384", 0x030A00]],
|
||||
@@ -4254,6 +4253,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["9/16384", 0x030A00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000302],
|
||||
["9/16384", 0x000202],
|
||||
@@ -4304,6 +4304,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B05]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B00]],
|
||||
@@ -4325,6 +4326,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030B01]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000C01],
|
||||
["9/16384", 0x000402],
|
||||
@@ -4388,6 +4390,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B01]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B00]],
|
||||
@@ -4409,6 +4412,7 @@
|
||||
},
|
||||
"Purplenum": {
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000802],
|
||||
["9/16384", 0x000302],
|
||||
@@ -4463,6 +4467,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030A00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B03]],
|
||||
@@ -4482,6 +4487,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030B01]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000502],
|
||||
["9/16384", 0x000902],
|
||||
@@ -4539,6 +4545,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B01]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILTAS": [["11/8192", 0x030B03]],
|
||||
@@ -4554,6 +4561,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["9/16384", 0x030B06]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000202],
|
||||
["9/16384", 0x000702],
|
||||
@@ -4607,6 +4615,7 @@
|
||||
"LA_DIMENIAN": [["9/16384", 0x030A00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILTAS": [["9/16384", 0x030A00]],
|
||||
@@ -4628,6 +4637,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030B00]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000902],
|
||||
["9/16384", 0x000402],
|
||||
@@ -4683,6 +4693,7 @@
|
||||
"LA_DIMENIAN": [["11/8192", 0x030B01]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["9/16384", 0x030A00]],
|
||||
@@ -4703,6 +4714,7 @@
|
||||
},
|
||||
"Whitill": {
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["9/16384", 0x000502],
|
||||
["9/16384", 0x000802],
|
||||
@@ -4755,6 +4767,7 @@
|
||||
"ILL_GILL": [["7/32768", 0x010309]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B03]],
|
||||
@@ -4776,6 +4789,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["11/8192", 0x030300]],
|
||||
"BARBA_RAY": [["7/8", 0x030500]],
|
||||
"BARBA_RAY_JOINT": [["7/8", 0x030500]],
|
||||
"Box-JungleNorth": [
|
||||
["7/8192", 0x030F00],
|
||||
["7/8192", 0x01024C]
|
||||
@@ -4823,6 +4837,7 @@
|
||||
"ILL_GILL": [["7/32768", 0x01030D]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031C]],
|
||||
"MERICAROL": [["7/8", 0x030500]],
|
||||
"MERICARAND": [["7/8", 0x030500]],
|
||||
"MERICUS": [["7/8", 0x030500]],
|
||||
"MERIKLE": [["7/8", 0x030500]],
|
||||
"MERILLIA": [["11/8192", 0x030B00]],
|
||||
@@ -4846,6 +4861,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x002600]],
|
||||
"BARBA_RAY": [["7/256", 0x030D15]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x030D15]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000407],
|
||||
["7/4096", 0x000B05],
|
||||
@@ -4918,6 +4934,7 @@
|
||||
"LA_DIMENIAN": [["1/512", 0x010317]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005500]],
|
||||
"MERICAROL": [["13/4096", 0x005B00]],
|
||||
"MERICARAND": [["13/4096", 0x005B00]],
|
||||
"MERICUS": [["13/4096", 0x003D00]],
|
||||
"MERIKLE": [["13/4096", 0x009500]],
|
||||
"MERILLIA": [["1/64", 0x000407]],
|
||||
@@ -4944,6 +4961,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x010335]],
|
||||
"BARBA_RAY": [["7/256", 0x01035F]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x01035F]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000707],
|
||||
["7/4096", 0x000306],
|
||||
@@ -5014,6 +5032,7 @@
|
||||
"LA_DIMENIAN": [["1/1024", 0x010229]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031D]],
|
||||
"MERICAROL": [["13/4096", 0x005600]],
|
||||
"MERICARAND": [["13/4096", 0x005600]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x003D00]],
|
||||
"MERILLIA": [["1/64", 0x000707]],
|
||||
@@ -5040,6 +5059,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x002700]],
|
||||
"BARBA_RAY": [["7/256", 0x01035E]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x01035E]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000307],
|
||||
["7/4096", 0x000206],
|
||||
@@ -5112,6 +5132,7 @@
|
||||
"LA_DIMENIAN": [["1/512", 0x010313]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005B00]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x010346]],
|
||||
"MERILLIA": [["1/64", 0x000307]],
|
||||
@@ -5137,6 +5158,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x010320]],
|
||||
"BARBA_RAY": [["7/256", 0x030D15]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x030D15]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000C06],
|
||||
["7/4096", 0x000406],
|
||||
@@ -5215,6 +5237,7 @@
|
||||
"LA_DIMENIAN": [["1/64", 0x000C06]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005500]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x005B00]],
|
||||
"MERILLIA": [["13/131072", 0x009305]],
|
||||
@@ -5241,6 +5264,7 @@
|
||||
"Purplenum": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x01030F]],
|
||||
"BARBA_RAY": [["7/256", 0x01035E]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x01035E]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000807],
|
||||
["7/4096", 0x000306],
|
||||
@@ -5311,6 +5335,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x004600]],
|
||||
"LOVE_RAPPY": [["1/2", 0x01031D]],
|
||||
"MERICAROL": [["13/131072", 0x001E00]],
|
||||
"MERICARAND": [["13/131072", 0x001E00]],
|
||||
"MERICUS": [["1/1024", 0x001001]],
|
||||
"MERIKLE": [["13/4096", 0x009500]],
|
||||
"MERILLIA": [["1/64", 0x000307]],
|
||||
@@ -5337,6 +5362,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x001006]],
|
||||
"BARBA_RAY": [["7/256", 0x000E02]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x000E02]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000507],
|
||||
["7/4096", 0x000107],
|
||||
@@ -5409,6 +5435,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x01030F]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031D]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x005E00]],
|
||||
"MERILLIA": [["13/4096", 0x001004]],
|
||||
@@ -5434,6 +5461,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x002000]],
|
||||
"BARBA_RAY": [["11/256", 0x000E02]],
|
||||
"BARBA_RAY_JOINT": [["11/256", 0x000E02]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000207],
|
||||
["7/4096", 0x000706],
|
||||
@@ -5506,6 +5534,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x010224]],
|
||||
"LOVE_RAPPY": [["1/2", 0x006900]],
|
||||
"MERICAROL": [["13/4096", 0x002F00]],
|
||||
"MERICARAND": [["13/4096", 0x002F00]],
|
||||
"MERICUS": [["13/4096", 0x006B00]],
|
||||
"MERIKLE": [["13/4096", 0x003D00]],
|
||||
"MERILLIA": [["1/64", 0x000E01]],
|
||||
@@ -5532,6 +5561,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["13/4096", 0x010224]],
|
||||
"BARBA_RAY": [["7/256", 0x001402]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x001402]],
|
||||
"Box-JungleNorth": [
|
||||
["13/8192", 0x000907],
|
||||
["7/4096", 0x000406],
|
||||
@@ -5610,6 +5640,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x002000]],
|
||||
"LOVE_RAPPY": [["1/2", 0x001006]],
|
||||
"MERICAROL": [["13/4096", 0x003B00]],
|
||||
"MERICARAND": [["13/4096", 0x003B00]],
|
||||
"MERICUS": [["13/4096", 0x004600]],
|
||||
"MERIKLE": [["13/4096", 0x001101]],
|
||||
"MERILLIA": [["1/512", 0x01011D]],
|
||||
@@ -5636,6 +5667,7 @@
|
||||
"Whitill": {
|
||||
"BARBAROUS_WOLF": [["1/64", 0x000807]],
|
||||
"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": [
|
||||
["13/8192", 0x000507],
|
||||
["7/4096", 0x000806],
|
||||
@@ -5706,6 +5738,7 @@
|
||||
"LA_DIMENIAN": [["1/64", 0x000D01]],
|
||||
"LOVE_RAPPY": [["1/2", 0x010132]],
|
||||
"MERICAROL": [["1/64", 0x008902]],
|
||||
"MERICARAND": [["1/64", 0x008902]],
|
||||
"MERICUS": [["1/64", 0x008B02]],
|
||||
"MERIKLE": [["13/4096", 0x002F00]],
|
||||
"MERILLIA": [["1/64", 0x000807]],
|
||||
@@ -5732,6 +5765,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["1/512", 0x01030F]],
|
||||
"BARBA_RAY": [["7/256", 0x000F02]],
|
||||
"BARBA_RAY_JOINT": [["7/256", 0x000F02]],
|
||||
"Box-JungleNorth": [
|
||||
["1/1024", 0x000107],
|
||||
["1/1024", 0x000607],
|
||||
@@ -5801,6 +5835,7 @@
|
||||
"LA_DIMENIAN": [["13/4096", 0x010225]],
|
||||
"LOVE_RAPPY": [["1/2", 0x005B00]],
|
||||
"MERICAROL": [["13/4096", 0x008902]],
|
||||
"MERICARAND": [["13/4096", 0x008902]],
|
||||
"MERICUS": [["13/4096", 0x002F00]],
|
||||
"MERIKLE": [["13/4096", 0x005E00]],
|
||||
"MERILLIA": [["1/64", 0x000C06]],
|
||||
@@ -5829,6 +5864,7 @@
|
||||
"Bluefull": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000406]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000405],
|
||||
["9/4096", 0x000B03],
|
||||
@@ -5897,6 +5933,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000B05]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000407]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x010125]],
|
||||
"MERILLIA": [["1/128", 0x000406]],
|
||||
@@ -5920,6 +5957,7 @@
|
||||
"Greennill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000706]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000705],
|
||||
["9/4096", 0x000304],
|
||||
@@ -5988,6 +6026,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000706]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000707]],
|
||||
"MERICAROL": [["7/256", 0x005600]],
|
||||
"MERICARAND": [["7/256", 0x005600]],
|
||||
"MERICUS": [["7/256", 0x008C01]],
|
||||
"MERIKLE": [["7/256", 0x000707]],
|
||||
"MERILLIA": [["1/128", 0x000706]],
|
||||
@@ -6011,6 +6050,7 @@
|
||||
"Oran": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000306]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000305],
|
||||
["9/4096", 0x000204],
|
||||
@@ -6081,6 +6121,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000306]],
|
||||
"LOVE_RAPPY": [["7/8", 0x010219]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000307]],
|
||||
"MERILLIA": [["1/128", 0x000306]],
|
||||
@@ -6104,6 +6145,7 @@
|
||||
"Pinkal": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000C05]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000C04],
|
||||
["9/4096", 0x000404],
|
||||
@@ -6178,6 +6220,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000C05]],
|
||||
"LOVE_RAPPY": [["7/8", 0x002300]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x005600]],
|
||||
"MERILLIA": [["1/128", 0x000406]],
|
||||
@@ -6201,6 +6244,7 @@
|
||||
"Purplenum": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000806]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000805],
|
||||
["9/4096", 0x000304],
|
||||
@@ -6271,6 +6315,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000E00]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000807]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000307]],
|
||||
"MERILLIA": [["1/128", 0x000306]],
|
||||
@@ -6294,6 +6339,7 @@
|
||||
"Redria": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000906]],
|
||||
"BARBA_RAY": [["3/32", 0x000E01]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000504],
|
||||
["9/4096", 0x000904],
|
||||
@@ -6362,6 +6408,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000906]],
|
||||
"LOVE_RAPPY": [["7/8", 0x01031D]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x000F01]],
|
||||
"MERIKLE": [["7/256", 0x001004]],
|
||||
"MERILLIA": [["1/128", 0x000506]],
|
||||
@@ -6385,6 +6432,7 @@
|
||||
"Skyly": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000206]],
|
||||
"BARBA_RAY": [["3/32", 0x000E01]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x000E01]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000205],
|
||||
["9/4096", 0x000704],
|
||||
@@ -6455,6 +6503,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000206]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000207]],
|
||||
"MERICAROL": [["7/256", 0x005601]],
|
||||
"MERICARAND": [["7/256", 0x005601]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000207]],
|
||||
"MERILLIA": [["1/128", 0x000205]],
|
||||
@@ -6478,6 +6527,7 @@
|
||||
"Viridia": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x010219]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000905],
|
||||
["9/4096", 0x000404],
|
||||
@@ -6548,6 +6598,7 @@
|
||||
"LA_DIMENIAN": [["1/64", 0x000406]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000907]],
|
||||
"MERICAROL": [["7/256", 0x008901]],
|
||||
"MERICARAND": [["7/256", 0x008901]],
|
||||
"MERICUS": [["7/256", 0x008B01]],
|
||||
"MERIKLE": [["7/256", 0x000407]],
|
||||
"MERILLIA": [["1/128", 0x000906]],
|
||||
@@ -6571,6 +6622,7 @@
|
||||
"Whitill": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000506]],
|
||||
"BARBA_RAY": [["3/32", 0x008901]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x008901]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000505],
|
||||
["9/4096", 0x000804],
|
||||
@@ -6643,6 +6695,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x000806]],
|
||||
"LOVE_RAPPY": [["7/8", 0x010222]],
|
||||
"MERICAROL": [["7/256", 0x000506]],
|
||||
"MERICARAND": [["7/256", 0x000506]],
|
||||
"MERICUS": [["7/256", 0x005601]],
|
||||
"MERIKLE": [["7/256", 0x008901]],
|
||||
"MERILLIA": [["1/128", 0x000506]],
|
||||
@@ -6666,6 +6719,7 @@
|
||||
"Yellowboze": {
|
||||
"BARBAROUS_WOLF": [["1/128", 0x000806]],
|
||||
"BARBA_RAY": [["3/32", 0x000F01]],
|
||||
"BARBA_RAY_JOINT": [["3/32", 0x000F01]],
|
||||
"Box-JungleNorth": [
|
||||
["9/4096", 0x000105],
|
||||
["9/4096", 0x000605],
|
||||
@@ -6738,6 +6792,7 @@
|
||||
"LA_DIMENIAN": [["1/128", 0x010225]],
|
||||
"LOVE_RAPPY": [["7/8", 0x000906]],
|
||||
"MERICAROL": [["7/256", 0x003B00]],
|
||||
"MERICARAND": [["7/256", 0x003B00]],
|
||||
"MERICUS": [["7/256", 0x010125]],
|
||||
"MERIKLE": [["7/256", 0x008B01]],
|
||||
"MERILLIA": [["1/128", 0x000106]],
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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,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)",
|
||||
}
|
||||
|
||||
@@ -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,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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
@@ -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,3 +1,2 @@
|
||||
{
|
||||
"AvailableIf": "F_0073 && (V_NumPlayers == 1)",
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
### 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] Created
|
||||
I 35932 2025-05-22 21:56:44 - [GameServer] Client connected: C-1 via TG-9300-PC_V2-pc-game_server
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
### 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] 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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user