Jump to content
  • 0

Variable for each NPC [ random ]


Hijirikawa

Question


  • Group:  Members
  • Topic Count:  19
  • Topics Per Day:  0.01
  • Content Count:  193
  • Reputation:   41
  • Joined:  07/21/16
  • Last Seen:  

need a little help with something, for instance i have 4 npcs and 4 variables, i want each npc to take one variable (randomly) however they should not contain the same variables at the same time, for instance

npc 1 = variable 1 with val of 1 
npc 2 = variable 3 with val of 3 
npc 3 = variable 4 with val of 4 
npc 4 = variable 2 with val of 2

basically if the variable is already assigned to an npc, it should not be assigned to another npc, any idea on how to do that?

Link to comment
Share on other sites

10 answers to this question

Recommended Posts

  • 1

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  667
  • Reputation:   674
  • Joined:  11/12/12
  • Last Seen:  

There are multiple ways to approach this. I personally find it easier to make a global variable containing all your values, and then having the NPCs access the array. For example:

prontera,151,183,0	script	NPC1	77,{
	dispbottom "Variable 1: " + $npc_values[0];
	end;
}

prontera,153,183,0	script	NPC2	77,{
	dispbottom "Variable 2: " + $npc_values[1];
	end;
}

prontera,155,183,0	script	NPC3	77,{
	dispbottom "Variable 3: " + $npc_values[2];
	end;
}

prontera,157,183,0	script	NPC4	77,{
	dispbottom "Variable 4: " + $npc_values[3];
	end;
}

-	script	yourscript_main	-1,{
	end;
OnInit:
	cleararray $npc_values, 0, 50;
	setarray $npc_values, 1, 2, 3, 4;
	
	// Shuffle the array
	for (.@i = getarraysize($npc_values) - 1; .@i > 0; .@i--) {
		.@j = rand(.@i + 1);
		
		.@temp = $npc_values[.@i];
		$npc_values[.@i] = $npc_values[.@j];
		$npc_values[.@j] = .@temp;
	}
	
	end;
}

 

This is handy if you plan on duplicating your NPCs, such as:

prontera,151,183,0	script	NPC#0	77,{
	.@id = atoi(strnpcinfo(2));
	
	dispbottom "Variable " + (.@id + 1) + ": " + $npc_values[.@id];
	end;
}

prontera,153,183,0	duplicate(NPC#0)	NPC#1	77
prontera,155,183,0	duplicate(NPC#0)	NPC#2	77
prontera,157,183,0	duplicate(NPC#0)	NPC#3	77

-	script	yourscript_main	-1,{
	end;
OnInit:
	cleararray $npc_values, 0, 50;
	setarray $npc_values, 1, 2, 3, 4;
	
	// Shuffle the array
	for (.@i = getarraysize($npc_values) - 1; .@i > 0; .@i--) {
		.@j = rand(.@i + 1);
		
		.@temp = $npc_values[.@i];
		$npc_values[.@i] = $npc_values[.@j];
		$npc_values[.@j] = .@temp;
	}
	
 	end;
}

 

If you plan on shuffling the arrays often, you can use the following custom script command:

// script.c
BUILDIN_FUNC(shufflearray)
{
	struct script_data* data;
	const char* name;
	struct map_session_data* sd = NULL;
	int array_size, i, j;
	int32 id;
	void * temp_val;

	// Copy-paste from getarraysize
	data = script_getdata(st, 2);

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

	name = reference_getname(data);
	id = reference_getid(data);

	if (not_server_variable(*name)) {
		sd = script_rid2sd(st);

		if (sd == NULL)
			return SCRIPT_CMD_SUCCESS;// no player attached
	}

	array_size = script_array_highest_key(st, sd, reference_getname(data), reference_getref(data));

	// Start shuffling the array
	for (i = array_size - 1; i > 0; i--) {
		j = rand() % (i + 1);

		temp_val = get_val2(st, reference_uid(id, i), reference_getref(data));
		script_removetop(st, -1, 0);
		set_reg(st, sd, reference_uid(id, i), name, get_val2(st, reference_uid(id, j), reference_getref(data)), reference_getref(data));
		script_removetop(st, -1, 0);
		set_reg(st, sd, reference_uid(id, j), name, temp_val, reference_getref(data));
	}

	return SCRIPT_CMD_SUCCESS;
}

// def
BUILDIN_DEF(shufflearray,"r"),

and use it as follow:

-	script	yourscript_main	-1,{
	end;
OnInit:
	cleararray $npc_values, 0, 50;
	setarray $npc_values, 1, 2, 3, 4;
	shufflearray $npc_values;
	end;
}

If you need something more specific, you'll have to give us more details xD

  • Upvote 2
Link to comment
Share on other sites

  • 1

  • Group:  Forum Moderator
  • Topic Count:  33
  • Topics Per Day:  0.01
  • Content Count:  1268
  • Reputation:   382
  • Joined:  02/03/12
  • Last Seen:  

23 hours ago, Tokei said:

There are multiple ways to approach this. I personally find it easier to make a global variable containing all your values, and then having the NPCs access the array. For example:

Why not just use npc variables? If the other npcs are duplicates of a single npc they can all share a single npc array. Then just shuffle the array as you go... You can never shuffle a deck enough.
 

prontera,151,183,0	script	NPC#0	77,{
	.@id = atoi(strnpcinfo(2));
	dispbottom "Variable " + (.@id + 1) + ": " + .npc_variables[.@id];
	end;
	
OnInit:
	.@len = getarraysize(.npc_variables);
	.npc_variables[.@len] = atoi(strnpcinfo(2))+1;
	for ( .@i = 0; .@i < .@len + 1; .@i++ ){
		.@n = ( rand(gettimetick(0)) % ( .@i + 1 ) );
		.@temp = .npc_variables[.@i];
		.npc_variables[.@i] = .npc_variables[.@n];
		.npc_variables[.@n] = .@temp;
	}
}

prontera,153,183,0	duplicate(NPC#0)	NPC#1	77
prontera,155,183,0	duplicate(NPC#0)	NPC#2	77
prontera,157,183,0	duplicate(NPC#0)	NPC#3	77

 

Edited by Skorm
Codebox does weird things now...
Link to comment
Share on other sites

  • 0

  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2348
  • Joined:  10/28/11
  • Last Seen:  

create different variable for each NPC (if within same NPC)... or separate into different NPC .... or save the variable in an array .... etc

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  667
  • Reputation:   674
  • Joined:  11/12/12
  • Last Seen:  

@Skorm It really depends on what your goal is; I stay away from npc variables as much as possible for a few reasons. I'm usually scripting for instances and NPC variables won't work as expected in such a case (the variables will be shared across instances if you use duplicates). I personally don't like having the OnInit label on duplicate NPCs either since the event gets called multiple times; that's what you're relying on here though xD. I usually end up adding code in the init part and I don't want it to be repeated everytime a duplicate NPC gets loaded.

And... you have to be careful while using strnpcinfo if you're having a floating base NPC, such as:

-	script	NPC_base	-1,{
	.@id = atoi(strnpcinfo(2));
	dispbottom "Variable " + (.@id + 1) + ": " + .npc_variables[.@id];
	end;
	
OnInit:
	.@len = getarraysize(.npc_variables);
	.npc_variables[.@len] = atoi(strnpcinfo(2)) + 1;
	//...
}

prontera,151,183,0	duplicate(NPC_base)	NPC#0	77
prontera,153,183,0	duplicate(NPC_base)	NPC#1	77
prontera,155,183,0	duplicate(NPC_base)	NPC#2	77
prontera,157,183,0	duplicate(NPC_base)	NPC#3	77

Also, in that script, you'll end up with OnInit being called 5 times (that's not the case in your sample, but that's just a mistake I don't want to have to deal with if I use floating NPCs). Anyway! It's just a preference for me. I make less mistakes that way and it's pretty much an habit now ;P.

Link to comment
Share on other sites

  • 0

  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2348
  • Joined:  10/28/11
  • Last Seen:  

@offtopic

1 hour ago, Tokei said:

I'm usually scripting for instances and NPC variables won't work as expected in such a case (the variables will be shared across instances if you use duplicates)

That's why instance have their own variable type. :D  ( 'variable_name )

You should use that too. When you write instance script using global variable, it's actually work just like the normal npc variable ... they shared across all the duplicate npcs.

global variables are actually more worst in some cases, they shared to every single npcs, not only their duplicate one.

You might also end up killing urself to debug the script when you accidentally have another script that using the same global variable in the future. 

OnInit:
	cleararray $npc_values, 0, 50;
	setarray $npc_values, 1, 2, 3, 4;

This practice should be avoid if possible, use the temporary global variable instead. Logically the permanent global variable shouldn't be use / or needed in any OnInit label..

The permanent global variable are evil especially to newbie who has no idea what it does. it bite you when you didn't control the usage.

 

back to topic,

most of the time I just use the npc variable and store the value in the array, use the #1, #2, #3 to differentiate them or...

use the setd / getd method ...

 

 

Edited by Emistry
Link to comment
Share on other sites

  • 0

  • Group:  Developer
  • Topic Count:  48
  • Topics Per Day:  0.01
  • Content Count:  1443
  • Reputation:   337
  • Joined:  10/17/12
  • Last Seen:  

@Tokei shufflearay is a nice function i could have use a few times now 

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  667
  • Reputation:   674
  • Joined:  11/12/12
  • Last Seen:  

@Emistry I wrote this script as a generic example. When you convert the NPCs to instance NPCs, you just change the global variables to instance variables. I usually put mine as "$et_<name_here>" for endless tower, then replace all to " 'et_". It's faster for me when I want to test a specific part of an instance @@. But... we don't know what Hijirikawa is going to use that for.

I do want the variable to be accessible from all the NPCs though; if you aren't using duplicates (the OP could be using 4 completely different NPCs with no code being shared at all), then NPC variables won't do. Well, I made a "setvariableofnpc" command which would solve that particular issue. With that said though, my solution works in all scenarios, even if you change your code midway for another approach.

Skrom's algorithm is also in n²; it works fine with 4 NPCs, but it can get very slow if you plan on duplicating more of them. There's a lot of repeated code being ran here too (sorry >.<'). Though, if you really want to use NPC variables, I don't think you can do it another way (so I still wouldn't go for it on my end xD).

  • Upvote 1
Link to comment
Share on other sites

  • 0

  • Group:  Forum Moderator
  • Topic Count:  33
  • Topics Per Day:  0.01
  • Content Count:  1268
  • Reputation:   382
  • Joined:  02/03/12
  • Last Seen:  

5 hours ago, Tokei said:

@Emistry I wrote this script as a generic example. When you convert the NPCs to instance NPCs, you just change the global variables to instance variables. I usually put mine as "$et_<name_here>" for endless tower, then replace all to " 'et_". It's faster for me when I want to test a specific part of an instance @@. But... we don't know what Hijirikawa is going to use that for.

I do want the variable to be accessible from all the NPCs though; if you aren't using duplicates (the OP could be using 4 completely different NPCs with no code being shared at all), then NPC variables won't do. Well, I made a "setvariableofnpc" command which would solve that particular issue. With that said though, my solution works in all scenarios, even if you change your code midway for another approach.

Skrom's algorithm is also in n²; it works fine with 4 NPCs, but it can get very slow if you plan on duplicating more of them. There's a lot of repeated code being ran here too (sorry >.<'). Though, if you really want to use NPC variables, I don't think you can do it another way (so I still wouldn't go for it on my end xD).

@Tokei Yeah I'm completely aware of that xD. I also understand where you're coming from before. Which is why in most of the scripts I answer I say "Ok, here is one way of doing it." It might not be optimal but a lot of the time information is omitted from the request. If the person requesting the script said they wanted to duplicate this npc 500 times I wouldn't do what I've done here, but we're not being paid and if the specifics aren't there I'm going to take the quicker route. Thank you for being so understanding.

Link to comment
Share on other sites

  • 0

  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2348
  • Joined:  10/28/11
  • Last Seen:  

10 hours ago, Tokei said:

a "setvariableofnpc" command

sound nice to have one ... :D  previously we have to do it using the set + getvariableofnpc ...

set(getvariableofnpc(.var, "TargetNPC"), 1);

 

same for the shufflearray too :D 

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  19
  • Topics Per Day:  0.01
  • Content Count:  193
  • Reputation:   41
  • Joined:  07/21/16
  • Last Seen:  

Sorry, I just got back and was only able to check this thread now.

Thank you for the great advice everyone, I might end up using Tokei's way since it initializes once only, basically I was thinking of a "Deal or No Deal" type of NPC event script and while I do have a working way to shuffle out the variables, it is what you would call not efficient, it works,but it ain't clean. The shuffle feature is really nice and could be used in multiple ways. Thanks again.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...