enable dcv1 native battle mode
This commit is contained in:
@@ -381,23 +381,6 @@ ChatCommandDefinition cc_bank(
|
||||
},
|
||||
unavailable_on_proxy_server);
|
||||
|
||||
ChatCommandDefinition cc_battle(
|
||||
{"$battle"},
|
||||
+[](const ServerArgs& a) {
|
||||
a.check_is_game(false);
|
||||
if (!is_v1(a.c->version())) {
|
||||
throw precondition_failed("$C6This command can\nonly be used on\nDC v1 and earlier");
|
||||
}
|
||||
|
||||
a.c->config.toggle_flag(Client::Flag::FORCE_BATTLE_MODE_GAME);
|
||||
if (a.c->config.check_flag(Client::Flag::FORCE_BATTLE_MODE_GAME)) {
|
||||
send_text_message(a.c, "$C6Battle mode enabled\nfor next game");
|
||||
} else {
|
||||
send_text_message(a.c, "$C6Battle mode disabled\nfor next game");
|
||||
}
|
||||
},
|
||||
unavailable_on_proxy_server);
|
||||
|
||||
static void server_command_bbchar_savechar(const ServerArgs& a, bool is_bb_conversion) {
|
||||
auto s = a.c->require_server_state();
|
||||
auto l = a.c->require_lobby();
|
||||
|
||||
+1
-2
@@ -35,7 +35,7 @@ public:
|
||||
// TODO: It'd be nice to use a pattern here (e.g. all server-side flags are
|
||||
// in the high bits) but that would require re-recording or manually
|
||||
// rewriting all the tests
|
||||
CLIENT_SIDE_MASK = 0xE73CFFFF7C0BFFFB,
|
||||
CLIENT_SIDE_MASK = 0xEF3CFFFF7C0BFFFB,
|
||||
|
||||
// Version-related flags
|
||||
CHECKED_FOR_DC_V1_PROTOTYPE = 0x0000000000000002,
|
||||
@@ -81,7 +81,6 @@ public:
|
||||
DEBUG_ENABLED = 0x0000000800000000,
|
||||
ITEM_DROP_NOTIFICATIONS_1 = 0x0010000000000000,
|
||||
ITEM_DROP_NOTIFICATIONS_2 = 0x0020000000000000,
|
||||
FORCE_BATTLE_MODE_GAME = 0x0800000000000000, // Server-side only
|
||||
|
||||
// Proxy option flags
|
||||
PROXY_SAVE_FILES = 0x0000001000000000,
|
||||
|
||||
+15
-11
@@ -351,7 +351,7 @@ struct C_LegacyLogin_PC_V3_03 {
|
||||
/* 08 */ le_uint32_t sub_version = 0;
|
||||
/* 0C */ uint8_t is_extended = 0;
|
||||
/* 0D */ uint8_t language = 0;
|
||||
/* 0E */ le_uint16_t unknown_a2 = 0;
|
||||
/* 0E */ le_uint16_t unused = 0;
|
||||
// Note: These are suffixed with 2 since they come from the same source data
|
||||
// as the corresponding fields in 9D/9E. (Even though serial_number and
|
||||
// serial_number2 have the same contents in 9E, they do not come from the same
|
||||
@@ -407,7 +407,7 @@ struct C_LegacyLogin_PC_V3_04 {
|
||||
/* 08 */ le_uint32_t sub_version = 0;
|
||||
/* 0C */ uint8_t is_extended = 0;
|
||||
/* 0D */ uint8_t language = 0;
|
||||
/* 0E */ le_uint16_t unknown_a2 = 0;
|
||||
/* 0E */ le_uint16_t unused = 0;
|
||||
/* 10 */ pstring<TextEncoding::ASCII, 0x10> serial_number;
|
||||
/* 20 */ pstring<TextEncoding::ASCII, 0x10> access_key;
|
||||
/* 30 */
|
||||
@@ -682,7 +682,7 @@ struct C_MenuSelection_10_Flag00 {
|
||||
template <TextEncoding Encoding>
|
||||
struct C_MenuSelectionT_10_Flag01 {
|
||||
C_MenuSelection_10_Flag00 basic_cmd;
|
||||
pstring<Encoding, 0x10> unknown_a1;
|
||||
pstring<Encoding, 0x10> name;
|
||||
} __packed__;
|
||||
using C_MenuSelection_DC_V3_10_Flag01 = C_MenuSelectionT_10_Flag01<TextEncoding::MARKED>;
|
||||
using C_MenuSelection_PC_BB_10_Flag01 = C_MenuSelectionT_10_Flag01<TextEncoding::UTF16>;
|
||||
@@ -702,7 +702,7 @@ check_struct_size(C_MenuSelection_PC_BB_10_Flag02, 0x28);
|
||||
template <TextEncoding Encoding>
|
||||
struct C_MenuSelectionT_10_Flag03 {
|
||||
C_MenuSelection_10_Flag00 basic_cmd;
|
||||
pstring<Encoding, 0x10> unknown_a1;
|
||||
pstring<Encoding, 0x10> name;
|
||||
pstring<Encoding, 0x10> password;
|
||||
} __packed__;
|
||||
using C_MenuSelection_DC_V3_10_Flag03 = C_MenuSelectionT_10_Flag03<TextEncoding::MARKED>;
|
||||
@@ -861,8 +861,10 @@ struct S_ReconnectSplit_19 {
|
||||
|
||||
// 20: Invalid command
|
||||
|
||||
// 21: GameGuard control (old versions of BB)
|
||||
// Format unknown
|
||||
// 21: Invalid command
|
||||
// My old notes call this command "GameGuard control (old versions of BB)", but
|
||||
// it's not clear if this is accurate. At least, BB US v1.24.3 and later do not
|
||||
// support this command.
|
||||
|
||||
// 0022: GameGuard check (BB)
|
||||
|
||||
@@ -891,8 +893,6 @@ struct SC_GameGuardCheck_BB_0022 {
|
||||
// failure.
|
||||
|
||||
struct S_ExchangeSecretLotteryTicketResult_BB_24 {
|
||||
// These fields map to unknown_a1 and unknown_a2 in the 6xDE command (but
|
||||
// their order is swapped here).
|
||||
le_uint16_t label = 0;
|
||||
uint8_t start_index = 0;
|
||||
uint8_t unused = 0;
|
||||
@@ -1316,10 +1316,14 @@ struct LobbyFlags {
|
||||
uint8_t disable_udp = 1;
|
||||
uint8_t lobby_number = 0;
|
||||
uint8_t block_number = 0;
|
||||
uint8_t unknown_a1 = 0;
|
||||
// When this flag is set in the lobby join commands (67/68), the client will
|
||||
// show the Battle option in the game creation menu. This only has an effect
|
||||
// on DCv1. On 11/2000, the option always appears but does nothing, and on
|
||||
// DCv2 and later, the game mode option is always present.
|
||||
uint8_t enable_battle_mode_v1 = 1;
|
||||
uint8_t event = 0;
|
||||
uint8_t unknown_a2 = 0;
|
||||
le_uint32_t unused = 0;
|
||||
uint8_t unused = 0;
|
||||
le_uint32_t random_seed = 0; // Unused for lobbies
|
||||
} __packed_ws__(LobbyFlags, 0x0C);
|
||||
|
||||
// Header flag = entry count (always 1 for 65 and 68; up to 0x0C for 67)
|
||||
|
||||
@@ -1275,7 +1275,6 @@ static void on_96(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
check_size_t<C_CharSaveInfo_DCv2_PC_V3_BB_96>(data);
|
||||
c->config.set_flag(Client::Flag::SHOULD_SEND_ENABLE_SAVE);
|
||||
send_update_client_config(c, false);
|
||||
send_server_time(c);
|
||||
}
|
||||
|
||||
static void on_B1(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
@@ -2232,7 +2231,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
item_id = cmd.basic_cmd.item_id;
|
||||
} else if (data.size() > sizeof(C_MenuSelection_DC_V3_10_Flag02)) {
|
||||
const auto& cmd = check_size_t<C_MenuSelection_DC_V3_10_Flag03>(data);
|
||||
team_name = cmd.unknown_a1.decode(c->language());
|
||||
team_name = cmd.name.decode(c->language());
|
||||
password = cmd.password.decode(c->language());
|
||||
menu_id = cmd.basic_cmd.menu_id;
|
||||
item_id = cmd.basic_cmd.item_id;
|
||||
@@ -4327,10 +4326,14 @@ shared_ptr<Lobby> create_game_generic(
|
||||
game->difficulty = difficulty;
|
||||
game->allowed_versions = s->compatibility_groups.at(static_cast<size_t>(creator_c->version()));
|
||||
static_assert(NUM_VERSIONS == 14, "Don't forget to update the group compatibility restrictions");
|
||||
if (!allow_v1 || (difficulty > 2) || (mode != GameMode::NORMAL)) {
|
||||
if (!allow_v1 || (difficulty > 2) || (mode == GameMode::CHALLENGE) || (mode == GameMode::SOLO)) {
|
||||
game->forbid_version(Version::DC_NTE);
|
||||
game->forbid_version(Version::DC_11_2000);
|
||||
game->forbid_version(Version::DC_V1);
|
||||
} else if (mode == GameMode::BATTLE) {
|
||||
game->forbid_version(Version::DC_NTE);
|
||||
game->forbid_version(Version::DC_11_2000);
|
||||
// v1 supports battle mode but not battle quests
|
||||
}
|
||||
switch (game->episode) {
|
||||
case Episode::NONE:
|
||||
@@ -4597,9 +4600,8 @@ static void on_0C_C1_E7_EC(shared_ptr<Client> c, uint16_t command, uint32_t, str
|
||||
|
||||
GameMode mode = GameMode::NORMAL;
|
||||
bool spectators_forbidden = false;
|
||||
if (cmd.battle_mode || c->config.check_flag(Client::Flag::FORCE_BATTLE_MODE_GAME)) {
|
||||
if (cmd.battle_mode) {
|
||||
mode = GameMode::BATTLE;
|
||||
c->config.clear_flag(Client::Flag::FORCE_BATTLE_MODE_GAME);
|
||||
}
|
||||
if (cmd.challenge_mode) {
|
||||
if (client_is_ep3) {
|
||||
|
||||
+5
-9
@@ -2118,13 +2118,9 @@ void send_join_lobby_t(shared_ptr<Client> c, shared_ptr<Lobby> l, shared_ptr<Cli
|
||||
S_JoinLobbyT<LobbyFlags, LobbyDataT, DispDataT> cmd;
|
||||
cmd.lobby_flags.client_id = c->lobby_client_id;
|
||||
cmd.lobby_flags.leader_id = l->leader_id;
|
||||
cmd.lobby_flags.disable_udp = 0x01;
|
||||
cmd.lobby_flags.lobby_number = lobby_type;
|
||||
cmd.lobby_flags.block_number = lobby_block;
|
||||
cmd.lobby_flags.unknown_a1 = 0;
|
||||
cmd.lobby_flags.event = l->event;
|
||||
cmd.lobby_flags.unknown_a2 = 0;
|
||||
cmd.lobby_flags.unused = 0;
|
||||
|
||||
vector<shared_ptr<Client>> lobby_clients;
|
||||
if (joining_client) {
|
||||
@@ -2194,13 +2190,9 @@ void send_join_lobby_xb(shared_ptr<Client> c, shared_ptr<Lobby> l, shared_ptr<Cl
|
||||
S_JoinLobby_XB_65_67_68 cmd;
|
||||
cmd.lobby_flags.client_id = c->lobby_client_id;
|
||||
cmd.lobby_flags.leader_id = l->leader_id;
|
||||
cmd.lobby_flags.disable_udp = 0x01;
|
||||
cmd.lobby_flags.lobby_number = lobby_type;
|
||||
cmd.lobby_flags.block_number = l->block;
|
||||
cmd.lobby_flags.unknown_a1 = 0;
|
||||
cmd.lobby_flags.event = l->event;
|
||||
cmd.lobby_flags.unknown_a2 = 0;
|
||||
cmd.lobby_flags.unused = 0;
|
||||
|
||||
vector<shared_ptr<Client>> lobby_clients;
|
||||
if (joining_client) {
|
||||
@@ -2247,7 +2239,6 @@ void send_join_lobby_dc_nte(shared_ptr<Client> c, shared_ptr<Lobby> l,
|
||||
S_JoinLobby_DCNTE_65_67_68 cmd;
|
||||
cmd.lobby_flags.client_id = c->lobby_client_id;
|
||||
cmd.lobby_flags.leader_id = l->leader_id;
|
||||
cmd.lobby_flags.disable_udp = 0x01;
|
||||
|
||||
vector<shared_ptr<Client>> lobby_clients;
|
||||
if (joining_client) {
|
||||
@@ -4068,6 +4059,11 @@ void send_ep3_disband_watcher_lobbies(shared_ptr<Lobby> primary_l) {
|
||||
}
|
||||
|
||||
void send_server_time(shared_ptr<Client> c) {
|
||||
// DC NTE and 11/2000 don't have this command
|
||||
if (is_pre_v1(c->version())) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t t = phosg::now();
|
||||
|
||||
time_t t_secs = t / 1000000;
|
||||
|
||||
Reference in New Issue
Block a user