Jump to content
Sign in to follow this  
JOHN007

Respawn as Squad Leader (Lose position when killed)

Recommended Posts

Hello.

 

Basically when the squad leader is killed, the position is given to the next rank. How do you prevent this from happening may I ask? The only script I can find online is for Arma3 but it does sometimes work correctly but on some maps ie Cherno, the Arma3 script dosen't work at all.

 

I have found no information regarding a script for Arma2 which keeps the squad leaders position? Here is the Arma3 script that is implemented at the moment.

 

if (hasInterface) then // Normal player
{
	CurrentGroup = group player;
	IsGroupLeader = false;
	if (leader CurrentGroup  == leader player) then
	{
		IsGroupLeader = true;
	};
	player addEventHandler ["Respawn",
	{
		if (IsGroupLeader) then //Reset Group Leader
		{
		CurrentGroup = group player;
		{[_x] joinSilent player} forEach (units CurrentGroup);
		CurrentGroup selectLeader player;
		};
	}];
};

This is placed into the main Init.sqf

 

Thankyou for your time and hope to speak soon.

 

Share this post


Link to post
Share on other sites

If you make them all playable, you can play down the ranks as each dies, little more realistic that way.

Or don't you want that ?

Share this post


Link to post
Share on other sites

Hello Chrisb thankyou very much for the reply much appreciated.

 

I'm afraid not, as the squad leader can only issue orders/missions. When the squad leader is killed, the role is taken to the next rank, problem is that they cannot issue orders/missions because the framework is tied to the original allocated squad leader. This breaks the whole game.

 

May I ask do you have any idea how we could fix this issue? Do you know anyone on the Arma forums who may be able to help? Its just incredibly difficult to get a response here on the forum so I am grateful for this Chris.

 

Thanks again for your time and hope to speak soon. 

 

 

Share this post


Link to post
Share on other sites
On ‎6‎/‎4‎/‎2018 at 8:12 PM, JOHN007 said:

Basically when the squad leader is killed, the position is given to the next rank. How do you prevent this from happening may I ask?

 . . .   . . .

I have found no information regarding a script for Arma2 which keeps the squad leaders position?

 

To my knowledge there's no way to stop group leadership from getting passed down when the leader is killed.  It occurs instantaneous in the background because a dead unit goes to grpNull, but a delay occurs in it getting called out until someone else in the group realizes the leader has been killed (something with knowsAbout ?).

 

Respawn and MPRespawn event handlers  can make a respawned player the group leader again.  Your script above does it.  Warfare also does it, running the Client_Killed.sqf and then the Client_PlayerRespawn.sqf.

 

But from your next post, I take it the issue is that the respawned unit can no longer issue orders or missions.

 

On ‎6‎/‎5‎/‎2018 at 4:46 PM, JOHN007 said:

 . . . the squad leader can only issue orders/missions. When the squad leader is killed, the role is taken to the next rank, problem is that they cannot issue orders/missions because the framework is tied to the original allocated squad leader. This breaks the whole game.

 

This is where the scripting maybe should have considered having the orders and missions issued by a player group leader rather than a specific unit.  Because the respawned unit will not be the same one that was placed in editor.  The variable assigned in editor will identify the dead unit.  The respawned unit will have a different identifier without a variable assigned (unless scripted to do so).

 

The editor variable can be reassigned to the respawned unit.


Option 1:
Reassign the editor variable when the unit respawns.

 

In the commander unit's respawn event handler add: 

SL_1 = _this select 0;

 

However doing that might cause problems if code or scripts handling the dead unit are still relying on the assigned variable.

And there would still remain the problem of no orders or missions being issued while player respawns, if that is an issue.


Option 2:
Revise the scripts, and in the commander unit init field in editor, place something like:

grpCommand = Group this;

In the scripts to issue orders and missions, instead of referencing the unit by variable, i.e:
 

if (isPlayer SL_1 && Alive SL_1) then 
{
	// SL_1 issues orders and missions.
	_missionAction = SL_1 addAction ["Issue New Mission", . . .]; 
	_ordersAction = SL_1 addAction ["Issue New Orders", . . .]; 
};

reference the group leader, like this:

if (isPlayer (Leader grpCommand) && Alive (Leader grpCommand)) then 
{
	// grpCommand leader is player and can issue orders and missions.
	_missionAction = (Leader grpCommand) addAction ["Issue New Mission", . . .]; 
	_ordersAction = (Leader grpCommand) addAction ["Issue New Orders", . . .]; 
};

This would be best for single player, multiplayer and dedicated server.

Edited by opusfmspol

Share this post


Link to post
Share on other sites

Hello opusfmspol thankyou very much for the reply much appreciated.

 

6 hours ago, opusfmspol said:

 

To my knowledge there's no way to stop group leadership from getting passed down when the leader is killed.  It occurs instantaneous in the background because a dead unit goes to grpNull, but a delay occurs in it getting called out until someone else in the group realizes the leader has been killed (something with knowsAbout ?).

 

I understand, there is no information regarding this issue with Arma2, there are similar posts stating the same, there's no way.

I've spent years on and off trying to fix this. Last night I bashed my head against the wall so hard something clicked. This is the diagnostic.

Instead of respawning at the base when killed, I implemented a custom revive framework, this works. 3 revives and your kicked from the server, it works correctly with Ace wounds also which is brilliant.

 

The script originally posted does actually work correctly, but only on some maps, so it does 99.9% work after much testing.

 

Unfortunately some maps don't work, but I have a theory, the maps that don't work have custom units for players. The units have the Squad leader, Medic and Engineer parameters setup correctly also.

 

So it may be that modded units don't work correctly with the script, but guess what?

 

The other night I found a thread in the bloody Steam forums for Arma3, followed the instructions writing the script into the main Init sqf but still no luck, until I executed the scipt with execVM. Its bloody worked! 

 

There is one problem here, the new script caused some serious FPS issues/lag? May I ask if you could have a look at this script before I follow your instructions which I am eternally grateful for, maybe this script could be altered slightly?

 

1. Give your squad leader the variable name "OurSquadLeader"

2. Create .sqf script

if (isServer) then
{
	CheckGroupLeader =
	{
		waitUntil 
		{
			(leader group OurSquadLeader) != OurSquadLeader) &&
			(alive OurSquadLeader)
		};
		{[_x] joinSilent OurSquadLeader)} forEach units group OurSquadLeader;	
		[] spawn CheckGroupLeader;
	};
[] spawn CheckGroupLeader;
};

3. Call script from main Init.sqf

 

This works correctly but causes serious lag issues? I haven't got the slightest clue as to why either? If we could fix this issue for the Arma2 community than we have a 1st fully working script for this problem.

 

Thankyou very much for your time and hope to speak soon.

Share this post


Link to post
Share on other sites

I would think it lags because it's using a suspension without sleep.  waitUntil checks condition (about) each frame.  How many FPS is running?  CPU gets tied up making high volume checks waiting for true.  But even when true does occur, it spawns right back into the waitUntil.  So CPU is getting kept busy with no rest.

 

Using Sleep 0.1 in the waitUntil could free up some lag.

If speed of the join is not critical, maybe use Sleep 0.25, or 0.5.  But at about 0.5 (twice per second) I would think players could start observing the join has a very slight delay.

If speed is critical then the sleep time becomes a tough balancing act, trying to find CPU friendly versus FPS.

Share this post


Link to post
Share on other sites

Hello Opusfmspol sorry for the late reply,

 

On ‎6‎/‎9‎/‎2018 at 8:43 AM, opusfmspol said:

I would think it lags because it's using a suspension without sleep.  waitUntil checks condition (about) each frame.

 

I have tried other scripts but failed, so it seems that this one is the best one at the moment, I'll follow your instructions and hopefully fix the lag issue. Would you recommend editing the script in anyway? Could it be altered somehow? Or in your opinion is the 'waituntil' parameter actually fixing this issue in the first place?

 

Thankyou very much for your expertise and hope to speak soon.

 

Share this post


Link to post
Share on other sites

The waitUntil is doing what one could expect; create a delay until condition is met.  But if run constantly it really should use a sleep.  It would be better if run only when really needed, i.e. at times when the squad leader is likely to have died/is respawning(reviving).

 

If your custom revive is using a 'HandleDamage' event handler, it might be better to have the (server side) waitUntil spawn inside the event handler whenever the result is such that the unit will lose group leadership.  So when the event handler completes, the unit loses group and the waituntil completes almost instantly.

 

If not using 'HandleDamage' perhaps you could similarly use it to minimize the time waitUntil is running.

Share this post


Link to post
Share on other sites
On ‎6‎/‎20‎/‎2018 at 6:33 PM, opusfmspol said:

The waitUntil is doing what one could expect; create a delay until condition is met.  But if run constantly it really should use a sleep.  It would be better if run only when really needed, i.e. at times when the squad leader is likely to have died/is respawning(reviving).

 

If your custom revive is using a 'HandleDamage' event handler, it might be better to have the (server side) waitUntil spawn inside the event handler whenever the result is such that the unit will lose group leadership.  So when the event handler completes, the unit loses group and the waituntil completes almost instantly.

 

If not using 'HandleDamage' perhaps you could similarly use it to minimize the time waitUntil is running.

Hello thankyou for the reply.

 

Over at Armaholic, a user has provided a great script, it works for Arma 2.

 

player addEventHandler ["Respawn",
{
    params ["_unit", "_corpse"];
    (group _unit) setGroupOwner (owner _unit); // not needed I don't think... just in case group isn't local
    (group _unit) selectLeader _unit; // group has to be local, Wiki says...
}];

The script works 99% but its much better than the original script.

May I ask do you know the base/class name for the ACE unconscious state?

This is what happens.

If the Squad leader is killed instantly, he stays as squad leader, no problem there.

The problem is when you get shot and you fall unconscious, you instantly lose squad leader status,(Goes to next rank)
If you are revived without dying, you will get back your squad leader status.

If you die while been unconscious, you don't get back the squad leader status?

Its just a guess, but I'm sure it would be included in the params ["_unit", "_corpse"]; section?

 

I believe that's the last piece of the puzzle, the Ace unconscious state has to be included.

 

Thankyou for your time and hope to speak soon.

Share this post


Link to post
Share on other sites

Haven't dug through ACE scripts, but I would suspect they use the setUnconscious command, and the status can be checked with the lifeState command.

 

An observation on the handler you found, selectLeader would be the only line doing anything in A2 or OA.  The params and setGroupOwner commands were introduced in Arma 3.  If not stopping script or causing error, they would be ignored.

 

For A2 or OA, one could use private as alternative to the params command:

Spoiler

// params ["_unit", "_corpse"];

private ["_unit", "_corpse"];
_unit = _this select 0;
_corpse = _this select 1;

 

,  but I don't think setGroupOwner has any alternative available in A2/OA, unless somebody else knows better.

 

With selectLeader the group does have to be local for it to work.  The local command can detect locality of a group in A3, but not in A2 or OA.  I once sought an A2/OA alternative for that because GC (Garbage Collector module, runs on server) seems not to delete groups in queue when they're not local to server.  But I could never find any alternative to detect locality of particular groups in A2/OA (i.e., which machine created the group, or now has locality, when not local to the server; see deleteGroup description).

Share this post


Link to post
Share on other sites

Hello and thankyou for the reply.

 

So I unpacked the Ace_Wounds PBO and found some interesting class/base strings. I don't see any standard A2/OA strings in any of the config files but I have found new strings that maybe could be allocated to the script?

 

Blackoutall.sqf

//#define DEBUG_MODE_FULL

#include "script_component.hpp"

private ["_unit", "_time", "_st", "_check", "_iss", "_fsm", "_xdam", "_isp", "_bdam", "_ndam"];

PARAMS_2(_unit,_time);

if (!local _unit) exitWith {};

_isp = isPlayer _unit;

_st = _unit getVariable "ace_w_state";
if (isNil "_st") then {_unit setVariable ["ace_w_state", 0]};
if (isNil "ace_sys_wounds_enabled") then {
	if (isNil {_unit getVariable "ace_w_carry"}) then {_unit setVariable ["ace_w_carry", objNull]};
	if (vehicle _unit == _unit) then {
		[_unit, 100] call FUNC(animator2);
	};
	_unit setVariable [QGVAR(uncon), true];
	_unit setVariable ["ace_w_unconlen", time + _time]; // bleeding and pain
	if (_isp) then {
		[true] spawn FUNC(blackoutp);
	} else {
		[_unit,true] spawn FUNC(blackoutai);
	};

 

Blackoutai.sqf

#include "script_component.hpp"
private ["_grpunit", "_isLeader", "_uncontime", "_bleed", "_pain", "_doex", "_uconl", "_carrier", "_grp"];
PARAMS_2(_unit,_knockout);
if (!local _unit) exitWith {};
if (isPlayer _unit) exitWith {};
_unit setVariable ["ace_w_wakeup",1];
_unit setVariable ["BIS_IS_inAgony",true];
//_unit setUnconscious true;
_grp = group _unit;
_isLeader = (_unit == leader _grp);
if (_isLeader) then {
	_newl = objNull;
	{
		private "_isu";
		_isu = _x call FUNC(isUncon);
		if (_x != _unit && !_isu && alive _x) exitWith {_newl = _x}
	} forEach units _grp;
	[QGVAR(selLeader), [_grp, _newl]] call CBA_fnc_globalEvent;
	{if (_x != _unit && alive _x) then {_x doFollow _newl}} forEach units _grp;
};
{_unit disableAI _x} forEach ["TARGET","AUTOTARGET","MOVE"];
// Drop out of static weapons 
if (vehicle _unit isKindOf "StaticWeapon") then {
	_unit action ["eject", vehicle _unit];
};
// Fall down from ladders
if (animationState _unit in ["ladderriflestatic","laddercivilstatic"]) then {
	_unit action ["ladderOff", (nearestBuilding _unit)];
	// Unit perhaps falls to death so we can exit script here anyway
	// Cancel last move order otherwise it attempts to climb up ladder again on waking up, when probably going unconscious again (loop)
	// if (currentCommand _unit == "MOVE") then { }; // Order it to wait
};

 

Blackoutp.sqf

// #define DEBUG_MODE_FULL
#include "script_component.hpp"
#define _state_blackingOut 801

private ["_knockout", "_dialog", "_grpunit", "_isLeader", "_uncontime", "_normtime", "_awaketime", "_bleed", "_pain", "_endtime", "_doex", "_uconl", "_carrier", "_grp"];

if (player getVariable ["ace_w_bout", false]) exitWith {};

player setVariable ["ace_w_bout",true];
player setVariable ["ace_w_wakeup",1];
//player setVariable ["BIS_IS_inAgony",true];
enableRadio false;
//player setUnconscious true;
PARAMS_1(_knockout);
_dialog = false;
_grp = group player;
_isLeader = (player == leader _grp);
if (_isLeader) then {
	_newl = objNull;
	{
		private "_isu";
		_isu = _x call FUNC(isUncon);
		if (_x != player && !_isu && alive _x) exitWith {_newl = _x}
	} forEach units _grp;
	if (!isNull _newl) then {
		[QGVAR(selLeader), [_grp, _newl]] call CBA_fnc_globalEvent;
		{if (_x != player && alive _x) then {_x doFollow _newl}} forEach units _grp;
	};
};

 

Playeractions.sqf

// #define DEBUG_MODE_FULL
#include "script_component.hpp"

// Self action, in light blue and most negative value
#define ACE_TEXT_LIGHTBLUE(Text) ("<t color='#0303ff'>" + ##Text + "</t>")
#define __STOPBLEED ACE_TEXT_LIGHTBLUE(localize "STR_ACE_UA_STOPBLEED")
#define __USEMORPHI ACE_TEXT_LIGHTBLUE(localize "STR_ACE_UA_USEMORPHI")
#define __USEEPI ACE_TEXT_LIGHTBLUE(localize "STR_ACE_UA_USEEPI")

#define _state_blackingOut 801 // semi-lucid

private ["_exitloop","_pain_action","_epi_action","_epi_and_morph"];
sleep 5;
if (isNil "ace_sys_wounds_enabled") exitWith {};

_nearMedicFacility = [player] call FUNC(nearMedicalFacility);
_epi_and_morph = if (!isNil "ace_sys_wounds_medics_only") then {
	if ([player] call FUNC(isMedic) || _nearMedicFacility) then {
		true
	} else {
		false
	}
} else {
	true
};

while {true} do {
	_bandage_action = -9999;
	_pain_action = -9999;
	_epi_action = -9999;
	waitUntil {alive player};
	sleep 1;

	while {true} do {
		if (alive player && !(player call FUNC(isUncon))) then {
			// bandage
			if ((player getVariable "ace_w_bleed") > 0 && _bandage_action == -9999) then {
				if (BND in magazines player) then {
					_bandage_action = player addAction [__STOPBLEED, QPATHTO_F(stopBleeding), BND,-1];
				};
			} else {
				if ((player getVariable "ace_w_bleed") == 0 && _bandage_action != -9999) then {
					player removeAction _bandage_action;
					_bandage_action = -9999;
				};
			};

			if (_epi_and_morph) then {
				// morphine
				if ((player getVariable "ace_w_pain") > 0 && _pain_action == -9999) then {
					if (MOR in magazines player) then {
						_pain_action = player addAction [__USEMORPHI, QPATHTO_F(stopPain),"",-1];
					};
				} else {
					if ((player getVariable "ace_w_pain") == 0 && _pain_action != -9999) then {
						player removeAction _pain_action;
						_pain_action = -9999;
					};
				};

				// epi
				if ((player getVariable "ace_w_state") >= _state_blackingOut && _epi_action == -9999) then {
					if (EPI in magazines player) then {
						_epi_action = player addAction [__USEEPI, QPATHTO_F(useEpi),"",-1];
					};
				} else {
					if ((player getVariable "ace_w_state") < _state_blackingOut && _epi_action != -9999) then {
						player removeAction _epi_action;
						_epi_action = -9999;
					};
				};
			};
		};

		// remove all actions
		if ((player call FUNC(isUncon)) || !alive player) exitWith {
			if (_bandage_action != -9999) then {
				player removeAction _bandage_action;
			};
			if (_epi_and_morph) then {
				if (_pain_action != -9999) then {
					player removeAction _pain_action;
				};
				if (_epi_action != -9999) then {
					player removeAction _epi_action;
				};
			};
		};
		sleep 0.5;
	};
};

 

Somewhere in the code, is the main parameter for what looks like Ace has named Blackout' for the unconscious state.

 

First I will try the new script you have provided, thankyou very much for the update on A3 parameters, I guess they would need to be edited for A2.

 

Its a shame because the Ace Dev website has closed. Vital information on that site.

 

Thanks for your time and hope to speak soon. 

Share this post


Link to post
Share on other sites

Now I remember why ACE and CBA scripts give me such a headache.  <sigh>

 

Looked into it a bit and seems ACE uses playActionNow and switchMove for the animations, and stored variables to track the state.

 

I suspect the ACE unconscious state your seeking might be:  (_unit getVariable "ace_sys_wounds_uncon").

 

Comes from this line:

_unit setVariable [QGVAR(uncon), true];

QGVAR comes from CBA_main, it's the passed component as a string, with the (var) variable added to the end.  In this case the component is "ace_sys_wounds".
Where the ACE script uses QGVAR(uncon) it translates to "ace_sys_wounds_uncon"
_unit setVariable [QGVAR(uncon), true]; translates to _unit setVariable ["ace_sys_wounds_uncon", true];

 

Be aware, it can return nil.  When I tested, it returned false for player at mission start.  But for AI it returned nil, until he got wounded.  It then returned false, until he fell unconscious at which time it returned true.

Share this post


Link to post
Share on other sites

Hello and thankyou for the reply.

 

This is complicated indeed, may I ask how exactly did you implement this code? I included the parameters but no effect, but it may not be configured correctly I'm not sure?

 

This is called from the main init.sqf

 

if (!isServer) then
// params ["_unit", "ace_sys_wounds_uncon"];

private ["_unit", "ace_sys_wounds_uncon"];
_unit = _this select 0;
ace_sys_wounds_uncon = _this select 1;

From further testing, example the squad leader can see the units on the bottom of the screen and can select them with F1 F2. 

If the squad leader is unconscious, (Unit1) Instantly the role is passed to the next rank (Unit2)

 

On Unit2 screen on the UI, I can see that only Unit2 is present? As soon as the squad leader dies from an unconscious state, Unit2 can now see Unit1 and Unit2 at the bottom of the screen?

 

Its difficult to explain, its like I need to find the parameters in the default Arma2 PBO's but I haven't got a clue where the configs are for respawning players.

 

I don't understand why there is no information regarding this? Plenty of posts requesting help in preventing this role switch, but no solution for Arma2. I believe we just need the correct strings, but finding them is difficult.

 

Thankyou for your time and hope to speak soon.

Share this post


Link to post
Share on other sites
10 hours ago, JOHN007 said:

Hello and thankyou for the reply.

 

This is complicated indeed, may I ask how exactly did you implement this code?

Someone with more CBA and ACE2 experience could probably help with this better than I could.  I haven't used CBA handlers in scripts.

 

An ACE extended event handler appears to control who takes leader when the leader goes unconscious.  There might be a CBA function which could be used to replace the handler after preinit is done (i.e., during init.sqf or initJIPcompatible.sqf), but I wouldn't know what function or the params to call it properly.

 

Observe this block in blackoutp.sqf (and the block in blackoutai.sqf is similar):

Spoiler

_grp = group player;
_isLeader = (player == leader _grp);
if (_isLeader) then {
	_newl = objNull;
	{
		private "_isu";
		_isu = _x call FUNC(isUncon);
		if (_x != player && !_isu && alive _x) exitWith {_newl = _x}
	} forEach units _grp;
	if (!isNull _newl) then {
		[QGVAR(selLeader), [_grp, _newl]] call CBA_fnc_globalEvent;
		{if (_x != player && alive _x) then {_x doFollow _newl}} forEach units _grp;
	};
};

 


It interprets as: "If player is group leader, identify a new leader (_newl); if _newl is not null, call a CBA globalevent using QGVAR(selLeader), and have each of the other group members doFollow."

 

The code used by the global event to select leader can be found near the bottom of "XEH_preinit.sqf" in ACE_Wounds.  Look for QGVAR(selLeader).  Params from above are [_grp, _newl].

{if (local (leader (_this select 0))) then {(_this select 0) selectLeader (_this select 1)}}

My thought is that you would want to revise/replace that handler code after it becomes set, so that generic groups would do the default but certain groups would selectLeader another way or not at all, however you decide.

 

All I did was run a simple test for the ACE 'unconscious' variable state using a radio trigger.

Spoiler

To recreate, in multiplayer editor:

   - Place a player unit.
   - Place a second unit (AI), named: B1.
   - Place an ACE Wounds "Enable Wounding System" module.
   - Place a Radio Alpha trigger, activated repeatedly, with onAct code: 


player sideChat format ["%1",(player getVariable "ace_sys_wounds_uncon")];

   - Save and launch the mission.

 

When in game, call the radio Alpha trigger.  Player variable "ace_sys_wounds_uncon" reads false.  (ACE Wounds initialized the player's variable as false, indicating the player is not unconscious.)

 

Exit and edit the mission.  Change the onAct code to read:


player sideChat format ["%1",(B1 getVariable "ace_sys_wounds_uncon")];

Save and launch the mission.  When in game, call the radio Alpha trigger.  B1 variable "ace_sys_wounds_uncon" reads <null>.  (ACE Wounds did not initialize the variable for an AI unit, the variable is nil.)

 

Wound the unit once in the leg, and call the trigger.  B1 variable reads false.  (ACE Wounds has initialized the variable for the AI, false indicates the unit is not unconscious.)

 

Keep wounding the unit's leg until he visibly goes unconscious, and call the trigger.  B1 variable reads true.  (ACE Wounds has (1): had the unit play the animation to go unconscious, and (2): registered the variable as true, he is now unconscious.  Then the leader handler for AI runs, and if the AI group had other members, new leader would be selected and they would follow the new leader.)

 

Share this post


Link to post
Share on other sites

Hello and thankyou for the detailed reply much appreciated.

 

I have tried to find any other information regarding these parameters before replying but no luck I'm afraid. I wouldn't know how to edit the script, this is complicated indeed. Do you know anyone with CBA and ACE experience with editing these scripts? I believe you have found the section 100%, but who actually wrote ACE wounds? Maybe we could contact the author because we are editing this work. We need those parameters.

 

So close now!

Share this post


Link to post
Share on other sites

Found that (CBA_eventHandlers getVariable "ace_sys_wounds_selleader") returns the QGVAR(selLeader) code stored in an array.

 

So I ran the following code using a radio trigger after mission start, and it worked.  The hint was shown when a leader went unconscious:

niv = [] spawn {
	waitUntil {!isNull CBA_eventHandlers};
	waitUntil {!isNil {CBA_eventHandlers getVariable "ace_sys_wounds_selleader"}};
	waitUntil {count (CBA_eventHandlers getVariable "ace_sys_wounds_selleader") > 0};

	_newCode = {hint "New leader being selected"};
	CBA_eventHandlers setVariable ["ace_sys_wounds_selleader",[_newCode],true];
};

 

Hopefully this can help you with changing the code to something that works for your mission.

Share this post


Link to post
Share on other sites
On ‎12‎/‎3‎/‎2018 at 9:33 AM, opusfmspol said:

Found that (CBA_eventHandlers getVariable "ace_sys_wounds_selleader") returns the QGVAR(selLeader) code stored in an array.

 

So I ran the following code using a radio trigger after mission start, and it worked.  The hint was shown when a leader went unconscious:


niv = [] spawn {
	waitUntil {!isNull CBA_eventHandlers};
	waitUntil {!isNil {CBA_eventHandlers getVariable "ace_sys_wounds_selleader"}};
	waitUntil {count (CBA_eventHandlers getVariable "ace_sys_wounds_selleader") > 0};

	_newCode = {hint "New leader being selected"};
	CBA_eventHandlers setVariable ["ace_sys_wounds_selleader",[_newCode],true];
};

 

Hopefully this can help you with changing the code to something that works for your mission.

 

Hello opusfmspol hope you are good thankyou for the reply.

 

This is great news! Sorry for the late reply, how on earth did you find the parameters? Epic stuff as always! I'm looking at the code now and I wouldn't even know how to convert this to be called from the main init script? This is beyond my capabilities with Arma scripting, CBA is on another level. Could that be possible may I ask? So we could have this script be called from the missions init file? Somehow implement the "ace_sys_wounds_selleader" script with the  (leader CurrentGroup  == leader player) parameters, would that be the correct method may I ask? I honestly wish I could code this right now, CBA has defeated me. I feel that we are so close now, if this could be implanted into a working script this would be the ultimate fix for ace. 

 

Thankyou very much for your time and expertise, hope to speak soon.

Share this post


Link to post
Share on other sites

It took painful tracking through the CBA and ACE addons.  The short of it:

 

1.  Review the wiki preprocessor commands, including its discussion page.  As you've already seen, CBA and ACE use complex macros.  You have to be familiar with the preprocessor commands to understand how the macros work.

 

2.  Review the CBA_Main file script_macros_common.hpp.  This is where the commonly used CBA macros get defined, with descriptions of their use.  The authors are also identified within.

 

3.  Review the files of CBA_Events PBO.  It has various CBA function scripts, and each identify their authors.

 

4.  Review ACE_sys_wounds file XEH_preInit.sqf.  This is where various ACE Wounds variables, functions and events get defined.

 

 

The steps taken and reasoning why;

Spoiler

 

In both Blackoutai.sqf and Blackoutp.sqf of ACE Wounds, this line is observed:


[QGVAR(selLeader), [_grp, _newl]] call CBA_fnc_globalEvent;

_grp is the group, _newl is the unit identified to assume leadership since the old leader has gone unconscious.  But what is QGVAR(selLeader)?

 

Go to CBA Main script_macros_common.hpp.  GVAR() and QGVAR() are commonly used CBA macros.  They're complex macros, so you have to refer to some other macros within to see how it gets put together.  GVAR() is a variable, QGVAR() is the variable name as a string.  In this case, QGVAR(selLeader) translates to string "ace_sys_wounds_selLeader".

 

What did calling on the CBA globalEvent function do?  The script is in CBA Events.  It calls the local and remoteEvent scripts.  Focus on the localEvent script.  It calls a defined code stored in CBA_eventHandlers.  But what code?

 

Go to ACE Wounds XEH_preInit.sqf.  Near the bottom is found this line:


[QGVAR(selLeader), {if (local (leader (_this select 0))) then {(_this select 0) selectLeader (_this select 1)}}] call CBA_fnc_addEventHandler;

Here is the code you would want changed so leadership of certain groups don't transfer.  CBA added the code; can CBA be used to change the code?

 

Go to CBA Events.  There are functions to add and remove event handlers, but not change or replace.  So what occurred when ACE added the event handler?

 

CBA Events fnc_addEventHandler.sqf shows how the call was dealt with.  QGVAR(selLeader) became an event handler type.  The code was stowed in an array (i.e., more than one block of code could get listed in the array).  When the QGVAR(selLeader) event gets called from the blackout scripts, each block of code listed in the array is run by the CBA localEvent function.

 

Could calling the CBA add and remove event functions remove that particular block of code and add a replacement code?  It might have been possible, but it turns out, no.  The addEventHandler script returns a handle which is needed to remove.  When ACE adds the eventHandler it doesn't capture the returned handle, so the handle becomes lost.

 

The event handler is stored in CBA_eventHandlers.  What is CBA_eventHandlers?  Go to CBA Events "XEH_preInit.sqf".  CBA_eventHandlers is a logic which gets created at preInit.

 

Could the stored handler array in the logic be queried?  Turns out yes, (CBA_eventHandlers getVariable "ace_sys_wounds_selleader") returns the array containing the blocks of code run when the event occurs.  After mission start, query of the array lists only the one block of code.

 

Could the code stored in the logic be directly changed after it was set during init?  Turns out, yes.  My test with the trigger showed that it could.

 

The found result is:  in logic CBA_eventHandlers you have a variable serving as an event handler.  The variable/event is "ace_sys_wounds_selLeader".  Its value is an array.  The array stores blocks of code.  Each of those blocks of code get run when the event occurs.  At mission start the array has only one block of code - that which you wish to change.

 

So in your init.sqf, change the code.

 

 

I'm hoping this was more clear than mud.  I took the journey so I understand, I hope you also can.

 

In your init.sqf try the following:

Spoiler

// Spawn, so waiting doesn't hold up the init.
_niv = [] spawn 
{
	// Define the new handler code, however you want certain groups not to transfer leadership, while others do the default; example:
	// GroupA, GroupB and GroupC are those which should not switch leaders.
	_newCode = 
	{
		if (local (leader (_this select 0))) then 
		{
			if !((_this select 0) in [groupA, groupB, groupC]) then 
			{
				(_this select 0) selectLeader (_this select 1)
			};
		}
	};

	// Wait for the CBA logic to be created.
	waitUntil {!isNull CBA_eventHandlers};

	// Wait for ACE Wounds to add the event handler to the logic.
	waitUntil {!isNil {CBA_eventHandlers getVariable "ace_sys_wounds_selleader"}};

	// Wait for the handler's array to have the original code.
	waitUntil {count (CBA_eventHandlers getVariable "ace_sys_wounds_selleader") > 0};

	// Replace the original code with the new code.
	CBA_eventHandlers setVariable ["ace_sys_wounds_selleader",[_newCode]];
};

 

 

Note:  I didn't do extensive playtesting.  This assumes ACE doesn't add any further blocks of code to the array during the mission.  When in doubt:

diag_log (CBA_eventHandlers getVariable "ace_sys_wounds_selleader");

and check the .rpt log.

Share this post


Link to post
Share on other sites

Hello opusfmspol thankyou for the reply.

 

This is outstanding! Brilliant stuff as always! Thankyou very much for helping us Arma 2 veterans, I salute you sir!

 

Going to review all segments now, hopefully get a much better understanding of CBA parameters, which always defeat me In the end, going to test out the new script, its looks god damn magnificent Captain! Epic as always! I'll post back ASAP.

 

Thanks again, hope to speak soon.

Share this post


Link to post
Share on other sites

Hello opusfmspol hope you are good.

 

Absolutely bloody brilliant Captain! 6 years tried to fix this issue! We Arma veterans owe you a beer sir! This is beyond World Class!

 

Its setup perfect, if the squad leader falls unconscious the whole screen including the HUD elements vanish, all you literally see is a black screen, nothing else, you have to prey that your medic attends to you. its bloody intense, and If you survived you will wake up, with all HUD elements in place. Fantastic! The best of all, the campaign continues, the server would have broke at that point.

 

Happy Holidays from myself and the Arma veterans!

 

Thanks again for your time and expertise on this server breaking issue, hope to speak soon.

 

 

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  

×