Selaa lähdekoodia

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!
Sader Fawall 6 vuotta sitten
vanhempi
commit
10e7035beb
4 muutettua tiedostoa jossa 204 lisäystä ja 1 poistoa
  1. 51 0
      doc/sample/npc_test_getunits.txt
  2. 65 1
      doc/script_commands.txt
  3. 87 0
      src/map/script.cpp
  4. 1 0
      src/map/script_constants.hpp

+ 51 - 0
doc/sample/npc_test_getunits.txt

@@ -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;
+}

+ 65 - 1
doc/script_commands.txt

@@ -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

+ 87 - 0
src/map/script.cpp

@@ -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"),

+ 1 - 0
src/map/script_constants.hpp

@@ -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 */