Jump to content
Sign in to follow this  
NGagedFX

SQS to SQF

Recommended Posts

I've been learning a lot of stuff about scripting lately, but there are some situations in which I still use SQS as I don't have a good SQF reference. I feel mixed up using 2 different types and I would prefer to just use SQF. However, there are a few thing I'm unable to "translate":

What would the following script look like if it were SQF?

[b]#start[/b]

_bomb = _this select 0
_target = nearestObject [_bomb, "CAR"]
[b]? (side _target != west):goto "repeat"
?(_target distance _bomb < 10):goto "boom"
goto "repeat"[/b]

[b]#boom[/b]
_charge = "M_Sidewinder_AA" createVehicle (getPos _bomb)
deleteVehicle _bomb
[b]exit[/b]

[b]#repeat[/b]
~1
[b]goto "start"[/b]

My main problems are how to ask a question and sent the script to another point if it's false,

how to make a script exit after a while and

how to make a script do nothing. Leaving the brackets empty gives me errors (for instance, if (Alive player) then {} )

Share this post


Link to post
Share on other sites

Instructions like while and for should be useful.

Your script in sqf syntax would be something like the following:

private["_bomb", "_target", "_charge"];

_bomb = _this select 0;
_target = nearestObject [_bomb, "CAR"];
while {(side _target != west) or (_target distance _bomb >= 10)} do
{
 sleep 1;
 _target = nearestObject [_bomb, "CAR"];
};

_charge = "M_Sidewinder_AA" createVehicle (getPos _bomb);
deleteVehicle _bomb;

Share this post


Link to post
Share on other sites

Ugh, .sqs - my mind shivers upon looking at it :D Untested, but here is my attempt, made while sleepy:

Deleted code, HitmanFF's version looked better and less sleepy :D

We do have commands like scopeName, breakOut, and breakTo, but I think the general consensus is to avoid using them as much as possible. Like in c, goto exists, but it's considered very bad practice (note the date it was written) to use it.

I'll let the experts correct me if I'm wrong or reading the .sqs wrong.

Btw, why do you need a scope that does nothing? Wouldn't a if !(alive player) then { ...code... }; be better? Or if you actually meant do nothing, I'd just comment the statement.

Edited by CarlGustaffa

Share this post


Link to post
Share on other sites
_bomb =  _this select 0;
waituntil { _target = nearestobject [_bomb,"CAR"]; (_target distance _bomb < 10 && side _target != WEST)};
_charge = "M_Sidewinder_AA" createVehicle (getPos _bomb);

Share this post


Link to post
Share on other sites

Looks brilliant :D

How often do the while and waitUntil syntax check for the condition to be true?

scopeName, breakOut and breakTo in SQF are used like the #name and goto "name" in SQS right? If I'm correct:

scopeName: defines the name of a specific point in the script

breakTo: returns the script to this specific point in order to continue from there

breakOut: will only make the script repeat this specific point in the script, then continue on from breakOut?

Btw, why do you need a scope that does nothing? Wouldn't a if !(alive player) then { ...code... }; be better? Or if you actually meant do nothing, I'd just comment the statement.

shk noted I was totally wrong on this one so I put it in spoilers to keep the thread clean. :)

For conditions to be met, I used if (condition) then { {action} else {} };

But I guess for is what should be used instead.

script.sqf:

_unit = _this select 0;

_unit setDamage 0.8;
for (Alive _unit) do {hint "Congratulations, you're still alive!"};
sleep 3;
hint "This was just to test a script";

If I'm right, when the player is still alive, the first hint should be shown and 3 secs later the 2nd hint should be shown. If the player is dead, the first hint won't be shown and 3 secs later the 2nd hint would be. I'm pretty bussy now so I can't test it out, but I assume that would be the correct use for the for syntax and to replace my old workaround. :)

Edited by NGagedFX

Share this post


Link to post
Share on other sites

Thanks shk, I already thought it was somewhat strange to make such a difference, so I went back to Google and found that with the if (condidition) then {action}; you didn't need to include an else statement. I've read some more info on the for syntax and it looks like it's used for loops with a limit/end (as like a pool from which a limited amount could be taken for the loop to end).

Share this post


Link to post
Share on other sites

So my IED script looks like this right now (and it works):

//init: nul = [this, "size"] execVM "scripts\IED.sqf"
//"size" can be "small", "medium" or "large"
//example:  nul = [this, "medium"] execVM "scripts\IED.sqf"

//private["_bomb", "_target", "_charge"];

_bomb = _this select 0;
_size = _this select 1;

_target = nearestObject [_bomb, "Car"];
while {(side _target != west) or (_target distance _bomb >= 10)} do
{
 sleep 1;
 _target = nearestObject [_bomb, "Car"];
};

switch (_size) do
{
   case "small":
   { 
       _charge = "R_57mm_HE" createVehicle (getPos _bomb);
   };

   case "medium":
   {
       _charge = "M_Sidewinder_AA" createVehicle (getPos _bomb);
       _charge = "M_Sidewinder_AA" createVehicle (getPos _bomb);
   };

   case "large":
   {
       _charge = "Bo_GBU12_LGB" createVehicle (getPos _bomb);
   };
};

deleteVehicle _bomb;

However, I also want to be able to detect tanks and soldier (or to be more specific, military-guys-on-foot). I tried the following which didn't work:

_targetType = ["Car", "Tank", "Man"];
_target = nearestObject [_bomb, _targetType];

Share this post


Link to post
Share on other sites

@HitmanFF:

Your use of "private" is unnecessary. Basically, "private" only matters if you are calling other code (e.g., a function) within a script, and then it only matters for the called code (and really, it only matters there if any local variable names between the main script and the called code overlap).

How often do the while and waitUntil syntax check for the condition to be true?

-snip-

See sbsmac's description below. It's more accurate than mine was.

Edited by ST_Dux
Partially incorrect info

Share this post


Link to post
Share on other sites

@ST_Dux

Since there's no way to know how the script will have been called, using 'private' is a very sensible precaution. I'd always recommend it even if you 'know' you're at no risk of overwriting variables from enclosing scopes. One of these days, you're going to cut and paste the code into a another context and if you haven't made the variables private you may be in for a nasty surprise...

There is a significant difference between 'while' and 'waituntil'. 'While' will continue looping - potentially up to thousands of times within a single frame. (The arma script scheduler will eventually interrupt a long-running while-loop but that's another story.)

'Waituntil' on the other hand evaluates its condition at most once per frame. You can think of

waituntil {some condition} ; 

as being equivalent to

while (! some condition) do {sleep 1 frame} ;

Share this post


Link to post
Share on other sites

But aren't these 'while' and 'waitUntil' syntac very recource intensive then? Especially since nearly every script will have atleast one of these running... Is it a good thing to add a sleep command or won't that have any noticable impact?

Share this post


Link to post
Share on other sites

Thanks for clearing up the specifics on while/waitUntil loops, sbsmac. I suspected I had some of the details wrong. I'm pretty sure that the script scheduling of ArmA 2 limits while loops to running once every .02 seconds, though (whereas ArmA executed the code as many times per frame as possible).

As for private, I still don't think it's necessary if you never intend to use the script outside of the standard "execVM 'myScript.sqf'" format. As long as you are using execVM to call it, the variables within will never overlap with anything else. I agree that it's a good precaution for publicly-released functions, though.

@NGagedFX:

Even with the .02 second delay, while loops can get a bit intensive, so I think it's good practice to add a short delay if the loop is going to be running for any considerable length of time. waitUntil, on the other hand, seems fine to run without a delay; with execution being limited to one time per frame, waitUntil loops don't seem to be all that resource-intensive.

Share this post


Link to post
Share on other sites

Oh it's almost always a good idea to add a sleep command in there. Several even, in some scripts. I also assume that waitUntil shouldn't be used without caution. Do I know for sure the event will come? A safeguard I use is often something like:

waitUntil {bSomeCondition || !alive player};
if (!alive player) exitWith {};
//Followed by the rest of the code...

You can have several of these safeguards running, it all depends on the circumstances and the nature of the script. But you get the idea, which is to simply quit the script if it doesn't make sense to wait any longer. It may be better to restart it again later if the conditions are right, than to have it constantly running, or worse, have several scripts stacked on top of eachother.

Share this post


Link to post
Share on other sites

@ST_Dux: private also makes a local var "in scope" for current and inner scopes. Let's say you have a var named _type, but you need to set its value inside an if-else statement. The if-else is an inner scope, and if _type is not pre-set, then _type won't have a value outside of the if-else. Here's an example from a bomb script of mine:

if (count _this > 2) then { _type = _this select 2; } else { _type = "h30"; };

If _type is not declared prior to the if-else, then it will have the value of "any" after that statement is run. This means you must preset the var with a value prior to the inner scope call, or just make it private.

I didn't see the value in private when I first started on SQF a year ago, but as my script library grew, I ran into problems and made it a habit. It's a good practice, but also you are correct in the fact that most cases it won't matter. I know that some of us here are programmers, and what you learn from experience is to follow good practices to avoid those nasty surprises later as sbsmac noted :)

Share this post


Link to post
Share on other sites

@AZCoder:

Interesting use of private. I've always found it easier to simply declare the variable as any value (e.g., an empty string) prior to using it in an inner scope.

Share this post


Link to post
Share on other sites

There's still something left I can't get to work. I want to be able to detect not only "Car", but also "Tank" and "Man". I tried the following, but it doesn't work. :(

_targetType = ["Car", "Tank", "Man"];
_target = nearestObject [_bomb, _targetType];

Share this post


Link to post
Share on other sites

nearestObject doesnt take an type array, just one type. Use nearestObjects instead.

Share this post


Link to post
Share on other sites

Stupid mistake from me. :rolleyes:

I nearly got it done, and Google servers are overloading thanks to me, but I keep coming across stuff that just doesn't make any sense for as far as my experience and knowledge reach and not everything is as well 'findable'.

For example:

_class = "LandVehicle";
hint format ["_variable: %1", _class];

Hint shows _variable: LandVehicle , which is good.

But I need to do it through a variable:

_vehiclesonly = true;
if (_vehiclesonly) then {_class = "LandVehicle"} else {_class = "Land"};
hint format ["_variable: %1", _class];

Even while the variable is defined within the script, a hint shows up _variable: any :confused::confused:

Edited by NGagedFX

Share this post


Link to post
Share on other sites

That's because you haven't declared _class earlier in the script so it is restricted to the scope of the 'then' or 'else' clause (depending on which branch is taken). Squint can warn you of these kinds of scope issues and many others.

Share this post


Link to post
Share on other sites

What a coinsidence, I downloaded it about an hour ago. :p I ran the setup, rebooted and it's like nothing has happened, there's not even something called "squint" on my pc so something went wrong there.

I already tried

private ["_vehiclesonly"];
_vehiclesonly = true;
if (_vehiclesonly) then {_class = "LandVehicle"} else {_class = "Land"};
hint format ["_variable: %1", _class];

but that didn't work either. :(

Share this post


Link to post
Share on other sites

Assuming the setup didn't give any errors then you should find squint under "start->all programs->Macs Tools". :)

You need to declare "_class" in the upper-most scope. Anything enclosed in braces counts as a new scope so when you write

then {_class = ...}

without having first declared it the net result is that you create a new variable called "_class" inside the scope of the braces so when you move on to the 'hint' line the variable doesn't exist.

Share this post


Link to post
Share on other sites

I feel a bit ashamed right now cause it's to goddamn obvious I should have declared _class instead of _vehiclesonly. :o

I had been scripting for a whole day and I was pretty tired so my brain was kinda low on logical creativity. :p

Does it matter though where you declare a certain variable? I primarily use other scripts as a reference and they always seem to use the private command on top of their script or just after selecting all variables (= _this select *; etc).

I haven't got a folder with Macs Tools or Squint, and I'm definitely in the need for such a program. Would be much faster then hitting preview, check the error arma shows and alt-tabbing back to notepad. I think I screwed up yesterday so I'll just do a 2nd attempt with a rested head. :D

Share this post


Link to post
Share on other sites

It doesn't matter where you private them, just do it before you use them and in the right scope.

Share this post


Link to post
Share on other sites
I haven't got a folder with Macs Tools or Squint,

Just to be clear, you won't see a folder use the file-browser/windows-explorer. However, if you press the start button then look under "All programs" you should see "Macs Tools".

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  

×