D34TH Posted April 29, 2017 Share Posted April 29, 2017 Just how much terrain awareness AI has? Could there be any automated way in which AI would consider the terrain details in and around an AO and instead of doing random, more or less tactically meaningful circular patrols to maybe focus (watch, patrol) on the high grounds, the approach routes with cover (forest, buildings, ditches etc) ? Do they know where the roads are ? Link to comment Share on other sites More sharing options...
D34TH Posted May 7, 2017 Author Share Posted May 7, 2017 given the huge potential and the level of enthusiasm on the subject i have taken a suicidal, bold first step into the world of Arma 3 coding with an amazing work designed to find one of the points on the highest elevation contour line around a given coordinate (the player in this case, but why not the center of an AO...) and to spawn a wonderful tower at that amazing bellevue location: Spoiler init = getposatl player; scancircle = 500; accuracy = scancircle*2; flagx = 0; flagy = 0; flagz = 0; maxflagz = 0; _coordinate = []; _tgtcoord = []; i=0; while {i<accuracy} do { dummy = createVehicle ["TargetP_Inf2_F", init, [], scancircle, "NONE"] ; _coordinate = getposasl dummy; diag_log format ["coordinate: %1",_coordinate]; flagx = _coordinate select 0; flagy = _coordinate select 1; flagz = _coordinate select 2; if (flagz > maxflagz) then {maxflagz = flagz; tgtflagx = flagx; tgtflagy = flagy; diag_log format ["newmax elevation coordinate is : %1 , %2 , %3",tgtflagx, tgtflagy, maxflagz]; }; deletevehicle dummy;i=i+1; }; _tgtcoord = [tgtflagx,tgtflagy,maxflagz]; diag_log format ["FINAL max elevation coordinate is : %1",_tgtcoord]; gg = [tgtflagx,tgtflagy,0]; createVehicle ["Land_TTowerBig_2_F", gg, [], 0, "CAN_COLLIDE"]; my extremely limited coding "abilities" (as demonstrated above; "don't make me regret this") assure me that a much better code to do this task would be a piece of cake for most of you .... my desire would be to write a function designed to find such a "high ground" (or more around an AO) in order to be able to send some AI to patrol there ... maybe a single scan of each map could generate a database of coordinates for that map to be used in a much better approach to coding this task ... ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- *ver1.1 also finds the minimum height coordinate and spawns a hospital there : Spoiler init = getposatl player; scanradius = 300; accuracy = scanradius*2; flagx = 0; flagy = 0; flagz = 0; maxflagz = 0; minflagz = 4000; _coordinate = []; _tgtcoord = []; _tgtmincoord = []; i=0; while {i<accuracy} do { dummy = createVehicle ["Land_PowerPoleWooden_small_F", init, [], scanradius, "NONE"] ; _coordinate = getposasl dummy; flagx = _coordinate select 0; flagy = _coordinate select 1; flagz = _coordinate select 2; if (flagz > maxflagz) then {maxflagz = flagz; tgtflagx = flagx; tgtflagy = flagy;} else {if (flagz >0 && flagz < minflagz) then {minflagz = flagz; tgtminx = flagx; tgtminy = flagy; }; deletevehicle dummy; i=i+1; }; }; _tgtcoord = [tgtflagx,tgtflagy,maxflagz]; _tgtmincoord = [tgtminx,tgtminy,minflagz]; diag_log format ["FINAL max elevation coordinate is : %1",_tgtcoord]; diag_log format ["FINAL min elevation coordinate is : %1",_tgtmincoord]; gg = [tgtflagx,tgtflagy,0]; ggmin = [tgtminx,tgtminy,0]; createVehicle ["Land_TTowerBig_2_F", gg, [], 0, "CAN_COLLIDE"]; createVehicle ["Land_Hospital_main_F", ggmin, [], 0, "CAN_COLLIDE"]; Link to comment Share on other sites More sharing options...
D34TH Posted May 8, 2017 Author Share Posted May 8, 2017 waypoints coordinates generator for patrolling high ground 1000m around an area: Spoiler init = getposatl player; j=30; flagx = 0; flagy = 0; flagz = 0; maxflagz = 0; _coordinate = []; _tgtcoord = []; while {j<1001} do { i=0; accuracy = j/10; while {i<accuracy} do { dummy = createVehicle ["Land_PowerPoleWooden_small_F", init, [], j, "NONE"] ; _coordinate = getposasl dummy; flagx = _coordinate select 0; flagy = _coordinate select 1; flagz = _coordinate select 2; if (flagz > maxflagz) then {maxflagz = flagz; tgtflagx = flagx; tgtflagy = flagy;}; deletevehicle dummy; i=i+1; }; _tgtcoord = [tgtflagx,tgtflagy,maxflagz]; diag_log format ["high elevation waypoint coordinates : %1",_tgtcoord]; gg = [tgtflagx,tgtflagy,0]; createVehicle ["Land_TTowerBig_2_F", gg, [], 0, "CAN_COLLIDE"]; j=j+30; }; waypoints coordinates generator for patrolling low ground (valley) 1000m around an area: Spoiler init = getposatl player; j=30; flagx = 0; flagy = 0; flagz = 0; minflagz = 9000; _coordinate = []; _tgtmincoord = []; while {j<1001} do { i=0; accuracy = j/10; while {i<accuracy} do { dummy = createVehicle ["Land_PowerPoleWooden_small_F", init, [], j, "NONE"] ; _coordinate = getposasl dummy; flagx = _coordinate select 0; flagy = _coordinate select 1; flagz = _coordinate select 2; if (flagz >0 && flagz < minflagz) then {minflagz = flagz; tgtminx = flagx; tgtminy = flagy; }; deletevehicle dummy; i=i+1; }; _tgtmincoord = [tgtminx,tgtminy,minflagz]; diag_log format ["low elevation waypoint coordinates: %1",_tgtmincoord]; ggmin = [tgtminx,tgtminy,0]; createVehicle ["Land_TTowerBig_2_F", ggmin, [], 0, "CAN_COLLIDE"]; j=j+30; }; Link to comment Share on other sites More sharing options...
Jochem Posted May 8, 2017 Share Posted May 8, 2017 Let me just say: great job so far! Since I personally think programmers should encourage and help each other, especially if someone's starting out, here's some tips: Avoid spawning objects when not it's not needed. It is one of the most expensive (read performance hitting) things a script can do. Always uses local variables instead of global ones when you can (_variable is local, variable is global). It's more secure and will prevent weird things from happening. Don't interpret these tips as something you should be ashamed of, I'm really quite impressed you managed to write something like this seeing you just started out. If it can help you, this code finds the heighest point in the given radius with 10m accuracy (altough it actually searches a square of that size not a circle) and is around 83x faster (42ms vs 3500ms execution time) when executed with a radius to search of 1000m: Spoiler _pos = getPos player; _radius = 1000; _highestPos = [0,0,0]; _highestHeight = 0; _posX = 0; _posY = 0; _startPos = (_pos getPos [245, 0]) getPos [245, -90]; _currentPos = _startPos; while{_posY < _radius}do{ while{_posX < _radius}do{ if(getTerrainHeightASL _currentPos > _highestHeight)then{ _highestHeight = getTerrainHeightASL _currentPos; _highestPos = _currentPos; }; _currentPos = _currentPos getPos [10,90]; _posX = _posX + 10; }; _posY = _posY + 10; _posX = 0; player setPos _startPos; _currentPos = _startPos getPos [_posY,-180]; }; player setPos _highestPos; Don't let that discourage you though. Nobody learns programming on a day and optimization will come naturally over time. I'm interested to see what you'll do next, keep up the good work! SkullCollector, Amentes and D34TH 3 Link to comment Share on other sites More sharing options...
D34TH Posted May 8, 2017 Author Share Posted May 8, 2017 @Jochem thank you ! i didn't know about getterrainheight ... spawning the objects was part for visual fun in the editor, part cause i only knew about getpos for player / object, and yes it froze the pc for some seconds ; using local variables was not an issue in the editor but i know it must be done if the code is to be used anywhere else. I am not a programmer ... so i am not ashamed ... it is just fun for me trying to understand how coding works in Arma ... and maybe, one day, help to see AI do more than circular random patrols as if unaware of any tactical value of the terrain topology and features around them. Thank you again for the kind words, the advice and the 83x faster code ! tiny question: is there any function similar to getTerrainheight to scan if a given area has vegetation, trees, rocks, water, constructions or roads on it ? Link to comment Share on other sites More sharing options...
Ryko Posted May 8, 2017 Share Posted May 8, 2017 I don't think there is a function for that: you can use nearObjects and scan for the general class names of what you're looking for. This will do everything but roads, for which you will need to use nearRoads. D34TH 1 Link to comment Share on other sites More sharing options...
D34TH Posted May 9, 2017 Author Share Posted May 9, 2017 @Jochem i'm getting better (20 ms) ... thank you again ! Spoiler _radius=1000; _r=10; _highestpos=[0,0,0]; _highestz = 0; _startpos = getpos player; while {_r<_radius} do { _ang=0; while {_ang<360} do { _currentpos = player getpos [_r,_ang]; _currentz = getTerrainHeightASL _currentpos; if (_currentz > _highestz) then { _highestz = _currentz; _highestpos = _currentpos;}; _ang = _ang + (360/(4+0.032*_r)); }; _r = _r + 10; }; player setPos _highestPos; Link to comment Share on other sites More sharing options...
Jochem Posted May 9, 2017 Share Posted May 9, 2017 For the terrain objects like trees and rocks: https://community.bistudio.com/wiki/nearestTerrainObjects Amazing work with the new version, I'm impressed you managed to cut off half the execution time. When I'm home I might try one of your suggestions about indexing the map at the start of the mission. I'm not very optimistic about it but we'll see, 20ms is a hard time to beat. Link to comment Share on other sites More sharing options...
D34TH Posted May 9, 2017 Author Share Posted May 9, 2017 Truth is i have inadvertently cheated at the long ranges accuracy since it is searching in arcs ... Spoiler if you replace _ang = _ang + (360/(4+0.032*_r)); with _ang = _ang + (360/(0.201*_r)); you look at a truer 10m accuracy with (10,000 measurements at 1000m similar to the squares method) with 80ms execution time I'll try an (archimede) spiral instead of multiple circles to see if it gets faster. About indexing the map i thought it was a good idea at the time only because i didn't know about getTerrainHeight , but since it exists there should already be a map coord database where it searches the heights... or it works in some other way ... thx ! Link to comment Share on other sites More sharing options...
D34TH Posted May 9, 2017 Author Share Posted May 9, 2017 did some further testing also with a random Spoiler _counter=0; _radius=1000; _npix=_radius^2/100; _i=1; _highestpos=[0,0,0]; _highestz = 0; _startpos = getpos player; while {_i<_npix} do { _counter = counter +1; _currentpos = player getpos [10+random _radius , random 360]; _currentz = getTerrainHeightASL _currentpos; if (_currentz > _highestz) then { _highestz = _currentz; _highestpos = _currentpos; }; _i = _i + 1; }; player setPos _highestPos; a spiral method Spoiler _counter=0; _acc=10010; _radius=1000 _r=10; _highestpos=[0,0,0]; _highestz = 0; _startpos = getpos player; while {_r<_acc} do { _counter = counter +1; _currentpos = player getpos [_r/(_acc/_radius),36*_r]; _currentz = getTerrainHeightASL _currentpos; if (_currentz > _highestz) then { _highestz = _currentz; _highestpos = _currentpos;}; _r = _r + 1; }; player setPos _highestPos; and circles at 10m accuracy Spoiler _counter =0; _radius=1000; _r=10; _highestpos=[0,0,0]; _highestz = 0; _startpos = getpos player; while {_r<_radius} do { _ang=0; while {_ang<360} do { _counter = counter +1; _currentpos = player getpos [_r,_ang]; _currentz = getTerrainHeightASL _currentpos; if (_currentz > _highestz) then { _highestz = _currentz; _highestpos = _currentpos;}; _ang = _ang + (360/(0.201*_r)); }; _r = _r + 10; }; player setPos _highestPos; and the results at 1000m, 10m accuracy were: square :65ms circles: 88ms random: 76ms spiral: 94ms Link to comment Share on other sites More sharing options...
Jochem Posted May 10, 2017 Share Posted May 10, 2017 (edited) Tried indexing the map, like I expected didn't work nearly as fast as the other solutions (for a 1000m radius). Also did some optimizing of my first code, runs around 38% faster (29ms vs 41ms) Spoiler _pos = getPosWorld player; _radius = 1000; _highestPos = [0,0,0]; _highestHeight = 0; _posX = 0; _posY = 0; _startPos = (_pos getPos [245, 0]) getPos [245, -90]; _currentPos = _startPos; for "_posY" from 10 to _radius step 10 do{ for "_posX" from 10 to _radius step 10 do{ if(getTerrainHeightASL _currentPos > _highestHeight)then{ _highestHeight = getTerrainHeightASL _currentPos; _highestPos = _currentPos; }; _currentPos = _currentPos getPos [10, 90]; }; _currentPos = _startPos getPos [_posY, -180]; }; Edited May 10, 2017 by Jochem Code fix D34TH 1 Link to comment Share on other sites More sharing options...
D34TH Posted May 10, 2017 Author Share Posted May 10, 2017 @ JOCHEM, nice, but why start it at(-245,+245) from the player position ? _startPos = [(_pos select 0) - 245,(_pos select 1) + 245,0]; ? need a bit of help with this one as i am trying to get the parachute removed and the backpack on back only after the landing .... : Spoiler _z=500; [player, (player call removebackpackback)] call setbackpackonchest; player addbackpack "B_Parachute"; player setpos [getpos player select 0,getpos player select 1,_z]; sleep 5; waitUntil {getposatl player select 2 < 1}; player call removebackpackback; [player, (player call removebackpackchest)] call setbackpackonback; the sleep 5 and waituntil do not work as intended ... Link to comment Share on other sites More sharing options...
Jochem Posted May 10, 2017 Share Posted May 10, 2017 Nah, I broke it apperently, fixed the code in the post above. 245 = ((_radius/2) - 5) It get's the uppder right corner of the square. I was a bit lazy and harcoded it in, but you can replace it with ((_radius/2) - 5). For your script, make it like this: []spawn{ _z=500; [player, (player call removebackpackback)] call setbackpackonchest; player addbackpack "B_Parachute"; player setpos [getpos player select 0,getpos player select 1,_z]; sleep 5; waitUntil {getposatl player select 2 < 1}; player call removebackpackback; [player, (player call removebackpackchest)] call setbackpackonback; } https://community.bistudio.com/wiki/sleep You dicovered scheduled and unscheduled execution, welcome to the complications of ArmA scripting. Link to comment Share on other sites More sharing options...
D34TH Posted May 10, 2017 Author Share Posted May 10, 2017 thank you! it works now Link to comment Share on other sites More sharing options...
D34TH Posted May 10, 2017 Author Share Posted May 10, 2017 off-topic, just for fun self paradrop with chestpack swap to back after landing: Spoiler []spawn{ _z=500; [player, (player call removebackpackback)] call setbackpackonchest; player addbackpack "B_Parachute"; player setpos [getpos player select 0,getpos player select 1,_z]; waitUntil {istouchingground player}; player call removebackpackback; [player, (player call removebackpackchest)] call setbackpackonback; }; paradrop eject with auto chestpack swap to back after landing (this would be nice as an action menu ...) Spoiler []spawn{ [player, (player call removebackpackback)] call setbackpackonchest; player addbackpack "B_Parachute"; player action ["eject",vehicle player]; waitUntil {istouchingground player}; player call removebackpackback; [player, (player call removebackpackchest)] call setbackpackonback; }; and safety parachute, for accidental ejection, detects ejection(keyboard), player falling and gives parachute, with auto open Spoiler []spawn{ waitUntil {inputAction "eject">0}; _i=getposasl player select 2 ; sleep 1; _f=getposasl player select 2 ; if ((_i-_f) > 2) then { [player, (player call removebackpackback)] call setbackpackonchest; player addbackpack "B_Parachute"; waituntil {getposasl player select 2 < 160}; player action ["OpenParachute", player]; waitUntil {istouchingground player}; player call removebackpackback; [player, (player call removebackpackchest)] call setbackpackonback; }; }; Link to comment Share on other sites More sharing options...
Miczils Posted May 11, 2017 Share Posted May 11, 2017 I think maybe @Ryko may want to look at those, no idea how that would affect the stability tho. Link to comment Share on other sites More sharing options...
D34TH Posted May 11, 2017 Author Share Posted May 11, 2017 If you start/ stop the para auto ejection script from an ASL action menu (auto para on/off) you only use resources when needed, give each player para eject action menu only when ASL sets it on and gain alot of time from not taking a parachute from the arsenal and not having to swap backpacks at the arsenal and after landing. Plus ASL could decide a paradrop action on the fly if needed. Would be like gearing up while in the air vehicle..... If you use the safety para script you wouldn't even have to add an action menu for each player, just the on/off for the ASL...i can only test the scripts on local unfortunately. Link to comment Share on other sites More sharing options...
Lost Bullet Posted May 11, 2017 Share Posted May 11, 2017 I really like those ideas, specially the give ASL the control over when to paradrop, in Gauntlet that could be easily implemented with the control being given to the pilot of the aircraft and when the action was performed everyone except pilot and co-pilot would be ejected from the helicopter/plane. That could even give the cool effect of the sequencial paradrop by forcing the eject with a given interval (e.g. every 0.5s) and forcing the parachute to open after a certain time (I can already imagine the cinematics of that!). Excellent ideas @D34TH Link to comment Share on other sites More sharing options...
Ryko Posted May 11, 2017 Share Posted May 11, 2017 Nice scripting, but I don't want to add magical solutions to problems which are due to a player simply not wanting to take the time to prepare. Link to comment Share on other sites More sharing options...
Lost Bullet Posted May 11, 2017 Share Posted May 11, 2017 5 minutes ago, Ryko said: Nice scripting, but I don't want to add magical solutions to problems which are due to a player simply not wanting to take the time to prepare. The part of the automatic parachute I agree with you, but having the control of when to eject given to the pilot (for example) would be awesome for a correct dropzone Link to comment Share on other sites More sharing options...
Ryko Posted May 11, 2017 Share Posted May 11, 2017 It'd also be ripe for abuse to force eject players. Link to comment Share on other sites More sharing options...
D34TH Posted May 11, 2017 Author Share Posted May 11, 2017 It takes away some of the realism, i agree. Being able to put backpack on chest and take a parachute from the inventory of an air vehicle while in flight would be another story Link to comment Share on other sites More sharing options...
D34TH Posted May 12, 2017 Author Share Posted May 12, 2017 @Jochem I could use some help when/if you find the time as i got steam coming out of my ears on this one ... Spoiler []spawn{ _excess = 10; _radius=50; _counter =0; while {_counter<_excess} do { waituntil {inputaction "pushtotalk">0}; _counter=(_counter +1); hint format ["radio counter %1", _counter ]; sleep 1; }; playsound "electricity_loop"; _pos = getPosWorld player; _highestPos = [0,0,0]; _highestHeight = 0; _posX = 0; _posY = 0; _startPos = (_pos getPos [_radius/2-5, 0]) getPos [_radius/2-5, -90]; _currentPos = _startPos; for "_posY" from 10 to _radius step 10 do{ for "_posX" from 10 to _radius step 10 do{ if(getTerrainHeightASL _currentPos > _highestHeight)then{ _highestHeight = getTerrainHeightASL _currentPos; _highestPos = _currentPos; }; _currentPos = _currentPos getPos [10, 90]; }; _currentPos = _startPos getPos [_posY, -180]; }; _grp = createGroup east; _snipercover =[]; for "_i" from 1 to 10 step 1 do{ _snipercover = createVehicle ["Land_Grave_dirt_F",_highestpos, [], 15, "none"]; }; _sniper = _grp createUnit ["O_T_sniper_F", getposatl _snipercover, [], 0, "can collide"]; _sniper setunitpos "auto"; _sniper setcombatmode "red"; _sniper setbehaviour "stealth"; _sniper dowatch getpos player; _sniper dotarget player; _sniper setskill 0.9; } counts number of "radio" transmissions and/or number of seconds as trigger (*atm i could only do it to work for the vanilla "TAB" key PushToTalk) and once _excess (10 sec and/or transmissions) is reached gives a sound warning and spawns a sniper and some "cover" for him at a high ground, at a distance of _radius (50m but could go up to 1000m) from player. Spoiler The plan was: 1 find ASL player, check if near AO 2 trigger excessive radio chatter, +/-give subtle warning to ASL 3 find high position to spawn a sniper 4 spawn sniper and some _snipercover at high position and make him "smart" and join the action 5 after 5 min remove sniper if not dead and the _snipercover obj created 6 reset radio chatter counter and make the script loop 1 i didn't try yet 2 its done but only for "vanilla PushToTalk" 3 its done / could be refined 4 done / still needs refinement to make the sniper smarter 5,6 i tried but did not manage to get it to work (*the counter hint is in there just for testing/debug) Link to comment Share on other sites More sharing options...
Jochem Posted May 14, 2017 Share Posted May 14, 2017 I knocked myself out, the code is a bit more complex, but I kept all the code in one file: Spoiler cs_spawnSniper = { //Pos needs to be in PositionAGL params["_pos","_target"]; //Create sniper _grp = createGroup east; _sniper = _grp createUnit ["O_T_sniper_F", _pos, [], 10, "FORM"]; _sniper setUnitPos "down"; _sniper setCombatMode "red"; _sniper setBehaviour "stealth"; //Sniper now knows about the target _sniper reveal [_target,4]; //Sniper will engage target _sniper doTarget _target; _sniper setSkill 0.9; }; cs_getHighestPos = { params["_pos","_radius"]; _highestPos = [0,0,0]; _highestHeight = 0; _posX = 0; _posY = 0; _startPos = (_pos getPos [(_radius/2)-5, 0]) getPos [(_radius/2)-5, -90]; _currentPos = _startPos; for "_posY" from 10 to _radius step 10 do{ for "_posX" from 10 to _radius step 10 do{ if((getTerrainHeightASL _currentPos > _highestHeight) && (west countSide (_currentPos nearEntities 250) == 0))then{ _highestHeight = getTerrainHeightASL _currentPos; _highestPos = _currentPos; }; _currentPos = _currentPos getPos [10, 90]; }; _currentPos = _startPos getPos [_posY, -180]; }; _highestPos; }; cs_init = { //https://community.bistudio.com/wiki/remoteExecCall { //https://github.com/michail-nikolaev/task-force-arma-3-radio/wiki/API%3A-Events ["DetectLRTraffic", "OnTangent", { params["_unit","_notUsed","_radioType"]; if(_radioType == 1)then{ if(player getVariable["LRIsSpeaking",false])then{ player setVariable["LRIsSpeaking",false,true]; player setVariable["LRTransmissionTime", ((player getVariable["LRTransmissionTime",0]) + (diag_tickTime - (player getVariable["LRStartedSpeaking",0]))), true]; player setVariable["LRStartedSpeaking",0,true]; }else{ player setVariable["LRIsSpeaking",true,true]; player setVariable["LRStartedSpeaking",diag_tickTime,true]; }; }; }, player] call TFAR_fnc_addEventHandler; } remoteExecCall ["bis_fnc_call", 0, true]; [{ { if(player getVariable["LRTransmissionTime",0] >= 10)then{ _posSniper = [getPosATL player,1000]call cs_getHighestPos; [_posSniper, player]call cs_spawnSniper; player setVariable["LRTransmissionTime",0,true]; }; } forEach allPlayers; } , 1, []] call CBA_fnc_addPerFrameHandler; }; The main thing about this is that it works in both SP/MP (altough for pure MP use some slight adjustments should be made for performance), is JIP compatible and doesn't contain any scheduled code (spawn, execVM). If you want to test it paste the code in a file (i.e. sniper.sqf) in the mission folder and execute these two lines: Spoiler call compile preprocessFileLineNumbers "sniper.sqf"; []call cs_init; D34TH 1 Link to comment Share on other sites More sharing options...
D34TH Posted May 14, 2017 Author Share Posted May 14, 2017 @Jochem I didn't test it yet but thank you ! I owe you some beers on this one ... Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now