Jump to content
pognivet

A nice little self-contained surrender script thing for ACE

Recommended Posts

I made this little thing so that enemies will actually surrender sometimes and you're not forced to genocide them all.

 

It was originally something that I saw Larrow use to make people sit in chairs until they detected an enemy, but I changed it to serve its current function.

 

_h = this spawn { 
waitUntil {morale _this <= -0.5 && _this call BIS_fnc_enemyDetected};
_this action ["Eject", vehicle _this];
["ace_captives_setSurrendered",[_this,true]] call CBA_fnc_globalEvent;
};

 

You put it in any unit's init line. If they can see an enemy and their morale goes below -0.5 they will surrender. If they're in a vehicle they should also get out before doing so, but it might not work as expected.

 

You can change the morale level check to to be whatever you want, but be warned: Arma's morale levels are really weird. You also cannot set a unit's morale or change it in any way except through indirect means. All you can do is check its value.

 

Morale can fluctuate between -1.0 and 1.0.

 

Everyone's morale seems to start at 0.8 no matter what their courage or stats are. Courage does, however, affect the rate at which morale recovers after a traumatic event. Courageous units will shake off suppression more quickly than cowardly units, but they will both be suppressed the same amount.

 

If you shoot 30 rounds full auto all around a guy from a few feet away but don't hit him his morale will always drop to exactly 0.198438, at least when I tested it in virtual reality. Once it hits this number it doesn't seem to go any lower unless they get hurt or something else happens at which point it will start to go into the negatives i.e. -0.158. It may also go into the negatives if nearby friends are also suppressed.

 

I don't know exactly what affects morale, but I assume the following:

 

Helps morale:

- Being healed

- Healing someone else

- Killing an enemy

- Shooting at an enemy/suppressing an enemy

- Nearby friendlies, especially heavy equipment

- Large number of units in squad

- Outnumbering the enemy and knowing it

 

Hurts morale:

- Friendlies dying or being hurt

- Killing civilians

- Being shot at/suppressed

- Strong/powerful enemy units nearby such as tanks or airplanes

- Being outnumbered by the enemy and knowing it

- Enemies in extremely close proximity or in multiple directions (flanks)

 

You should really edit it based on the units you're using with it. For a WW2 mission with battle-hardened soldiers I chose -0.75. They won't give up easily, but if you kill a lot of people in their squad, spray them with bullets for a long time or flank them really bad and cut them off from everyone else they'll give up.

 

If you wanted something more like Saddam Hussein's army during the coalition invasion then maybe set it for -0.25 or -0.15. You have to experiment a little to find the sweet spot. This way, if you wanted to, you could end a battle without killing a single person just by having overwhelming superiority and firepower.

 

I thought someone might find it useful so I'm posting it here.

 

Obviously, you need ACE, but you can edit this little script to make the enemy surrender in another way that doesn't require ACE if you want to.

 

It is possible that this can cause a weird form of script lag in missions with a large amount of units. This manifests itself as S.T.A.L.K.E.R.: Shadow Of Chernobyl-style microstutter. I believe this is because the engine will check every second for their morale levels until they either surrender or die which can overload the engine. This can seemingly be mitigated to an extent by using the NO LOGS parameter in the Arma 3 launcher.

  • Like 3
  • Thanks 2

Share this post


Link to post
Share on other sites

After some experimenting I have this to add:

 

{_h = _x spawn { 
waitUntil {morale _this <= -0.95 && _this call BIS_fnc_enemyDetected};
_this action ["Eject", vehicle _this];
["ace_captives_setSurrendered",[_this,true]] call CBA_fnc_globalEvent;
};} foreach units group this

 

Use that on a squad leader to have it done for all members of his squad automatically, so you don't gotta do it for each one.

 

Rough morale estimates:

 

-.15 through -.35 = Get shot at once or twice and surrender. If they even see a tank coming near them, even if the tank is not firing, they will shit their pants and surrender sometimes. Maybe criminals or really shitty police.

 

-.35 through -.60 = Get sprayed up real good like with a M249 and surrender. Reserve forces, garrisons, recruits, people in training.

 

-.60 through -.75 = Take fire and be injured or have a lot of friends die in a short amount of time and surrender. Average insurgent nobody.

 

-.75 through -.95 = Get shot or injured more than once, be shot at constantly, watch your friends die and only surrender when there's no other choice. Sometimes never surrenders if their morale doesn't drop enough and they then seek martyrdom. Hardcore insurgents, regular trained army.

 

-1 - Unknown, possibly never surrenders. I don't know what can make morale hit rock bottom. May only surrender in the most dire and disturbing circumstances. Special forces?

 

I pretty much only use -.75 through -.95 for the most part.

  • Like 1

Share this post


Link to post
Share on other sites

With all things arma related, don't assume things, test them out, the commands are already there.

 

Also some sidenotes, morale will sometimes never drop to -0.5 or below for some units, even with 4 tanks firing at a single infantry unit, the morale value will stick to -0.478something.

This probably depends on a lot more that's most likely out of the scope of the mission maker, since even game difficulty settings have an influence on the morale of a unit, so the values that seem to work for you won't work at all for someone with a different setting.

Better use fleeing command, since at the time this returns true, a unit is already set to get the heck out of this situation.

 

Morale of the story, don't use morale.

 

Cheers

  • Thanks 1

Share this post


Link to post
Share on other sites
1 hour ago, Grumpy Old Man said:

With all things arma related, don't assume things, test them out, the commands are already there.

 

Also some sidenotes, morale will sometimes never drop to -0.5 or below for some units, even with 4 tanks firing at a single infantry unit, the morale value will stick to -0.478something.

This probably depends on a lot more that's most likely out of the scope of the mission maker, since even game difficulty settings have an influence on the morale of a unit, so the values that seem to work for you won't work at all for someone with a different setting.

Better use fleeing command, since at the time this returns true, a unit is already set to get the heck out of this situation.

 

Morale of the story, don't use morale.

 

Cheers

I only say assume because it's behavior that I've observed in virtual reality, but I can't provide any hard data or proof other than a change in morale value which could be caused by any number of indirect factors other than the ones I've stated. You could call it a strong and informed assumption.

 

I'll try using the flee check and see how it works. It seems much more efficient.

 

I do have a question though: is there some possible way to allow a unit to both flee and surrender? Ideally, as it would most likely be in real life, a person would try to first flee if they had the opportunity, but once they realized that there is no escape they would surrender in order to save their life. An example would be someone happened upon by a police officer while breaking into a building. Once they realize the police officer is there they would immediately take off running because there is a chance of escape, but if they became surrounded they would have no choice other than to surrender or to fight their way out. Unfortunately, if your surrender condition is based on whether or not a unit is fleeing they cannot do both, they will only surrender. Is there a way to code around this?

Share this post


Link to post
Share on other sites
31 minutes ago, pognivet said:

I only say assume because it's behavior that I've observed in virtual reality, but I can't provide any hard data or proof other than a change in morale value which could be caused by any number of indirect factors other than the ones I've stated. You could call it a strong and informed assumption.

 

I'll try using the flee check and see how it works. It seems much more efficient.

 

I do have a question though: is there some possible way to allow a unit to both flee and surrender? Ideally, as it would most likely be in real life, a person would try to first flee if they had the opportunity, but once they realized that there is no escape they would surrender in order to save their life. An example would be someone happened upon by a police officer while breaking into a building. Once they realize the police officer is there they would immediately take off running because there is a chance of escape, but if they became surrounded they would have no choice other than to surrender or to fight their way out. Unfortunately, if your surrender condition is based on whether or not a unit is fleeing they cannot do both, they will only surrender. Is there a way to code around this?

 

You could take different factors into account for something like this, an injured unit for example could be more likely to just drop its weapons and surrender, a more healthy unit could try to escape at first, but only as long as he has a certain amount of ammo left.

Nothing a few damage or ammo checks couldn't handle. Though stuff like this tends to get complicated really fast if you have to take different outcomes into consideration. As example you could also check if the unit in question is being currently assigned as a target to enemies, constantly getting hit/fired at and check the distance to its aggressor. For stuff like this you either keep it simple or dive head first into FSM:

 

bMPoQh8.png

 

Imagine doing this exclusively in .sqf, nightmare come true.

You also need to ask the question if any player will even notice if a unit is fleeing but not surrendering and go from there.

 

Cheers

Share this post


Link to post
Share on other sites
4 minutes ago, Grumpy Old Man said:

 

You could take different factors into account for something like this, an injured unit for example could be more likely to just drop its weapons and surrender, a more healthy unit could try to escape at first, but only as long as he has a certain amount of ammo left.

Nothing a few damage or ammo checks couldn't handle. Though stuff like this tends to get complicated really fast if you have to take different outcomes into consideration. As example you could also check if the unit in question is being currently assigned as a target to enemies, constantly getting hit/fired at and check the distance to its aggressor. For stuff like this you either keep it simple or dive head first into FSM:

 

bMPoQh8.png

 

Imagine doing this exclusively in .sqf, nightmare come true.

You also need to ask the question if any player will even notice if a unit is fleeing but not surrendering and go from there.

 

Cheers

Thanks for all your input. I've never tried messing with FSMs. I try to keep things simple, but I also enjoy Arma the most when its dynamic and reactive. Sadly, I can't have it both ways. I guess I'll give it my best shot.

 

I really like your low ammo idea as well. As far as this little init thing goes perhaps I should make it so when fleeing is activated and they're out of ammo they surrender, or maybe fleeing/low ammo/less than 3 or 4 squadmembers left alive. It would add another nice layer of A.I. "thought".

Share this post


Link to post
Share on other sites
2 hours ago, pognivet said:

Thanks for all your input. I've never tried messing with FSMs. I try to keep things simple, but I also enjoy Arma the most when its dynamic and reactive. Sadly, I can't have it both ways. I guess I'll give it my best shot.

 

I really like your low ammo idea as well. As far as this little init thing goes perhaps I should make it so when fleeing is activated and they're out of ammo they surrender, or maybe fleeing/low ammo/less than 3 or 4 squadmembers left alive. It would add another nice layer of A.I. "thought".

 

You could also limit the time in which a unit will surrender, so you won't end up with units that surrender 15mins after the battle is over.

Also regarding your note in the first post of the engine overloading, a single morale check doesn't take more than a fraction of a millisecond, roughly 0.0004ms on my rig.

At this point I'd say don't put this stuff into an units init field, but rather define a function in the init.sqf and just run the function from inside the units init field, this way you have a central location where you can tweak the snippet, instead of having to edit every single init box for the smallest change.

I put this snippet together as an example on how this could look like in init.sqf:

 


GOM_fnc_enemySurrenderInit = {

	params [["_enemySide",east]];//defaults enemy side to east if no parameter given
	GOM_fnc_addSurrenderUnits = true;
	GOM_fnc_surrenderUnits = [];
	while {GOM_fnc_addSurrenderUnits} do {

		_enemies = allUnits select {alive _x AND side _x isEqualTo _enemySide AND !(_x getVariable ["GOM_fnc_enemySurrender",false])};//adds all units of enemyside that are currently not handled by the surrender system, to catch spawned units during mission runtime

		{

			_x spawn GOM_fnc_enemySurrenderLoop;
			_x setVariable ["GOM_fnc_enemySurrender",true];//unit is being handled, flag set
			GOM_fnc_surrenderUnits pushBack _x;

		} forEach _enemies;

		//only announce every 15 seconds
		if (GOM_fnc_debug AND round time mod 15 == 0) then {systemchat format ["GOM_fnc_surrender controlling %1 %2 units",count GOM_fnc_surrenderUnits,_enemySide]};

		sleep 1;//one single check every second is okay, _enemies evaluation only takes ~0.05ms

	}





};

GOM_fnc_surrender = {

	params ["_unit"];
	GOM_fnc_surrenderUnits = GOM_fnc_surrenderUnits - [_unit];
	_unit setVariable ["GOM_fnc_surrendered",true];
	_unit playmove "AmovPercMstpSsurWnonDnon";
	_unit setCaptive true;


};


GOM_fnc_enemySurrenderLoop = {

	params ["_unit"];

	//loop only runs on alive and non surrendered units
	while {alive _unit OR !(_unit getVariable ["GOM_fnc_surrendered",false])} do {

		waituntil {fleeing _unit};//waituntil runs once every frame at most, fleeing only costs 0.0004ms, no sleep needed

		if (GOM_fnc_debug) then {systemchat format ["%1 is fleeing!",_unit]};

		//add all cases to handle here, immediately followed by exitWiths, starting with the most unlikely outcome

		_noAmmo = count primaryWeaponMagazine _unit isEqualTo 0;

		if (_noAmmo) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: No ammo!",_unit]};


		};

		_lowAmmo = count (magazines _unit select {_x isEqualTo (primaryWeaponMagazine _unit select 0) OR _x isEqualTo (handgunMagazine _unit select 0)}) < 2; //unit has less than 2 magazines for his weapons

		if (_lowAmmo) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: Low ammo!",_unit]};


		};

		_lowHealth = damage _unit >= 0.3;//you can add a random chance to this

		if (_lowHealth) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: Injured!",_unit]};


		};

		_lowMorale = morale _unit <= -0.8;//for testing purposes, seriously don't use morale for anything

		if (_lowMorale) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: Low Morale!",_unit]};


		};

		sleep 1 + random 1;//wait randomly between 1 and 2 seconds

	};

	//unit either dead or surrendered, remove him from array
	GOM_fnc_surrenderUnits = GOM_fnc_surrenderUnits - [_unit];
	true;

};

GOM_fnc_debug = true;
_init = [east] spawn GOM_fnc_enemySurrenderInit;

Easily readable and you can add conditions as you seem fit.

You could probably have more control using hit eventhandlers and a random chance, so enemies might throw the towel if injured above a certain point.

This snippet doesn't make almost all enemies instantly surrender, so it's still a rare occasion.

Also remove the morale check or leave it in, with -0.8 it's rarely triggering.

 

Cheers

  • Like 1

Share this post


Link to post
Share on other sites
18 hours ago, Grumpy Old Man said:

 

You could also limit the time in which a unit will surrender, so you won't end up with units that surrender 15mins after the battle is over.

Also regarding your note in the first post of the engine overloading, a single morale check doesn't take more than a fraction of a millisecond, roughly 0.0004ms on my rig.

At this point I'd say don't put this stuff into an units init field, but rather define a function in the init.sqf and just run the function from inside the units init field, this way you have a central location where you can tweak the snippet, instead of having to edit every single init box for the smallest change.

I put this snippet together as an example on how this could look like in init.sqf:

 



GOM_fnc_enemySurrenderInit = {

	params [["_enemySide",east]];//defaults enemy side to east if no parameter given
	GOM_fnc_addSurrenderUnits = true;
	GOM_fnc_surrenderUnits = [];
	while {GOM_fnc_addSurrenderUnits} do {

		_enemies = allUnits select {alive _x AND side _x isEqualTo _enemySide AND !(_x getVariable ["GOM_fnc_enemySurrender",false])};//adds all units of enemyside that are currently not handled by the surrender system, to catch spawned units during mission runtime

		{

			_x spawn GOM_fnc_enemySurrenderLoop;
			_x setVariable ["GOM_fnc_enemySurrender",true];//unit is being handled, flag set
			GOM_fnc_surrenderUnits pushBack _x;

		} forEach _enemies;

		//only announce every 15 seconds
		if (GOM_fnc_debug AND round time mod 15 == 0) then {systemchat format ["GOM_fnc_surrender controlling %1 %2 units",count GOM_fnc_surrenderUnits,_enemySide]};

		sleep 1;//one single check every second is okay, _enemies evaluation only takes ~0.05ms

	}





};

GOM_fnc_surrender = {

	params ["_unit"];
	GOM_fnc_surrenderUnits = GOM_fnc_surrenderUnits - [_unit];
	_unit setVariable ["GOM_fnc_surrendered",true];
	_unit playmove "AmovPercMstpSsurWnonDnon";
	_unit setCaptive true;


};


GOM_fnc_enemySurrenderLoop = {

	params ["_unit"];

	//loop only runs on alive and non surrendered units
	while {alive _unit OR !(_unit getVariable ["GOM_fnc_surrendered",false])} do {

		waituntil {fleeing _unit};//waituntil runs once every frame at most, fleeing only costs 0.0004ms, no sleep needed

		if (GOM_fnc_debug) then {systemchat format ["%1 is fleeing!",_unit]};

		//add all cases to handle here, immediately followed by exitWiths, starting with the most unlikely outcome

		_noAmmo = count primaryWeaponMagazine _unit isEqualTo 0;

		if (_noAmmo) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: No ammo!",_unit]};


		};

		_lowAmmo = count (magazines _unit select {_x isEqualTo (primaryWeaponMagazine _unit select 0) OR _x isEqualTo (handgunMagazine _unit select 0)}) < 2; //unit has less than 2 magazines for his weapons

		if (_lowAmmo) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: Low ammo!",_unit]};


		};

		_lowHealth = damage _unit >= 0.3;//you can add a random chance to this

		if (_lowHealth) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: Injured!",_unit]};


		};

		_lowMorale = morale _unit <= -0.8;//for testing purposes, seriously don't use morale for anything

		if (_lowMorale) exitWith {
			_surrender = _unit call GOM_fnc_surrender;
		if (GOM_fnc_debug) then {systemchat format ["%1 surrendered! Reason: Low Morale!",_unit]};


		};

		sleep 1 + random 1;//wait randomly between 1 and 2 seconds

	};

	//unit either dead or surrendered, remove him from array
	GOM_fnc_surrenderUnits = GOM_fnc_surrenderUnits - [_unit];
	true;

};

GOM_fnc_debug = true;
_init = [east] spawn GOM_fnc_enemySurrenderInit;

Easily readable and you can add conditions as you seem fit.

You could probably have more control using hit eventhandlers and a random chance, so enemies might throw the towel if injured above a certain point.

This snippet doesn't make almost all enemies instantly surrender, so it's still a rare occasion.

Also remove the morale check or leave it in, with -0.8 it's rarely triggering.

 

Cheers

Thank you for all the time and effort you put into this thread and assisting in improving this featurette, Grumpy Old Man. It is very helpful.

 

I will experiment with what you provided me and post some results.

Share this post


Link to post
Share on other sites

Hello, everyone! This seems like a nice script, but does it work for multiplayer and coop missions? And how would I set it up without ACE? Thank you in advance! 🙂

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

×