Added script command getunits (#3389)

* Closes #3159.
* Adds script commands getunits, getmapunits, and getareaunits.
* Replacement for script commands getusers, getmapusers, getareausers. (In a future commit)
Thanks to @sader1992, @Atemo, and @anacondaqq!
This commit is contained in:
Sader Fawall 2018-10-10 16:33:01 +02:00 committed by Aleos
parent 2e9319afda
commit 10e7035beb
4 changed files with 204 additions and 1 deletions

View File

@ -0,0 +1,51 @@
//===== rAthena Script =======================================
//= Sample: getunits Test
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20180831
//===== Description: =========================================
//= An example of getunits command script
//============================================================
prontera,145,177,0 script getunits Test 857,{
mes "server information option will take a while if there is large amount of objects";
switch(select("server information:map information")){
case 1:
mes "server information";
mes getunits(BL_PC,.@Character$[0]) + " Character Online.";
mes getunits(BL_MOB,.@Monster$[0]) + " Monster.";
mes getunits(BL_PET,.@Pet$[0]) + " Pet.";
mes getunits(BL_HOM,.@Homunculus$[0]) + " Homunculus.";
mes getunits(BL_MER,.@Mercenary$[0]) + " Mercenary.";
mes getunits(BL_NPC,.@NPC$[0]) + " NPC.";
break;
case 2:
clear;
mes "input the map name.";
input .@input$;
clear;
mes "map information : " + .@input$;
mes getmapunits(BL_PC,.@input$,.@Character$[0]) + " Character Online.";
mes getmapunits(BL_MOB,.@input$,.@Monster$[0]) + " Monster.";
mes getmapunits(BL_PET,.@input$,.@Pet$[0]) + " Pet.";
mes getmapunits(BL_HOM,.@input$,.@Homunculus$[0]) + " Homunculus.";
mes getmapunits(BL_MER,.@input$,.@Mercenary$[0]) + " Mercenary.";
mes getmapunits(BL_NPC,.@input$,.@NPC$[0]) + " NPC.";
}
mes "select for more info";
setarray .@list$,"Character","Monster","Pet","Homunculus","Mercenary","NPC";
.@s = select(implode(.@list$,":")) -1;
clear;
copyarray .@name$[0], getd(".@" + .@list$[.@s] + "$"), getarraysize(getd(".@" + .@list$[.@s] + "$"));
mes "count : " + getarraysize(.@name$);
freeloop(1);
for(.@i=0;.@i<getarraysize(.@name$);.@i++){
mes (.@i+1) + " - " + .@name$[.@i];
if((.@i + 1) == 100){
mes "and more ...";
break;
}
}
freeloop(0);
end;
}

View File

@ -3,7 +3,7 @@
//===== By:==================================================
//= rAthena Dev Team
//===== Last Updated:========================================
//= 20171011
//= 20180831
//===== Description:=========================================
//= A reference manual for the rAthena scripting language.
//= Commands are sorted depending on their functionality.
@ -3206,6 +3206,70 @@ within the specified area - an x1/y1-x2/y2 square on the specified map.
This is useful for maps that are split into many buildings, such as all the
"*_in" maps, due to all the shops and houses.
---------------------------------------
*getunits(<type>{,<array_variable>[<first value>]})
*getmapunits(<type>,<"map name">{,<array_variable>[<first value>]})
*getareaunits(<type>,<"map name">,<x1>,<y1>,<x2>,<y2>{,<array_variable>[<first value>]})
The 'getunits' command will return the number of <type> objects active on the server.
The 'getmapunits' command will return the number of <type> objects active on the
specified <"map name">.
The 'getareaunits' command will return the number of <type> objects actively located
within the specified area where <x1>, <y1>, <x2>, <y2> form the area.
Type is the type of object to search for:
BL_PC - Character objects
BL_MOB - Monster objects
BL_PET - Pet objects
BL_HOM - Homunculus objects
BL_MER - Mercenary objects
BL_NPC - NPC objects
BL_ELEM - Elemental objects
If <array_variable> is provided:
- An int variable will return the list of GID.
- A string variable will return the list of names.
Example 1:
// getting the players count and building a string array of the names.
.@num = getunits(BL_PC,.@array$[0]);
mes "the number of Users Connected to the server is " + .@num + " .";
mes "list of Players names :";
freeloop(1); // for if the list was too big.
for(.@i=0;.@i<getarraysize(.@array$);.@i++)
mes (.@i + 1) + " " + .@array$[.@i];
freeloop(0);
end;
Example 2:
// getting the npc count in Prontera and building a string array of the names.
.@num = getmapunits(BL_NPC,"prontera",.@array$[0]);
mes "the number of NPCs in Prontera is " + .@num + " .";
mes "list of NPCs name :";
freeloop(1); // for if the list was too big.
for(.@i=0;.@i<getarraysize(.@array$);.@i++)
mes (.@i + 1) + " " + .@array$[.@i];
freeloop(0);
end;
Example 3:
// getting the monster count in Prontera with specific coordinates and building a int array of the GIDs.
.@num = getareaunits(BL_MOB,"prontera",154,186,159,182,.@array[0]);
mes "the number of Monsters in Prontera in that Coordinates is " + .@num + " .";
mes "list of Monsters GID :";
freeloop(1); // for if the list was too big.
for(.@i=0;.@i<getarraysize(.@array);.@i++)
mes (.@i + 1) + " " + .@array[.@i];
freeloop(0);
end;
---------------------------------------
\\
2,2.- Guild-related commands

View File

@ -11059,6 +11059,90 @@ BUILDIN_FUNC(getareausers)
return SCRIPT_CMD_SUCCESS;
}
/*==========================================
* getunits(<type>{,<array_variable>[<first value>]})
* getmapunits(<type>,<"map name">{,<array_variable>[<first value>]})
* getareaunits(<type>,<"map name">,<x1>,<y1>,<x2>,<y2>{,<array_variable>[<first value>]})
*------------------------------------------*/
BUILDIN_FUNC(getunits)
{
struct block_list *bl = NULL;
struct map_session_data *sd = NULL;
struct script_data *data = NULL;
char *command = (char *)script_getfuncname(st);
const char *str;
const char *name;
int type = script_getnum(st, 2);
int size = 0;
int32 idx, id;
int16 m = 0, x0 = 0, y0 = 0, x1 = 0, y1 = 0;
struct s_mapiterator *iter = mapit_alloc(MAPIT_NORMAL, bl_type(type));
if (!strcmp(command, "getmapunits"))
{
str = script_getstr(st, 3);
if ((m = map_mapname2mapid(str)) < 0) {
script_pushint(st, -1);
st->state = END;
ShowWarning("buildin_%s: Unknown map '%s'.\n", command, str);
return SCRIPT_CMD_FAILURE;
}
if (script_hasdata(st, 4))
data = script_getdata(st, 4);
}
else if (!strcmp(command, "getareaunits"))
{
str = script_getstr(st, 3);
if ((m = map_mapname2mapid(str)) < 0) {
script_pushint(st, -1);
st->state = END;
ShowWarning("buildin_%s: Unknown map '%s'.\n", command, str);
return SCRIPT_CMD_FAILURE;
}
x0 = script_getnum(st, 4);
y0 = script_getnum(st, 5);
x1 = script_getnum(st, 6);
y1 = script_getnum(st, 7);
if (script_hasdata(st, 8))
data = script_getdata(st, 8);
}
else
{
if (script_hasdata(st, 3))
data = script_getdata(st, 3);
}
if (data)
{
if (!data_isreference(data))
{
ShowError("buildin_%s: not a variable\n", command);
script_reportdata(data);
st->state = END;
return SCRIPT_CMD_FAILURE;
}
id = reference_getid(data);
idx = reference_getindex(data);
name = reference_getname(data);
}
for (bl = (struct block_list*)mapit_first(iter); mapit_exists(iter); bl = (struct block_list*)mapit_next(iter))
{
if (!m || (m == bl->m && !x0 && !y0 && !x1 && !y1) || (bl->m == m && (bl->x >= x0 && bl->y <= y0) && (bl->x <= x1 && bl->y >= y1)))
{
if (data)
set_reg(st, sd, reference_uid(id, idx + size), name, (is_string_variable(name) ? (void*)status_get_name(bl) : (void*)__64BPRTSIZE(bl->id)), reference_getref(data));
size++;
}
}
mapit_free(iter);
script_pushint(st, size);
return SCRIPT_CMD_SUCCESS;
}
/*==========================================
*------------------------------------------*/
static int buildin_getareadropitem_sub(struct block_list *bl,va_list ap)
@ -24029,6 +24113,9 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(getmapguildusers,"si"),
BUILDIN_DEF(getmapusers,"s"),
BUILDIN_DEF(getareausers,"siiii"),
BUILDIN_DEF(getunits, "i?"),
BUILDIN_DEF2(getunits, "getmapunits", "is?"),
BUILDIN_DEF2(getunits, "getareaunits", "isiiii?"),
BUILDIN_DEF(getareadropitem,"siiiiv"),
BUILDIN_DEF(enablenpc,"s"),
BUILDIN_DEF(disablenpc,"s"),

View File

@ -7295,6 +7295,7 @@
export_constant(BL_PET);
export_constant(BL_HOM);
export_constant(BL_MER);
export_constant(BL_NPC);
export_constant(BL_ELEM);
/* skill damage mapflag types */