Jump to content
Sign in to follow this  
clock_x

Script errors with findBody script

Recommended Posts

I've been messing with Arma stuff since OPF 2001 and still know next to nothing, if you do get A3 there is a lot more help with some very clever people.

 

You can sort of make AI forget in A2, I found if you  ungroup a unit then have it join another group it will reset it's target as long as the target is no longer visible.

But if you have waypoints it will forget those as well and doing it for a whole group is difficult, unit disableAI "Target" or "AutoTarget"  will limit them to what they see rather than hear.

When shooting starts you restore them back to original settings 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

In OPF I only bothered to build fancy bunkers and let AI fight each other and then bomb everything with a simple airstrike or artillery script.  😀

 

Managed to get this one again:

Error in expression
<+ [_x, Eagle1, Eagle2] };}  foreach ( nearestObjects [vehicle _deadguy, ["Man">
  Error position: <nearestObjects [vehicle _deadguy, ["Man">
  Error 0 elements provided, 3 expected
File D:\Eigene Dateien\Documents\ArmA 2\missions\OP%20GECKOHUNT%20v3%2e0%2e9%20Final.Takistan\scripts\alarm\FindBody.sqf, line 50

For this part:
 

if (!alive _x) then { _remove = _remove + [_x, Eagle1, Eagle2] };

}  foreach ( nearestObjects [vehicle _deadguy, ["Man"], 100]);// ERROR HERE / LINE 50

_finders = nearestObjects [vehicle _deadguy, ["Man"], 100] - _remove;

player globalChat format ["Findbody.sqf - deadguy:%1 finders:%2" ,_deadguy, _finders];

 

Share this post


Link to post
Share on other sites

I don't have time right now but the error is because _deadguy doesn't exist.

 

example using the following code with a _deadguy the code works but delete _deadguy it and you get the error.

hint str (nearestObjects [vehicle _deadguy, ["Man"], 100]);

Share this post


Link to post
Share on other sites

Ah I see, makes sense. There is a good chance I got this error after I hid(deleted) a body.

Going to try this then:

{
if (!isnull(_x) && {!alive _x} ) then { _remove = _remove + [_x, Eagle1, Eagle2] };

} foreach ( nearestObjects [vehicle _deadguy, ["Man"], 100]);

_finders = nearestObjects [vehicle _deadguy, ["Man"], 100] - _remove; 

 

Edit: Doing this made the same error appear later on in:

{

if (!isnull(_x) && {!alive _x} ) then { _remove = _remove + [_x, Eagle1, Eagle2] };

}  foreach ( nearestObjects [vehicle _deadguy, ["Man"], 50]);

_spotters = nearestObjects [vehicle _deadguy, ["Man"], 50] - _remove;

Changed it to:


{

if (!isnull(_x) && {!alive _x} ) then { _remove = _remove + [_x, Eagle1, Eagle2] };

}  foreach ( nearestObjects [vehicle finder, ["Man"], 50]);

_spotters = nearestObjects [vehicle finder, ["Man"], 50] - _remove;

Haven't gotten the error since.

Share this post


Link to post
Share on other sites

yea you still get the first error (_deadguy) because the nearestobjects is executed outside of the foreach so changing the if statement will have no effect the error has happened.

Changing to finder look like it should work as long as it always exist.

 

I did think of finding the [x,y,z] of dead guy at beginning of script and storing it in an array and then use that for the position. 

Share this post


Link to post
Share on other sites

_deadguypos = getPosATL _deadguy;

 

{ if (!isnull(_x) && {!alive _x} ) then { _remove = _remove + [_x, Eagle1, Eagle2] };

} foreach ( nearestObjects [_deadguypos , ["Man"], 50]);

_spotters = nearestObjects [_deadguypos , ["Man"], 50] - _remove;

 

Like this?

Share this post


Link to post
Share on other sites

That looks like it shoiuld work, I also see another issue with the  _x domove getopos  _deadguy I would change that again in case _deadguy is deleted

Share this post


Link to post
Share on other sites

Soo the position thing was a very good idea. Replaced all the getpos _deadguy lines with _deadguypos. Works good!

I had a few other problems. If there were more than one _finders it got kinda stuck until one specific unit went to the position. If there were alot it went on for a while or went completely stuck.

I added another distance query:

               _x move _deadguypos;
              if (_x distance _deadguypos < 4) then { finder = _x; };

Seems to work alot better now, only tested once tho, need some sleep. 😀

 

Another thing was, agents got into _finders and _spotters. I added this:

if (!isnull(_x) && {!alive _x} && {_deadguyside != side _x} ) then { _remove = _remove + [_x, Eagle1, Eagle2] };

 

And a few other minor changes like adding !isNull and fixing a bug: _deadguyside != side _x changed to-> _deadguyside == side _x, dunno how I got this wrong.

 

Here is the full script up to date:

Spoiler

/*
OPFOR, once
condition: this
name : EHlist
EHlist = thislist;
{_x addEventHandler ["killed",{_this execVM "FindBody.sqf"}]} forEach EHlist;
also note use of -- {_x addEventHandler ["fired",{alarm = true}]} forEach EHlist;

Author base code: Laggy
Improvement of base code: palyarmerc
Extensions for 'geckohunt': clockx
Helped with improvements: f2k sel
*/

_deadguy = _this select 0;
_killer = _this select 1;
_numsidedeadguy = getNumber (configFile >> "CfgVehicles" >> typeOf _deadguy  >> "side");
_deadguypos = getPosATL _deadguy; 
_finders = [];
_remove = [];

_deadguyside = [EAST,WEST,RESISTANCE,CIVILIAN] select _numsidedeadguy;
_killerside = side _killer;

_deadguy spawn { sleep 60; if (!isNull _this) then {_Body_Vultures = [_this] execVM "scripts\crows\BodyVultures.sqf";};sleep 300;if (!isNull _this) then {deleteVehicle _this };};

					   if (mein_debug>0) then {  
                player globalChat format ["FindBody.sqf - deadguy:%1 killer:%2 deadguyside:%3 killerside:%4", _deadguy, _killer, _deadguyside, _killerside];
                       };
					   
if (_deadguy in FBList) exitWith {
sleep 1;
detected = true; 
{_x setbehaviour "COMBAT";
sleep 5;
_x reveal [player, 0.5];
} foreach FBlist;
if (mein_debug>0) then {player globalChat format ["FindBody.sqf - deadguy:%1 in FeruzAbad.", _deadguy];};
};
					  
					   
	sleep 5;				   

while { ((_deadguyside != _killerside) AND !(alive _deadguy) AND !(preAlarm) AND !(alarm) AND !(isNull _deadguy) AND (side _killer == west) AND (_deadguyside == east)) } do
{

//sleep 1;				   

{

if (!isnull(_x) && {!alive _x} && {_deadguyside != side _x} ) then { _remove = _remove + [_x, Eagle1, Eagle2] };// fliter out unwanted stuff and place in an array

}  foreach ( nearestObjects [_deadguypos, ["Man"], 100]);//this is the array were looking through (_finders)

_finders = nearestObjects [_deadguypos, ["Man"], 100] - _remove;// should remove all deadunits however many and player

player globalChat format ["Findbody.sqf - deadguy:%1 finders:%2" ,_deadguy, _finders];// retruns all units - deadguy and player
 
   
   if (count _finders > 0) then
   {
      {
         if ((_x != vehicle _deadguy) AND (alive _x) AND (_deadguyside == side _x)) then
         {
            if ((_x knowsAbout vehicle _deadguy > 0.4)) then
            {
				
               _x move _deadguypos; 
			  if (_x distance _deadguypos < 4) then { finder = _x; };
			   
            };

         };
      } forEach _finders;
         

  };

sleep 5;
if (!isNil ('finder') && {!isNull finder}) then {
                      
if ((!isNull _deadguy) AND (alive finder) AND (finder distance _deadguy < 4)) then { 

if (mein_debug>0) then { player globalChat format ["FindBody.sqf - deadguy:%1 finder:%2", _deadguy, finder]; };
finder setunitpos "middle";
finder disableAI "MOVE";
finder reveal [player, 0.5]; //NEW WIP
preAlarm = true;
sleep 5;
if (!detected) then {
sleep (floor (random 5));
_shout1 = [leader (group finder), _killer] execVM "scripts\ShoutSound.sqf";
};
if (mein_debug>0) then {player globalChat "FindBody.sqf - AI detected body";};
                       
																				};

};
}; //end of loop

if (!isNil "finder") then {

if (!isnull(finder) && {!alive finder} ) then {finder setunitpos "UP";finder enableAI "MOVE";};	
						


if (preAlarm) then {

{

if (!isnull(_x) && {!alive _x} && {_deadguyside != side _x}) then { _remove = _remove + [_x, Eagle1, Eagle2] };

}  foreach ( nearestObjects [_deadguypos, ["Man"], 50]);

_spotters = nearestObjects [_deadguypos, ["Man"], 50] - _remove;

	 if (mein_debug>0) then { player globalChat format ["FindBody.sqf - deadguy:%1 spotters:%2", finder, _spotters]; };
     preAlarm = false;


    if (finder in EHlistBerg) then 
    {

	
// --------------------------------AA_CAMP---------------------------------------------------------	
	if (finder in (list Nighttime7_1)) then {
   
	if (genOff) then { sleep 30; };
	
									};
// -------------------------------------------------------------------------------------------- 
					
         if (!radioObj) then {sleep (30 + (random 30));} else {sleep (70 + (random 120));};

    };

			


           {
              if ((_x != vehicle _deadguy) AND (alive _x) AND (_deadguyside == side _x) AND (side _x == EAST)) then
              {
                 detected = true;
				 _x setBehaviour "COMBAT"; //NEW
				 
				if (finder distance player < 120 && finder hasWeapon "ItemRadio") then {
				 
				_answer = ["s0", "s01", "s02", "s03", "s04", "s05"] call BIS_fnc_selectRandom;
				finder say3d _answer;			 
				 
																						};
																					

if (!action) then {
		KRON_UPS_reinforcement3 = true;
		KRON_UPS_reinforcement3_pos = _deadguypos;
					};
		
									
  if (mein_debug>0) then { player globalChat format ["FindBody.sqf - KRON_UPS_reinforcement3_pos - deadguy:%1", _deadguy];};
												

         if (radioObj) then {

		KRON_UPS_reinforcement0 = true; 
		KRON_UPS_reinforcement0_pos = _deadguypos;

							if (mein_debug>0) then { 
  player globalChat format ["FindBody.sqf - KRON_UPS_reinforcement0_pos - deadguy:%1", _deadguy];
												};
			     };


		sleep 60;
        _x setBehaviour "AWARE"; //NEW

		if !(isNull _deadguy) then {

				deleteVehicle _deadguy;
				
				                if (mein_debug>0) then {player globalChat "FindBody.sqf - Deleting Body after detected";};
				
									};

              } else {if (mein_debug>0) then {player globalChat format ["FindBody.sqf - deadguy:%1 - all spotters:%2 dead", _deadguy, _spotters];};};
           } forEach _spotters;
		   
                   } else {
				   
				   sleep 120; 
				   
				   if (!isNull _deadguy) then { 
				   
				   deleteVehicle _deadguy; 				   
				   if (mein_debug>0) then {player globalChat "FindBody.sqf - Deleting Body after !preAlarm";};
				   
											};
				   
							};		
} else {

				   sleep 120;
				   
				   if (!isNull _deadguy) then { 
				   
				   deleteVehicle _deadguy; 				   
				   if (mein_debug>0) then {player globalChat "FindBody.sqf - Deleting Body after isNil finder";};
				   
											};
											
		};					
				
                if (mein_debug>0) then {player globalChat "FindBody.sqf - END of script";};
				sleep 5;
                if (!isNil "_shout1") then {terminate _shout1;};      
									

 

 

Share this post


Link to post
Share on other sites

Can't see how agents gets in, as were only looking for "man"  strange.

you shouldn't need any  !(alive _deadguy)  references as the EVH only fires if he's dead so it is redundant.

I do notice you have one more _deadguy that needs replacing

 

if ((!isNull _deadguy) AND (alive finder) AND (finder distance _deadguy < 4)) then {

 

One thing I don't like is using several nearestobjects commands inside the while loop they are quite slow commands especially if there are a lot of units around.

I wonder if it would work if they were done before the while and then just use the results.

Share this post


Link to post
Share on other sites

Gonna try this but I think I need to up the range to 200 or something to make sure there are enough around, that could be a problem, because if too many are around, it get's too crowded.

Something else that could happen is pats from outside the range walk in and right over the deadguy and nothing happens, which would look really strange.

 

I removed the !alive _deadguy condition and changed the distance thing to _deadguypos.

 

I'm thinking how I can change this line(141) too:

if ((_x != vehicle _deadguy) AND (alive _x) AND (_deadguyside == side _x) AND (side _x == EAST)) then

Or if I even need to change it. Like what happens if _deadguy is null and it asks if the finder is not the deadguy. I guess it should be true? Maybe I don't need to change it then.

On the other hand finder comes from _finders which got all non alive units removed, thus the _deadguy too, in that case I could just delete it.

Share this post


Link to post
Share on other sites

I thought about moving the neareastobjects then realised it needs to be updated within the script or it would only work for units there at death.

I think (_x != vehicle _deadguy)  could be deleted if it's no longer in the array maybe something could be done with (_deadguyside == side _x)

 

in nearestobjects you can also do side check  instead of "man"  you could use "RU_Soldier"  I forget the other base unit names.

All the units returned would be the same side so no need to check them making the array smaller.

 

 

 

Share this post


Link to post
Share on other sites
16 minutes ago, f2k sel said:

I thought about moving the neareastobjects then realised it needs to be updated within the script or it would only work for units there at death.

Yeah..I think I'm gonna leave it as it is. If I'm not wrong I tested this at one point already.

 

I would need to check for TK_INS_Soldier, TK_Soldier and TK_Special_Forces then.

I have some civilians grouped with OFPOR too, so TK_CIV needs to be there too.

{
if (!isnull(_x) && {!alive _x}) then { _remove = _remove + [_x, Eagle1, Eagle2] };
}  foreach ( nearestObjects [_deadguypos, ["TK_INS_Soldier", "TK_Soldier", "TK_Special_Forces", "TK_CIV"], 70]);
_finders = nearestObjects [_deadguypos, ["TK_INS_Soldier", "TK_Soldier", "TK_Special_Forces", "TK_CIV"], 70] - _remove;

So that would mean I could delete the (_deadguyside == side _x) too, if it works.

Edit: Removed: && {_deadguyside != side _x}.

Edit2: Just tested it and I get finders:[].

Maybe I did something wrong?

Share this post


Link to post
Share on other sites

It looks right but not knowing how the sides are set up I can't say for sure, sometimes things aren't worth the effort this may be one of them.

 

one little thing that may make it look a little better would be hidebody before it's deleted

 

_deadguy spawn { sleep 60; _Body_Vultures = [_this] execVM "scripts\crows\BodyVultures.sqf";sleep 295;hidebody _this;sleep 5;deletevehicle _this };

 

Basically it just sinks the unit slowly under the ground before being deleted.

Share this post


Link to post
Share on other sites

I added hidebody, looks better!

 

I sometimes still get agents...

{

if (!isnull(_x) && {!alive _x} && {_deadguyside != side _x} ) then { _remove = _remove + [_x, Eagle1, Eagle2] };

}  foreach ( nearestObjects [_deadguypos, ["Man"], 60]);//this is the array were looking through (_finders)

_finders = nearestObjects [_deadguypos, ["Man"], 60] - _remove;

player globalChat format ["Findbody.sqf - deadguy:%1 finders:%2" ,_deadguy, _finders];

That means some of the agents are units which are east?! Don't know what else I can do about it.

One other thing that never really worked in all my alarm scripts is that the shoutsound.sqf doesn't get terminated.

It's called

_shout1 = [leader (group finder), _killer] execVM "scripts\ShoutSound.sqf";

_shout2 = [leader (group finder), _killer] execVM "scripts\ShoutSound.sqf";

_shout3 = [leader (group finder), _killer] execVM "scripts\ShoutSound.sqf";

_shout4 = [leader (group finder), _killer] execVM "scripts\ShoutSound.sqf";

in the different scripts. And at the end of each script I got:

if (!isNil "_shout1") then {terminate _shout1;};   

But when for example the findbody script ends after the everything triggered the unit still continues to shout.

 

Here is my shoutsound.sqf:

Spoiler

//_shout1 = [_unit, _target] execVM "scripts\ShoutSound.sqf";
//author base code:Rydygier
//changed for ai talk: clockx
// init.sqf ;
// set up your group  variables
// mygroup1 setVariable ["endscript",true];
// mygroup2 setVariable ["endscript",true];//ect
// mygroup will be the original group name whatever your using change to match


_unit = _this select 0;
_target = _this select 1;
_unit_group = group _unit;

//if (!(_unit in (list EHlistBerg_T))) exitWith {player globalChat format ["ShoutSound.sqf - END group: %1 out of bounce", _unit_group];}; //obsolete
 if (isNil {_unit_group getVariable "endscript"}) exitWith {player globalChat format ["ShoutSound.sqf - END - no var defined for %1", _unit_group];};
 
_variable = _unit_group getVariable "endscript";

if (!_variable) exitwith {if (mein_debug>0) then {player globalChat format ["ShoutSound.sqf - END - group: %1 already executing", _unit_group];};};// it looks at the group name and if variable is false it should exit //SCRIPT ERROR _VARIABLE UNDEFINED

_unit_group setVariable ["endscript", false];// set to false to prevent it starting again;


while { ({alive _x} count units (_unit_group) > 0) && ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120)) } do //repeat cycles as long unitis not killed
	{
	
	sleep 1;
	
	_alivecount = ({alive _x} count units _unit_group);


		if (_alivecount == 1) then {
		
				if (50 > random 100) then {
		
  if (mein_debug>0) then {  		
       player globalChat format ["ShoutSound.sqf - group: %1 alive: %2 target: %3", _unit_group, _alivecount, _target];
				          };
										 
					_shouts = 
		[
		["s1",10+(random 20)],
		["s2",10+(random 20)],
		["s3",10+(random 20)],
		["s4",10+(random 20)],
		["s5",10+(random 20)]
		];
		
		while {((count _shouts) > 0) && (_alivecount == 1)} do //internal loop - lasts as long as there is at least one not played yet shout in the playlist
		{
		_selection = floor (random (count _shouts));//random playlist position number
		_shout = _shouts select _selection;//pick random element from _shouts
		_sleep = _shout select 1;//length
		_shout = _shout select 0;//name

		_shouts set [_selection,"Delete"];
		_shouts = _shouts - ["Delete"];//remove for now chosen shout from the playlist, so will be not repeated in this cycle

               

		_shouter = units _unit_group call BIS_fnc_selectRandom;

	if (mein_debug>0) then { 
	player globalChat format ["ShoutSound.sqf - unit:%1 shout: %2 time: %3 shouter: %4 group: %5", _unit, _shout, _sleep, _shouter, _unit_group];
					        };


	if ( ( _shouter == _unit ) && ( _unit hasWeapon "ItemRadio" ) && !(_shouter call ace_sys_wounds_fnc_isUncon)) then { 
	

		_shouter say3d "s17"; _shouter say3d _shout; _shouter say3d "s16"; sleep _sleep; 

								} else {
if !(_shouter call ace_sys_wounds_fnc_isUncon) then {
		_shouter say3d _shout; 
		sleep _sleep; } else { sleep 5; };
	
										};

 



		if (({alive _x} count units (_unit_group) < 1) && ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120))) exitWith {if (mein_debug>0) then {player globalChat format ["ShoutSound.sqf - end"];};};
		};
		
				} else {
				        
						  if (mein_debug>0) then {  		
       player globalChat format ["ShoutSound.sqf - group: %1 alive: %2 target: %3", _unit_group, _alivecount, _target];
				          };
				
													_shouts = 
		[
		["s9",5+(random 25)],
		["s10",5+(random 25)],
		["s11",5+(random 25)],
		["s12",5+(random 25)],
		["s13",5+(random 25)]	
		];
		
		while {((count _shouts) > 0) && (_alivecount == 1)} do //internal loop - lasts as long as there is at least one not played yet shout in the playlist
		{
		_selection = floor (random (count _shouts));//random playlist position number
		_shout = _shouts select _selection;//pick random element from _shouts
		_sleep = _shout select 1;//length
		_shout = _shout select 0;//name

		_shouts set [_selection,"Delete"];
		_shouts = _shouts - ["Delete"];//remove for now chosen shout from the playlist, so will be not repeated in this cycle

               

		_shouter = units _unit_group call BIS_fnc_selectRandom;

	if (mein_debug>0) then { 
	player globalChat format ["ShoutSound.sqf - unit:%1 shout: %2 time: %3 shouter: %4 group: %5", _unit, _shout, _sleep, _shouter, _unit_group];
					        };

	if ( ( _shouter == _unit ) && ( _unit hasWeapon "ItemRadio" ) && !(_shouter call ace_sys_wounds_fnc_isUncon) ) then { 
	

		_shouter say3d "s17"; _shouter say3d _shout; _shouter say3d "s16"; sleep _sleep; 

								} else {

if !(_shouter call ace_sys_wounds_fnc_isUncon) then {
		_shouter say3d _shout; 
		sleep _sleep; } else { sleep 5; };
	
										};




		if (({alive _x} count units (_unit_group) < 1) && ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120))) exitWith {if (mein_debug>0) then {player globalChat format ["ShoutSound.sqf - end"];};};
		};
		
		};
		
		};
		
		
		if (_alivecount == 2) then {
		
		if (50 > random 100) then {

		  if (mein_debug>0) then {  		
       player globalChat format ["ShoutSound.sqf - group: %1 alive: %2 target: %3", _unit_group, _alivecount, _target];
				          };
		
							_shouts = 
		[
		["s1",2+(random 28)],
		["s2",2+(random 28)],
		["s3",2+(random 28)],
		["s4",2+(random 28)],
		["s5",2+(random 28)],
		["s6",2+(random 28)],
		["s14",2+(random 28)],
		["s15",2+(random 28)]		
		];
		
		while {((count _shouts) > 0) && (_alivecount == 2)} do //internal loop - lasts as long as there is at least one not played yet shout in the playlist
		{
		_selection = floor (random (count _shouts));//random playlist position number
		_shout = _shouts select _selection;//pick random element from _shouts
		_sleep = _shout select 1;//length
		_shout = _shout select 0;//name

		_shouts set [_selection,"Delete"];
		_shouts = _shouts - ["Delete"];//remove for now chosen shout from the playlist, so will be not repeated in this cycle

               

		_shouter = units _unit_group call BIS_fnc_selectRandom;

	if (mein_debug>0) then { 
	player globalChat format ["ShoutSound.sqf - unit:%1 shout: %2 time: %3 shouter: %4 group: %5", _unit, _shout, _sleep, _shouter, _unit_group];
					        };

	if ( ( _shouter == _unit ) && ( _unit hasWeapon "ItemRadio" ) && !(_shouter call ace_sys_wounds_fnc_isUncon) ) then { 
	

		_shouter say3d "s17"; _shouter say3d _shout; _shouter say3d "s16"; sleep _sleep; 

								} else {

if !(_shouter call ace_sys_wounds_fnc_isUncon) then {
		_shouter say3d _shout; 
		sleep _sleep; } else { sleep 5; };
	
										};




		if (({alive _x} count units (_unit_group) < 1) && ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120))) exitWith {if (mein_debug>0) then {player globalChat format ["ShoutSound.sqf - end"];};};
		};
		
		} else {

		  if (mein_debug>0) then {  		
       player globalChat format ["ShoutSound.sqf - group: %1 alive: %2 target: %3", _unit_group, _alivecount, _target];
				          };
		
									_shouts = 
		[
		["s9",2+(random 28)],
		["s10",2+(random 28)],
		["s11",2+(random 28)],
		["s12",2+(random 28)],
		["s13",2+(random 28)],
		["s6",2+(random 28)],
		["s14",2+(random 28)],
		["s15",2+(random 28)]		
		];
		
		while {((count _shouts) > 0) && (_alivecount == 2)} do //internal loop - lasts as long as there is at least one not played yet shout in the playlist
		{
		_selection = floor (random (count _shouts));//random playlist position number
		_shout = _shouts select _selection;//pick random element from _shouts
		_sleep = _shout select 1;//length
		_shout = _shout select 0;//name

		_shouts set [_selection,"Delete"];
		_shouts = _shouts - ["Delete"];  //remove for now chosen shout from the playlist, so will be not repeated in this cycle

               

		_shouter = units _unit_group call BIS_fnc_selectRandom;

	if (mein_debug>0) then { 
	player globalChat format ["ShoutSound.sqf - unit:%1 shout: %2 time: %3 shouter: %4 group: %5", _unit, _shout, _sleep, _shouter, _unit_group];
					        };

	if ( ( _shouter == _unit ) && ( _unit hasWeapon "ItemRadio" ) && !(_shouter call ace_sys_wounds_fnc_isUncon) ) then { 
	

		_shouter say3d "s17"; _shouter say3d _shout; _shouter say3d "s16"; sleep _sleep; 

								} else {

if !(_shouter call ace_sys_wounds_fnc_isUncon) then {
		_shouter say3d _shout; 
		sleep _sleep; } else { sleep 5; };
	
										};




		if (({alive _x} count units (_unit_group) < 1) && ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120))) exitWith {if (mein_debug>0) then {player globalChat format ["ShoutSound.sqf - end"];};};
		};
		
		};

		
		};
		
		if (_alivecount > 2) then {
		
		  if (mein_debug>0) then {  		
       player globalChat format ["ShoutSound.sqf - group: %1 alive: %2 target: %3", _unit_group, _alivecount, _target];
				          };
		
			_shouts = 
		[
		["s1",0+(random 30)],
		["s2",0+(random 30)],
		["s3",0+(random 30)],
		["s4",0+(random 30)],
		["s5",0+(random 30)],
		["s6",0+(random 30)],
		["s7",0+(random 30)],
		["s8",0+(random 30)],
		["s9",0+(random 30)],
		["s10",0+(random 30)],
		["s11",0+(random 30)],
		["s12",0+(random 30)],
		["s13",0+(random 30)],
		["s14",0+(random 30)],
		["s15",0+(random 30)]		
		];
		
		while {((count _shouts) > 0) && (_alivecount > 2)} do //internal loop - lasts as long as there is at least one not played yet shout in the playlist
		{
		_selection = floor (random (count _shouts));//random playlist position number
		_shout = _shouts select _selection;//pick random element from _shouts
		_sleep = _shout select 1;//length
		_shout = _shout select 0;//name

		_shouts set [_selection,"Delete"];
		_shouts = _shouts - ["Delete"];//remove for now chosen shout from the playlist, so will be not repeated in this cycle

               

		_shouter = units _unit_group call BIS_fnc_selectRandom;

	if (mein_debug>0) then { 
	player globalChat format ["ShoutSound.sqf - unit:%1 shout: %2 time: %3 shouter: %4 group: %5", _unit, _shout, _sleep, _shouter, _unit_group];
					        };

	if ( ( _shouter == _unit ) && ( _unit hasWeapon "ItemRadio" ) && !(_shouter call ace_sys_wounds_fnc_isUncon) ) then { 
	

		_shouter say3d "s17"; _shouter say3d _shout; _shouter say3d "s16"; sleep _sleep; 

								} else {

if !(_shouter call ace_sys_wounds_fnc_isUncon) then {
		_shouter say3d _shout; 
		sleep _sleep; } else { sleep 5; };
	
										};

 



		if (({alive _x} count units (_unit_group) < 1) && ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120))) exitWith {if (mein_debug>0) then {player globalChat format ["ShoutSound.sqf - end"];};};
		};
		
		};

	};
	
	
// endof script sets it back to true so can run again
_unit_group setVariable ["endscript",true];
	
	if (mein_debug>0) then {player globalChat format ["ShoutSound.sqf - END"];};

 

 

Share this post


Link to post
Share on other sites

I've not had that in any tests, maybe one of your other scripts is creating something

 

example

_agent = createAgent ["SoldierWB", position player, [], 0, "FORM"];

 

I'll have to try it later with some of them around and see what happens. I can't really test shout as I don't have ace but I may be able to find a way to kill it.

 

I did rewrite the whole front end using just one nearestobjects but I'm not sure it will interface correctly with rest of your script and I may have missed something.


 

_deadguy = _this select 0;
_killer  = _this select 1;

_remove  = [];
_finders = [];
_finder  = objnull;
_prealarm = false;
_deadguypos = getpos _deadguy;

_deadguy spawn { sleep 3; _Body_Vultures = [_this] execVM "scripts\crows\BodyVultures.sqf";sleep 20;hidebody _this;sleep 4;deletevehicle _this };// default effect

if (side _deadguy == side _killer) exitwith {hint "sides same"};// side check

while { (!_preAlarm  AND !isnull _deadguy) } do
 { _finders  = [];// clear array for refreshing

     {// foreach nearobjects
       if (alive _x) then {_finders = _finders + [_x]};// build array of alive units
       }  foreach ( nearestObjects [_deadguypos, ["Man"], 100]);// look through units
   
   _finders = _finders - [eagle1,eagle2];// remove elements,
    
     {// foreach )finders
          if (_x knowsAbout vehicle _deadguy > 0.4) exitWith {
                                                            _x domove _deadguypos;
                                                              _finder = _x;
                                                                if (mein_debug>0) then {player globalChat "FindBody.sqf - AI detected body";};
                                                                 _shout1 = [leader (group _finder), _killer] execVM "scripts\ShoutSound.sqf";    
                                                            };//exitwith  ends loop when finds first guy that knows >0.4
     } foreach _finders;// end foreach finders
    
    
    if (!isnull _finder or !alive _finder)  then {waituntil{sleep 1;!alive _finder or _finder distance _deadguypos <4}};// checks finder status
    
    if (!isnull _deadguy and alive _finder) then {  // examine body
             _finder setunitpos "middle";
               _finder disableAI "MOVE";
                _finder reveal [player, 1]; //NEW WIP
                  _preAlarm = true
                  };// changes stance if body found  
     sleep 4;

     };// end while
    
     // rest of code

 

Share this post


Link to post
Share on other sites
Quote

I've not had that in any tests, maybe one of your other scripts is creating something

 

Maybe UPSMON or could be ACE. I don't have any AI addons activated right now like Zeus.

I'll have a look into UPSMON.

I do have a lot of triggers and logics everywhere, some dead animals too. But it's not like I sided them with EAST or something.

I guess the highest possibilty is that ACE creates invisible EAST stuff. I remember Zeus creating targets for the AI to shoot, maybe ACE is doing something in a similar matter.

I have some plants and bushes around from MAP EU which is part of ACE too.

Since I don't get many errors and bugs anymore it won't be long until I start testing the vanilla version, maybe that will shine some light.

 

You don't really need ACE for the shout script.

_shouter call ace_sys_wounds_fnc_isUncon - this is just to check if they are unconsious, can simply be removed I guess.

I extracted soundfiles from arma2:oa for the shouts, just random takistani AI files.

 

The part you rewrote looks promising, but it's gonna be some work to switch it out, I'm gonna give it a try.

One thing that could be missing are more side queries, if units kill themselves by not knowing how to use a parachute or if they die by an explosion the _killer side is civ.

Everything else looks solid with first look.

Share this post


Link to post
Share on other sites

I only wrote it to see if I could tidy it up a little. 

I just tried creating some agents and the although it finds them the script still seems to work around them without any issues.

 

while { ({alive _x} count units (_unit_group) > 0) && _loop and ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120)) } do //repeat cycles as long unitis not killed

 

this seems to be the bit that's doing the looping.

If the finder moves away from the player > 120 it ends.

 

you could try and mod it  like this and see if it helps

 

_loop = true;
while { ({alive _x} count units (_unit_group) > 0) && _loop and ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120)) } do //repeat cycles as long unitis not killed
    {
    _loop=false;
    sleep 1;

Share this post


Link to post
Share on other sites
Quote

this seems to be the bit that's doing the looping.

If the finder moves away from the player > 120 it ends.

Yea I know, I just thought the whole script would still end if I use terminate from another script.

The 120 distance thing is working just fine, it's the hearable range defined for the sounds too so that's why I got this.

I want to terminate it to avoid too many units/groups talking at the same time and to signal the player that the process of him getting detected is over.

The thing is _loop is local and I want to end it from another script (e.g. findbody).

I could work around it with !detected like this:

while { ({alive _x} count units (_unit_group) > 0) && !detected and ((leader (_unit_group) distance _target < 120) OR (leader (_unit_group) distance player < 120)) }

But that's not really the best solution since the alarm scripts can trigger if the player is already detected, for reinforcement positions for example.

Share this post


Link to post
Share on other sites

Ok I see.

 

if (!isNil "_shout1") then {terminate _shout1;};

 

should work   did you define it so it will work outside of the scope where it is created.

 

something like     _shout1 = nil; at benining of script.

 

The problem may be that some variables will not get rest correctly.

Share this post


Link to post
Share on other sites

I added _shout1 = nil; to the beginning of findbody and it worked!

I always forget that there are different scopes inside a single script..

 

Share this post


Link to post
Share on other sites

I tried the cleaned up version.

 

There is one part that is confusing me.

          if (_x knowsAbout vehicle _deadguy > 0.4) exitWith {
                                                            _x domove _deadguypos;
                                                              _finder = _x;
                                                                if (mein_debug>0) then {player globalChat "FindBody.sqf - AI detected body";};
                                                                 _shout1 = [leader (group _finder), _killer] execVM "scripts\ShoutSound.sqf";    
                                                            };//exitwith  ends loop when finds first guy that knows >0.4

This happens always pretty fast. But as I understand it, exitWith exits the while loop and the next important part inside the loop doesn't even happen which is:

 if (!isnull _finder or !alive _finder)  then {waituntil{sleep 1;!alive _finder or _finder distance _deadguypos <4}};// checks _finder status
    
    if (!isnull _deadguy and alive _finder) then {  // examine body
             _finder setunitpos "middle";
               _finder disableAI "MOVE";
                _finder reveal [player, 1];
                  _preAlarm = true
                  };// changes stance if body found 

So pretty much nothing happens after that.

 

 

Quote

The problem may be that some variables will not get rest correctly.

Yes of course!

Basically i need to add group _finder setVariable ["endscript",true]; to the terminate part inside findBody. Seems to work fine.

 

 

And about the agents...

 

if (!isnull(_x) && {!alive _x} && {_deadguyside != side _x} ) then { _remove = _remove + [_x] };

 

I tried this and Eagle1+Eagle2 are returned as finders. But they shouldn't because they are not the same side as the dead guy. So I guess _deadguyside != side _x is simply not working.

Share this post


Link to post
Share on other sites

Your forgetting  that the current scope is the foreach so it exits back to the while 

 

example , this just exits the foreach  when _x is greater than 2 the while continues to loop.

 

while {alive player} do {
    hint str time/60;
       {player sidechat str _x; sleep 1;if (_x > 2)  exitwith {hint "End foreach scope"}} foreach [1,2,3,4,5,6];    
sleep 1;    
    };// end while

Agents are strange, they report as "men" the only command thing |'ve come up with it to build an array of them.

 

Agents returns an odd array which you can't seem to remove them directly form nearestobjects

 

so I build a new array and remove that also note this bit [agent _x]   you need to use the prefix agent

agnt = [];{ agnt = agnt +  [agent _x] } foreach agents;hint str (nearestObjects [thistrigger,["man"],100] - agnt);  //does seem to work

 

so  in your code you would use

agnt = [];

{ agnt = agnt +  [agent _x] } foreach agents;

_finders= _finders - agnt;

 

I'm not sure what happens if deadguy is an agent.

 

Share this post


Link to post
Share on other sites
Quote

Your forgetting  that the current scope is the foreach so it exits back to the while 

Oh right, forEach is it's own scope.

The error was that I didn't change preAlarm to _preAlarm.

 

I did a few tests with various situations and it seems to work fine.

There was a few tests where the AI didn't show much interest in it's dead squadmate.

I think this is happening because UPSMON gives them orders too. (AI is scouting the area running back and forth or running away, fleeing)

Since _x domove _deadguypos; isn't spammed anymore in the loop but rather the loop exits with it, this could be happening more often I guess? If I don't understand anything wrong again.

It happens quiet often(6 out of 10 times), it seems the script only triggers if the deadguy dies right next to his mate or if the unit walks by accident next to him. I could be wrong though, it happened in the old version too but not as often.

 

 

About the agents ... since they don't seem to do any harm, maybe we just let them be. 😀

I did implement the code to remove the agents, didn't get any errors so far, I will see what happens.

 

Here is the updated full script:

 

Spoiler

_deadguy = _this select 0;
_killer  = _this select 1;

_remove  = [];
_finders = [];
_spotters = [];
_finder  = objnull;
_prealarm = false;
_deadguypos = getpos _deadguy;
_shout1 = nil;
agnt = []; //test
{ agnt = agnt +  [agent _x] } foreach agents; //test

_deadguy spawn { sleep 60; _Body_Vultures = [_this] execVM "scripts\crows\BodyVultures.sqf";sleep 300;hidebody _this;sleep 4;deletevehicle _this };// default effect

if (side _deadguy == side _killer OR side _killer == civilian) exitwith {if (mein_debug>0) then { player globalChat format ["FindBody.sqf - _killer:%1 is same side or CIV as _deadguy:%2", _killer, _deadguy]; };};// side check

if (_deadguy in FBList) exitWith {
sleep 1;
detected = true; 
{_x setbehaviour "COMBAT";
sleep 5;
_x reveal [player, 0.5];
} foreach FBlist;
if (mein_debug>0) then {player globalChat format ["FindBody.sqf - deadguy:%1 in FeruzAbad.", _deadguy];};
};

while { (!_preAlarm  AND !isnull _deadguy) } do
 { _finders  = [];// clear array for refreshing

     {// foreach nearobjects
       if (alive _x) then {_finders = _finders + [_x]};// build array of alive units
       }  foreach ( nearestObjects [_deadguypos, ["Man"], 100]);// look through units
   
   _finders = _finders - [eagle1,eagle2,agnt];// remove elements,
   if (mein_debug>0) then { player globalChat format ["FindBody.sqf - _finders:%1", _finders]; };
     {// foreach )_finders
          if (_x knowsAbout vehicle _deadguy > 0.4) exitWith {
                                                            _x domove _deadguypos;
                                                              _finder = _x;
                                                                if (mein_debug>0) then {player globalChat "FindBody.sqf - AI detected body";};
                                                                 _shout1 = [leader (group _finder), _killer] execVM "scripts\ShoutSound.sqf";    
                                                            };//exitwith  ends loop when finds first guy that knows >0.4
     } foreach _finders;// end foreach _finders
    
    if (mein_debug>0) then {player sideChat "1";};
    if (!isnull _finder or !alive _finder)  then {waituntil{sleep 1;!alive _finder or _finder distance _deadguypos <4}};// checks _finder status
   if (mein_debug>0) then { player globalChat format ["2 - _finder:%1", _finder]; };
    if (!isnull _deadguy and alive _finder) then {  // examine body
	    if (mein_debug>0) then {player sideChat "3";};
             _finder setunitpos "middle";
               _finder disableAI "MOVE";
                _finder reveal [player, 1];
                  _preAlarm = true
                  };// changes stance if body found  
     sleep 4;

     };// end while
    
     // rest of code
	 
	 
	 
	 if (!isNil "_finder") then {

if (!isnull(_finder) && {!alive _finder} ) then {_finder setunitpos "UP";_finder enableAI "MOVE";};	
						


if (_preAlarm) then {
/*
{

if (!isnull(_x) && {!alive _x}) then { _remove = _remove + [_x,Eagle1,Eagle2] };

}  foreach ( nearestObjects [_deadguypos, ["Man"], 50]);

_spotters = nearestObjects [_deadguypos, ["Man"], 50] - _remove;
*/
	  {
       if (alive _x) then {_spotters = _spotters + [_x]};// build array of alive units
       }  foreach ( nearestObjects [_deadguypos, ["Man"], 50]);// look through units
   
   _spotters = _spotters - [eagle1,eagle2,agnt];// remove elements,

	 if (mein_debug>0) then { player globalChat format ["FindBody.sqf - _finder:%1 spotters:%2", _finder, _spotters]; };
     _preAlarm = false;


    if (_finder in EHlistBerg) then 
    {

	
// --------------------------------AA_CAMP---------------------------------------------------------	
	if (_finder in (list Nighttime7_1)) then {
   
	if (genOff) then { sleep 30; };
	
									};
// -------------------------------------------------------------------------------------------- 
					
         if (!radioObj) then {sleep (30 + (random 30));} else {sleep (70 + (random 120));};

    };		


           {
              if ((alive _x) AND (side _x == EAST)) then
              {
                 detected = true;
				 _x setBehaviour "COMBAT"; //NEW
				 
				if (_finder distance player < 120 && _finder hasWeapon "ItemRadio") then {
				 
				_answer = ["s0", "s01", "s02", "s03", "s04"] call BIS_fnc_selectRandom;
				_finder say3d _answer;			 
				 
																						};
																					

if (!action) then {
		KRON_UPS_reinforcement3 = true;
		KRON_UPS_reinforcement3_pos = _deadguypos;
					};
		
									
  if (mein_debug>0) then { player globalChat format ["FindBody.sqf - KRON_UPS_reinforcement3_pos - deadguy:%1", _deadguy];};
												

         if (radioObj) then {

		KRON_UPS_reinforcement0 = true; 
		KRON_UPS_reinforcement0_pos = _deadguypos;

							if (mein_debug>0) then { 
  player globalChat format ["FindBody.sqf - KRON_UPS_reinforcement0_pos - deadguy:%1", _deadguy];
												};
			     };


		sleep 60;
        _x setBehaviour "AWARE"; //NEW

		if !(isNull _deadguy) then {

				hidebody _deadguy; sleep 5; deletevehicle _deadguy;
				
				                if (mein_debug>0) then {player globalChat "FindBody.sqf - Deleting Body after detected";};
				
									};

              } else {if (mein_debug>0) then {player globalChat format ["FindBody.sqf - deadguy:%1 - all spotters:%2 dead", _deadguy, _spotters];};};
           } forEach _spotters;
		   
                   } else {
				   
				   sleep 120; 
				   
				   if (!isNull _deadguy) then { 
				   
				   hidebody _deadguy; sleep 5; deletevehicle _deadguy;			   
				   if (mein_debug>0) then {player globalChat "FindBody.sqf - Deleting Body after !preAlarm";};
				   
											};
				   
							};		
} else {

				   sleep 120;
				   
				   if (!isNull _deadguy) then { 
				   
				  hidebody _deadguy; sleep 5; deletevehicle _deadguy;		   
				   if (mein_debug>0) then {player globalChat "FindBody.sqf - Deleting Body after isNil _finder";};
				   
											};
											
		};					
				
                if (mein_debug>0) then {player globalChat "FindBody.sqf - END of script";};
				sleep 5;
                if (!isNil "_shout1") then {terminate _shout1;group _finder setVariable ["endscript",true];};      

 

 

Share this post


Link to post
Share on other sites

I noticed in both scripts the problem is if they don't see the unit die it doesn't register with knowsabout , if all units know  less than 0.4  the  loop ends.

They can't see dead bodies.        That's not true they can see it.

 

Maybe units should look at dead body when crows arrive then the script should fire.

 

I threw in this line right after this line  _finders = _finders - [eagle1,eagle2,agnt];// remove elements,

[_deadguy,_finders] spawn {_deadguy = _this select 0; _finders = _this select 1;sleep 30; {_x lookat _deadguy;sleep 1} foreach _finders };// I see crows

 

Now even a unit who is looking away turns to look at body when crows arrive.

 

 

 

Share this post


Link to post
Share on other sites
Quote

Maybe units should look at dead body when crows arrive then the script should fire. 

 

So I should implement lookAt or doWatch. I think I need to use unit doWatch objNull; after too?

I encountered another problem with:

 

    if (!isnull _finder or !alive _finder)  then {waituntil{sleep 1;!alive _finder or _finder distance _deadguypos <4}};// checks _finder status

 

I hid(deleted) a corpse and ..

 

   if (mein_debug>0) then {player globalChat format ["FindBody.sqf - _finder:%1 close to _deadguy", _finder]; };

 

returned <null-object> and I still got detected with only dead and null units around.

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  

×