Permalink
Browse files

Merge pull request #2279 from Helianthella/prompt

deprecate buildin_prompt, bake it into buildin_select
  • Loading branch information...
MishimaHaruna committed Oct 22, 2018
2 parents 388359c + 5c59f23 commit 239b7eb61eca00ff1ba24999daaa2b001afa736d
Showing with 42 additions and 106 deletions.
  1. +12 −7 doc/script_commands.txt
  2. +1 −1 src/map/clif.c
  3. +24 −98 src/map/script.c
  4. +5 −0 src/map/script.h
View
@@ -714,6 +714,8 @@ MAX_BANK_ZENY - Maximum Zeny in the bank
MAX_BG_MEMBERS - Maximum BattleGround members
MAX_CHAT_USERS - Maximum Chat users
MAX_REFINE - Maximum Refine level
MAX_MENU_OPTIONS - Maximum NPC menu options
MAX_MENU_LENGTH - Maximum NPC menu string length
Send targets and status options are also hard-coded and can be found
in 'doc/constants.md'.
@@ -1600,21 +1602,24 @@ perfectly equivalent.
---------------------------------------
*select("<option>"{, "<option>", ...})
*prompt("<option>"{, "<option>", ...})
This function is a handy replacement for 'menu' that doesn't use a complex
label structure. It will return the number of menu option picked,
starting with 1. Like 'menu', it will also set the variable @menu to
contain the option the user picked.
label structure. It will return the number of the menu option picked,
starting with 1. If the player presses cancel, the script is terminated.
if (select("Yes:No") == 1)
if (select("Yes", "No") == 1)
mes("You said yes, I know.");
And like 'menu', the selected option is consistent with grouped options
and empty options.
'prompt' works almost the same as select, except that when a character
clicks the Cancel button, this function will return 255 instead.
---------------------------------------
*prompt("<option>"{, "<option>", ...})
This function behaves exactly like select(), but when a player presses cancel
it returns MAX_MENU_OPTIONS and the script is not terminated. You almost always
want to use select() rather than prompt().
---------------------------------------
View
@@ -12342,7 +12342,7 @@ static void clif_parse_NpcSelectMenu(int fd, struct map_session_data *sd)
int npc_id = RFIFOL(fd,2);
uint8 select = RFIFOB(fd,6);
if( (select > sd->npc_menu && select != 0xff) || select == 0 ) {
if( (select > sd->npc_menu && select != MAX_MENU_OPTIONS) || select == 0 ) {
#ifdef SECURE_NPCTIMEOUT
if( sd->npc_idle_timer != INVALID_TIMER ) {
#endif
View
@@ -6099,11 +6099,11 @@ static BUILDIN(menu)
sd->state.menu_or_input = 1;
/* menus beyond this length crash the client (see bugreport:6402) */
if( StrBuf->Length(&buf) >= 2047 ) {
if( StrBuf->Length(&buf) >= MAX_MENU_LENGTH - 1 ) {
struct npc_data * nd = map->id2nd(st->oid);
char* menu;
CREATE(menu, char, 2048);
safestrncpy(menu, StrBuf->Value(&buf), 2047);
CREATE(menu, char, MAX_MENU_LENGTH);
safestrncpy(menu, StrBuf->Value(&buf), MAX_MENU_LENGTH - 1);
ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf));
clif->scriptmenu(sd, st->oid, menu);
aFree(menu);
@@ -6112,13 +6112,13 @@ static BUILDIN(menu)
StrBuf->Destroy(&buf);
if( sd->npc_menu >= 0xff )
if( sd->npc_menu >= MAX_MENU_OPTIONS )
{// client supports only up to 254 entries; 0 is not used and 255 is reserved for cancel; excess entries are displayed but cause 'uint8' overflow
ShowWarning("buildin_menu: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
ShowWarning("buildin_menu: Too many options specified (current=%d, max=%d).\n", sd->npc_menu, MAX_MENU_OPTIONS - 1);
script->reportsrc(st);
}
}
else if( sd->npc_menu == 0xff )
else if( sd->npc_menu == MAX_MENU_OPTIONS )
{// Cancel was pressed
sd->state.menu_or_input = 0;
st->state = END;
@@ -6200,119 +6200,43 @@ static BUILDIN(select)
sd->state.menu_or_input = 1;
/* menus beyond this length crash the client (see bugreport:6402) */
if( StrBuf->Length(&buf) >= 2047 ) {
if( StrBuf->Length(&buf) >= MAX_MENU_LENGTH - 1 ) {
struct npc_data * nd = map->id2nd(st->oid);
char* menu;
CREATE(menu, char, 2048);
safestrncpy(menu, StrBuf->Value(&buf), 2047);
CREATE(menu, char, MAX_MENU_LENGTH);
safestrncpy(menu, StrBuf->Value(&buf), MAX_MENU_LENGTH - 1);
ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf));
clif->scriptmenu(sd, st->oid, menu);
aFree(menu);
} else
clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
if( sd->npc_menu >= 0xff ) {
ShowWarning("buildin_select: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
if( sd->npc_menu >= MAX_MENU_OPTIONS ) {
ShowWarning("buildin_select: Too many options specified (current=%d, max=%d).\n", sd->npc_menu, MAX_MENU_OPTIONS - 1);
script->reportsrc(st);
}
} else if( sd->npc_menu == 0xff ) {// Cancel was pressed
} else if(sd->npc_menu == MAX_MENU_OPTIONS) { // Cancel was pressed
sd->state.menu_or_input = 0;
st->state = END;
} else {// return selected option
int menu = 0;
sd->state.menu_or_input = 0;
for( i = 2; i <= script_lastdata(st); ++i ) {
text = script_getstr(st, i);
sd->npc_menu -= script->menu_countoptions(text, sd->npc_menu, &menu);
if( sd->npc_menu <= 0 )
break;// entry found
}
pc->setreg(sd, script->add_variable("@menu"), menu);
script_pushint(st, menu);
st->state = RUN;
}
return true;
}
/// Displays a menu with options and returns the selected option.
/// Behaves like 'menu' without the target labels, except when cancel is
/// pressed.
/// When cancel is pressed, the script continues and 255 is returned.
///
/// prompt(<option_text>{,<option_text>,...}) -> <selected_option>
///
/// @see menu
static BUILDIN(prompt)
{
int i;
const char *text;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
#ifdef SECURE_NPCTIMEOUT
sd->npc_idle_type = NPCT_MENU;
#endif
if( sd->state.menu_or_input == 0 )
{
struct StringBuf buf;
StrBuf->Init(&buf);
sd->npc_menu = 0;
for( i = 2; i <= script_lastdata(st); ++i )
{
text = script_getstr(st, i);
if( sd->npc_menu > 0 )
StrBuf->AppendStr(&buf, ":");
StrBuf->AppendStr(&buf, text);
sd->npc_menu += script->menu_countoptions(text, 0, NULL);
}
st->state = RERUNLINE;
sd->state.menu_or_input = 1;
/* menus beyond this length crash the client (see bugreport:6402) */
if( StrBuf->Length(&buf) >= 2047 ) {
struct npc_data * nd = map->id2nd(st->oid);
char* menu;
CREATE(menu, char, 2048);
safestrncpy(menu, StrBuf->Value(&buf), 2047);
ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf));
clif->scriptmenu(sd, st->oid, menu);
aFree(menu);
} else
clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
if( sd->npc_menu >= 0xff )
{
ShowWarning("buildin_prompt: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
script->reportsrc(st);
if (strncmp(get_buildin_name(st), "prompt", 6) == 0) {
pc->setreg(sd, script->add_variable("@menu"), MAX_MENU_OPTIONS);
script_pushint(st, MAX_MENU_OPTIONS); // XXX: we should really be pushing -1 instead
st->state = RUN;
} else {
st->state = END;
}
}
else if( sd->npc_menu == 0xff )
{// Cancel was pressed
sd->state.menu_or_input = 0;
pc->setreg(sd, script->add_variable("@menu"), 0xff);
script_pushint(st, 0xff);
st->state = RUN;
}
else
{// return selected option
} else {// return selected option
int menu = 0;
sd->state.menu_or_input = 0;
for( i = 2; i <= script_lastdata(st); ++i )
{
for( i = 2; i <= script_lastdata(st); ++i ) {
text = script_getstr(st, i);
sd->npc_menu -= script->menu_countoptions(text, sd->npc_menu, &menu);
if( sd->npc_menu <= 0 )
break;// entry found
}
pc->setreg(sd, script->add_variable("@menu"), menu);
pc->setreg(sd, script->add_variable("@menu"), menu); // TODO: throw a deprecation warning for scripts using @menu
script_pushint(st, menu);
st->state = RUN;
}
@@ -24994,7 +24918,7 @@ static void script_parse_builtin(void)
BUILDIN_DEF(close2,""),
BUILDIN_DEF(menu,"sl*"),
BUILDIN_DEF(select,"s*"), //for future jA script compatibility
BUILDIN_DEF(prompt,"s*"),
BUILDIN_DEF2(select, "prompt", "s*"),
//
BUILDIN_DEF(goto,"l"),
BUILDIN_DEF(callsub,"l*"),
@@ -25608,6 +25532,8 @@ static void script_hardcoded_constants(void)
script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false, false);
script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false, false);
script->set_constant("MAX_REFINE",MAX_REFINE,false, false);
script->set_constant("MAX_MENU_OPTIONS", MAX_MENU_OPTIONS, false, false);
script->set_constant("MAX_MENU_LENGTH", MAX_MENU_LENGTH, false, false);
script->constdb_comment("status options");
script->set_constant("Option_Nothing",OPTION_NOTHING,false, false);
View
@@ -64,6 +64,9 @@ struct item_data;
#define SCRIPT_EQUIP_TABLE_SIZE 20
#define MAX_MENU_OPTIONS 0xFF
#define MAX_MENU_LENGTH 0x800
//#define SCRIPT_DEBUG_DISP
//#define SCRIPT_DEBUG_DISASM
//#define SCRIPT_DEBUG_HASH
@@ -177,6 +180,8 @@ struct item_data;
#define BUILDIN(x) bool buildin_ ## x (struct script_state* st)
#define get_buildin_name(st) ( script->get_str((int)(script_getdata((st), 0)->u.num)) )
#define script_fetch(st, n, t) do { \
if( script_hasdata((st),(n)) ) \
(t)=script_getnum((st),(n)); \

0 comments on commit 239b7eb

Please sign in to comment.