From 211787e349e0249fc032b3b51f8649af613f5ecf Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Thu, 1 Sep 2016 22:02:39 +0300 Subject: Add hack for avoid npc_str buffer size limitation. Now for npc_str used global variable. And it cant be used in any functions except input related buildins. --- src/emap/clif.c | 20 ++++++++++ src/emap/clif.h | 2 + src/emap/init.c | 3 ++ src/emap/script_buildins.c | 92 ++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 105 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/emap/clif.c b/src/emap/clif.c index 63b7cc0..d3bf523 100644 --- a/src/emap/clif.c +++ b/src/emap/clif.c @@ -37,6 +37,7 @@ #include "emap/struct/sessionext.h" extern bool isInit; +extern char global_npc_str[1001]; static inline void RBUFPOS(const uint8 *p, unsigned short pos, @@ -1739,3 +1740,22 @@ void eclif_party_info_post(struct party_data *p, clif->party_option(p, sd, 2); } } + +/// NPC text input dialog value (CZ_INPUT_EDITDLGSTR). +/// 01d5 .W .L .?B +void eclif_parse_NpcStringInput(int fd, + struct map_session_data* sd) +{ + int message_len = RFIFOW(fd, 2) - 8; + int npcid = RFIFOL(fd, 4); + const char *message = RFIFOP(fd, 8); + + if (message_len <= 0) + return; // invalid input + + if (message_len > 1000) + message_len = 1000; + + safestrncpy(global_npc_str, message, message_len); + npc->scriptcont(sd, npcid, false); +} diff --git a/src/emap/clif.h b/src/emap/clif.h index 4838dc6..1353cc7 100644 --- a/src/emap/clif.h +++ b/src/emap/clif.h @@ -103,4 +103,6 @@ void eclif_parse_WalkToXY(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void eclif_party_info_post(struct party_data *p, struct map_session_data *sd); +void eclif_parse_NpcStringInput(int fd, + struct map_session_data* sd) __attribute__((nonnull (2))); #endif // EVOL_MAP_CLIF diff --git a/src/emap/init.c b/src/emap/init.c index fb95d32..23a2a88 100644 --- a/src/emap/init.c +++ b/src/emap/init.c @@ -77,6 +77,7 @@ extern int langScriptId; extern int mountScriptId; bool isInit; +char global_npc_str[1001]; HPExport struct hplugin_info pinfo = { @@ -89,6 +90,7 @@ HPExport struct hplugin_info pinfo = HPExport void plugin_init (void) { isInit = false; + *global_npc_str = 0; htreg_init(); skilld_init(); @@ -327,6 +329,7 @@ HPExport void plugin_init (void) skill->validate_additional_fields = eskill_validate_additional_fields; clif->useskill = eclif_useskill; clif->pWalkToXY = eclif_parse_WalkToXY; + clif->pNpcStringInput = eclif_parse_NpcStringInput; pc->jobchange = epc_jobchange; langScriptId = script->add_str("Lang"); diff --git a/src/emap/script_buildins.c b/src/emap/script_buildins.c index 2ada5ca..b0cf499 100644 --- a/src/emap/script_buildins.c +++ b/src/emap/script_buildins.c @@ -34,6 +34,7 @@ #include "emap/utils/formatutils.h" extern int mountScriptId; +extern char global_npc_str[1001]; uint32 MakeDWord(uint16 word0, uint16 word1) { @@ -304,8 +305,8 @@ BUILDIN(requestLang) sd->state.menu_or_input = 0; int lng = -1; - if (*sd->npc_str) - lng = lang_getId(sd->npc_str); + if (*global_npc_str) + lng = lang_getId(global_npc_str); script_pushint(st, lng); st->state = RUN; } @@ -333,7 +334,7 @@ BUILDIN(requestItem) int item = 0; - if (!*sd->npc_str) + if (!*global_npc_str) { ShowWarning("npc string not found\n"); script_pushint(st, 0); @@ -341,7 +342,7 @@ BUILDIN(requestItem) return false; } - if (sscanf (sd->npc_str, "%5d", &item) < 1) + if (sscanf (global_npc_str, "%5d", &item) < 1) { ShowWarning("input data is not item id\n"); script_pushint(st, 0); @@ -381,7 +382,7 @@ BUILDIN(requestItems) sd->state.menu_or_input = 0; st->state = RUN; - if (!*sd->npc_str) + if (!*global_npc_str) { ShowWarning("npc string not found\n"); script_pushstr(st, aStrdup("0,0")); @@ -389,7 +390,7 @@ BUILDIN(requestItems) return false; } - script_pushstr(st, aStrdup(sd->npc_str)); + script_pushstr(st, aStrdup(global_npc_str)); } return true; } @@ -418,7 +419,7 @@ BUILDIN(requestItemIndex) int item = -1; - if (!*sd->npc_str) + if (!*global_npc_str) { script_pushint(st, -1); ShowWarning("npc string not found\n"); @@ -426,7 +427,7 @@ BUILDIN(requestItemIndex) return false; } - if (sscanf (sd->npc_str, "%5d", &item) < 1) + if (sscanf (global_npc_str, "%5d", &item) < 1) { script_pushint(st, -1); ShowWarning("input data is not item id\n"); @@ -469,7 +470,7 @@ BUILDIN(requestItemsIndex) sd->state.menu_or_input = 0; st->state = RUN; - if (!*sd->npc_str) + if (!*global_npc_str) { script_pushstr(st, aStrdup("-1")); ShowWarning("npc string not found\n"); @@ -477,7 +478,7 @@ BUILDIN(requestItemsIndex) return false; } - script_pushstr(st, aStrdup(sd->npc_str)); + script_pushstr(st, aStrdup(global_npc_str)); } return true; } @@ -513,7 +514,7 @@ BUILDIN(requestCraft) sd->state.menu_or_input = 0; st->state = RUN; - if (!*sd->npc_str) + if (!*global_npc_str) { ShowWarning("npc string not found\n"); script->reportsrc(st); @@ -521,7 +522,7 @@ BUILDIN(requestCraft) return false; } - script_pushstr(st, aStrdup(sd->npc_str)); + script_pushstr(st, aStrdup(global_npc_str)); } return true; } @@ -2100,3 +2101,70 @@ BUILDIN(toLabel) script_pushlabel(st, script_getnum(st, 2)); return true; } + +// replace default input with bigger text buffer +/// Get input from the player. +/// For numeric inputs the value is capped to the range [min,max]. Returns 1 if +/// the value was higher than 'max', -1 if lower than 'min' and 0 otherwise. +/// For string inputs it returns 1 if the string was longer than 'max', -1 is +/// shorter than 'min' and 0 otherwise. +/// +/// input({,{,}}) -> +BUILDIN(input) +{ + struct script_data* data; + int64 uid; + const char* name; + int min; + int max; + struct map_session_data *sd = script->rid2sd(st); + if (sd == NULL) + return true; + + data = script_getdata(st, 2); + if (!data_isreference(data)) + { + ShowError("script:input: not a variable\n"); + script->reportdata(data); + st->state = END; + return false; + } + uid = reference_getuid(data); + name = reference_getname(data); + min = (script_hasdata(st,3) ? script_getnum(st,3) : script->config.input_min_value); + max = (script_hasdata(st,4) ? script_getnum(st,4) : script->config.input_max_value); + +#ifdef SECURE_NPCTIMEOUT + sd->npc_idle_type = NPCT_WAIT; +#endif + + if (!sd->state.menu_or_input) + { + // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + if (is_string_variable(name)) + clif->scriptinputstr(sd, st->oid); + else + clif->scriptinput(sd, st->oid); + } + else + { + // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + if (is_string_variable(name)) + { + int len = (int)strlen(global_npc_str); + script->set_reg(st, sd, uid, name, global_npc_str, script_getref(st,2)); + script_pushint(st, (len > max ? 1 : len < min ? -1 : 0)); + } + else + { + int amount = sd->npc_amount; + script->set_reg(st, sd, uid, name, (const void *)h64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2)); + script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0)); + } + st->state = RUN; + } + return true; +} -- cgit v1.2.3-70-g09d2