Jump to content
Sign in to follow this  
Blanco

Randomwatch for searchlights

Recommended Posts

Hi, I always wanted a searchglight in OFP and I'm pleased we got a full working example in Arma. Thx BIS.

I've wrote a simple watchscript for the searchlight.

- slow moving to make it realistic. clockwise & counterclockwise

- random bearing

- random pitch (min 2m, max 45m above sealevel, we don't want him to spot planes)

- Searchlight stays on when the "gunner" got killed, but turns out when the lens got shot.

Here it is :

Quote[/b] ]

;watch script for searchlights 0.2

;written by Blanco

_unit = _this select 0

_dis = 200

#loop

?!alive _unit : exit

_dir = random 360

_steps = random 350 + 10

_steps = _steps - _steps %1

;hint format ["Dir is %1 in %2 steps",_dir,_steps]

~2

;hint "Heading for a new direction"

_x = 0

_i = -1

_maxheight = 45

_minheight = 2

_inc = -0.2

_height = (2 + random 43)

;hint format ["height = %1",_height]

~1

?random 2 < 1 : _i = 1

?random 2 < 1 : _inc = 0.2

#steps

?!alive gunner _unit : goto "unitdied"

_dir = _dir + _i

?_dir < 0: _dir = _dir +360

?_dir > 360: _dir = _dir -360

_upos = getpos _unit

_cposx = _upos select 0

_cposy = _upos select 1

_cposz = _upos select 2

_height = (_height - _inc)

?(_height > _maxheight) : _inc = 0.2

?(_height < _minheight) : _inc = -0.2

?alive _unit : _unit doWatch [_cposx + ((sin _dir) * _dis), _cposy + ((cos _dir) * _dis),(_height - _inc)]

;hint format ["Direction is %1\n%2 Steps to go\nHeight is %3",_dir,_steps,(_height - _inc)]

~0.2

_steps = _steps - 1

?_steps > 0 : goto "steps"

goto "loop"

#unitdied

;hint "unitdied"

_gl = "logic" createvehicle [0,0,0]

_gl moveingunner _unit

@!alive _unit

deletevehicle _gl

exit

Run it with :

Quote[/b] ] [name of the searchlight] exec "randomwatch.sqs"

You may also put the searchlight in a tower with this line in the initialisation field of the searchlight

Quote[/b] ] this setpos [(getpos this select 0),(getpos this select 1),3.8]

3.8 is the height, adjust it when necessary

Here's a demomission : http://rapidshare.com/files/9033990/Searchlight_watch_script.Sara.zip

Hope you like it. wink_o.gif

Share this post


Link to post
Share on other sites

Heya m8, very nice job, very useful for many ppl...

If you don't mind me suggesting... I would suggest to write everything in SQF format for ArmA, as that's the new / optimized way of coding, aswell as that there are preload and process functions etc. etc. Again, only a suggestion m8, nice job either way!

Share this post


Link to post
Share on other sites

I have to learn that stuff first, I'm not familiar with sqf.

Any good tutorials around yet?

Or can someone convert my script into the new format so I can see how it's done?

Glad you like it.

Share this post


Link to post
Share on other sites
I have to learn that stuff first, I'm not familiar with sqf.

Any good tutorials around yet?

Or can someone convert my script into the new format so I can see how it's done?

Glad you like it.

Based on my current knowledge biggrin_o.gif:

Basicly, every line that's not comment, the returning result of a function or the opening of a while, if, etc, needs a ; at the end.

@... is replaced by waituntil{...};

~.. is replaced by sleep ..;

;... comment is replaced by // ... comment

? ... : ... is replaced by if (...) then { .. }; and you can use else, this will be ran when the first condition=false instead of true: if (...) then { .. } else { .. };

goto ".." and #.. is replaced by while {..} do { .. }; together with if and else you can recreate the same loop possibilities as before but probably more efficient!

Switch is also awesome to use, More info about Control Structures

You need to define the used private (not global) variables by: private ["_var1","_var2","_var3"]; you do not have to define _this as that's always private.

Instead of running scripts with exec you need to use execVM if you wish to run SQF scripts...

Functions work the same as scripts, altough you call the functions instead of execVM them:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">randomInt = compile preprocessfile "functions\randomint.sqf";

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">_i = [1,5] call RandomInt;

The difference between scripts (execVM/Spawn) and functions (call) is that scripts can be running parallel, while a function (call) is first completing the function and is usually receiving a returned value, before it continues the script in which you called the function. So you can load different variables in your script, with the output of different functions called with their own parameters. Or the function could just run some code without returned value, while the script will wait for it to complete before continueing the script.

What I do is preload the used scripts into variables (like functions):

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">six_scr_misinit = compile preprocessFile "scripts\misinit.sqf";

And then when I need the script, I spawn it (as with functions you would call them):

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">[] spawn six_scr_misinit;

The main reason I use this personally, is that the scripts are all compiled and loaded before, and you can keep spawning them as many times as you want without the game reloading the script every single time from file, plus that you find problems with the scripts(syntax) right away as they are processed at the start.

You can of coarse preload and spawn things only nececairy for lets say client or server, by creating a gamelogic that's named server (which could actually be named anything), by testing if it's local: if(local server) then { .1. } else { .2. }; if the script is ran on the server, it will run the code at 1, and if it's ran on the client it will run the code at 2.

Loaded functions/scripts are global if they are loaded in global variables (without _ in front of them), as such you can initiate (most of) them at the start in init.sqs etc, while using them throughout any script. While more specific scripts or functions can be loaded later, when they are needed.

OFPEC has loads of functions in SQF, so you could have a look there and see if there is smth you can use as a base to understand the syntax. http://www.ofpec.com/ed_depot/functions.php The BIS Community WIKI also has some SQF scripting basics afaik: http://community.bistudio.com

If you don't get it converted somehow, just let me know, if I got some spare time here and there I will convert it as an example for you smile_o.gif

Examples: (BTW the forum messes up the tabs etc, so they are replaced by spaces)

While and waituntil (this script waits for six_bc to become true, then puts it back to false, executes some code, and then waits again till six_bc = true, until a certain condition is met and then _run is set to false and as such ends the loop):<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">///////////////////////////////////////////////////////////

// ArmA - loop_cl.sqf by Sickboy (sb_at_6thSense.eu)

///////////////////////////////////////////////////////////

private ["_run","_obj1f","_obj2f","_obj3f","obj4f"];

_obj1f=false; _obj2f=false; _obj3f=false; _obj4f=false;

_run = true;

while{_run} do

{

waitUntil {six_bc};

six_bc = false;

if(overcast != six_overcast) then { 0 setOvercast six_overcast };

if(fog != six_fog) then { 0 setFog six_fog };

if(six_daci) then

{

if(six_obj1act && six_obj1d && !_obj1f) then { _obj1f=true; hint "Objective 1: Done" };

if(six_obj2act && six_obj2d && !_obj2f) then { _obj2f=true; hint "Objective 2: Done" };

if(six_obj3act && six_obj3d && !_obj3f) then { _obj3f=true; hint "Objective 3: Done" };

if(six_obj4act && six_obj4d && !_obj4f) then { _obj4f=true; hint "Objective 4: Done" };

if(six_obj1d && six_obj2d && six_obj3d && six_obj4d) then { "outro" spawn six_scr_cam; _run = false};

};

};

A function, for returning valid players (Alive and not null) as an array of objects, from an array of strings. I define all the possible players=["s1","s2","s3"....] and use a script loop that uses this function to update a currentplayer array according to current alive and valid players, and possibly added players through JIP:<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">///////////////////////////////////////////////////////////

// ArmA - fnPlayers.sqf by Sickboy (sb_at_6thSense.eu)

// Input - Array with players as strings

// Output - Array with alive players as objects

///////////////////////////////////////////////////////////

private ["_y","_f","_r"];

_r = [];

{

_y = call compile _x; _f = format["%1",_y];

if ((_f != "scalar bool array string 0xe0ffffef") && (_f != "<NULL-object>")) then{if (alive _y) then { _r = _r + [_y] }};

} foreach _this;

_r

Share this post


Link to post
Share on other sites

Thx, but I need time to understand the new syntax. It's still Chinese for me.

I'm kind of familiar with if, then & else statements but while, do, from, switch are new to me.

I 've started with OFP scripting without any scripting knowledge, except for a little BASIC from school. I've learned a lot by watching other people's scripts.

I extracted the whole ArmA campaign and I couldn't find one sqf script. At this moment I can't even make the examples on the wiki work...

Share this post


Link to post
Share on other sites

Well, how do you think most of us learned? I haven't had a single computer lesson in my whole life, altough I have been busy with computers at home since I was 10 smile_o.gif)

This is the converted script... I did not try it yet, as that needs to wait until at least tonight... but it should work, might even use some optimizations here.. Kegetys posted some nice examples of how to use breakout and breakto... I might update if I feel like it smile_o.gif

Remember, you must use execVM to run it, or if you preprocessed it into a variable, Spawn.

Again... the forum messes my tabs, so I replaced tabs by spaces smile_o.gif

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">//watch script for searchlights 0.2

//written by Blanco

//converted to SQF by Sickboy (sb_at_6thSense.eu)

private ["_run","_unit","_dis","_steps","_x","_i","_maxheight","_minheight","_inc","_height","_upos","_cposx","_cposy","_cposz"];

_unit = _this select 0;

_dis = 200;

_run = true;

while{_run} do

{

    if (not alive _unit) then

    {

         _run = false;

    } else {

         _dir = random 360;

         _steps = random 350 + 10;

         _steps = _steps - _steps %1;

         //hint format ["Dir is %1 in %2 steps",_dir,_steps];

         sleep 2;

         //hint "Heading for a new direction";

         _x = 0;

         _i = -1;

         _maxheight = 45;

         _minheight = 2;

         _inc = -0.2;

         _height = (2 + random 43);

         //hint format ["height = %1",_height];

         sleep 1;

         if (random 2 < 1) then { _i = 1; _inc = 0.2 };

         while{_steps > 0} do

         {

              if(not alive gunner _unit) then

              {

                   _run = false;

              } else {

                   _upos = getpos _unit; _cposx = _upos select 0; _cposy = _upos select 1;     _cposz = _upos select 2; _height = (_height - _inc);

                   _dir = _dir + _i;

                   if(_dir < 0) then { _dir = _dir + 360 };

                   if(_dir > 360) then { _dir = _dir - 360 };

                   if(_height > _maxheight) then { _inc = 0.2 };

                   if(_height < _minheight) then { _inc = -0.2 };

                   if(alive _unit) then { _unit doWatch [_cposx + ((sin _dir) * _dis), _cposy + ((cos _dir) * _dis),(_height - _inc)] };

                   //hint format ["Direction is %1\n%2 Steps to go\nHeight is %3",_dir,_steps,(_height - _inc)];

                   _steps = _steps - 1;

                   sleep 0.2;

              };

         };

    };

};

//hint "unitdied";

if(alive _unit) then

{

    _gl = "logic" createvehicle [0,0,0];

    _gl moveingunner _unit;

    waituntil{not alive _unit};

    deletevehicle _gl;

};

Share this post


Link to post
Share on other sites

terrific script Blanco!

this converts one of your many pioneering OFP scripts (need I recall e.g. LogicCam to anyone?) to Armed Assault notworthy.gif

Share this post


Link to post
Share on other sites

Sickboy how do i get it to work in the editor it never lets me run

[this] execVM "script.sqf" or any other way?? how can i get it to work wink_o.gif

Share this post


Link to post
Share on other sites
Sickboy how do i get it to work in the editor it never lets me run

[this] execVM "script.sqf" or any other way?? how can i get it to work  wink_o.gif

Do you get some kind of error while you try to run it like that?

I usually load everything in my scripts and use the init fields etc as less as possible, but just give names to all the objects I wish to use in scripts.

Please post the contents of script.sqf (if it isn't the sqf that I posted above) if you had an error.

I think I read somewhere that "call" could not be used in the mission editor, but afaik execVM should work just as fine as exec..

Just checked, im actually using an execVM in the onActivation of a trigger for displaying some debug info, and that at least works, now im not sure about the init fields...

Share this post


Link to post
Share on other sites

Thx, sickboy. It all looks so obvious when I see the conversion, it definitly helps me to understand the syntax.

I did some tests with enemy AI and it seems that AI tries to kill the gamelogic when the original gunner got killed; Good luck wink_o.gif

I had to add a _gl setcaptive true line at the end to prevent this and I was really suprised it worked. (afaik see)

I always thought Setcaptive had no effect on gamelogics but it seems it does.

@Redface : I already tried logiccam and It doesn't seems to work anymore in ArmA,I dunno why.

Share this post


Link to post
Share on other sites

I tried you conversion Sickboy and it doesn't work or I don't know how to run it.

I've made an init with

Quote[/b] ]

watchscript=compile preprocessfile "watch.sqf";

sleep 1;

[sL1] call watchscript;

That gave me an error.

http://img.photobucket.com/albums/v228/blanco2/CAtafgan/error.jpg

Then I tried it via execVM...

Quote[/b] ][sL1] execVM "watch.sqf"

or

Quote[/b] ]SL1 execVM "watch.sqf"

No succes...

Can you tell me how to run this, cause I don't have a clue...

How can I use parameters? Same way as in sqs scripts?

Share this post


Link to post
Share on other sites
...

Please share the error, as that will help me understand what's wrong smile_o.gif)

I can take a look tonight if we don't get it debugged by the error report. You can read your errors back in your arma.rpt folder in %USERPROFILE%\local settings\application data\arma

%USERPROFILE% is usually C:\Documents and Settings\yourname

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">watchscript=compile preprocessfile "watch.sqf";

sleep 1;

[SL1] call watchscript;

is wrong, as it is no function, in this case you should use spawn:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">watchscript=compile preprocessfile "watch.sqf";

sleep 1;

[SL1] spawn watchscript;

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">[SL1] execVM "watch.sqf"

Is fine

Share this post


Link to post
Share on other sites

the error

here's what I found in that rpt file

Quote[/b] ]

if (not alive _unit) th>

Error position: <while{_run} do

{

if (not alive _unit) th>

Error Missing ;

Error in expression <this select 0;

_dis = 200;

_run = true

while{_run} do

When I run it with [sL1] execVM "watch.sqf" I got :

type script expected nothing, i'm not allowed to press the ok button.

Share this post


Link to post
Share on other sites
When I run it with [sL1] execVM "watch.sqf" I got :

type script expected nothing, i'm not allowed to press the ok button.

Try with: dummy=[sL1] execVM "watch.sqf"   dummy can be anything. (thanks to raedor for the tip), altough I prefer using the loading of the script in a variable and spawning it, especially handy/optimized when using multiple search lights! Will check error and update in a sec...

update: _run = true was missing ; so: _run = true;

Share this post


Link to post
Share on other sites
huh..in what line? The 9th?

yes, I already updated my post with the fix aswell

im gonna take a look at the script within a mission, brb will update

Share this post


Link to post
Share on other sites

I'm sorry if i'm messing up your efforts.

But I've experienced or suffered some strange behaviour with my own searchlight script. What I wanted to do is a script to let your guard search a defined angle. The script looks just like this:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">comment "Script by BadAss, Feel free to use and modify

visit www.mapfact.net and www.mapfact.net/forum_arma

contact: badass@mapfact-team.net";

private["_sl","_ang","_del","_dir","_dirneg","_dirpos"];

_sl=_this select 0;

_ang=_this select 1;

_del=_this select 2;

_dir=getDir _sl;_dirneg=_dir-_ang/2;_dirpos=_dir+_ang/2;

while {alive gunner _sl} do

{

while {(alive gunner _sl)&&(_dir>_dirneg)} do

{

_dir=_dir - 1;

_sl setDir _dir;gunner _sl setFormDir _dir;

sleep _del;

};

sleep (_del*5);

while {(alive gunner _sl)&&(_dir<_dirpos)} do

{

_dir=_dir + 1;

_sl setDir _dir;gunner _sl setFormDir _dir;

sleep _del;

};

};

In theory it works pretty okay but - and that's my pain - not always. In my little test mission only one of three guards is turning his rounds.

The two lazy guards will eventually start when you get near enough - not exactly the way a searchlight is expected to work.

Sometimes the searchlights are nervously twitching at their turning points. I don't have any clue why. Bad thing: they don't do it regularily.

Here's the little testing mission that I've made.

Any help and ideas are appreciated, so take my thanks in advance.

Share this post


Link to post
Share on other sites
@ Dec. 28 2006,20:30)]...

Roger, looking at both.

Had to remove MAP_misc from the addon arrays and the map_misc_logic --> just logic wink_o.gif

Share this post


Link to post
Share on other sites
@ Dec. 28 2006,20:55)]Sorry, you're right. It's just because we're making our first little ArmA ad... erm. Wait and see. tounge2.gif

As if I didn't know tounge2.gif

Still on it, it's indeed weird, but I have at least found that if you remove the _sl setdir's the movement is a lot more smooth.

BadAss Update: This seems to work fine!

Tabs replaced by 4x space for [ code ] block, added extra while loop for 10.000x10.000 loops

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">comment "Script by BadAss, Feel free to use and modify

visit www.mapfact.net and www.mapfact.net/forum_arma

contact: badass@mapfact-team.net

Edited by Sickboy (sb_at_6thSense.eu) with dowatch-direction code from Blanco";

private["_sl","_ang","_del","_dir","_dirneg","_dirpos","_dis","_upos","_cposx","_cposy","_cposz","_run"];

_sl=_this select 0;

_ang=_this select 1;

_del=_this select 2;

_dir=getDir _sl;_dirneg=_dir-_ang/2;_dirpos=_dir+_ang/2;

_dis=200;_upos=getpos _sl; _cposx=_upos select 0; _cposy=_upos select 1; _cposz=_upos select 2;

_run=true;

while {_run} do

{

   while {alive gunner _sl} do

   {

       while {(alive gunner _sl)&&(_dir>_dirneg)} do

       {

           _dir=_dir - 1;

           _sl doWatch [_cposx + ((sin _dir) * _dis), _cposy + ((cos _dir) * _dis),_cposz];

           sleep _del;

       };

       sleep (_del*5);

       while {(alive gunner _sl)&&(_dir<_dirpos)} do

       {

           _dir=_dir + 1;

           _sl doWatch [_cposx + ((sin _dir) * _dis), _cposy + ((cos _dir) * _dis),_cposz];

           sleep _del;

       };

   };

};The problem seems to be an engine bug or by design?? when an unit is turned with setformdir it doesn't relate properly when ur far away from it :S Can't do better at the moment smile_o.gif

Blanco:

When I used the SQF script as I posted it a few posts ago, it works fine when using: dummy=[this] execVM "script.sqf"   in the init line of the light, should also work for you I guess smile_o.gif

Share this post


Link to post
Share on other sites

Great work! Now they're real guards. Thank you! biggrin_o.gif I've never been into that sin and cos stuff, but i'll try and see if i get it someday... tounge2.gif

Btw. maybe you've noticed? The searchlight guys are really wearing NVGoggles by default. huh.gif

Share this post


Link to post
Share on other sites

@sickboy: Instead of using (and computing everytime) sin dir and cos dir, check the "similarities" to vectorDir wink_o.gif

Share this post


Link to post
Share on other sites
@ Dec. 28 2006,22:28)]Great work! Now they're real guards. Thank you! biggrin_o.gif I've never been into that sin and cos stuff, but i'll try and see if i get it someday... tounge2.gif

Btw. maybe you've noticed? The searchlight guys are really wearing NVGoggles by default. huh.gif

No biggie, and im no star with the cos etc either smile_o.gif

About the NVG, I actually didn't notice, was concentrating on getting the stuff fixed asap, share it and get on with my own stuff biggrin_o.gif but too bad they dont put it down auto smile_o.gif But I guess you solved that already? smile_o.gif

@sickboy: Instead of using (and computing everytime) sin dir and cos dir, check the "similarities" to vectorDir wink_o.gif
Thanks for the tip m8! Will take a look at it, but was merely fixing and converting to sqf (for Blanco) without really bothering about the structures or used functions.. That's for another day smile_o.gif  goodnight.gif

Share this post


Link to post
Share on other sites
@sickboy: Instead of using (and computing everytime) sin dir and cos dir, check the "similarities" to vectorDir wink_o.gif

What would it look like then?

But I guess you solved that already?
Just ignored it so far, but why not. Good idea. wink_o.gif

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  

×