Skip to content

Commit b1c063a

Browse files
committed
Fix "Double continuation" warning when using an item during NPC interaction
With item_enabled_npc allowing item usage while an NPC dialog is open, using an item attached a second script to the player. The NPC's script was backed up into the item script's bk_st and then reported as a lost "Double continuation", discarding the conversation the player was in. The player is now detached from the running script before the item script is executed, and reattached to it afterwards, so an item that does not open a window of its own leaves the conversation intact. Detaching the script is not enough on its own, because the answer a menu() or input() is waiting for is kept in the session data rather than in the script state. An item script that opened a menu of its own found that pending answer already set and read it as its own, returning a selection the player never made for it, so a dungeon teleport scroll used while an NPC menu was open warped the player immediately instead of asking where to go. The pending answer is now saved and cleared before the item script runs, and handed back only when the previous script is reattached. An item script that does pause to show its own window is a different case: by that point the client is already displaying that window, so the previous conversation can no longer be resumed and its script is released instead. Restoring it there would leave the client showing one dialog while the server expects another, which locks the player out of both. Based on rathena commit: commit 3c93e30 Author: Lemongrass3110 <lemongrass@kstp.at> Date: Wed Oct 29 18:36:28 2025 +0000 Fixed an issue with item_enabled_npc (#9606) Fixes #8625 Thanks to @thanna Fixes #3471
1 parent bd8fe24 commit b1c063a

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

‎src/map/pc.c‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5496,7 +5496,51 @@ static int pc_useitem(struct map_session_data *sd, int n)
54965496
if (nameid == ITEMID_MEGAPHONE)
54975497
sd->state.using_megaphone = 1;
54985498

5499+
// Save the script the player is currently attached to, so that using an item doesn't
5500+
// clobber an NPC conversation already in progress. (issue #3471)
5501+
struct script_state *previous_st = sd->st;
5502+
bool previous_menu_or_input = false;
5503+
int previous_npc_menu = 0;
5504+
int previous_npc_amount_min = 0;
5505+
int previous_npc_amount_max = 0;
5506+
5507+
if (previous_st != NULL) {
5508+
// A menu() or input() the previous script is waiting on left its answer pending in the
5509+
// session data. The item script must not read it as its own, or its menu() would return
5510+
// a selection the player never made for it and its input() a number meant for the NPC.
5511+
previous_menu_or_input = (sd->state.menu_or_input != 0);
5512+
previous_npc_menu = sd->npc_menu;
5513+
previous_npc_amount_min = sd->npc_amount_min;
5514+
previous_npc_amount_max = sd->npc_amount_max;
5515+
sd->state.menu_or_input = 0;
5516+
sd->npc_menu = 0;
5517+
5518+
// Detach the player from the running script, so the item script doesn't back it up.
5519+
script->detach_rid(previous_st);
5520+
}
5521+
54995522
script->run_use_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
5523+
5524+
if (previous_st != NULL) {
5525+
if (sd->st != NULL) {
5526+
// The item script paused to show a window of its own, so that is what the client
5527+
// displays now and the previous conversation can no longer be resumed. Whatever it
5528+
// is waiting for belongs to the item script, so the saved state is dropped with it.
5529+
script->free_state(previous_st);
5530+
} else {
5531+
// Detaching cleared the RID, so it has to be restored before reattaching.
5532+
previous_st->rid = sd->bl.id;
5533+
script->attach_state(previous_st);
5534+
5535+
// The client still shows the previous script's window, so its pending answer is
5536+
// handed back for whenever the player gets around to it.
5537+
sd->state.menu_or_input = (previous_menu_or_input ? 1 : 0);
5538+
sd->npc_menu = previous_npc_menu;
5539+
sd->npc_amount_min = previous_npc_amount_min;
5540+
sd->npc_amount_max = previous_npc_amount_max;
5541+
}
5542+
}
5543+
55005544
script->potion_flag = 0;
55015545

55025546
// If Earth Spike Scroll is used while SC_EARTHSCROLL is active, there is a chance to don't consume the scroll. [Kenpachi]

0 commit comments

Comments
 (0)