OFPEC Forum
Editors Depot - Mission Editing and Scripting => OFP - Editing/Scripting General => Topic started by: Blanco on 10 Jun 2005, 02:45:47
-
Hello,
I hope I can explain this....
I have a script to make a object turn (via setdir) in a random direction between a maximum left & right arc.
Suppose my object's direction is 313 and the max step is 80 degrees, than the object can turn between azimuth 33 & 233...
Because :
1)
313 - 80 = 233
2)
313 + 80 = 393, but I have to correct this so the result stay between 360 degrees. So 393 -360 = 33
So far so good, that works fine.
The problem is when the old heading is below 360 degrees and the new heading is above 360 degrees, the object turns counterclockwise, but the shortest way is clockwise.
How can I calculate this so the object always takes the shortest turn to get there?
_mg = _this select 0
_mainhdg = getdir _mg
_step = 80
;calculate the random heading the first time
_newhdg = (_mainhdg + ((random _step) - (random _step)))
? _newhdg < 0: _newhdg = _newhdg + 360
? _newhdg > 360: _newhdg = _newhdg - 360
#searchloop
? (getdir _mg - _newhdg) < 10 and (getdir _mg - _newhdg) > - 10: goto "pauze"
? (getdir _mg - _newhdg) > 0: _mg setdir ((getdir _mg) - 1)
? (getdir _mg - _newhdg) < 0: _mg setdir ((getdir _mg) + 1)
player globalchat format ["MH=%1 NH =%2 DIR= %3",_mainhdg,_newhdg,getdir _mg]
~0.09
goto "searchloop"
#pauze
_newhdg = (_mainhdg + ((random _step) - (random _step)))
?_newhdg > 360 : _newhdg = _newhdg - 360
?_newhdg < 0 : _newhdg = _newhdg + 360
~2 + random 2
goto "searchloop"
Actually, I think this is a shitty code, I'm sure this can be done easier, but I'm bad with math... :-\
Please help me out.
-
Blast... I got around this exact problem a while back, can't think what i did with the code... I'll have a think and see if i can remember what i did. It wasnt over difficult at any rate.
-
try something like this (note: I have made up the names of some variables and see that I have used _step and so have you but for something else):
_change = _newDir - _oldDir
if (abs(_change) > (abs (_change + 360) % 360)) then {_change = (_change + 360) % 360}
_step = _change/abs(_change)
#loop
_mg setDir ((getDir _mg) + _step)
if (abs((getDir _mg) - _newDir) > abs(_step)) then {goto"loop"}
exit
EDIT:
Instead of the loop you could use a while:
_change = _newDir - _oldDir
if (abs(_change) > (abs (_change + 360) % 360)) then {_change = (_change + 360) % 360}
_step = _change/abs(_change)
while {abs((getDir _mg) - _newDir) > abs(_step)} do {_mg setDir ((getDir _mg) + _step)}
exit
-
Yes, I think THobson has got it there. Abs and the modulus stir vague memories...
This topic reminds me of a function I've been meaning to submit, ClockwiseOf.sqf (http://www.ofpec.com/editors/funcref.php?letter=C#ClockwiseOf). It doesn't seem directly applicable to your situation, but then again it's sort of related. Anyhow, it's in the funcs depot now.
And completely unrelated to this topic, i just found out that in a script, any variables you initialise within the curly braces of an 'if... then {}' clause (or a while, or anything else) are local to that clause only. I know that this is how it works in java, but it's interesting to see that it happens in FP script too. For example, try this:
if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]
-
Um... correct me if I'm wrong but that snippet by THobson always returns a positive value for _step.
-
Peanut - it shouldn't
Try putting
_newDir = 5
_oldDir = 10
_change = -5
5 is < 355 so _change stays as -5
-5/(abs(-5)) = -1
-
Okay, I was wrong about that, but try
_newDir = 340
_oldDir = 10
_change = 330
_step = 1,
which is the wrong way.
-
Blanco: here's my own crappy, inelegant code:
_mg = _this select 0
_mainhdg = getdir _mg
;search parameters
_step = 80
_twostep = _step * 2
_tol = 10
_inc = 1
;calculate the random heading the first time
_newhdg = (_mainhdg + _step - (random _twostep))
;convert heading to 0-360
_newhdg = (_newhdg mod 360)
? _newhdg < 0:_newhdg = _newhdg + 360
#searchloop
_mgdir = getdir _mg
? (abs(_mgdir - _newhdg) < _tol): goto "pauze"
if (_mgdir > _newhdg) then {goto "skip1"}
_rturn = _mgdir - newhdg
_lturn = (_mgdir + 360) - _newhdg
goto "skip2"
#skip1
_rturn = (_newhdg + 360) - _mgdir
_lturn = _newhdg - _mgdir
#skip2
if (abs(_lturn) < abs(_rturn)) then {_mgdir = _mgdir - _inc} else {_mgdir = _mgdir + _inc}
;convert heading to 0-360
_mgdir = (_mgdir mod 360)
? _mgdir < 0:_mgdir = _mgdir + 360
;done
_obj setdir _mgdir
player globalchat format ["MH=%1 NH =%2 DIR= %3",_mainhdg,_newhdg,getdir _obj]
~0.09
goto "searchloop"
#pauze
_newhdg = (_mainhdg + _step - (random _twostep))
_newhdg = (_newhdg mod 360)
?_newhdg < 0:_newhdg = _newhdg + 360
~2 + random 2
goto "searchloop"
-
So Fragorl,
As long as you declare the variable first, then you are safe?
i.e.:
myVar = 0
if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]
if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]
-
Thx, it seems to work but I have to use the loop method because I need the delay and don't know how I can implement that delay in the while-do thingy. (it's chinese 4 me)
I need it for a scripted searchlight script (based on Mgspot.sqs from Sui) using the light of a machinegun. When the player runs through the lightbeam, the gunner sounds the alarm and try to kill you. Once spotted, the light follows whereever you go.
Not really fullproof because it still follows you when you hide behind an obstacle or when you are far away,... I need a LOS script for that. :-\
I have an idea to solve this without a LOS script, but it requires lots of testing.
Thx alot all of you.
-
Well spotted Mr. Peanut. That will teach me not to just dash off a script. Here is a better version:
_change = _newDir - _oldDir
if (abs(_change) > (abs (_change + 360) % 360)) then {_change = (_change + 360) % 360}
if (_change > 180) then {_change = _change - 360}
if (_change < -180) then {_change = _change + 360}
_step = _change/abs(_change)
#loop
_mg setDir ((getDir _mg) + _step)
if (abs((getDir _mg) - _newDir) > abs(_step)) then {goto"loop"}
exit
-
So Fragorl,
As long as you declare the variable first, then you are safe?
i.e.:
myVar = 0
if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]
Exactly. In that situation, you are safe. For both hints, you get out the value '5'. This works identically to java, and is a sensible way to do it when you think about it.
I will make a note in the command reference.
-
A good additon to the knowledge base. I don't know java, but I had come across what I then saw as the problem of not being able to initialise a new variable in an if statement. I had not realised the variable was being created, but only with a very limited scope. I just knew that it didn't exist after the statement so I now intialise them before the if statement, which often has a side effect of not requiring an else caluse. What I started writing as:
if (condition) then {_var = a} else {_var = b}
I now write as:
_var = b
if (condition) then {_var = a}