From 81c6a59d4b7643f9969461f1b92c34ad5fbcd95a Mon Sep 17 00:00:00 2001 From: jasonch Date: Wed, 11 Sep 2024 03:19:59 +0800 Subject: [PATCH 1/6] `getmobdrops` refactor Avoid the use of global temporary variables --- src/map/script.c | 87 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/src/map/script.c b/src/map/script.c index 8ecddd7fc43..490d54d57b9 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -12284,36 +12284,87 @@ static BUILDIN(monster) *------------------------------------------*/ static BUILDIN(getmobdrops) { - int class_ = script_getnum(st,2); - int i, j = 0; - struct mob_db *monster; + struct map_session_data *sd = NULL; + int mob_id = script_getnum(st, 2); + struct mob_db *monster = NULL; + struct script_data *data1 = script_getdata(st, 3); + struct script_data *data2 = NULL; + const char *varname1 = NULL; + const char *varname2 = NULL; + int varid1 = 0; + int varid2 = 0; + int num = 0; - if( !mob->db_checkid(class_) ) - { + if (!data_isreference(data1) || reference_toconstant(data1)) { + ShowError("buildin_getmobdrops: Target argument must be a variable\n"); + script->reportdata(data1); + st->state = END; + return false; + } + + varname1 = reference_getname(data1); + varid1 = reference_getid(data1); + + if (!is_int_variable(varname1)) { + ShowError("buildin_getmobdrops: Target argument must be an integer variable\n"); + script->reportdata(data1); + st->state = END; + return false; + } + + if (script_hasdata(st, 4)) { + data2 = script_getdata(st, 4); + + if (!data_isreference(data2) || reference_toconstant(data2)) { + ShowError("buildin_getmobdrops: Target argument must be a variable\n"); + script->reportdata(data1); + st->state = END; + return false; + } + + varname2 = reference_getname(data2); + varid2 = reference_getid(data2); + + if (data2 == NULL || !is_int_variable(varname2)) { + ShowError("buildin_getmobdrops: 2nd target argument must be an integer variable\n"); + script->reportdata(data2); + st->state = END; + return false; + } + } + + if (not_server_variable(*varname1) || (data2 != NULL && not_server_variable(*varname2))) { + sd = script->rid2sd(st); + if (sd == NULL) { + script_pushint(st, 0); + return true; // player variable but no player attached + } + } + + monster = mob->db(mob_id); + + if (!mob->db_checkid(mob_id) || monster == NULL) { script_pushint(st, 0); return true; } - monster = mob->db(class_); - - for( i = 0; i < MAX_MOB_DROP; i++ ) - { - if( monster->dropitem[i].nameid < 1 ) + for (int i = 0; i < MAX_MOB_DROP; i++) { + if (monster->dropitem[i].nameid < 1) continue; - if( itemdb->exists(monster->dropitem[i].nameid) == NULL ) + if (itemdb->exists(monster->dropitem[i].nameid) == NULL) continue; - mapreg->setreg(reference_uid(script->add_variable("$@MobDrop_item"), j), monster->dropitem[i].nameid); - mapreg->setreg(reference_uid(script->add_variable("$@MobDrop_rate"), j), monster->dropitem[i].p); - - j++; + script->set_reg(st, sd, reference_uid(varid1, num), varname1, (const void *)h64BPTRSIZE(monster->dropitem[i].nameid), reference_getref(data1)); + if (data2 != NULL) + script->set_reg(st, sd, reference_uid(varid2, num), varname2, (const void *)h64BPTRSIZE(monster->dropitem[i].p), reference_getref(data2)); + num++; } - mapreg->setreg(script->add_variable("$@MobDrop_count"), j); - script_pushint(st, 1); + script_pushint(st, num); return true; } + /*========================================== * Same as monster but randomize location in x0,x1,y0,y1 area *------------------------------------------*/ @@ -28996,7 +29047,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(produce,"i"), BUILDIN_DEF(cooking,"i"), BUILDIN_DEF(monster,"siisii???"), - BUILDIN_DEF(getmobdrops,"i"), + BUILDIN_DEF(getmobdrops,"ii?"), BUILDIN_DEF(areamonster,"siiiisii???"), BUILDIN_DEF(killmonster,"ss?"), BUILDIN_DEF(killmonsterall,"s?"), From e0fa6d8f158f4962c043ea72079c6ed569c582eb Mon Sep 17 00:00:00 2001 From: jasonch Date: Wed, 11 Sep 2024 03:20:08 +0800 Subject: [PATCH 2/6] `getmobdrops` doc update --- doc/script_commands.txt | 47 ++++++++--------------------------------- 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 1c4bb8aa3ab..675ad568f0a 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -4333,54 +4333,25 @@ Example: --------------------------------------- -*getmobdrops() +*getmobdrops(, {, }); -This command will find all drops of the specified mob and return the item -IDs and drop percentages into arrays of temporary global variables. -getmobdrops() returns true if successful and false if the mob ID doesn't -exist. - -Upon executing this, - -$@MobDrop_item[] is a global temporary number array which contains the - item IDs of the monster's drops. - -$@MobDrop_rate[] is a global temporary number array which contains the - drop percentages of each item. (1 = .01%) - -$@MobDrop_count is the number of item drops found. - -Be sure to use $@MobDrop_count to go through the arrays, and not -'getarraysize', because the temporary global arrays are not cleared -between runs of 'getmobdrops'. If a mob with 7 item drops is looked up, -the arrays would have 7 elements. But if another mob is looked up and it -only has 5 item drops, the server will not clear the arrays for you, -overwriting the values instead. So in addition to returning the 5 item -drops, the 6th and 7th elements from the last call remain, and you will -get 5+2 item drops, of which the last 2 don't belong to the new mob. -$@MobDrop_count will always contain the correct number (5), unlike -getarraysize() which would return 7 in this case. +This command will find drops information of the specified , copy the +item ids on to and drop rate on to if provided. +Returns the number of items found. Will return 0 if is invalid. Example: - // get a Mob ID from the user input(.@mob_id); - if (getmobdrops(.@mob_id)) { // getmobdrops() returns true on success - // immediately copy global temporary variables into scope - // variables, since we don't know when getmobdrops() will get - // called again for another mob, overwriting your global temporary - // variables. - .@count = $@MobDrop_count; - copyarray(.@item[0], $@MobDrop_item[0], .@count); - copyarray(.@rate[0], $@MobDrop_rate[0], .@count); - + .@count = getmobdrops(.@mob_id, .@item, .@rate); + + if (.@count == 0) { + mes("No drops found."); + } else { mes(getmonsterinfo(.@mob_id, MOB_NAME) + " - " + .@count + " drops found:"); for (.@i = 0; .@i < .@count; ++.@i) { mes(.@item[.@i] + " (" + getitemname(.@item[.@i]) + ") " + .@rate[.@i]/100 + ((.@rate[.@i]%100 < 10) ? ".0":".") + .@rate[.@i]%100 + "%"); } - } else { - mes("Unknown monster ID."); } close(); From b0340cd3ab6b8a327c4a955171137382559bcdb1 Mon Sep 17 00:00:00 2001 From: Venseer Date: Tue, 29 Oct 2024 19:09:45 -0300 Subject: [PATCH 3/6] Improved atCommand(iteminfo) --- conf/messages.conf | 2 +- src/map/atcommand.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/conf/messages.conf b/conf/messages.conf index c096fb2f931..c1ca477a39a 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -1323,7 +1323,7 @@ // @iteminfo 1276: Please enter an item name/ID (usage: @ii/@iteminfo ). -1277: Item: '%s'/'%s'[%d] (%d) Type: %s | Extra Effect: %s +1277: Item: '%s'/'%s' (%d) Type: %s | Extra Effect: %s 1278: None 1279: With script 1280: NPC Buy:%dz, Sell:%dz | Weight: %.1f diff --git a/src/map/atcommand.c b/src/map/atcommand.c index e3fc633d86f..13f989f49b9 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -7717,14 +7717,22 @@ ACMD(iteminfo) clif->message(fd, atcmd_output); count = MAX_SEARCH; } + StringBuf buf; + StrBuf->Init(&buf); for (i = 0; i < count; i++) { struct item_data *item_data = item_array[i]; if (item_data != NULL) { - snprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, MSGTBL_ITEMINFO_DETAILS), // Item: '%s'/'%s'[%d] (%d) Type: %s | Extra Effect: %s - item_data->name, item_data->jname, item_data->slot, item_data->nameid, + + struct item link_item = { 0 }; + link_item.nameid = item_data->nameid; + clif->format_itemlink(&buf, &link_item); + + snprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, MSGTBL_ITEMINFO_DETAILS), // Item: '%s'/'%s' (%d) Type: %s | Extra Effect: %s + item_data->name, StrBuf->Value(&buf), item_data->nameid, itemdb->typename(item_data->type), (item_data->script == NULL) ? msg_fd(fd, MSGTBL_ITEMINFO_NONE) : msg_fd(fd, MSGTBL_ITEMINFO_WITH_SCRIPT) // None / With script ); + StrBuf->Clear(&buf); clif->message(fd, atcmd_output); snprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, MSGTBL_ITEMINFO_NPC_DETAILS), item_data->value_buy, item_data->value_sell, item_data->weight / 10.); // NPC Buy:%dz, Sell:%dz | Weight: %.1f @@ -7741,6 +7749,7 @@ ACMD(iteminfo) clif->message(fd, atcmd_output); } } + StrBuf->Destroy(&buf); return true; } From 45004f93ceb6fb6a100a8b6000911c76da50dc19 Mon Sep 17 00:00:00 2001 From: Venseer Date: Tue, 29 Oct 2024 19:21:48 -0300 Subject: [PATCH 4/6] Improved atCommand(mobinfo) --- src/map/atcommand.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index e3fc633d86f..1a19ce163eb 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -7156,14 +7156,14 @@ ACMD(mobinfo) unsigned char msize[3][7] = {"Small", "Medium", "Large"}; unsigned char mrace[12][11] = {"Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Boss", "Non-Boss"}; unsigned char melement[10][8] = {"Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead"}; - char atcmd_output2[CHAT_SIZE_MAX]; + StringBuf buf; struct item_data *item_data; struct mob_db *monster, *mob_array[MAX_SEARCH]; int count; int i, k; memset(atcmd_output, '\0', sizeof(atcmd_output)); - memset(atcmd_output2, '\0', sizeof(atcmd_output2)); + StrBuf->Init(&buf); if (!*message) { clif->message(fd, msg_fd(fd, MSGTBL_MOBINFO_USAGE)); // Please enter a monster name/ID (usage: @mobinfo ). @@ -7253,23 +7253,22 @@ ACMD(mobinfo) } #endif - if (item_data->slot) - snprintf(atcmd_output2, sizeof(atcmd_output2), " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, (float)droprate / 100); - else - snprintf(atcmd_output2, sizeof(atcmd_output2), " - %s %02.02f%%", item_data->jname, (float)droprate / 100); - - strcat(atcmd_output, atcmd_output2); - + struct item link_item = { 0 }; + link_item.nameid = monster->dropitem[i].nameid; + StrBuf->AppendStr(&buf, " - "); + clif->format_itemlink(&buf, &link_item); + StrBuf->Printf(&buf, " %02.02f%%", (float)droprate / 100); if (++j % 3 == 0) { - clif->message(fd, atcmd_output); - strcpy(atcmd_output, " "); + clif->message(fd, StrBuf->Value(&buf)); + StrBuf->Clear(&buf); } } if (j == 0) clif->message(fd, msg_fd(fd, MSGTBL_MOBINFO_NO_DROPS)); // This monster has no drops. else if (j % 3 != 0) - clif->message(fd, atcmd_output); + clif->message(fd, StrBuf->Value(&buf)); + StrBuf->Clear(&buf); // mvp if (monster->mexp) { snprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, MSGTBL_MOBINFO_MVP_BONUS_EXP), monster->mexp); // MVP Bonus EXP:%u @@ -7282,19 +7281,21 @@ ACMD(mobinfo) continue; if (monster->mvpitem[i].p > 0) { j++; - if(item_data->slot) - snprintf(atcmd_output2, sizeof(atcmd_output2), " %s%s[%d] %02.02f%%", j != 1 ? "- " : "", item_data->jname, item_data->slot, (float)monster->mvpitem[i].p / 100); - else - snprintf(atcmd_output2, sizeof(atcmd_output2), " %s%s %02.02f%%", j != 1 ? "- " : "", item_data->jname, (float)monster->mvpitem[i].p / 100); - strcat(atcmd_output, atcmd_output2); + struct item link_item = { 0 }; + link_item.nameid = monster->mvpitem[i].nameid; + StrBuf->AppendStr(&buf, j != 1 ? " - " : ""); + clif->format_itemlink(&buf, &link_item); + StrBuf->Printf(&buf, " %02.02f%%", (float)monster->mvpitem[i].p / 100); } } + if (j == 0) clif->message(fd, msg_fd(fd, MSGTBL_MOBINFO_NO_MVP_PRIZES)); // This monster has no MVP prizes. else - clif->message(fd, atcmd_output); + clif->message(fd, StrBuf->Value(&buf)); } } + StrBuf->Destroy(&buf); return true; } From 5d5c3423b0b2fee1419c668e9711fab7dfd5d6d1 Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 31 Oct 2024 23:33:37 +0000 Subject: [PATCH 5/6] Update mailmap and AUTHORS list Signed-off-by: Haru --- .mailmap | 2 ++ AUTHORS | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index e78b7564528..00afb5674dd 100644 --- a/.mailmap +++ b/.mailmap @@ -32,6 +32,8 @@ Guilherme G. Menaldo Guilherme G. Menaldo Guilherme G. Menaldo Haru Haruna +jasonch <31005928+jasonch35@users.noreply.github.com> +jasonch jsn Jenkijo KeiKun Kei Kenpachi diff --git a/AUTHORS b/AUTHORS index 8282be548f4..7becedd66f1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -71,7 +71,7 @@ jaBote jaBote jaBote Jackson -jasonch <31005928+jasonch35@users.noreply.github.com> +jasonch Jedzkie Jenkijo Jesusaves @@ -80,7 +80,6 @@ jmanfffreak joel Jônatas Andreta Jose Luis Rivera Flores -jsn j-tkay KeiKun Kenpachi @@ -180,6 +179,7 @@ tungsinpei TungSinpei ultramage Unknown +Venseer Victor vietlubu Vincent Thibault From 484691a0a2ad6abaa3618b2155f98b1e1bb801c0 Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 31 Oct 2024 23:34:09 +0000 Subject: [PATCH 6/6] Release v2024.10 Signed-off-by: Haru --- CHANGELOG.md | 12 ++++++++++++ doc/constants_pre-re.md | 2 +- doc/constants_re.md | 2 +- src/config/core.h | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edad21744cb..608b9c2b66a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,17 @@ If you are reading this in a text editor, simply ignore this section ### Removed --> +## [v2024.10] `October 2024` + +### Changed + +- Changed the `getmobdrops()` script command to avoid the use of global temporary variables. (#3319) + - The caller now specifies an array that will be filled with the requested data. + - The amount of filled entries will be returned as the command's return value. The caller should only read up to that amount of entries from the array, as it may contain previous leftover values past that point. + - See the script_commands documentation for further details. +- Improved the output of the `@mobinfo` atcommand to include item links for the mob drops, on clients that support it. Unsupported clients will gracefully fall back to just printing the names. #3328 +- Improved the output of the `@iteminfo` atcommand to include item links, on clients that support it. Unsupported clients will gracefully fall back to just printing the names. #3329 + ## [v2024.09] `September 2024` ### Added @@ -3170,6 +3181,7 @@ Note: everything included in this release is part of PR #3198 which consists of - New versioning scheme and project changelogs/release notes (#1853) [Unreleased]: https://github.com/HerculesWS/Hercules/compare/stable...master +[v2024.10]: https://github.com/HerculesWS/Hercules/compare/v2024.09...v2024.10 [v2024.09]: https://github.com/HerculesWS/Hercules/compare/v2024.08...v2024.09 [v2024.08]: https://github.com/HerculesWS/Hercules/compare/v2024.06...v2024.08 [v2024.06]: https://github.com/HerculesWS/Hercules/compare/v2024.05...v2024.06 diff --git a/doc/constants_pre-re.md b/doc/constants_pre-re.md index 024f579e542..53b58d33bee 100644 --- a/doc/constants_pre-re.md +++ b/doc/constants_pre-re.md @@ -4878,7 +4878,7 @@ ### Server defines - `PACKETVER`: 20190530 -- `HERCULES_VERSION`: 202409000 +- `HERCULES_VERSION`: 202410000 - `MAX_LEVEL`: 175 - `MAX_STORAGE`: 600 - `MAX_GUILD_STORAGE`: 500 diff --git a/doc/constants_re.md b/doc/constants_re.md index 7f116999fb3..9d583556ef5 100644 --- a/doc/constants_re.md +++ b/doc/constants_re.md @@ -4878,7 +4878,7 @@ ### Server defines - `PACKETVER`: 20190530 -- `HERCULES_VERSION`: 202409000 +- `HERCULES_VERSION`: 202410000 - `MAX_LEVEL`: 175 - `MAX_STORAGE`: 600 - `MAX_GUILD_STORAGE`: 500 diff --git a/src/config/core.h b/src/config/core.h index 83bd05a1c97..8b7f92bb1cf 100644 --- a/src/config/core.h +++ b/src/config/core.h @@ -22,7 +22,7 @@ #define CONFIG_CORE_H /// Hercules version. From tag vYYYY.MM(+PPP) -> YYYYMMPPP -#define HERCULES_VERSION 202409000 +#define HERCULES_VERSION 202410000 /// Max number of items on @autolootid list #define AUTOLOOTITEM_SIZE 10