Skip to content

Commit

Permalink
inarray script commands (#3071)
Browse files Browse the repository at this point in the history
Thanks to @Anacondaqq, @Lemongrass3110, @Jeybla, @secretdataz, @aleos89, @Atemo and @hurtsky for reviewing and testing.
  • Loading branch information
sader1992 authored and Lemongrass3110 committed May 27, 2018
1 parent a12c79f commit 151c847
Show file tree
Hide file tree
Showing 3 changed files with 356 additions and 0 deletions.
115 changes: 115 additions & 0 deletions doc/sample/inarray.txt
@@ -0,0 +1,115 @@
//===== rAthena Script =======================================
//= Sample: inarray
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20180424
//===== Description: =========================================
//= Demonstrates the 'inarray' and 'countinarray' commands.
//============================================================

prontera,160,190,3 script inarray sample 847,{
switch(select("inarray:countinarray")){
case 1: //inarray command test
mes "[inarray Test]";
setarray .@array1[0],100,200,300,400,500,600,700;
setarray .@array2$[0],"One Hundred","Two Hundred","Three Hundred","Four Hundred","Five Hundred","Six Hundred","Seven Hundred";

mes .@array2$[inarray(.@array1,100)]; //return One Hundred
mes .@array2$[inarray(.@array1,300)]; //return Three Hundred

//mes .@array2$[inarray(.@array1,800)]; //this will return with an error
//800 is not an element of the array .@array1

mes "" + inarray(.@array1,800); //this return -1
//800 is not an element of the array .@array1

close;
case 2: //countinarray command test
switch(select("Basic:Advanced")){
case 1:
mes "[countinarray Basic Test]";
setarray .@array$[0],"rathena","ragnarok","poring","script";
mes "the array elements: ";
for(.@i=0;.@i<getarraysize(.@array$);.@i++)
mes .@array$[.@i];

input .@element$;
clear;

//also in this example we are using normal variable instead of an array
//arrays are variables but with more than one index
//so you can use array or variable

//using countinarray command
mes "[countinarray Basic Test]";
if(countinarray(.@array$[0], .@element$) == 1)
mes "we found " + .@element$ + " inside the array";
else
mes .@element$ + " is not an element of the array";
/*
without using countinarray command
------------------------------------------
for(.@i=0;.@i<getarraysize(.@array$);.@i++){
if(.@array$[.@i] == .@element$){
.@count ++;
}
}
if(.@count == 1)
mes "we found " + .@element$ + " inside the array";
else
mes .@element$ + " is not an element of the array";
------------------------------------------
*/
close;

case 2:
mes "[countinarray Advanced Test]";
setarray .@array[0],50,40,80,90,70,500,60,400,700,1,2,2,2,2;
mes "open the script and read to know what's going on";
mes " ";

//50 and 70 are elements of the array
//we make new array that have the values 50 and 70
//you will see this all over the sample
setarray .@array2[0],50,70;
//2 cases true, so the command returns 2
mes "searching for 50 and 70";
mes "return " + countinarray(.@array[0], .@array2[0]);
mes " ";

//50 is an element of the array
//100 is not an element of the array
setarray .@array3[0],50,100;
//1 case true, so the command returns 1
mes "searching for 50 and 100";
mes "return " + countinarray(.@array[0], .@array3[0]);
mes " ";

//586 and 100 are not elements of the array
setarray .@array4[0],586,100;
//0 case true, so the command returns 0
mes "searching for 586 and 100";
mes "return " + countinarray(.@array[0], .@array4[0]);
mes " ";

//1 and 1 are elements of the array
setarray .@array5[0],1,1;
//2 cases true, so the command returns 2
mes "searching for 1 and 1";
mes "return " + countinarray(.@array[0], .@array5[0]);
mes " ";

//2 is an element of the array, but it's in four indexes
//the command will return the number valid cases
//so here the command returns 4
//this can be used to know the count of an element inside an array
.@variable = 2;

mes "searching for 2";
mes "return " + countinarray(.@array[0], .@variable);

close;
}
}
}
56 changes: 56 additions & 0 deletions doc/script_commands.txt
Expand Up @@ -2260,6 +2260,62 @@ array, shifting all the elements beyond this towards the beginning.

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

*inarray <array name>,<value>;

This command returns the index of the first matching value found in the array.
It will return -1 if the value is not found.

setarray .@array[0], 100, 200, 300, 400, 500, 600, 100;

inarray(.@array[0], 200);
//return 1 because 200 is in index 1
//another way to say it that .@array[1] == 200

.@index = inarray(.@array[0], 600);
//.@index is now 5 because .@array[5] == 600

inarray(.@array[0], 100);
//while index 6 is also 100, the command will return the first instance it finds
//return 0 because .@array[0] == 100

inarray(.@array[0], 800);
//return -1 because 800 is not an element of the array .@array

For more details, see the sample in 'doc/sample/inarray.txt'.

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

*countinarray <array name>{[<start index>]},<array name>{[<start index>]};

This command will check for matches between the array values and return the number of matches.
While being optional, if [<start index>] is supplied, the search will begin from the given index value.

setarray .@array[0], 100, 200, 300, 400, 500, 600;

.@variable = 100;
if(countinarray(.@array[0], .@variable))
mes "The number 100 was found in the array @array";

countinarray(.@array[0], .@variable);
//return 1 because the number 100 is an element of the array .@array

setarray .@array2[0],100,500;
countinarray(.@array[0], .@array2[0]);
//return 2 because the numbers 100 and 500 are elements of the array .@array

setarray .@array3[0],100,700;
countinarray(.@array[0], .@array3[0]);
//return 1 because the number 100 is an element of the array .@array
//but the number 700 is not an element of the array .@array

//also you can change the position between the arrays in the command
if(countinarray(.@array[0], .@array3[0]) == countinarray(.@array3[0], .@array[0]))
//This is true

For more details, see the sample in 'doc/sample/inarray.txt'.

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

======================================
|2.- Information-retrieving commands.|
======================================
Expand Down
185 changes: 185 additions & 0 deletions src/map/script.cpp
Expand Up @@ -6659,6 +6659,189 @@ BUILDIN_FUNC(getelementofarray)
return SCRIPT_CMD_SUCCESS;
}

/// Return the index number of the first matching value in an array.
/// ex: inarray arr,1;
///
/// inarray <array variable>,<value>;
BUILDIN_FUNC(inarray)
{
struct script_data *data;
const char* name;
int id, i, array_size;
struct map_session_data* sd = NULL;
struct reg_db *ref = NULL;
data = script_getdata(st, 2);

if (!data_isreference(data))
{
ShowError("buildin_inarray: not a variable\n");
script_reportdata(data);
st->state = END;
return SCRIPT_CMD_FAILURE;
}

name = reference_getname(data);
ref = reference_getref(data);

if (not_server_variable(*name) && !script_rid2sd(sd))
return SCRIPT_CMD_FAILURE;

array_size = script_array_highest_key(st, sd, name, ref) - 1;

if (array_size > SCRIPT_MAX_ARRAYSIZE)
{
ShowError("buildin_inarray: The array is too large.\n");
script_reportdata(data);
st->state = END;
return SCRIPT_CMD_FAILURE;
}

id = reference_getid(data);
if (is_string_variable(name))
{
const char* temp;
const char* value;
value = script_getstr(st, 3);
for (i = 0; i <= array_size; ++i)
{
temp = (char*)get_val2(st, reference_uid(id, i), ref);
script_removetop(st, -1, 0);
if (!strcmp(temp, value))
{
script_pushint(st, i);
return SCRIPT_CMD_SUCCESS;
}

}
}
else
{
int temp, value;
value = script_getnum(st, 3);
for (i = 0; i <= array_size; ++i)
{
temp = (int32)__64BPRTSIZE(get_val2(st, reference_uid(id, i), ref));
script_removetop(st, -1, 0);
if (temp == value)
{
script_pushint(st, i);
return SCRIPT_CMD_SUCCESS;
}

}
}

script_pushint(st, -1);
return SCRIPT_CMD_SUCCESS;
}

/// Return the number of matches in two arrays.
/// ex: countinarray arr[0],arr1[0];
///
/// countinarray <array variable>,<array variable>;
BUILDIN_FUNC(countinarray)
{
struct script_data *data1 , *data2;
const char* name1;
const char* name2;
int id1, id2, i, j, array_size1, array_size2, case_count = 0;
struct map_session_data* sd = NULL;
struct reg_db *ref1 = NULL, *ref2 = NULL;
data1 = script_getdata(st, 2);
data2 = script_getdata(st, 3);

if (!data_isreference(data1) || !data_isreference(data2))
{
ShowError("buildin_countinarray: not a variable\n");
script_reportdata(data1);
script_reportdata(data2);
st->state = END;
return SCRIPT_CMD_FAILURE;
}

name1 = reference_getname(data1);
name2 = reference_getname(data2);
ref1 = reference_getref(data1);
ref2 = reference_getref(data2);

if (not_server_variable(*name1) && not_server_variable(*name2) && !script_rid2sd(sd))
return SCRIPT_CMD_FAILURE;

array_size1 = script_array_highest_key(st, sd, name1, ref1) - 1;
array_size2 = script_array_highest_key(st, sd, name2, ref2) - 1;

if (array_size1 > SCRIPT_MAX_ARRAYSIZE || array_size2 > SCRIPT_MAX_ARRAYSIZE)
{
ShowError("buildin_countinarray: The array is too large.\n");
script_reportdata(data1);
script_reportdata(data2);
st->state = END;
return SCRIPT_CMD_FAILURE;
}

i = reference_getindex(data1);
j = reference_getindex(data2);
if (array_size1 < i || array_size2 < j)
{ //To prevent unintended behavior
ShowError("buildin_countinarray: The given index of the array is higher than the array size.\n");
script_reportdata(data1);
script_reportdata(data2);
st->state = END;
return SCRIPT_CMD_FAILURE;
}

id1 = reference_getid(data1);
id2 = reference_getid(data2);
if (is_string_variable(name1) && is_string_variable(name2))
{
const char* temp1;
const char* temp2;
for (; i <= array_size1; ++i)
{
temp1 = (char*)get_val2(st, reference_uid(id1, i), ref1);
for (j = reference_getindex(data2); j <= array_size2; j++)
{
temp2 = (char*)get_val2(st, reference_uid(id2, j), ref2);
if (!strcmp(temp1, temp2))
{
case_count++;
}
script_removetop(st, -1, 0);
}
script_removetop(st, -1, 0);
}
}
else if (!is_string_variable(name1) && !is_string_variable(name2))
{
int temp1, temp2;
for (; i <= array_size1; ++i)
{
temp1 = (int32)__64BPRTSIZE(get_val2(st, reference_uid(id1, i), ref1));
for (j = reference_getindex(data2); j <= array_size2; j++)
{
temp2 = (int32)__64BPRTSIZE(get_val2(st, reference_uid(id2, j), ref2));
if (temp1 == temp2)
{
case_count++;
}
script_removetop(st, -1, 0);
}
script_removetop(st, -1, 0);
}
}
else
{
ShowError("buildin_countinarray: Arrays does not match , You can't compare int array to string array.\n");
script_reportdata(data1);
script_reportdata(data2);
st->state = END;
return SCRIPT_CMD_FAILURE;
}

script_pushint(st, case_count);
return SCRIPT_CMD_SUCCESS;
}

/////////////////////////////////////////////////////////////////////
/// ...
///
Expand Down Expand Up @@ -24141,6 +24324,8 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(getarraysize,"r"),
BUILDIN_DEF(deletearray,"r?"),
BUILDIN_DEF(getelementofarray,"ri"),
BUILDIN_DEF(inarray,"rv"),
BUILDIN_DEF(countinarray,"rr"),
BUILDIN_DEF(getitem,"vi?"),
BUILDIN_DEF(rentitem,"vi?"),
BUILDIN_DEF(rentitem2,"viiiiiiii?"),
Expand Down

0 comments on commit 151c847

Please sign in to comment.