Jump to content
Sign in to follow this  
Raziaar

foreach list _trigger

Recommended Posts

Hey guys. I'm actually using ArmA, not ArmA 2, but the ArmA scripting forums are barren and I figure the answer will still be the same for this.

I'm trying various things to help me gain a better grasp at scripting and learn all the syntax. So far it's very frustrating, even with my C# background.

Anyway, what I'm working on right now is a silly little script(no real practical use) that will let a player issue a command that will cause all units of a lower rank to face in the direction of the player and issue a salute for a set period of time before resuming what they were doing.

I've been running into snags however.

First off, I was trying it like this. A addaction for the unit which calls this script.

_unit = _this select 0;

_radius = createTrigger ["EmptyDetector", getPos _unit];
_radius setTriggerActivation [format["%1",side _unit], "PRESENT", false];
_radius setTriggerArea [10, 10, 0, false];
_radius setTriggerStatements ["this", 
	"{
		if (name _x != name _unit && rating _x < rating _unit) then 
		{
                              /*do some stuff here*/
                       }
	 } foreach thislist", 
	""];

Which works in a sense, that the code compiles, but for some reason even if the _unit has a higher rating than the _x units, it doesn't go into the statement. I've tested this with hints which do not show up. I have tested that it's possible to determine the rating of the _unit variable by testing with hints... but for some reason in this statement it doesn't work. And I don't know why. It doesn't even work if I test if rating _unit > 5000 which is absolutely true, since the one i'm testing has a rating of corporal which is 7500.

And secondly, I tried the following, which is what the title of this thread is named for.

_unit = _this select 0;

_radius = createTrigger ["EmptyDetector", getPos _unit];
_radius setTriggerActivation [format["%1",side _unit], "PRESENT", false];
_radius setTriggerArea [10, 10, 0, false];

{
if (name _x != name _unit && rating _x < rating _unit) then
{
	sleep random 1;
	_x playMove "AmovPercMstpSlowWrflDnon_Salute";
	_x disableAI "Anim";
	sleep random 2;
	_x enableAI "Anim";
}


} foreach list _radius;

This does not work at all. It seems there are no values inside of the list of the trigger when doing it way. It worked when I was using the "thislist" command within the array activation, but not here. Using a hint to test, it says it has no shape... which I assume to mean the array has no length. But why does it have a length when it's done in the onactivation area?

Why is this? How can I fix this?

Also, on an unrelated note, how can I make a unit face the direction that another unit is at? Not facing in the same direction as the unit, but rather turning to face the unit in whichever direction has to be rotated to face him.

EDIT: I found a different command and tried something different. This seems to work except for one tiny problem.

_unit = _this select 0;

_radius = createTrigger ["EmptyDetector", getPos _unit];
_radius setTriggerActivation [format["%1",side _unit], "PRESENT", false];
_radius setTriggerArea [10, 10, 0, false];

_radius setTriggerStatements ["this", "", ""];

_radius setEffectCondition "
{
	if (rating _x < 500) then 
	{
		sleep random 1;
		_x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
		_x disableAI ""Anim"";
		sleep random 2;
		_x enableAI ""Anim"";

	}
} foreach thislist";

The problem is, those sleep commands do not work! they give me errors! I don't know why they are not working. Maybe they cannot be parsed or something within the string statement.

Whatever shall I do? :(

Edited by Raziaar

Share this post


Link to post
Share on other sites

in 1) _unit is undefined inside the setTriggerStatements execution statement I believe. Did you debug it?

Do you use diag_log or -showScriptErrors.

In any case you need to post the errors.

Using notepad++ with the plugin from i0n0s helps a lot. Get it from OFPEC.

Replace " code "" code "" code " with single quotes: " code ' code ' code ".

Share this post


Link to post
Share on other sites
in 1) _unit is undefined inside the setTriggerStatements execution statement I believe. Did you debug it?

Do you use diag_log or -showScriptErrors.

In any case you need to post the errors.

Using notepad++ with the plugin from i0n0s helps a lot. Get it from OFPEC.

Replace " code "" code "" code " with single quotes: " code ' code ' code ".

Hello. Thank you for the response. I did not know anything about diag_log or -showScriptErrors. All I've had to go by have been the little blurb of errors that pop up within the game when I try to execute the script... been doing a ton of back and forth.

I will look into those things and post a response back.

Share this post


Link to post
Share on other sites

Moved stuff from effects to the onAct field and put it inside a spawn so the sleeps work:

_radius setTriggerStatements ["this", "nul = thislist spawn {
 {
   if (rating _x < 500) then 
   {
     sleep random 1;
     _x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
     _x disableAI ""Anim"";
     sleep random 2;
     _x enableAI ""Anim"";
   }
 } foreach _this;
};", ""];

Share this post


Link to post
Share on other sites
Moved stuff from effects to the onAct field and put it inside a spawn so the sleeps work:

_radius setTriggerStatements ["this", "nul = thislist spawn {
 {
   if (rating _x < 500) then 
   {
     sleep random 1;
     _x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
     _x disableAI ""Anim"";
     sleep random 2;
     _x enableAI ""Anim"";
   }
 } foreach _this;
};", ""];

Thank you. That looked very much like what I was trying to do before with my first code snippet, but with that spawn command it's better. I had not known about the spawn command.

Is there a reason why my _unit variable conditions are not being evaluated as true, even though they are entirely true?

From my programming experience, I'm assuming that it's because the _unit variable is defined as a local variable. However, I would assume that this variable would still be populated within the spawn command, but it appears not to be. Is there a way to remedy this or must I declare _unit to be a global variable instead? And if I do, will the variable still be in memory when the script exits and I would have to manually delete it?

Share this post


Link to post
Share on other sites

Yes, _unit is local to the script. But the spawn that gets created by the trigger is a different "script". Thus, it has it's own vars. So, you have to either make the unit var global or pass it to the spawn as a parameter:

_radius setTriggerStatements ["this", format ["nul = [%1,thislist] spawn {
 _unit = _this select 0;
 {
   if (rating _x < 500) then 
   {
     sleep random 1;
     _x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
     _x disableAI ""Anim"";
     sleep random 2;
     _x enableAI ""Anim"";
   }
 } foreach (_this select 1);
};",_unit], ""];

Share this post


Link to post
Share on other sites
Yes, _unit is local to the script. But the spawn that gets created by the trigger is a different "script". Thus, it has it's own vars. So, you have to either make the unit var global or pass it to the spawn as a parameter:

_radius setTriggerStatements ["this", format ["nul = [%1,thislist] spawn {
 _unit = _this select 0;
 {
   if (rating _x < 500) then 
   {
     sleep random 1;
     _x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
     _x disableAI ""Anim"";
     sleep random 2;
     _x enableAI ""Anim"";
   }
 } foreach (_this select 1);
};",_unit], ""];

Thank you. I was wondering how to pass extra paramters into a script other than the caller.

I assumed simply adding an extra one within an array would make that variable call the script as well, rather than simply being passed as a variable.

EDIT: I need to go to bed. I've been at this way too long.

Having an issue with the variable _unit being passed in and assigned to the other local variable... without retaining any of the information about it, such as the rating or the name or anything like that.

Maybe after I sleep I'll have a clear head. Thanks for all of your help thus far. I may just go ahead and delete the global variable after the script is ready end to save myself all of this trouble. I don't know if it makes that much of a difference to have it global instead of local simply for the duration of this script. Or if there's a way to fix the issue I described just above.

Edited by Raziaar

Share this post


Link to post
Share on other sites

Yeah, I don't know why the variable passed into the spawn command doesn't retain any of the information it previously had. It's not even the same typeOf variable anymore.

Is there any way I can pass it through ensuring that it retains the same pointer to the original object, without resorting to a global variable?

Share this post


Link to post
Share on other sites

It's a bug or an oversight in design. Unit's without an assigned name can not be refered everywhere without breaking something.

Units without name are named by default in this manner:

B 1-1-A:1

Name of a unit with a player:

B 1-1-A:1 (stm shuko)

So, if you decide to refer to a unit with that in a trigger etc, the game's interpreter doesn't get it. Instead of expects something else and usually says there is a missing ] or ;.

Name the unit either in editor or with setvehiclevarname.

I named my guy as "dude". Made a radio trigger with this in onact.

nul = [player] execvm "salute.sqf"

salute.sqf:

_unit = _this select 0;

_radius = createTrigger ["EmptyDetector", getPos _unit];
_radius setTriggerActivation [format["%1",side _unit], "PRESENT", false];
_radius setTriggerArea [10, 10, 0, false];
_radius setTriggerStatements ["this", format ["nul = [%1,thislist] spawn {
 _unit = _this select 0;
 {
   if (rating _x < 500) then 
   {
     sleep random 1;
     _x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
     _x disableAI ""Anim"";
     sleep random 2;
     _x enableAI ""Anim"";
   }
 } foreach (_this select 1);
};",_unit], ""];

Share this post


Link to post
Share on other sites
It's a bug or an oversight in design. Unit's without an assigned name can not be refered everywhere without breaking something.

Units without name are named by default in this manner:

B 1-1-A:1

Name of a unit with a player:

B 1-1-A:1 (stm shuko)

So, if you decide to refer to a unit with that in a trigger etc, the game's interpreter doesn't get it. Instead of expects something else and usually says there is a missing ] or ;.

Name the unit either in editor or with setvehiclevarname.

I named my guy as "dude". Made a radio trigger with this in onact.

nul = [player] execvm "salute.sqf"

salute.sqf:

_unit = _this select 0;

_radius = createTrigger ["EmptyDetector", getPos _unit];
_radius setTriggerActivation [format["%1",side _unit], "PRESENT", false];
_radius setTriggerArea [10, 10, 0, false];
_radius setTriggerStatements ["this", format ["nul = [%1,thislist] spawn {
 _unit = _this select 0;
 {
   if (rating _x < 500) then 
   {
     sleep random 1;
     _x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
     _x disableAI ""Anim"";
     sleep random 2;
     _x enableAI ""Anim"";
   }
 } foreach (_this select 1);
};",_unit], ""];

Hello. Thanks again for the reply. Unfortunately, I had already named my unit this whole time in the editor. He was named "general" just as a temporary name.

Here, I think the reason you cannot see the problem I'm having is because you're still using the if statement that doesn't ask anything about the _unit.

Change your if statement to be the following: if (rating _x < rating _unit)

And make sure that he has a higher rank than the other units... like corporal or something with the other guys as privates.

You will see that it never steps into the if statement, even though the statement would reveal itself to be true one would think. If you add a hint to check the rating of the _unit before the statement executes, you will be able to see what I mean. The rating will show as "dude" for you(or "general" for me), and any other information about the variable will as well. So it's effectively lost all of the information about the original _unit after it was transferred into the spawn code bracket.

2weja03.jpg

11gk3ll.jpg

The following is my changes for you to see what I mean.

salute.sqf:

_unit = _this select 0;

hint format ["Rating of _unit before 'spawn': %1", rating _unit];
sleep 3;

_radius = createTrigger ["EmptyDetector", getPos _unit];
_radius setTriggerActivation [format["%1",side _unit], "PRESENT", false];
_radius setTriggerArea [10, 10, 0, false];
_radius setTriggerStatements ["this", format ["nul = [%1,thislist] spawn {
 _unit = _this select 0;

 hint format['Rating of _unit inside ''spawn'': %1', rating _unit];
 sleep 3;
 {
   if (rating _x < rating _unit) then 
   {
     sleep random 1;
     _x playMove ""AmovPercMstpSlowWrflDnon_Salute"";
     _x disableAI ""Anim"";
     sleep random 2;
     _x enableAI ""Anim"";
   }
   else {hint 'Not entered if statement';}
 } foreach (_this select 1);
};",_unit], ""];

And on an unrelated note, I figured out how to solve one of my other questions I mentioned at the end of this thread. After writing a script to determine which direction one unit was from another with all the math... finding the length of the vectors, normalizing the vectors, doing the dot product and stuff... I realized that I was able to accomplish it easily using the "tan2" function, which I had no idea about because it didn't seem like what I needed.

Anyway, I wanted to thank you very much for all the help you've been giving me shk. We're not quite there yet, but we will be. This script that I have in this thread doesn't do a whole lot, and it's kind of pointless... but it's helped me out a remarkably great deal in understanding the intricacies of scripting in ArmA which will stick with me for quite a while. Once I learn all the syntax and the quirks, I'll be able to pump stuff out.

Edited by Raziaar

Share this post


Link to post
Share on other sites

Ah.

The reason why you get "general" instead of a number in the 2nd hint is because you have a format command inside another format. It doesn't work because the %1 inside the 2nd format is replaced by the value from the first (outmost) format.

Anyway, the script works just fine. You get the "Not entered if statement" once, because the thislist includes the general unit as well, his rating is not lower than his own rating. To get rid of that you can do:

if (rating _x <= rating _unit) then

Or you can add an if which checks that _x is not _unit.

Share this post


Link to post
Share on other sites
Ah.

The reason why you get "general" instead of a number in the 2nd hint is because you have a format command inside another format. It doesn't work because the %1 inside the 2nd format is replaced by the value from the first (outmost) format.

Anyway, the script works just fine. You get the "Not entered if statement" once, because the thislist includes the general unit as well, his rating is not lower than his own rating. To get rid of that you can do:

if (rating _x <= rating _unit) then

Or you can add an if which checks that _x is not _unit.

Ah, thank you so much. It does appear now that it's working. For some reason I wasn't getting it before... or maybe I was simply looking too much at my hint as debugging and not realizing that it was taking up the value of the other format variable.

Thank you again for all of your help. I've certainly learned a lot from spending so many hours messing with this and trying other things as well.

It's kind of weird when they do their animation... they sort of bounce their gun up and down a couple times, then salute, then bounce their gun up and down a couple of other times and then they are finished.

Any idea what that is about?

Share this post


Link to post
Share on other sites

I've never really messed with anims so can't help you there.

Share this post


Link to post
Share on other sites
I've never really messed with anims so can't help you there.

Alright, that's cool.

Thanks again for all of your help, you have been a godsend.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×