add dynamic switching in EnemyDamageSync
This commit is contained in:
+15
-14
@@ -50,29 +50,29 @@ public:
|
||||
SEND_FUNCTION_CALL_ACTUALLY_RUNS_CODE = 0x0000000000004000,
|
||||
SEND_FUNCTION_CALL_NO_CACHE_PATCH = 0x0000000000008000,
|
||||
CAN_RECEIVE_ENABLE_B2_QUEST = 0x0000000000020000,
|
||||
AWAITING_ENABLE_B2_QUEST = 0x0000000000040000, // Server-side only
|
||||
AWAITING_ENABLE_B2_QUEST = 0x0000000000040000,
|
||||
|
||||
// State flags
|
||||
LOADING = 0x0000000000100000, // Server-side only
|
||||
LOADING_QUEST = 0x0000000000200000, // Server-side only
|
||||
LOADING_RUNNING_JOINABLE_QUEST = 0x0000000000400000, // Server-side only
|
||||
LOADING_TOURNAMENT = 0x0000000000800000, // Server-side only
|
||||
IN_INFORMATION_MENU = 0x0000000001000000, // Server-side only
|
||||
AT_WELCOME_MESSAGE = 0x0000000002000000, // Server-side only
|
||||
LOADING = 0x0000000000100000,
|
||||
LOADING_QUEST = 0x0000000000200000,
|
||||
LOADING_RUNNING_JOINABLE_QUEST = 0x0000000000400000,
|
||||
LOADING_TOURNAMENT = 0x0000000000800000,
|
||||
IN_INFORMATION_MENU = 0x0000000001000000,
|
||||
AT_WELCOME_MESSAGE = 0x0000000002000000,
|
||||
SAVE_ENABLED = 0x0000000004000000,
|
||||
HAS_EP3_CARD_DEFS = 0x0000000008000000,
|
||||
HAS_EP3_MEDIA_UPDATES = 0x0000000010000000,
|
||||
HAS_AUTO_PATCHES = 0x0000004000000000,
|
||||
AT_BANK_COUNTER = 0x0000000080000000, // Server-side only
|
||||
SHOULD_SEND_ARTIFICIAL_ITEM_STATE = 0x0001000000000000, // Server-side only
|
||||
SHOULD_SEND_ARTIFICIAL_ENEMY_AND_SET_STATE = 0x0040000000000000, // Server-side only
|
||||
SHOULD_SEND_ARTIFICIAL_OBJECT_STATE = 0x0080000000000000, // Server-side only
|
||||
SHOULD_SEND_ARTIFICIAL_FLAG_STATE = 0x0002000000000000, // Server-side only
|
||||
SHOULD_SEND_ARTIFICIAL_PLAYER_STATES = 0x0200000000000000, // Server-side only
|
||||
AT_BANK_COUNTER = 0x0000000080000000,
|
||||
SHOULD_SEND_ARTIFICIAL_ITEM_STATE = 0x0001000000000000,
|
||||
SHOULD_SEND_ARTIFICIAL_ENEMY_AND_SET_STATE = 0x0040000000000000,
|
||||
SHOULD_SEND_ARTIFICIAL_OBJECT_STATE = 0x0080000000000000,
|
||||
SHOULD_SEND_ARTIFICIAL_FLAG_STATE = 0x0002000000000000,
|
||||
SHOULD_SEND_ARTIFICIAL_PLAYER_STATES = 0x0200000000000000,
|
||||
SHOULD_SEND_ENABLE_SAVE = 0x0004000000000000,
|
||||
SWITCH_ASSIST_ENABLED = 0x0000000100000000,
|
||||
IS_CLIENT_CUSTOMIZATION = 0x0100000000000000,
|
||||
EP3_ALLOW_6xBC = 0x1000000000000000, // Server-side only
|
||||
EP3_ALLOW_6xBC = 0x1000000000000000,
|
||||
|
||||
// Cheat mode and option flags
|
||||
INFINITE_HP_ENABLED = 0x0000000200000000,
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
DEBUG_ENABLED = 0x0000000800000000,
|
||||
ITEM_DROP_NOTIFICATIONS_1 = 0x0010000000000000,
|
||||
ITEM_DROP_NOTIFICATIONS_2 = 0x0020000000000000,
|
||||
HAS_ENEMY_DAMAGE_SYNC_PATCH = 0x2000000000000000, // Must be same as in EnemyDamageSync*.s
|
||||
|
||||
// Proxy option flags
|
||||
PROXY_SAVE_FILES = 0x0000001000000000,
|
||||
|
||||
@@ -266,6 +266,8 @@ static vector<shared_ptr<CompiledFunctionCode>> compile_function_code(
|
||||
compiled->long_name = it.second;
|
||||
} else if (it.first == "description") {
|
||||
compiled->description = it.second;
|
||||
} else if (it.first == "client_flag") {
|
||||
compiled->client_flag = stoull(it.second, nullptr, 0);
|
||||
} else {
|
||||
throw runtime_error("unknown metadata key: " + it.first);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ struct CompiledFunctionCode {
|
||||
std::string short_name; // Based on filename
|
||||
std::string long_name; // From .meta name directive
|
||||
std::string description; // From .meta description directive
|
||||
uint64_t client_flag = 0; // From .meta client_flag directive
|
||||
uint32_t menu_item_id = 0;
|
||||
bool hide_from_patches_menu = false;
|
||||
uint32_t specific_version = 0; // 0 = not a client-selectable patch
|
||||
|
||||
@@ -296,6 +296,15 @@ uint16_t Lobby::quest_version_flags() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t Lobby::client_extension_flags() const {
|
||||
for (auto lc : this->clients) {
|
||||
if (lc && !lc->check_flag(Client::Flag::HAS_ENEMY_DAMAGE_SYNC_PATCH)) {
|
||||
return 0x01;
|
||||
}
|
||||
}
|
||||
return 0x81;
|
||||
}
|
||||
|
||||
void Lobby::load_maps() {
|
||||
auto rare_rates = this->rare_enemy_rates ? this->rare_enemy_rates : MapState::DEFAULT_RARE_ENEMIES;
|
||||
|
||||
|
||||
@@ -213,6 +213,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
void create_item_creator(Version logic_version = Version::UNKNOWN);
|
||||
uint8_t effective_section_id() const;
|
||||
uint16_t quest_version_flags() const;
|
||||
uint8_t client_extension_flags() const;
|
||||
void load_maps();
|
||||
void create_ep3_server();
|
||||
|
||||
|
||||
+3
-3
@@ -2724,8 +2724,8 @@ static const vector<DATEntityDefinition> dat_enemy_definitions({
|
||||
{0x0110, F_EP3, 0x0000000000000001, "TObjNpcWalkingMeka_Hero"}, // Small talking robot in Morgue
|
||||
{0x0111, F_EP3, 0x0000000000000001, "TObjNpcWalkingMeka_Dark"}, // Small talking robot in Morgue
|
||||
|
||||
// Episode 3 scientist and aide NPCs. These NPC take all the same params as
|
||||
// the NPCs defined above, but also:
|
||||
// Episode 3 scientist and aide NPCs. These NPCs take all the same params
|
||||
// as the NPCs defined above, but also:
|
||||
// angle.x = model number (clamped to [0, 3] for scientists, [0, 2] for
|
||||
// aides)
|
||||
// The two type values for scientists (00D4 and 00D5) are direct aliases
|
||||
@@ -2931,7 +2931,7 @@ static const vector<DATEntityDefinition> dat_enemy_definitions({
|
||||
// Monest that has param1 = 3 and param2 = 10. This looks like just an
|
||||
// off-by-one error on Sega's part where they accidentally shifted the
|
||||
// parameters down by one place. As described above, this Monest expels
|
||||
// 6 Mothmants, then no more after they are killed.
|
||||
// 6 Mothmants immediately, then no more after those 6 are killed.
|
||||
{0x0042, F_V0_V4, 0x0000000000180006, "TObjEneBm3FlyNest"},
|
||||
|
||||
// Savage Wolf or Barbarous Wolf. Params:
|
||||
|
||||
+8
-3
@@ -450,6 +450,7 @@ asio::awaitable<C_ExecuteCodeResult_B3> send_function_call(
|
||||
override_relocations_offset,
|
||||
ignore_actually_runs_code_flag);
|
||||
c->function_call_response_queue.emplace_back(promise);
|
||||
c->enabled_flags |= code->client_flag;
|
||||
co_return co_await promise->get();
|
||||
}
|
||||
|
||||
@@ -467,6 +468,7 @@ asio::awaitable<void> send_function_call_multi(
|
||||
last_promise = make_shared<AsyncPromise<C_ExecuteCodeResult_B3>>();
|
||||
c->function_call_response_queue.emplace_back(last_promise);
|
||||
send_function_call(c->channel, c->enabled_flags, code);
|
||||
c->enabled_flags |= code->client_flag;
|
||||
}
|
||||
if (c->channel->connected()) {
|
||||
co_await last_promise->get();
|
||||
@@ -1994,7 +1996,7 @@ void send_join_game(shared_ptr<Client> c, shared_ptr<Lobby> l) {
|
||||
cmd.variations = l->variations;
|
||||
cmd.client_id = c->lobby_client_id;
|
||||
cmd.leader_id = l->leader_id;
|
||||
cmd.disable_udp = 0x01; // Unused on PC/XB/BB
|
||||
cmd.disable_udp = l->client_extension_flags();
|
||||
cmd.difficulty = l->difficulty;
|
||||
cmd.battle_mode = (l->mode == GameMode::BATTLE) ? 1 : 0;
|
||||
cmd.event = l->event;
|
||||
@@ -2029,7 +2031,7 @@ void send_join_game(shared_ptr<Client> c, shared_ptr<Lobby> l) {
|
||||
S_JoinGame_DCNTE_64 cmd;
|
||||
cmd.client_id = c->lobby_client_id;
|
||||
cmd.leader_id = l->leader_id;
|
||||
cmd.disable_udp = 0x01;
|
||||
cmd.disable_udp = l->client_extension_flags();
|
||||
cmd.variations = l->variations;
|
||||
size_t player_count = populate_lobby_data(cmd);
|
||||
send_command_t(c, 0x64, player_count, cmd);
|
||||
@@ -2158,6 +2160,7 @@ 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 = l->client_extension_flags();
|
||||
cmd.lobby_flags.lobby_number = lobby_type;
|
||||
cmd.lobby_flags.block_number = lobby_block;
|
||||
cmd.lobby_flags.event = l->event;
|
||||
@@ -2230,6 +2233,7 @@ 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 = l->client_extension_flags();
|
||||
cmd.lobby_flags.lobby_number = lobby_type;
|
||||
cmd.lobby_flags.block_number = l->block;
|
||||
cmd.lobby_flags.event = l->event;
|
||||
@@ -2279,6 +2283,7 @@ 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 = l->client_extension_flags();
|
||||
|
||||
vector<shared_ptr<Client>> lobby_clients;
|
||||
if (joining_client) {
|
||||
@@ -2401,7 +2406,7 @@ void send_update_lobby_data_bb(std::shared_ptr<Client> c) {
|
||||
}
|
||||
|
||||
void send_player_leave_notification(shared_ptr<Lobby> l, uint8_t leaving_client_id) {
|
||||
S_LeaveLobby_66_69_Ep3_E9 cmd = {leaving_client_id, l->leader_id, 1, 0};
|
||||
S_LeaveLobby_66_69_Ep3_E9 cmd = {leaving_client_id, l->leader_id, l->client_extension_flags(), 0};
|
||||
uint8_t cmd_num;
|
||||
if (l->is_game()) {
|
||||
cmd_num = l->check_flag(Lobby::Flag::IS_SPECTATOR_TEAM) ? 0xE9 : 0x66;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.meta hide_from_patches_menu
|
||||
.meta name="DMC"
|
||||
.meta description="Mitigates effects\nof enemy health\ndesync"
|
||||
.meta client_flag="0x2000000000000000"
|
||||
|
||||
.versions 3OJ2 3OJ3 3OJ4 3OJ5 3OE0 3OE1 3OE2 3OP0
|
||||
|
||||
@@ -18,11 +19,18 @@ start:
|
||||
|
||||
|
||||
|
||||
.data <VERS 0x801E40C4 0x801E4648 0x801E481C 0x801E4594 0x801E4528 0x801E4528 0x801E45E8 0x801E4C24>
|
||||
.data 8
|
||||
cmpwi r0, 0
|
||||
beq +0x0C
|
||||
|
||||
|
||||
|
||||
# Don't allow 6x0A to set total_damage; we'll do it with 6xE4 instead
|
||||
.data <VERS 0x800F6064 0x800F6368 0x800F6594 0x800F6490 0x800F6308 0x800F6308 0x800F64A0 0x800F6468>
|
||||
.data 4
|
||||
.address <VERS 0x800F6064 0x800F6368 0x800F6594 0x800F6490 0x800F6308 0x800F6308 0x800F64A0 0x800F6468>
|
||||
nop
|
||||
bl set_enemy_total_damage_hook
|
||||
|
||||
|
||||
|
||||
@@ -129,8 +137,11 @@ start:
|
||||
.deltaof code_start, code_end
|
||||
.address 0x800041C0
|
||||
code_start:
|
||||
|
||||
handle_6xE4: # [std] (G_IncrementEnemyDamage_Extension_6xE4* cmd @ r3) -> void
|
||||
lwz r12, [r13 - <VERS 0x50A0 0x5098 0x5078 0x5078 0x5088 0x5088 0x5068 0x5028>]
|
||||
andi. r12, r12, 0x0080
|
||||
beqlr
|
||||
|
||||
mflr r0
|
||||
stw [r1 + 4], r0
|
||||
stwu [r1 - 0x20], r1
|
||||
@@ -224,6 +235,11 @@ on_TObjectV8047c128_add_hp_with_sync: # [std] (TObjectV8047c128* ene @ r3, int1
|
||||
on_TObjectV8047c128_subtract_hp_with_sync: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4) -> void
|
||||
li r5, 0
|
||||
on_add_or_subtract_hp: # [std] (TObjectV8047c128* ene @ r3, int16_t amount @ r4, bool is_add @ r5) -> void
|
||||
|
||||
lwz r12, [r13 - <VERS 0x50A0 0x5098 0x5078 0x5078 0x5088 0x5088 0x5068 0x5028>]
|
||||
andi. r12, r12, 0x0080
|
||||
beq on_add_or_subtract_hp_skip_send
|
||||
|
||||
lhz r0, [r3 + 0x1C]
|
||||
cmplwi r0, 0x1000
|
||||
blt on_add_or_subtract_hp_skip_send
|
||||
@@ -293,6 +309,15 @@ on_add_or_subtract_hp_tail_call_subtract_hp:
|
||||
|
||||
|
||||
|
||||
set_enemy_total_damage_hook:
|
||||
lwz r12, [r13 - <VERS 0x50A0 0x5098 0x5078 0x5078 0x5088 0x5088 0x5068 0x5028>]
|
||||
andi. r12, r12, 0x0080
|
||||
bnelr
|
||||
sth [r1 + 0x0E], r3
|
||||
blr
|
||||
|
||||
|
||||
|
||||
# TODO: Remove this when no longer necessary
|
||||
debug_hook1:
|
||||
mflr r0
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.meta hide_from_patches_menu
|
||||
.meta name="DMC"
|
||||
.meta description="Mitigates effects\nof enemy health\ndesync"
|
||||
.meta client_flag="0x2000000000000000"
|
||||
|
||||
.versions 4OJB 4OJD 4OJU 4OED 4OEU 4OPD 4OPU
|
||||
|
||||
@@ -16,6 +17,30 @@ write_call_to_code_multi:
|
||||
start:
|
||||
call write_static_patches
|
||||
call write_incr_hp_with_sync
|
||||
call write_6x0A_patch
|
||||
ret
|
||||
|
||||
|
||||
|
||||
write_6x0A_patch:
|
||||
push 5
|
||||
push <VERS 0x002B3B55 0x002B4625 0x002B5BB5 0x002B56C5 0x002B58A5 0x002B56E5 0x002B59B5>
|
||||
push 1
|
||||
call +4
|
||||
.deltaof on_6x0A_patch_start, on_6x0A_patch_end
|
||||
pop eax
|
||||
push dword [eax]
|
||||
call on_6x0A_patch_end
|
||||
|
||||
on_6x0A_patch_start: # (TObjectV004434c8* this @ eax, int16_t amount @ cx) -> bool @ eax
|
||||
test byte [0x006354B8], 0x80
|
||||
jnz on_6x0A_patch_skip_write
|
||||
mov [esp + 0x16], ax
|
||||
on_6x0A_patch_skip_write:
|
||||
ret
|
||||
|
||||
on_6x0A_patch_end:
|
||||
call write_call_to_code_multi
|
||||
ret
|
||||
|
||||
|
||||
@@ -65,6 +90,9 @@ on_add_or_subtract_hp_start: # (TObjectV004434c8* this @ eax, int16_t amount @
|
||||
push eax
|
||||
push ecx
|
||||
push ebx
|
||||
|
||||
test byte [0x006354B8], 0x80
|
||||
jz on_add_or_subtract_hp_skip_send
|
||||
movzx edx, word [eax + 0x1C] # ene->entity_id
|
||||
cmp edx, 0x1000
|
||||
jl on_add_or_subtract_hp_skip_send
|
||||
@@ -120,14 +148,12 @@ on_add_or_subtract_hp_end:
|
||||
write_static_patches:
|
||||
.include WriteCodeBlocksXB
|
||||
|
||||
# Don't let 6x0A handler overwrite total_damage
|
||||
.data <VERS 0x002B3B55 0x002B4625 0x002B5BB5 0x002B56C5 0x002B58A5 0x002B56E5 0x002B59B5>
|
||||
.data 5
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
.data <VERS 0x002DB7A0 0x002DC370 0x002DDC30 0x002DD700 0x002DDC00 0x002DD730 0x002DDC80>
|
||||
.data 9
|
||||
flag_check_start:
|
||||
cmp dword [0x006354B8], 0
|
||||
je +0x38
|
||||
flag_check_end:
|
||||
|
||||
.data <VERS 0x00537180 0x00537800 0x0053EB20 0x0053BFA0 0x0053B840 0x0053BFA0 0x0053C340>
|
||||
.data 8
|
||||
@@ -143,6 +169,9 @@ handle_6xE4: # [std] (G_6xE4* cmd @ [esp + 4]) -> void
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
test byte [0x006354B8], 0x80
|
||||
jz handle_6xE4_return
|
||||
mov ebx, [esp + 0x10] # cmd
|
||||
movzx eax, word [ebx + 2]
|
||||
cmp eax, 0x1000
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.meta hide_from_patches_menu
|
||||
.meta name="DMC"
|
||||
.meta description="Mitigates effects\nof enemy health\ndesync"
|
||||
.meta client_flag="0x2000000000000000"
|
||||
|
||||
entry_ptr:
|
||||
reloc0:
|
||||
@@ -26,6 +27,9 @@ handle_6xE4_start: # (G_6xE4* cmd @ [esp + 4]) -> void
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
test byte [0x00AAB27C], 0x80
|
||||
jz handle_6xE4_return
|
||||
mov ebx, [esp + 0x10] # cmd
|
||||
movzx eax, word [ebx + 2]
|
||||
cmp eax, 0x1000
|
||||
@@ -135,6 +139,8 @@ handle_6xE4_end:
|
||||
call on_add_or_subtract_hp_end
|
||||
|
||||
on_add_or_subtract_hp_start: # (TObjectV00b441c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
|
||||
test byte [0x00AAB27C], 0x80
|
||||
jz on_add_or_subtract_hp_skip_send
|
||||
movzx eax, word [ecx + 0x1C] # ene->entity_id
|
||||
cmp eax, 0x1000
|
||||
jl on_add_or_subtract_hp_skip_send
|
||||
@@ -183,9 +189,24 @@ on_add_or_subtract_hp_end:
|
||||
|
||||
|
||||
|
||||
# Don't let 6x0A handler overwrite total_damage
|
||||
mov byte [0x0078781F], 0x90
|
||||
mov dword [0x00787820], 0x90909090
|
||||
push 5
|
||||
push 0x0078781F
|
||||
push 1
|
||||
call +4
|
||||
.deltaof on_6x0A_patch_start, on_6x0A_patch_end
|
||||
pop eax
|
||||
push dword [eax]
|
||||
call on_6x0A_patch_end
|
||||
|
||||
on_6x0A_patch_start: # (TObjectV00b441c0* this @ ecx, int16_t amount @ [esp + 4]) -> bool @ eax
|
||||
test byte [0x00AAB27C], 0x80
|
||||
jz on_6x0A_patch_skip_write
|
||||
mov [esp + 0x0A], cx
|
||||
on_6x0A_patch_skip_write:
|
||||
ret
|
||||
|
||||
on_6x0A_patch_end:
|
||||
call write_call_to_code_multi
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user