Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getmobdrops refactor #3319

Merged
merged 2 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 9 additions & 38 deletions doc/script_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4333,54 +4333,25 @@ Example:

---------------------------------------

*getmobdrops(<mob id>)
*getmobdrops(<mob_id>, <item_id_array>{, <drop_rate_array>});

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 <mob_id>, copy the
item ids on to <item_id_array> and drop rate on to <drop_rate_array> if provided.
Returns the number of items found. Will return 0 if <mob_id> 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();

Expand Down
87 changes: 69 additions & 18 deletions src/map/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
jasonch35 marked this conversation as resolved.
Show resolved Hide resolved
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
*------------------------------------------*/
Expand Down Expand Up @@ -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?"),
Expand Down
Loading