wogz187 1085 Posted November 1, 2020 @omri2050, Here's a function which requires the unit to enter "fleeing" state before surrendering. Spoiler You_fnc_capture={ params [["_grp", grpNull, []]]; [_grp] spawn { { waitUntil {sleep 1; fleeing _x}; if (fleeing _x) exitWith { _x setCaptive true; _x action ["surrender", _x] }; } forEach units (_this select 0); }; }; [group this] spawn you_fnc_capture; Have fun! 1 Share this post Link to post Share on other sites
Gunter Severloh 3949 Posted November 1, 2020 Adding to the code to have the surrendering ai to drop or put down their weapons would add a bit more immersion to it. 2 Share this post Link to post Share on other sites
wogz187 1085 Posted November 1, 2020 @Gunter Severloh, Here ya go, Spoiler You_fnc_capture={ params [["_grp", grpNull, []]]; [_grp] spawn { { waitUntil {sleep 1; fleeing _x}; if (fleeing _x) exitWith { _x setVariable ["you_surrender", true]; _x setCaptive true; _x action ["surrender", _x]; removeAllWeapons _x; removeHeadgear _x; _x unlinkItem "NVGoggles"; removeAllItems _x; }; } forEach units (_this select 0); }; }; [group this] spawn you_fnc_capture; *edit: let's stick a variable in there And a button, [player, "Capture Unit", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_connect_ca.paa", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_connect_ca.paa", "(_this distance cursorTarget) <4 && {cursorTarget getvariable ""you_surrender""} && {alive cursorTarget} && {!((faction cursorTarget) == (faction _this))}", "isNull objectParent _this", {}, {}, { cursorTarget disableAI "ALL"; cursorTarget switchMove "revive_secured"; [cursorTarget, _caller] spawn {private _time= time + 30; waitUntil {time>_time || ((_this select 0) distance (_this select 1))>10}; deleteVehicle (_this select 0); systemChat "Captive Secured"; }; }, {}, [], 5, 0, false, false] call BIS_fnc_holdActionAdd; Captive is hog-tied for 30 seconds or until player moves away. Have fun! 3 Share this post Link to post Share on other sites
ZaellixA 383 Posted November 1, 2020 (edited) Well, for the "drop their weapons" part I have a prepared script (used in a personal project). Here it is in case you would like to use it or adapt it to your needs /* * Function named You_fnc_surrender */ // Get the passed parameters params[["_unit", objNull, [objNull]]]; // Get the unit // Do some parameter checking if(_unit isEqualTo objNull) exitWith { // Log the error and print a message to the user ["Given unit is null"] call BIS_fnc_error; }; // Give the script to the scheduler private _nil = [_unit] spawn { // Get the parameters _unit = _this select 0; // The unit to surrender // Drop weapons _wh = "GroundWeaponHolder_Scripted" createVehicle (getPos _unit); // Create a ground weapon holder // Drop primary weapon _unit action["DropWeapon", _wh, primaryWeapon _unit]; // Drop the primary weapon waitUntil { uiSleep 0.5; // Wait a bit to save some CPU cycles (primaryWeapon _unit) isEqualTo ""; // Wait until main weapon is dropped }; // Drop handgun _unit action["DropWeapon", _wh, handgunWeapon _unit]; // Drop the handgun waitUntil { uiSleep 0.5; // Wait a bit to save some CPU cycles (handgunWeapon _unit) isEqualTo ""; // Wait until handgun is dropped }; // Drop secondary weapon _unit action["DropWeapon", _wh, secondaryWeapon _unit]; // Drop the secondary weapon waitUntil { uiSleep 0.5; // Wait a bit to save some CPU cycles (secondaryWeapon _unit) isEqualTo ""; // Wait until secondary weapon is dropped }; // Make the unit surrender _unit action["Surrender", _unit]; // Surrender _unit setCaptive true; // Set as captive // Delete the ground weapon holder deleteVehicle _wh; // Needs to be checked. The weapons that were dropped may be destroyed. // In this case we are to remove the deleteVehicle command. }; Please note that this function does not remove all the items from the unit as it is meant to add some "immersion/realism", where you wouldn't expect the items of a unit to just vanish. Instead, the unit drops all its weapons. It is quite straight forward to remove any of the drops in order to make the unit not drop any of its weapons. Additionally, you could use something like private _cWeapon = currentWeapon; // Get the current weapon _unit action["DropWeapon", _wh, _cWeapon]; // Drop current weapon waitUntil { uiSleep 0.5; // Sleep a bit to save some CPU cycles !((currentWeapon _unit) isEqualTo _cWeapon); // Wait until current is dropped }; in order to make the unit drop only its currently holding weapon. So, you could possibly use the above function in the same way wogz187 suggests like (copying wogz187's code and changing some parts) // Set your function You_fnc_capture = { // Get parameters params [["_grp", grpNull, [grpNull]]]; // Get the group (added valid types) // Pass code to the scheduler [_grp] spawn { private _grpUnits = units (_this select 0); // Get the units directly // Wait until the group flees waitUntil { sleep 1; // Sleep to save some CPU fleeing (_grpUnits select 0); // Check only one of the units // because the whole group flees as a whole or none at all }; { _x setVariable ["you_surrender", true]; // Keep this variable if you want [_x] call You_fnc_surrender; // Make the unit surrender } forEach _grpUnits; }; }; // Call your function [group this] call you_fnc_capture; // Changed spawn to call as there's no need to spawn it (no sleep in the function) Hope this helps a wee bit. Happy ArmA and please don't hesitate to ask more questions if you want to. Edited November 1, 2020 by ZaellixA Deleted the if() exitWith{} part as it was not needed 2 Share this post Link to post Share on other sites
wogz187 1085 Posted November 1, 2020 @ZaellixA, Nice. My previous post didn't make sense but we should still exit if the group is null. Quote [group this] call you_fnc_capture; // Changed spawn to call as there's no need to spawn it (no sleep in the function) That's how I originally wrote the it but then I thought it was redundant because the function if called, read straight it would be, [params] call {[params] spawn {script};}; //instead of, [params] spawn {script}; Is that wrong? Have fun! Share this post Link to post Share on other sites
ZaellixA 383 Posted November 1, 2020 (edited) 2 hours ago, wogz187 said: Is that wrong? I can't see something wrong with what you got. I only changed the spawn to call because in the main body of the function there's no sleep (or other "delay") command, so there's no actual reason to give the whole function to the scheduler, you can just execute it. Obviously, inside the function, you do give some code to the scheduler with spawn but this has nothing to do with the execution of the function. The function actually just gets the parameters and passes them to the code that is given to the scheduler. Thus, no sleeps in the function, so no need to spawn instead of call. So, I thought it would be better not to clutter the scheduler with scripts. Of course one could omit entirely the creation of a function and just do something like /* * Script file called surrender.sqf */ // Get parameters params [["_grp", grpNull, [grpNull]]]; // Get the group (added valid types) // Pass code to the scheduler [_grp] spawn { private _grpUnits = units (_this select 0); // Get the units directly // Wait until the group flees waitUntil { sleep 1; // Sleep to save some CPU fleeing (_grpUnits select 0); // Check only one of the units // because the whole group flees as a whole or none at all }; { _x setVariable ["you_surrender", true]; // Keep this variable if you want [_x] call You_fnc_surrender; // Make the unit surrender } forEach _grpUnits; }; And then just call the script like [group this] call compile preprocessFileLineNumbers "surrender.sqf"; Although, using compile preprocessFileLineNumbers is not the best idea ever. So you could change the script a little bit like /* * Script file called surrender.sqf */ // Get parameters params [["_grp", grpNull, [grpNull]]]; // Get the group (added valid types) private _grpUnits = units _grp; // Get the units // Wait until the group flees waitUntil { sleep 1; // Sleep to save some CPU fleeing (_grpUnits select 0); // Check only one of the units // because the whole group flees as a whole or none at all }; { _x setVariable ["you_surrender", true]; // Keep this variable if you want [_x] call You_fnc_surrender; // Make the unit surrender } forEach _grpUnits; and instead of calling the script that will just get the parameter and then just pass it to the code that the scheduler will handle, you can give the script directly to the scheduler. The only overhead imposed to the scheduler here is to get the parameter and create the local variable to hold it. I am not sure how much this is for ArmA but I would be it is nothing compared to the rest of the script commands. So with the above script, you should call it like [group this] execVM "surrender.sqf"; Please, keep in mind that I have NOT tested any of those scripts so I cannot guarantee that they work. Additionally, I haven't performed any performance tests, so I cannot say whether one or the other way of calling and/or structuring the code is more efficient and in what way than the other. I would be glad to hear your opinions and results on any of those topics. Happy ArmA :). Edited November 1, 2020 by ZaellixA Corrected the script 1 Share this post Link to post Share on other sites
wogz187 1085 Posted November 2, 2020 (edited) @omri2050, The first script posted above was based on a single test. Upon further testing there are a lot of problems. Not the least of which-- fleeing is super unreliable! If the units are spawned in the editor, and they have more than 0% ammunition, it is almost impossible to make them flee. With 0% ammo they will flee pretty much immediately (that's how I tested the above). Depleting ammo within the mission has a different effect than starting with no ammo, for some reason. So, under most circumstances the first code is totally useless. This works a little better, Spoiler You_fnc_capture={ params [["_grp", grpNull, []]]; you_captureState={ _this switchMove ""; _this setVariable ["you_surrender", true]; _this setCaptive true; _this action ["surrender", _this]; removeAllWeapons _this; removeHeadgear _this; removeAllItems _this; }; { [_x]spawn{ waitUntil {sleep 1; !alive (_this select 0) || fleeing (_this select 0) || damage (_this select 0) >0.5}; if (!alive (_this select 0) || !isNull objectParent (_this select 0)) exitWith {false}; (_this select 0) call you_captureState; }; } forEach units _grp; }; null=[group this] call you_fnc_capture; pasted into the init of one unit in the group. And, null=[this, "Capture Unit", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_connect_ca.paa", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_connect_ca.paa", "(_this distance cursorTarget) <4 && {cursorTarget getvariable ""you_surrender""} && {alive cursorTarget} && {!((faction cursorTarget) == (faction _this))}", "isNull objectParent _this", {}, {}, { cursortarget setVariable ["you_surrender", false]; cursorTarget disableAI "ALL"; cursorTarget switchMove "revive_secured"; [cursorTarget, _caller] spawn {private _time= time + 30; waitUntil {time>_time || ((_this select 0) distance (_this select 1))>10}; deleteVehicle (_this select 0); (_this select 1) sideChat "Captive Secured"; }; }, {}, [], 5, 0, false, false] call BIS_fnc_holdActionAdd; pasted into the init of player(s). Have fun! Edited November 2, 2020 by wogz187 updated 2 Share this post Link to post Share on other sites
wogz187 1085 Posted November 2, 2020 (edited) @omri2050, Here's a completely different method, Example Mission (drive) Spoiler null=[group this] spawn { private _grp= (_this select 0); private _num= count units _grp; private _grpStr= 100 / _num; { _x setVariable ["you_grpStr", _grpStr]; } forEach units _grp; }; paste into init of one unit in group init.sqf (or whatever), you_captureState={ _this switchMove ""; _this setVariable ["you_surrender", true]; _this setCaptive true; _this action ["surrender", _this]; removeAllWeapons _this; removeHeadgear _this; removeAllItems _this; }; addMissionEventHandler ["EntityKilled", { params ["_unit", "_killer"]; private _grp= group _unit; private _count = {alive _x} count units _grp; private _per= _unit getVariable "you_grpStr"; private _num= _per * _count; //systemChat format ["%1, %2, %3", _count, _per, _num]; if (_num > 59) exitWith {false}; if (!((faction _unit) == (faction _killer)) && !((faction _unit) == "CIV_f")) exitWith { if (_killer==player && _killer distance _unit < 50) then { { private _surrender=selectRandom [true, false]; if (_surrender || fleeing _unit) then { if (alive _x) then { _x call you_captureState }; }; } forEach units (group _unit); }; }; }]; and the capture button (init.sqf, player init, whatever), null=[player, "Capture Unit", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_connect_ca.paa", "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_connect_ca.paa", "(_this distance cursorTarget) <4 && {cursorTarget getvariable ""you_surrender""} && {alive cursorTarget} && {!((faction cursorTarget) == (faction _this))}", "isNull objectParent _this", {}, {}, { cursortarget setVariable ["you_surrender", false]; cursorTarget disableAI "ALL"; cursorTarget switchMove "revive_secured"; [cursorTarget, _caller] spawn {private _time= time + 30; waitUntil {time>_time || ((_this select 0) distance (_this select 1))>10}; deleteVehicle (_this select 0); (_this select 1) sideChat "Captive Secured"; }; }, {}, [], 5, 0, false, false] call BIS_fnc_holdActionAdd; Once the majority of the group is killed there is a chance the rest will surrender. Have fun! Edited November 3, 2020 by wogz187 updated link 3 Share this post Link to post Share on other sites