make $exit work without a quest loaded on most versions
This commit is contained in:
+29
-12
@@ -908,24 +908,41 @@ ChatCommandDefinition cc_exit(
|
|||||||
{"$exit"},
|
{"$exit"},
|
||||||
+[](const ServerArgs& a) {
|
+[](const ServerArgs& a) {
|
||||||
auto l = a.c->require_lobby();
|
auto l = a.c->require_lobby();
|
||||||
if (l->is_game()) {
|
if (!l->is_game()) {
|
||||||
if (l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS) || l->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) {
|
// Client is in the lobby; send them to the login server (main menu)
|
||||||
G_UnusedHeader cmd = {0x73, 0x01, 0x0000};
|
|
||||||
a.c->channel.send(0x60, 0x00, cmd);
|
|
||||||
a.c->floor = 0;
|
|
||||||
} else if (is_ep3(a.c->version())) {
|
|
||||||
a.c->channel.send(0xED, 0x00);
|
|
||||||
} else {
|
|
||||||
throw precondition_failed("$C6You must return to\nthe lobby first");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
send_self_leave_notification(a.c);
|
send_self_leave_notification(a.c);
|
||||||
if (!a.c->config.check_flag(Client::Flag::NO_D6)) {
|
if (!a.c->config.check_flag(Client::Flag::NO_D6)) {
|
||||||
send_message_box(a.c, "");
|
send_message_box(a.c, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
send_client_to_login_server(a.c);
|
send_client_to_login_server(a.c);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (is_ep3(a.c->version())) {
|
||||||
|
// Client is on Ep3; command ED triggers game exit
|
||||||
|
a.c->channel.send(0xED, 0x00);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS) || l->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) {
|
||||||
|
// Client is in a quest; command 6x73 triggers game exit
|
||||||
|
G_UnusedHeader cmd = {0x73, 0x01, 0x0000};
|
||||||
|
a.c->channel.send(0x60, 0x00, cmd);
|
||||||
|
a.c->floor = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (a.c->config.check_flag(Client::Flag::HAS_SEND_FUNCTION_CALL) &&
|
||||||
|
a.c->config.check_flag(Client::Flag::SEND_FUNCTION_CALL_ACTUALLY_RUNS_CODE)) {
|
||||||
|
auto s = a.c->require_server_state();
|
||||||
|
shared_ptr<const CompiledFunctionCode> fn;
|
||||||
|
try {
|
||||||
|
fn = s->function_code_index->get_patch("ExitAnywhere", a.c->config.specific_version);
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
|
if (fn) {
|
||||||
|
send_function_call(a.c, fn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw precondition_failed("$C6You must return to\nthe lobby first");
|
||||||
},
|
},
|
||||||
+[](const ProxyArgs& a) {
|
+[](const ProxyArgs& a) {
|
||||||
if (a.ses->is_in_game) {
|
if (a.ses->is_in_game) {
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
mov r2, 0
|
||||||
|
mova r0, [addrs]
|
||||||
|
mov.l r1, [r0]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov.l r1, [r0 + 4]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov r2, 1
|
||||||
|
mov.l r1, [r0 + 8]
|
||||||
|
rets
|
||||||
|
mov.w [r1], r2
|
||||||
|
.align 4
|
||||||
|
addrs:
|
||||||
|
.data 0x8C4ED300
|
||||||
|
.data 0x8C4ED344
|
||||||
|
.data 0x8C4E8D88
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
mov r2, 0
|
||||||
|
mova r0, [addrs]
|
||||||
|
mov.l r1, [r0]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov.l r1, [r0 + 4]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov r2, 1
|
||||||
|
mov.l r1, [r0 + 8]
|
||||||
|
rets
|
||||||
|
mov.w [r1], r2
|
||||||
|
.align 4
|
||||||
|
addrs:
|
||||||
|
.data 0x8C4ED300
|
||||||
|
.data 0x8C4ED344
|
||||||
|
.data 0x8C4E8D88
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
mov r2, 0
|
||||||
|
mova r0, [addrs]
|
||||||
|
mov.l r1, [r0]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov.l r1, [r0 + 4]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov r2, 1
|
||||||
|
mov.l r1, [r0 + 8]
|
||||||
|
rets
|
||||||
|
mov.w [r1], r2
|
||||||
|
.align 4
|
||||||
|
addrs:
|
||||||
|
.data 0x8C4E6DA0
|
||||||
|
.data 0x8C4E6DE4
|
||||||
|
.data 0x8C4E2828
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
mov r2, 0
|
||||||
|
mova r0, [addrs]
|
||||||
|
mov.l r1, [r0]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov.l r1, [r0 + 4]
|
||||||
|
mov.l [r1], r2
|
||||||
|
mov r2, 1
|
||||||
|
mov.l r1, [r0 + 8]
|
||||||
|
rets
|
||||||
|
mov.w [r1], r2
|
||||||
|
.align 4
|
||||||
|
addrs:
|
||||||
|
.data 0x8C4DC800
|
||||||
|
.data 0x8C4DC844
|
||||||
|
.data 0x8C4D8288
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x4748], r0
|
||||||
|
stw [r13 - 0x4744], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x4938], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x4748], r0
|
||||||
|
stw [r13 - 0x4744], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x4938], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x4728], r0
|
||||||
|
stw [r13 - 0x4724], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x4918], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x4760], r0
|
||||||
|
stw [r13 - 0x475C], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x4950], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x4758], r0
|
||||||
|
stw [r13 - 0x4754], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x4948], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x4738], r0
|
||||||
|
stw [r13 - 0x4734], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x4928], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x4738], r0
|
||||||
|
stw [r13 - 0x4734], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x4928], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
li r0, 0
|
||||||
|
stw [r13 - 0x46E8], r0
|
||||||
|
stw [r13 - 0x46E4], r0
|
||||||
|
li r0, 1
|
||||||
|
sth [r13 - 0x48D8], r0
|
||||||
|
blr
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x00632934], eax # is_in_quest = false
|
||||||
|
mov [0x00632930], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x00723F88], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x006321CC], eax # is_in_quest = false
|
||||||
|
mov [0x006321C8], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x00723808], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x0062D374], eax # is_in_quest = false
|
||||||
|
mov [0x0062D370], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x0071E8E8], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x0062D914], eax # is_in_quest = false
|
||||||
|
mov [0x0062D910], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x0071EF48], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x0063544C], eax # is_in_quest = false
|
||||||
|
mov [0x00635448], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x00726A88], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x00632934], eax # is_in_quest = false
|
||||||
|
mov [0x00632930], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x00723F88], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x00632CCC], eax # is_in_quest = false
|
||||||
|
mov [0x00632CC8], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x00724308], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# This function implements $exit in a game when no quest is loaded.
|
||||||
|
|
||||||
|
.meta name="Exit anywhere"
|
||||||
|
.meta description=""
|
||||||
|
.meta hide_from_patches_menu
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
|
||||||
|
start:
|
||||||
|
xor eax, eax
|
||||||
|
mov [0x00A95624], eax # is_in_quest = false
|
||||||
|
mov [0x00A955E0], eax # dat_source_type = NONE
|
||||||
|
inc eax
|
||||||
|
mov [0x00AAE6D4], ax # should_leave_game = true
|
||||||
|
ret
|
||||||
Reference in New Issue
Block a user