Jump to content

Recommended Posts

With @Larrow's assistance, I was able to hash out the program I wanted to manage my soldiers with addAction menus.  I will create a mod thread when I have the vehicle assignment actions added.

 

Full script:


myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { [ grpNull ] };
TAG_fnc_hasBlankHC = {
	_bool = false;
	{
		_x params[ "_HCGrp", "_HCActionID" ];
		
		if ( isNull _HCGrp ) exitWith {_bool = true;};
	}forEach myGrps;
	_bool;
};
TAG_fnc_isLastHCMan = {
	_bool = false;
	{
		_x params[ "_HCGrp", "_HCActionID" ];
		if (( Group cursorTarget isEqualTo _HCGrp ) && {{ alive _x }count units _HCGrp isEqualTo 1}) exitWith {_bool = true;};
	}forEach myGrps;
	_bool;	
};
TAG_fnc_JoinFunction = {
	_unit = _this select 0;
	_grp = _this select 1;
	_str = _this select 2;
	//accepting variable "unit or from Group" and "target group"
	if (_str == "unit") then {
		[_unit] joinSilent _grp;
	}else {
		{
			[ _x ] joinSilent _grp;
		}forEach units _unit;
	};	
		_leader = Leader _grp;
		{
			if(!(_leader isEqualTo _x) && {(rankId _x) > (rankId _leader)}) then {
				_leader = _x;
			};
		}forEach units _grp;
		_grp selectLeader _leader;
};
TAG_fnc_createNewHCGroup = {
	params[ "_unit", [ "_create", true ], [ "_wholeGroup", false ] ];
	
	_CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
	_PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
	_SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
		
	{
		_x params[ "_HCGrp", "_HCActionID" ];
		
		if ( !isNull _HCGrp && { { alive _x }count units _HCGrp isEqualTo 0 } ) then {
			
			deleteGroup _HCGrp;
			player hcRemoveGroup _HCGrp;
			
			if ( _HCActionID isEqualType 0 ) then {
				player removeAction _HCActionID;
			};
			
			myGrps set [ _forEachIndex, [ grpNull ] ];
			_HCGrp = grpNull;
		};
		
		if ( _create && { isNull _HCGrp } ) then {
			private [ "_group" ];
			
			if !( isPlayer _unit ) then {
				_group = createGroup side player;
			}else{
				_group = group player;
			};
			
			_group setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
				"Yankee",
				_CompanyNames select _forEachIndex,
				_PlatoonNames select _forEachIndex,
				_SquadNames select _forEachIndex
			];
			
			if !( _unit in units _group ) then {
				_oldGroup = group _unit;
				
				if ( _wholeGroup ) then {
					units _oldGroup joinSilent _group;
				}else{
					[ _unit ] joinSilent _group;
				};
				
				if ( count units _oldGroup isEqualTo 0 ) then {
					deleteGroup _oldGroup;
				};
			};
			
			_actionID = if !( isPlayer _unit ) then {
				player hcSetGroup [ _group ];
				[ _group ] call TAG_fnc_joinHCGroup;
				[ _group ] call TAG_fnc_groupJoinHCGroup;
			}else{
				objNull;
			};
			
			myGrps set [ _forEachIndex, [ _group, _actionID ] ];
			_create = false;
		};
	}forEach myGrps;
	
};

TAG_fnc_grpJoinMe = {  
	player addAction [ "Group Join Me", {
		cursorTarget setCaptive false;
		{[ _x ] joinSilent group player;}forEach units group cursorTarget;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
    	!(isnull cursortarget) && (_this isEqualTo _target) && {
			(cursorTarget isKindof 'Man') && {
				(alive cursortarget) && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						(leader group cursorTarget isEqualTo cursorTarget) && {
								({alive _x} count units group cursorTarget > 1) &&
								(({ alive _x } count units group cursorTarget) + ({ alive _x } count units group player) < 12)
							}
						}
					}
				}
			}"
	];
};

TAG_fnc_joinMe = {  
	player addAction [ "Join Me", {
		
		cursorTarget setCaptive false;
		[ cursorTarget ] joinSilent group player;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
    	!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						!(group cursortarget isEqualTo group player) && {
							({ alive _x } count units group player < 12) 
						}
					}
				}
			}
		}"
	];
};

TAG_fnc_groupJoinHCGroup = {
	params[ "_HCGrp" ];
	_actionID = player addAction [ format [ "Group Join %1", groupID _HCGrp ], {
		params[ "_target", "_caller", "_ID", "_args" ];
		[ Group cursorTarget, _args, "" ] call TAG_fnc_JoinFunction;
		if (Group cursorTarget in myGrps) then {
			[ objNull, false ] call TAG_fnc_createNewHCGroup;
		};
	}, _HCGrp, 1, false, true, "", format ["
		_group = %1 call BIS_fnc_groupFromNetId;
		!(isnull cursortarget) && (_this isEqualTo _target) && {
			(cursorTarget isKindof 'Man') && {
				(alive cursortarget) && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && { 
						(call TAG_fnc_hasBlankHC) && {
							!(Group cursorTarget isEqualTo _group) && { 
								!(Group player isEqualTo _group) && {
									(leader group cursorTarget isEqualTo cursorTarget) && {
										({ alive _x } count units (group cursorTarget) > 1) && {
											({ alive _x } count units (_group) > 0) &&
											(({ alive _x } count units (_group)) + ({ alive _x } count units cursorTarget) < 12)
										}
									}	
								}
							}
						}
					}
				}
			}
		}", str ( _HCGrp call BIS_fnc_netId ) ]
	];
	_actionID;
};
TAG_fnc_joinHCGroup = {
	params[ "_HCGrp" ];

	_actionID = player addAction [ format [ "Join %1", groupID _HCGrp ], {
		params[ "_target", "_caller", "_ID", "_args" ];

		[ cursorTarget, _args, "unit" ] call TAG_fnc_JoinFunction;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, _HCGrp, 1, false, true, "", format [ "
		_group = %1 call BIS_fnc_groupFromNetId;
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						!(group cursortarget isEqualTo _group) && {
							({ alive _x } count units (_group) > 0) &&
							({ alive _x } count units (_group) < 12) 
						}
					}
				}
			}
		}", str ( _HCGrp call BIS_fnc_netId ) ]
	];
	
	_actionID
};

TAG_fnc_HCActions = {
	
	player addAction [ "Unit to HC Group", {
		
		[ cursorTarget, true ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
							(call TAG_fnc_hasBlankHC)
					}
				}
			}
		}"
	];
	
	player addAction [ "Group to HC Group", {
		
		[ cursorTarget, true, true ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && { 
						!(hcLeader Group cursorTarget isEqualTo player) && {
							(call TAG_fnc_hasBlankHC) && { 
								leader group cursorTarget isEqualTo cursorTarget &&
								count units group cursorTarget > 1
							}
						}
					}	
				}
			}
		}"
	];
	
	player addAction [ "Dismiss HC Group", {
		
		player hcRemoveGroup group cursorTarget;
		{
			_x params[ "_group", "_action" ];
			if ( _group isEqualTo group cursorTarget ) exitWith {
				player removeAction _action;
				player hcRemoveGroup _group;
				myGrps set [ _forEachIndex, [ grpNull ] ];
			};
		}forEach myGrps;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						leader group cursorTarget isEqualTo cursorTarget &&
						{ group cursorTarget isEqualTo ( _x select 0 ) }count myGrps > 0
					}
				}
			}
		}"
	];
};

_null = [ player, true ] call TAG_fnc_createNewHCGroup;
_null = [] call TAG_fnc_joinMe;
_null = [] call TAG_fnc_grpJoinMe;
_null = [] call TAG_fnc_HCActions;

Share this post


Link to post
Share on other sites

I have a much much longer rough copy of this that allows me to add and remove from HC with no problems.  However, I am now using arrays and magic and trying to slim this thing down.  This is more than a third of the size compared to what it used to be, and is ALMOST where I want it.

 

Main issues:

1) Group ID format isn't right.  I've tried all sorts of syntax variations, I am unsure how to use format with:

 

_x setGroupId ["%GroupNames %GroupCompany %GroupPlatoon %GroupSquad","Yankee",format ['"%1","%2","%3"',_array1 select _foreachindex,_array2 select _foreachindex,_array3 select _foreachindex]];
        [_this] joinsilent (_x);

2) The next not so noticeable problem, but is to me, is that there are only supposed to be 9 HC teams at any given time.  The first group I assign is to be assigned to the player via:

null = player spawn formnewhcgroup;

This gets executed before the player uses action menu on new squads.  The idea is once select 0 is assigned to the player, the if conditions that search if the index isNil or has no alive players should always be false because player is in the group.  I can infinitely add HC groups from units on my side however, at least until i hit game array limitations...  this isn't intended.  I only want 10 groups because 9 HC groups are all f-keys register.  Anyways, I don't think I can declare my array like this:

 

mygrps = [grpNull];
for "_i" from 0 to 9 do {mygrps set [_i,grpNull];};

 

I'm used to actual languages that let me declare my array size and type without initializing it with anything.  Sadly, I had more luck with this monster:
 

mygrp0 = grpNull;
mygrp1 = grpNull;
mygrp2 = grpNull;
mygrp3 = grpNull;
mygrp4 = grpNull;
mygrp5 = grpNull;
mygrp6 = grpNull;
mygrp7 = grpNull;
mygrp8 = grpNull;
mygrp9 = grpNull;

mygrps  = [mygrp0,mygrp1,mygrp2,mygrp3,mygrp4,mygrp5,mygrp6,mygrp7,mygrp8,mygrp9];

I don't think my forEach loop is keeping mygrps unique.  I think the game registers isNil on every unit I select, even beyond 10 because select 1 never gets called.  I noticed the problem when my unit's group ID changed as soon as I recruited a man into my HC module.  I think they are hijacking select 0.

 

edit:

I think the difference is noticeable between my longer older variable array, and the newer grpNull array that is assigned inside of another scope locally, instead of being a global and passed in to be modified.

Share this post


Link to post
Share on other sites

One last thing, another potential problem I saw was what happens when a new magic is passed in?

 

{if ((isNil {_x}) || ({ alive _x } count units (_x) == 0)) exitWith {
        _x = createGroup side player;
        _x setGroupId ["%GroupNames %GroupCompany %GroupPlatoon %GroupSquad","Yankee",format ['"%1","%2","%3"',_array1 select _foreachindex,_array2 select _foreachindex,_array3 select _foreachindex]];
        [_this] joinsilent (_x);
        if!(isPlayer _this)then{player hcsetgroup [_x];};    
    };}forEach mygrps;

 

_x represents the magic for whatever is in that array index when it is iterated through.  but look at this little number:

 

({ alive _x } count units (_x) == 0)

count units (_x) is counting the units in magic variable _x for the groups I am iterating through.  Now look over at { alive _x }.  Alive _x gets passed in magic variable _x from count units, but doesn't _x already force alive _x to inherit it?  Or is it overwritten with the count units result?  I am curious.

Share this post


Link to post
Share on other sites
1 hour ago, stuguy said:

Group ID format isn't right.  I've tried all sorts of syntax variations, I am unsure how to use format with:

No need for format, the command itself is the format.

setGroupID [ "format code", name1, name2 ... nameN ]

 

1 hour ago, stuguy said:

The next not so noticeable problem, but is to me, is that there are only supposed to be 9 HC teams at any given time.

 

1 hour ago, stuguy said:

This gets executed before the player uses action menu on new squads.  The idea is once select 0 is assigned to the player, the if conditions that search if the index isNil

Its never Nil as you fill your array with grpNull's to begin with.

 

1 hour ago, stuguy said:

can infinitely add HC groups from units on my side however, at least until i hit game array limitations...  this isn't intended.

You never update your array with the created group, so each element is always grpNull.

 

1 hour ago, stuguy said:

Anyways, I don't think I can declare my array like this:

 


mygrps = [grpNull];
for "_i" from 0 to 9 do {mygrps set [_i,grpNull];};

There is nothing wrong with that, but there are easier ways to do it.

 

1 hour ago, stuguy said:

_x represents the magic for whatever is in that array index when it is iterated through.  but look at this little number:

 


({ alive _x } count units (_x) == 0)

Nothing wrong here either. As _x is a magic variable handled by the engine the _x in the scope of alive will not destroy/change the _x from the outer scope ( units _x ).

As they are treated as byValue rather than byReference even making changes to _x within the inner scope will still not destroy/change the outer scopes value. for instance..

{
    {
        if ( _x in [ 1, 3, 5 ] ) then {
            _x = 0;
        };
        systemChat format[ "Inner scope _x = %1", _x ];
    }count _x;
    systemChat format[ "Outer scope _x = %1", _x ];
}forEach [ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8, 9, 10 ] ];

 

Spoiler

myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { grpNull };


grpSigns = ["Join Y-X-1-1","Join Y-N-1-1","Join Y-N-1-2","Join Y-N-2-1","Join Y-N-2-2","Join Y-W-1-1","Join Y-W-1-2","Join Y-W-2-1","Join Y-W-2-2","Join Y-X-1-1","Join Y-X-1-2"];

TAG_fnc_formNewHCGroup = {
	params[ "_unit" ];
	
    _CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
    _PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
    _SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
    
    {
    	_x params[ "_grp" ];
    	if ( isNull _grp || { { alive _x } count units _grp == 0 } ) exitWith {
	        _newGrp = createGroup side player;
	        _newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
	        	"Yankee",
	        	_CompanyNames select _forEachIndex,
	        	_PlatoonNames select _forEachIndex,
	        	_SquadNames select _forEachIndex
	        ];
	        [ _unit ] joinSilent _newGrp;
	        myGrps set [ _forEachIndex, _newGrp ];
	        if !( isPlayer _unit ) then {
	        	player hcSetGroup [ _newGrp ];
	        };    
    	};
    }forEach myGrps;
};


TAG_fnc_joinMe = {
	params[ "_unit" ];
	
	_unit setCaptive false;
	_unit joinAsSilent [ group player, 2 ];
};

TAG_fnc_recruitFriendly = {  
    player addAction [ "Join Me", {
	    	cursorTarget call TAG_fnc_joinMe
	    },
	    nil,
	    1,
	    false,
	    true,
	    "",
	    "!( isNull cursorTarget ) && _this isEqualTo _target && { cursorTarget isKindof 'Man' && { alive cursorTarget && { side cursorTarget isEqualTo side player || captive cursorTarget }}}",
    ];
};

TAG_fnc_makeSquadLeader = {
    player addAction [ "Team Lead", {
    		cursorTarget call TAG_fnc_formNewHCGroup
    	},
    	nil,
    	1,
    	false,
    	true,
    	"",
    	"!(isnull cursortarget) && _this isEqualTo _target && { cursorTarget isKindof 'Man' && { alive cursorTarget && { ( side cursorTarget isEqualTo side player || captive cursorTarget ) && !(group cursorTarget in myGrps) }}}",
    ];
};

_null = player spawn TAG_fnc_formNewHCGroup;
_null = [] spawn TAG_fnc_recruitFriendly;
_null = [] spawn TAG_fnc_makeSquadLeader;
  • Array size and quick fill
  • Null test on array element
  • Correct formatting for setGroupID
  • Update myGrps with new group
  • Changes to action conditions & lazy eval

Untested, just reformatted with some of the changes as mentioned.

 

  • Like 1

Share this post


Link to post
Share on other sites

Thanks a ton.  I hope you enjoy your beer.

 

Quote

No need for format, the command itself is the format.

 


setGroupID [ "format code", name1, name2 ... nameN ]

 

I was aware that setGroupID had it's own format, but everything I was trying was throwing errors, and I couldn't find examples of working concepts with proper syntax making use of variables.  Thanks for supplying a fix, I will use that example in all future code from now on.  I hope it helps others too.

 

Quote

 

21 hours ago, stuguy said:

This gets executed before the player uses action menu on new squads.  The idea is once select 0 is assigned to the player, the if conditions that search if the index isNil

Its never Nil as you fill your array with grpNull's to begin with.

 

In previous code, I was explicitly checking for Group _this == grpNull.  However, I was getting "any".  So I tried a few different concepts.  My original code didn't use grpNull at all.  I used a switch statement and literally checked in and out squads.  The program was huge, but worked flawlessly.  Thanks for squaring this away.

 

Quote
21 hours ago, stuguy said:

Anyways, I don't think I can declare my array like this:

 



mygrps = [grpNull];
for "_i" from 0 to 9 do {mygrps set [_i,grpNull];};

There is nothing wrong with that, but there are easier ways to do it.

 

I saw the apply command and wanted to give it a go, but I am used to being able to cast an array type and size with one command.  I was experimenting with different ideas to reduce the amount of lines of code.  I love compact, efficient code.  The replacement you gave me works flawlessly, thank you.

 

Quote
21 hours ago, stuguy said:

_x represents the magic for whatever is in that array index when it is iterated through.  but look at this little number:

 



({ alive _x } count units (_x) == 0)

Nothing wrong here either. As _x is a magic variable handled by the engine the _x in the scope of alive will not destroy/change the _x from the outer scope ( units _x ).

As they are treated as byValue rather than byReference even making changes to _x within the inner scope will still not destroy/change the outer scopes value. for instance..

I spent some good amount of time trying to find more detailed documentation of magic variable inheritance, and cases where a new scope is initialized and local magic variables are the same as the level above it.  I was about to start testing with hint to make sure they were the same or not just to be sure.  Thanks for clarifying the inheritance of variables in that particular instance, more time saved. 

 

 

Quote
21 hours ago, stuguy said:

can infinitely add HC groups from units on my side however, at least until i hit game array limitations...  this isn't intended.

You never update your array with the created group, so each element is always grpNull.

I believed this was the case.  It was late and I didn't want to keep trying different methods to assign variables into my global array.  The setting of variables in my forEach array statement was genius.  You saved me quite a bit of time trying to come up with that solution.

 

 

Overall, the program was solid.  There were two serious bugs however.  The syntax:

//your condition in TAG_fnc_recruitFriendly

 "!( isNull cursorTarget ) && _this isEqualTo _target && { cursorTarget isKindof 'Man' && { alive cursorTarget && { side cursorTarget isEqualTo side player || captive cursorTarget }}}",

//should be

'(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(group player == group cursorTarget) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false
  
//your condition in TAG_fnc_makeSquadLeader
"!(isnull cursortarget) && _this isEqualTo _target && { cursorTarget isKindof 'Man' && { alive cursorTarget && { ( side cursorTarget isEqualTo side player || captive cursorTarget ) && !(group cursorTarget in myGrps) }}}",
    
//should be
'(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(Group cursortarget in mygrps) || (Group cursorTarget == Group player) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false

That was a quick fix when the debugger threw the error.  My IDE had the entire section colored like a string, where as the original was colored properly like code.  I copy pasted previously working code and that fixed that.

 

I also added a case that prevented me from passing units that were already in MyGrps[index] back into makesquadleader.  The new code looks like this:

 

myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { grpNull };
grpSigns = ["Me","Y-N-1-1","Y-N-1-2","Y-N-2-1","Y-N-2-2","Y-W-1-1","Y-W-1-2","Y-W-2-1","Y-W-2-2","Y-X-1-1","Y-X-1-2"];
TAG_fnc_formNewHCGroup = {
	params[ "_unit" ];
    _CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
    _PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
    _SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
    {
    	_x params[ "_grp" ];
    	if ( isNull _grp || { { alive _x } count units _grp == 0 } ) exitWith {
	        _newGrp = createGroup side player;
	        _newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
	        	"Yankee",
	        	_CompanyNames select _forEachIndex,
	        	_PlatoonNames select _forEachIndex,
	        	_SquadNames select _forEachIndex
	        ];
	        [ _unit ] joinSilent _newGrp;
	        myGrps set [ _forEachIndex, _newGrp ];
	        if !( isPlayer _unit ) then {
	        	player hcSetGroup [ _newGrp ];
	        };    
    	};
    }forEach myGrps;
};
TAG_fnc_joinMe = {
	params[ "_unit" ];
	_unit setCaptive false;
	_unit joinAsSilent [ group player, 2 ];
};
TAG_fnc_recruitFriendly = {  
	player addaction ["Join Me", {cursorTarget call TAG_fnc_joinMe},nil,1,false,true,"",format ['(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(group player == group cursorTarget) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false];
};
TAG_fnc_makeSquadLeader = {
    player addaction ["Team Lead", {cursorTarget call TAG_fnc_formNewHCGroup},nil,1,false,true,"",format ['(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(Group cursortarget in mygrps) || (Group cursorTarget == Group player) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false];
};
_null = player spawn TAG_fnc_formNewHCGroup;
_null = [] spawn TAG_fnc_recruitFriendly;
_null = [] spawn TAG_fnc_makeSquadLeader;

This program works as intended.  To use, the mission only needs a player with High command module synced to him and a HC sub command synced to that in GEeditor.  This code can be run via sqf or executed in the debug console.  It takes a few seconds for the action menus to pop up, but they work.

 

 

What's it all do?  For those wondering.  Your player becomes high commander and can easily walk up to units in his faction and wheel mouse units into his group, or add them to a squad leader subordinate.  It also allows you to pull subordinates back into your squad via wheel mouse.  Quick and easy peasy.  My other mile long script has join HC squad actions and add vehicle actions, but the vehicle part is riddled with bugs.  I will add those in another thread later.

  • Like 1

Share this post


Link to post
Share on other sites

I hit another road block and I have been scrambling for sources and tricks to get around this.  I am still working on my squad management script for easy troop management on the fly.  To make things tidy and more compact, I wanted to fire off a bunch of add actions all at once in a {}forEach array; statement.  However, the magic variables do not pass into the addAction, with the exception of the addAction string.  _forEachIndex passes into the first segment for name string.  However, magic _x and _forEachIndex do NOT pass down into the code or string of conditions segments, which I need to make each addAction unique.  So I will edit the post above this one to give it the latest WORKING code that allows me to add and remove troops.  I will then post the code I am experimenting with in this post.  I have a working model already, but I had to manually declare each and every addAction, 9 times...not ideal.  I want to handle it in a loop with magic, if possible.  I'm hoping it isn't something dumb like create local variables before the addAction that equal my magic that is getting the axe in addAction.  Which...come to think of it, namespaces and locals are worth trying.

 

	{
		player addaction [format ["Join %1",grpSigns select _forEachIndex], {cursortarget joinAssilent [_x,2]},nil,1,false,true,"",format ['
		(!(isnull cursortarget) 
		&& (alive cursortarget)
		&& ((side cursortarget) == side player)		
		&& !(group cursortarget == _x) 
		&& ({ alive _x } count units (_x) > 0) 
		&& ({ alive _x } count units (_x) < 12) 
		&& (cursorTarget isKindof "Man") 
		&& !((side cursortarget) == civilian) 
		|| (captive cursorTarget))'],15,false];
	}forEach myGrps;

 

edit: this code segment will replace :

TAG_fnc_recruitFriendly

 

as I am attempting to design this to allow the player to recruit units into his team or his subordinate teams.

Share this post


Link to post
Share on other sites

Thank you for the beer :)

 

9 hours ago, stuguy said:

There were two serious bugs however.  The syntax:


//your condition in TAG_fnc_recruitFriendly

 "!( isNull cursorTarget ) && _this isEqualTo _target && { cursorTarget isKindof 'Man' && { alive cursorTarget && { side cursorTarget isEqualTo side player || captive cursorTarget }}}",

//should be

'(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(group player == group cursorTarget) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false
  
//your condition in TAG_fnc_makeSquadLeader
"!(isnull cursortarget) && _this isEqualTo _target && { cursorTarget isKindof 'Man' && { alive cursorTarget && { ( side cursorTarget isEqualTo side player || captive cursorTarget ) && !(group cursorTarget in myGrps) }}}",
    
//should be
'(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(Group cursortarget in mygrps) || (Group cursorTarget == Group player) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false

That was a quick fix when the debugger threw the error.  My IDE had the entire section colored like a string, where as the original was colored properly like code.

The condition of an action is a String, as you can see from the above quote, all four lines are coloured green as String.

The problem with your conditions is that they are..

  • Not lazy evaluated, so even if the cursortarget is Null the rest of the condition is still evaluated.
  • You check the side and group of cursorTarget before even checking that it is a valid Man.
  • You check for not side civillian after you have already evaluated side is equal to player
  • No need to specifically specify 15, false and these are default values.
  • I added _this isEqualTo _target so as stop in MP one player accessing actions on another player
"
	!( isNull cursorTarget ) && _this isEqualTo _target && {	//if is null or user not actions host then exit with false
		cursorTarget isKindof 'Man' && {	//If not a man exit as false
			alive cursorTarget && {			//If not alive exit as false
				side cursorTarget isEqualTo side player || captive cursorTarget //If not side player or captive then false
			}
		}
	}
"

You have to remember that these actions are placed on the player and as such they will be evaluated each frame. Using lazy eval will make sure the condition is exited quickly when one of the condition is false, plus also stops evaluations on a null if there is no cursorTarget.

 

 

2 hours ago, stuguy said:

I have a working model already, but I had to manually declare each and every addAction, 9 times...not ideal.  I want to handle it in a loop with magic, if possible.  I'm hoping it isn't something dumb like create local variables before the addAction that equal my magic that is getting the axe in addAction.  Which...come to think of it, namespaces and locals are worth trying.

The code is deferred until the action is used, by this time the action has no idea what _x represents. Use the arguments part of the action to pass in the value.

Same with the condition, here you will need to format in something that can be reconstructed as a group, below I use the BI functions for netID which are SP compatible and format it into the condition as a String. When the condition is evaluated the String is reconstructed back into a group.

{
	player addAction [ format [ "Join %1", groupID _x ], {
			params[ "_target", "_caller", "_ID", "_args" ];
			cursorTarget joinAsSilent [ _args, 2 ];
		},
		_x,	//Pass group as argument into action
		1,false,true,"",
					//vvv reconstruct NetID into group
		format [ "
			_group = %1 call BIS_fnc_groupFromNetId;
			!(isnull cursortarget) && _this isEqualTo _target && {
				cursorTarget isKindof 'Man' && {
					alive cursortarget && {
						( side cursortarget isEqualTo side player || captive cursorTarget ) && {
							!(group cursortarget isEqualTo _group) && {
								({ alive _x } count units (_group) > 0) &&
								({ alive _x } count units (_group) < 12) 
							}
						}
					}
				}
			}
	", str ( _x call BIS_fnc_netId ) ]];	//Format NetID of group as String into condition
}forEach myGrps;

 

Share this post


Link to post
Share on other sites
11 hours ago, stuguy said:

I was explicitly checking for Group _this == grpNull.

You cannot compare ( == ) a null group.

grpNull == grpNull	//false
grpNull isEqualTo grpNull	//true
isNull grpNull	//true

 

Share this post


Link to post
Share on other sites

Thanks for the response.  Just wanted to point out that in the addAction condition section, you are correct that it takes string.  However, if we use format in place of the string, you can't use format [" ",_vars].  You must use format[' ',_vars].  Because the section is technically a string, putting a string type command in a string requires the inverse character ', not ".

Share this post


Link to post
Share on other sites

I updated the code to where I was going with it.  There were some syntax errors in what you had, but for the most part, once again, solid code.  There was a bug, or I say, a lack of compatibility between your code and my entire program.  So I rewrote the program and edited this post. 

 

edit: There is now a bug in this program that prevents the player from joining myGrps select 0 and forces the myGrps select 0 to always be used for all joining.  I am trying to squash.

edit2: I squashed most bugs.  I had to rewrite fnc_frmNewHCGrp a tad in the middle.  I also wasn't evaluating the if conditions to fit what I was trying to do exactly right.  There was still a hiccup, but the code seemed to execute mostly correct.  I am checking multiple times to make sure this isn't some sort of problem with the scheduler.

edit3: I reproduced the "bug".  So the code executes and runs fine, but if I add a guy to a new team and bring him back into my squad, that team is no longer available to my recUnit function.  It would have to do with a condition in that function...  I can, however, add a leader back into that squadron, but the recUnit will not see him anymore.  I am leaning on:

 

 

myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { grpNull };
TAG_fnc_frmNewHCGrp = {
	params[ "_unit" ];
    _CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
    _PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
    _SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
    {
    	_x params[ "_grp" ];
    	if ( isNull _grp ) then {
	        _newGrp = createGroup side player;
	        _newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
	        	"Yankee",
	        	_CompanyNames select _forEachIndex,
	        	_PlatoonNames select _forEachIndex,
	        	_SquadNames select _forEachIndex
	        ];
			myGrps set [ _forEachIndex, _newGrp ];
		};
	    if (!( isNull _unit ) && ( { alive _x } count units _grp == 0 ))  exitWith {
			[ _unit ] joinSilent _grp;
			if !( isPlayer _unit ) then {
	        	player hcSetGroup [ _grp ];
	        };
	    };    
	}forEach myGrps;
};
TAG_fnc_joinMe = {
	params[ "_unit","_grp" ];
	_unit setCaptive false;
	_unit joinAsSilent [ _grp, 2 ];
};
TAG_fnc_recUnit = {
	{
		player addAction [ format [ "Join %1", groupID _x ], {
				params[ "_target", "_caller", "_ID", "_args" ];
				[ cursorTarget, _args ] call TAG_fnc_JoinMe;
			},_x,1,false,true,"",format ['
				_group = %1 call BIS_fnc_groupFromNetId;
				!(isnull cursortarget) 
				&& (_this isEqualTo _target) 
					&& {(cursorTarget isKindof "Man")
						&& {(alive cursortarget) 
							&& {( side cursortarget isEqualTo side player || captive cursorTarget ) 
								&& {!(group cursortarget isEqualTo _group) 
									&& {({ alive _x } count units (_group) > 0 ) && ({ alive _x } count units (_group) < 12) 
								}
							}
						}
					}
				}', str ( _x call BIS_fnc_netId ) ],15,false];
	}forEach myGrps;
};
TAG_fnc_mkSqLead = {
    player addaction ["Team Lead", {cursorTarget call TAG_fnc_frmNewHCGrp},nil,1,false,true,"",format ['(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(Group cursortarget in mygrps) || (Group cursorTarget == Group player) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false];
};
_null = objNull spawn TAG_fnc_frmNewHCGrp;
_null = [player, (myGrps select 0)] spawn TAG_fnc_frmNewHCGrp;
_null = [] spawn TAG_fnc_recUnit;
_null = [] spawn TAG_fnc_mkSqLead;

but I don't see yet why this would permanently remove an option for a squad that should eventually become true again.

 

Current Program:

myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { grpNull };
TAG_fnc_frmNewHCGrp = {
	params[ "_unit" ];
    _CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
    _PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
    _SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
    {
    	_x params[ "_grp" ];
    	if ( isNull _grp ) then {
	        _newGrp = createGroup side player;
	        _newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
	        	"Yankee",
	        	_CompanyNames select _forEachIndex,
	        	_PlatoonNames select _forEachIndex,
	        	_SquadNames select _forEachIndex
	        ];
			myGrps set [ _forEachIndex, _newGrp ];
		};
	    if (!( isNull _unit ) && !( { alive _x } count units _grp > 0 ))  exitWith {
			[ _unit ] joinSilent _grp;
			if !( isPlayer _unit ) then {
	        	player hcSetGroup [ _grp ];
	        };
	    };    
	}forEach myGrps;
};
TAG_fnc_joinMe = {
	params[ "_unit","_grp" ];
	_unit setCaptive false;
	_unit joinAsSilent [ _grp, 2 ];
};
TAG_fnc_recUnit = {
	{
		player addAction [ format [ "Join %1", groupID _x ], {
				params[ "_target", "_caller", "_ID", "_args" ];
				[ cursorTarget, _args ] call TAG_fnc_JoinMe;
			},_x,1,false,true,"",format ['
				_group = %1 call BIS_fnc_groupFromNetId;
				!(isnull cursortarget) && (_this isEqualTo _target) 
					&& {(cursorTarget isKindof "Man")
						&& {(alive cursortarget) 
							&& {( side cursortarget isEqualTo side player || captive cursorTarget ) 
								&& {!(group cursortarget isEqualTo _group) 
									&& {({ alive _x } count units (_group) > 0 ) && ({ alive _x } count units (_group) < 12) 
								}
							}
						}
					}
				}', str ( _x call BIS_fnc_netId ) ],15,false];
	}forEach myGrps;
};
TAG_fnc_mkSqLead = {
    player addaction ["Team Lead", {cursorTarget call TAG_fnc_frmNewHCGrp},nil,1,false,true,"",format ['(!(isnull cursortarget) && (alive cursortarget) && ((side cursortarget) == side player) && !(Group cursortarget in mygrps) || (Group cursorTarget == Group player) && (cursorTarget isKindof "Man")) && !((side cursortarget) == civilian) || (captive cursorTarget)'],15,false];
};
_null = objNull spawn TAG_fnc_frmNewHCGrp;
_null = player spawn TAG_fnc_frmNewHCGrp;
_null = [] spawn TAG_fnc_recUnit;
_null = [] spawn TAG_fnc_mkSqLead;

edit: The bug, I believe, is in the conditions.  For some odd reason, it only allows for the joining of the player group.  I am going to set the whole condition to "true" and see if there are any other errors.

Share this post


Link to post
Share on other sites

Hmm.  It seems your code does not pass any arguments when the forEach loop iterates through the next cycle.  For the next 9 squads, there is no squad ID, and selecting the action does nothing because no arguments were passed into

TAG_fnc_joinMe

edit: I know why.  The squads are not created at compilation, they are created during runtime as needed.  So when the addActions are created, there are no squad strings or group variables for it to pass, as the 9 of them are grpNull until assigned.  I will have to force the code to createGroup and ID on compilation, but keep the squads blank of units, save the player's group.

 

edit2: I just want to clarify, your code was most likely written for the singular part of the program, and it works with minor syntax corrections.  However, I have to change the program to work with your code, which I needed and thank you for :)

 

edit3: I updated the program above this post.  It still has bugs and I am trying to squash, if you don't see an update, feel free to give your thoughts.

 

Share this post


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

However, if we use format in place of the string, you can't use format [" ",_vars].  You must use format[' ',_vars].  Because the section is technically a string, putting a string type command in a string requires the inverse character ', not ".

Sorry but you are mistaken, manually placing a String in another String you would need to use the opposite quotes from the outer pair e.g

"This is a String containing 'another String'"

OR

you can double quote it

"This is a String containing ""another String"""

However formatting one String into another will not break it e.g

str name player

would retrun "Larrow" yet

format[ "My players name is %1", str name player]

will produce "My players name is ""Larrow""" where the internal string is double quoted for you.

 

My code in the previous post was not meant as a direct fix but only to show how to get your variables into the action and was tested as working by replacing myGrps with the groups of four units I had placed in the editor.

 

1 hour ago, stuguy said:

For the next 9 squads, there is no squad ID, and selecting the action does nothing because no arguments were passed into

In TAG_fnc_formNewHCGroup when you update the myGrps with the newly created group, if it was a null entry also create the action on the player.

You could even extend the functionality by saving the actionID along with the group in myGrps. During the iteration you could check each group for any remaining units and if there are none clean up the group by deleting it and removing the associated action from the player.

Share this post


Link to post
Share on other sites
1 hour ago, Larrow said:

Sorry but you are mistaken, manually placing a String in another String you would need to use the opposite quotes from the outer pair e.g


"This is a String containing 'another String'"

OR

you can double quote it


"This is a String containing ""another String"""

However formatting one String into another will not break it e.g


str name player

would retrun "Larrow" yet


format[ "My players name is %1", str name player]

will produce "My players name is ""Larrow""" where the internal string is double quoted for you.

 

My code in the previous post was not meant as a direct fix but only to show how to get your variables into the action and was tested as working by replacing myGrps with the groups of four units I had placed in the editor.

 

In TAG_fnc_formNewHCGroup when you update the myGrps with the newly created group, if it was a null entry also create the action on the player.

You could even extend the functionality by saving the actionID along with the group in myGrps. During the iteration you could check each group for any remaining units and if there are none clean up the group by deleting it and removing the associated action from the player.

 

I just updated the program.  See two posts above your last response. 

 

edit: mostly squashed now.  In the last test, myGrps selec 1 didn't register as an option for other men to join, but all the other HC squads, including mine, did register in the action menu.  I am retesting and making sure this isn't some wierd delay.

edit2: I figured out what was going on.  Though I am still stumped.  I updated my post above.

Share this post


Link to post
Share on other sites

I can't figure it out.  I've been at it all day.  I've tried hundreds of different ways of creating my teams using loops for the addActions but they just don't seem to want to cooperate.  Manually assigning them one by one just seems to be the easiest way.  I will submit two programs.  Both are similar, but only one allows you to fully add and remove the units from all teams at once.  I have a third program, but it was miles long and i wanted to avoid such travesty.

 

Doesn't quite work, all teams other than player's team do not register as select-able options:

myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { grpNull };

TAG_fnc_initHCGrps = {
	{
    	_newGrp = createGroup side player;
	    _newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad","Yankee",CompanyNames select _forEachIndex,PlatoonNames select _forEachIndex,SquadNames select _forEachIndex];
		myGrps set [ _forEachIndex, _newGrp ];	   
	}forEach myGrps;
};
TAG_fnc_frmNewHCGrp = {
	params[ "_unit" ];
    _CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
	_PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
	_SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
	{
		_x params[ "_grp" ];
		switch (_unit) do {
			case "init": {
				_newGrp = createGroup side player;
				_newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
					"Yankee",
					_CompanyNames select _forEachIndex,
					_PlatoonNames select _forEachIndex,
					_SquadNames select _forEachIndex
				];
				if !(Group player isEqualTo (myGrps select 0)) then {
					[ player ] joinSilent _newGrp select 0;
				};
				myGrps set [ _forEachIndex, _newGrp ];
			};
			default {
				if (( isNull _grp ) || ( { alive _x } count units _grp == 0 )) exitWith {
					_newGrp = createGroup side player;
					_newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
						"Yankee",
						_CompanyNames select _forEachIndex,
						_PlatoonNames select _forEachIndex,
						_SquadNames select _forEachIndex
					];
					[ _unit ] joinSilent _newGrp;
					player hcSetGroup [ _newGrp ];
					myGrps set [ _forEachIndex, _newGrp ];
				};
			};
		};
	}forEach myGrps;
};
TAG_fnc_joinMe = {
	params[ "_unit","_grp" ];
	_unit setCaptive false;
	_unit joinAsSilent [ _grp, 2 ];
};
TAG_fnc_recUnit = {
	{
		player addAction [ format [ "Join %1", groupID _x ], {
				params[ "_target", "_caller", "_ID", "_args" ];
				[ cursorTarget, _args ] call TAG_fnc_JoinMe;
			},_x,1,false,true,"",format ['
				_group = %1 call BIS_fnc_groupFromNetId;
				!(isnull cursortarget) 
				&& (_this isEqualTo _target) 
					&& {(cursorTarget isKindof "Man")
						&& {(alive cursortarget) 
							&& {( side cursortarget isEqualTo side player || captive cursorTarget ) 
								&& {!(group cursortarget isEqualTo _group) 
									&& {({ alive _x } count units (_group) > 0 ) && ({ alive _x } count units (_group) < 12) 
								}
							}
						}
					}
				}', str ( _x call BIS_fnc_netId )],15,false];
	}forEach myGrps;
};
TAG_fnc_mkSqLead = {
    player addaction ["Team Lead", {cursorTarget call TAG_fnc_frmNewHCGrp},nil,1,false,true,"",format ['(
		!(isnull cursortarget)
		&& {(cursorTarget isKindof "Man")
			&& {(alive cursortarget) 
				&& {( side cursortarget isEqualTo side player || captive cursorTarget ) 
					&& {!(Group cursortarget in myGrps ) || ( Group cursorTarget isEqualTo Group player)
					}
				}
			}
		})'],15,false];
};

_null = "init" spawn TAG_fnc_frmNewHCGrp;
_null = [] spawn TAG_fnc_recUnit;
_null = [] spawn TAG_fnc_mkSqLead;

 

If I remove some of the conditions from the program in the recUnit function, I can assign units to all teams, but it is unsightly and I can add units to a team until the game crashes:

 

myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { grpNull };

TAG_fnc_initHCGrps = {
	{
    	_newGrp = createGroup side player;
	    _newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad","Yankee",CompanyNames select _forEachIndex,PlatoonNames select _forEachIndex,SquadNames select _forEachIndex];
		myGrps set [ _forEachIndex, _newGrp ];	   
	}forEach myGrps;
};
TAG_fnc_frmNewHCGrp = {
	params[ "_unit" ];
    _CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
	_PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
	_SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
	{
		_x params[ "_grp" ];
		switch (_unit) do {
			case "init": {
				_newGrp = createGroup side player;
				_newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
					"Yankee",
					_CompanyNames select _forEachIndex,
					_PlatoonNames select _forEachIndex,
					_SquadNames select _forEachIndex
				];
				if !(Group player isEqualTo (myGrps select 0)) then {
					[ player ] joinSilent _newGrp select 0;
				};
				myGrps set [ _forEachIndex, _newGrp ];
			};
			default {
				if (( isNull _grp ) || ( { alive _x } count units _grp == 0 )) exitWith {
					_newGrp = createGroup side player;
					_newGrp setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
						"Yankee",
						_CompanyNames select _forEachIndex,
						_PlatoonNames select _forEachIndex,
						_SquadNames select _forEachIndex
					];
					[ _unit ] joinSilent _newGrp;
					player hcSetGroup [ _newGrp ];
					myGrps set [ _forEachIndex, _newGrp ];
				};
			};
		};
	}forEach myGrps;
};
TAG_fnc_joinMe = {
	params[ "_unit","_grp" ];
	_unit setCaptive false;
	_unit joinAsSilent [ _grp, 2 ];
};
TAG_fnc_recUnit = {
	{
		player addAction [ format [ "Join %1", groupID _x ], {
				params[ "_target", "_caller", "_ID", "_args" ];
				[ cursorTarget, _args ] call TAG_fnc_JoinMe;
			},_x,1,false,true,"",format ['
				_group = %1 call BIS_fnc_groupFromNetId;
				!(isnull cursortarget) 
				&& {(cursorTarget isKindof "Man")
					&& {(alive cursortarget) 
						&& {( side cursortarget isEqualTo side player || captive cursorTarget) 
							//&& {!(group cursortarget isEqualTo _group) 
								//&& {({ alive _x } count units (_group) > 0 ) && ({ alive _x } count units (_group) < 12) 
								//}
							//}
						}
					}
				}', str ( _x call BIS_fnc_netId )],15,false];
	}forEach myGrps;
};
TAG_fnc_mkSqLead = {
    player addaction ["Team Lead", {cursorTarget call TAG_fnc_frmNewHCGrp},nil,1,false,true,"",format ['(
		!(isnull cursortarget)
		&& {(cursorTarget isKindof "Man")
			&& {(alive cursortarget) 
				&& {( side cursortarget isEqualTo side player || captive cursorTarget ) 
					&& {!(Group cursortarget in myGrps ) || ( Group cursorTarget isEqualTo Group player)
					}
				}
			}
		})'],15,false];
};

_null = "init" spawn TAG_fnc_frmNewHCGrp;
_null = [] spawn TAG_fnc_recUnit;
_null = [] spawn TAG_fnc_mkSqLead;

 

Share this post


Link to post
Share on other sites

Something like... ?

Test Mission

Spoiler


myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { [ grpNull ] };

TAG_fnc_createNewHCGroup = {
	params[ "_unit", [ "_create", true ], [ "_wholeGroup", false ] ];
	
	_CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
	_PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
	_SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
		
	{
		_x params[ "_HCGrp", "_HCActionID" ];
		
		if ( !isNull _HCGrp && { { alive _x }count units _HCGrp isEqualTo 0 } ) then {
			
			deleteGroup _HCGrp;
			player hcRemoveGroup _HCGrp;
			
			if ( _HCActionID isEqualType 0 ) then {
				player removeAction _HCActionID;
			};
			
			myGrps set [ _forEachIndex, [ grpNull ] ];
			_HCGrp = grpNull;
		};
		
		if ( _create && { isNull _HCGrp } ) then {
			private [ "_group" ];
			
			if !( isPlayer _unit ) then {
				_group = createGroup side player;
			}else{
				_group = group player;
			};
			
			_group setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
				"Yankee",
				_CompanyNames select _forEachIndex,
				_PlatoonNames select _forEachIndex,
				_SquadNames select _forEachIndex
			];
			
			if !( _unit in units _group ) then {
				_oldGroup = group _unit;
				
				if ( _wholeGroup ) then {
					units _oldGroup joinSilent _group;
				}else{
					[ _unit ] joinSilent _group;
				};
				
				if ( count units _oldGroup isEqualTo 0 ) then {
					deleteGroup _oldGroup;
				};
			};
			
			_actionID = if !( isPlayer _unit ) then {
				player hcSetGroup [ _group ];
				[ _group ] call TAG_fnc_joinHCGroup
			}else{
				objNull
			};
			
			myGrps set [ _forEachIndex, [ _group, _actionID ] ];
			_create = false;
		};
	}forEach myGrps;
	
};


TAG_fnc_recruitFriendly = {  
	player addAction [ "Join Me", {
		
		cursorTarget setCaptive false;
		[ cursorTarget ] joinSilent group player;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
    	!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						!(group cursortarget isEqualTo group player) && {
							({ alive _x } count units group player < 12) 
						}
					}
				}
			}
		}"
	];
};

TAG_fnc_joinHCGroup = {
	params[ "_HCGrp" ];

	_actionID = player addAction [ format [ "Join %1", groupID _HCGrp ], {
		params[ "_target", "_caller", "_ID", "_args" ];

		[ cursorTarget ] joinSilent _args;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, _HCGrp, 1, false, true, "", format [ "
		_group = %1 call BIS_fnc_groupFromNetId;
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						!(group cursortarget isEqualTo _group) && {
							({ alive _x } count units (_group) > 0) &&
							({ alive _x } count units (_group) < 12) 
						}
					}
				}
			}
		}", str ( _HCGrp call BIS_fnc_netId ) ]
	];
	
	_actionID
};

TAG_fnc_HCActions = {
	
	player addAction [ "Unit to HC Group", {
		
		[ cursorTarget, true ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget )
				}
			}
		}"
	];
	
	player addAction [ "Group to HC Group", {
		
		[ cursorTarget, true, true ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						leader group cursorTarget isEqualTo cursorTarget &&
						count units group cursorTarget > 1
					};
				}
			}
		}"
	];
	
	player addAction [ "Dismiss HC Group", {
		
		player hcRemoveGroup group cursorTarget;
		{
			_x params[ "_group", "_action" ];
			if ( _group isEqualTo group cursorTarget ) exitWith {
				player removeAction _action;
				player hcRemoveGroup _group;
				myGrps set [ _forEachIndex, [ grpNull ] ];
			};
		}forEach myGrps;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						leader group cursorTarget isEqualTo cursorTarget &&
						{ group cursorTarget isEqualTo ( _x select 0 ) }count myGrps > 0
					};
				}
			}
		}"
	];
};

_null = [ player, true ] call TAG_fnc_createNewHCGroup;
_null = [] call TAG_fnc_recruitFriendly;
_null = [] call TAG_fnc_HCActions;

 

 

  • Like 1

Share this post


Link to post
Share on other sites
8 hours ago, Larrow said:

Something like... ?

My God man!  You coded like a maniac there.  Yes, this program is solid.  I could either have a working program with a bug that prevented other units from joining an HC squad if he had previously joined my squad, or had a program that constantly listed all options in order to function.  What you have here is brilliant.  I saw how you check in and out the old squads by removing them if someone leaves a group.  I think that would help efficiency by erasing unused assets.  I like the group join feature as well.  I was thinking to add those in myself but you beat me to it.  There are just a few more conditions I need to add, like not allowing for the option to create new teams if units are present in all HC groups, not allowing team leaders to create new groups, apply add group feature only to group leaders, and allow players to add groups to his own squad too.  Thanks again.  I hope you enjoy your frosty beverage :D

 

edit:

@Larrow I keep seeing

_this isEqualTo _target

is _this the group argument?  I am unsure what is passed into the string section of addAction, or how _target and _ID and all those others are passed in.  I do understand params aand how it can be used to pull out variables.  So my guess is that addAction passes in certain criteria in a certain order, though I am unsure what that is.

Share this post


Link to post
Share on other sites

EDIT: I'm dumb.  I was editing the wrong files.   I got the group add to me feature working.

I added this little doodad and it will not work.  I checked the individual conditions and they should work... 

TAG_fnc_grpJoinMe = {  
	player addAction [ "Group Join Me", {
		cursorTarget setCaptive false;
		{[ _x ] joinSilent group player;}forEach units group cursorTarget;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
    	!(isnull cursortarget) && (_this isEqualTo _target) && {
			(cursorTarget isKindof 'Man') && {
				(alive cursortarget) && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						(leader group cursorTarget isEqualTo cursorTarget) && {
								({alive _x} count units group cursorTarget > 1) &&
								(({ alive _x } count units group cursorTarget) + ({ alive _x } count units group player) < 12)
							};
						}
					}
				}
			}
		}"
	];
};
_null = [] call TAG_fnc_grpJoinMe;

I figured out how to use the HCActions.  So I was able to get a mock draft of groupJoinHCGroup working.  However, I cannot modify the conditions.  The game ignores any attempt I make to add logic to prevent redundant commands or ineligible conditions.  Below, the game ignores the ({ alive _x } count units (group cursorTarget) > 1) condition.  To fire this function, I added an additional call in the TAG_fnc_createNewHCGroup function.

 

TAG_fnc_groupJoinHCGroup = {
	params[ "_HCGrp" ];
	_actionID = player addAction [ format [ "Group Join %1", groupID _HCGrp ], {
		params[ "_target", "_caller", "_ID", "_args" ];
		[ Group cursorTarget, _args, "" ] call TAG_fnc_JoinFunction;
		//{[ _x ] joinSilent _args;}forEach units Group cursorTarget;
		if (Group cursorTarget in myGrps) then {
			[ objNull, false ] call TAG_fnc_createNewHCGroup;
		};
	}, _HCGrp, 1, false, true, "", format [ "
		_group = %1 call BIS_fnc_groupFromNetId;
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						!(group cursortarget isEqualTo _group) && {
							(leader group cursorTarget isEqualTo cursorTarget) && {
								({ alive _x } count units (group cursorTarget) > 1) && {
									({ alive _x } count units (_group) > 0) &&
									(({ alive _x } count units (_group)) + ({ alive _x } count units cursorTarget) < 12)
								{
							}
						}
					}
				}
			}
		}", str ( _HCGrp call BIS_fnc_netId ) ]
	];
	_actionID
};                          

 

 

 

Share this post


Link to post
Share on other sites

I'm also thinking about writing up a call function for adding units to groups instead of using joinSilent in the addAction code block.  I like joinAsSilent because I can specify an index.  I usually select 2 because it is not leader.  I do, however, want all units being added individually to the group check their ranks.  I always want the highest rank to promote himself to 1.  Thus, I will write a call function for adding units individually.  I'm thinking along the lines of checking forEach units in the receiving group, and mark which index is highest rank.  Then compare the index with the unit being added and see which is higher.  Whoever is higher joinAsSilent 1 and the other joinAsSilent 2.  I'm not asking for a code, I want to try something first :)

 

fn_GetRankNum = {
	_rankNum = "none";
	switch (rank _this) do {  
		case "PRIVATE" : {_rankNum = 1;};
		case "CORPORAL" : {_rankNum = 2;};
		case "SERGEANT" : {_rankNum = 3;};
		case "LIEUTENANT" : {_rankNum = 4;};
		case "CAPTAIN" : {_rankNum = 5;};
		case "MAJOR" : {_rankNum = 6;};
		case "COLONEL" : {_rankNum = 7;};
		default {_rankNum = 0;};
	};
	_rankNum;
};
TAG_fnc_JoinFunction = {
	_unit = _this select 0;
	_grp = _this select 1;
	_str = _this select 2;
	//accepting variable "unit or from Group" and "target group"
	if (_str == "unit") then {
		[_unit] joinSilent _grp;
	}else {
		{
			[ _x ] joinSilent _grp;
		}forEach units _unit;
	};	
		_leader = units _grp select 0;
		{
			if !(isNil {units _grp select (_forEachIndex + 1)}) then {
				if((units _grp select (_forEachIndex + 1) call fn_GetRankNum) > (_leader call fn_GetRankNum) ) then {
					_leader = units _grp select (_forEachIndex+1);
				}; 
			};
		}forEach units _grp;
		_grp selectLeader _leader;
};

This is my new join.  It works.

Share this post


Link to post
Share on other sites

@Larrow

I cannot modify the conditions in the addAction "Form New HC Group" without breaking everything in TAG_fnc_HCActions.  Do you have documentation on lazy eval?  I tried adding several different versions of the below condition, even following the examples of other addActions you wrote, but anything I put in to Form New HC Group breaks the entire function after I add units into my group.

&& {!(leader group cursorTarget isEqualTo cursorTarget) }

I am also unable to modify my new function TAG_fnc_groupJoinHCGroup to prevent singular units, and non leader units from using the function.  I want to eliminate redundant commands in the menu.  Only squad leaders with troops should have the option to group join the player or another squad.  Any singular man should be able to join with the program as is.  I am also using my new join command now in most cases where units join other groups.  My TAG_fnc_JoinFunction automatically finds the highest ranking man and selects him to be leader when two groups, or a singular man, is added to another group.  This is not applicable to the functions that add units or groups to player, naturally.

 

New program.  The game throws a syntax bug.  It doesn't seem to like the Dismiss HC Group action.  I cannot fix it.  Nothing I try works.  I don't have a resource on how you do your conditional syntax.

myGrps = [];
myGrps resize 10;
myGrps = myGrps apply { [ grpNull ] };

TAG_fnc_createNewHCGroup = {
	params[ "_unit", [ "_create", true ], [ "_wholeGroup", false ] ];
	
	_CompanyNames = ["CompanyXray","CompanyNovember","CompanyNovember","CompanyNovember","CompanyNovember","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyWhiskey","CompanyXray"];
	_PlatoonNames = ["Platoon1","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1","Platoon1","Platoon2","Platoon2","Platoon1"];
	_SquadNames = ["Squad1","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad1","Squad2","Squad2"];
		
	{
		_x params[ "_HCGrp", "_HCActionID" ];
		
		if ( !isNull _HCGrp && { { alive _x }count units _HCGrp isEqualTo 0 } ) then {
			
			deleteGroup _HCGrp;
			player hcRemoveGroup _HCGrp;
			
			if ( _HCActionID isEqualType 0 ) then {
				player removeAction _HCActionID;
			};
			
			myGrps set [ _forEachIndex, [ grpNull ] ];
			_HCGrp = grpNull;
		};
		
		if ( _create && { isNull _HCGrp } ) then {
			private [ "_group" ];
			
			if !( isPlayer _unit ) then {
				_group = createGroup side player;
			}else{
				_group = group player;
			};
			
			_group setGroupIdGlobal [ "%GroupNames %GroupCompany %GroupPlatoon-%GroupSquad",
				"Yankee",
				_CompanyNames select _forEachIndex,
				_PlatoonNames select _forEachIndex,
				_SquadNames select _forEachIndex
			];
			
			if !( _unit in units _group ) then {
				_oldGroup = group _unit;
				
				if ( _wholeGroup ) then {
					units _oldGroup joinSilent _group;
				}else{
					[ _unit ] joinSilent _group;
				};
				
				if ( count units _oldGroup isEqualTo 0 ) then {
					deleteGroup _oldGroup;
				};
			};
			
			_actionID = if !( isPlayer _unit ) then {
				player hcSetGroup [ _group ];
				[ _group ] call TAG_fnc_joinHCGroup
			}else{
				objNull
			};
			
			myGrps set [ _forEachIndex, [ _group, _actionID ] ];
			_create = false;
		};
	}forEach myGrps;
	
};


TAG_fnc_recruitFriendly = {  
	player addAction [ "Join Me", {
		
		cursorTarget setCaptive false;
		[ cursorTarget ] joinSilent group player;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
    	!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						!(group cursortarget isEqualTo group player) && {
							({ alive _x } count units group player < 12) 
						}
					}
				}
			}
		}"
	];
};

TAG_fnc_joinHCGroup = {
	params[ "_HCGrp" ];

	_actionID = player addAction [ format [ "Join %1", groupID _HCGrp ], {
		params[ "_target", "_caller", "_ID", "_args" ];

		[ cursorTarget ] joinSilent _args;
		[ objNull, false ] call TAG_fnc_createNewHCGroup;
		
	}, _HCGrp, 1, false, true, "", format [ "
		_group = %1 call BIS_fnc_groupFromNetId;
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						!(group cursortarget isEqualTo _group) && {
							({ alive _x } count units (_group) > 0) &&
							({ alive _x } count units (_group) < 12) 
						}
					}
				}
			}
		}", str ( _HCGrp call BIS_fnc_netId ) ]
	];
	
	_actionID
};

TAG_fnc_HCActions = {
	
	player addAction [ "Unit to HC Group", {
		
		[ cursorTarget, true ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget )
				}
			}
		}"
	];
	
	player addAction [ "Group to HC Group", {
		
		[ cursorTarget, true, true ] call TAG_fnc_createNewHCGroup;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						leader group cursorTarget isEqualTo cursorTarget &&
						count units group cursorTarget > 1
					};
				}
			}
		}"
	];
	
	player addAction [ "Dismiss HC Group", {
		
		player hcRemoveGroup group cursorTarget;
		{
			_x params[ "_group", "_action" ];
			if ( _group isEqualTo group cursorTarget ) exitWith {
				player removeAction _action;
				player hcRemoveGroup _group;
				myGrps set [ _forEachIndex, [ grpNull ] ];
			};
		}forEach myGrps;
		
	}, [], 1, false, true, "", "
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						leader group cursorTarget isEqualTo cursorTarget &&
						{ group cursorTarget isEqualTo ( _x select 0 ) }count myGrps > 0
					};
				}
			}
		}"
	];
};

_null = [ player, true ] call TAG_fnc_createNewHCGroup;
_null = [] call TAG_fnc_recruitFriendly;
_null = [] call TAG_fnc_HCActions;

There are a few quirks in the program, but for the most part, it works.  Dismiss does not function, as your conditions had a syntax error.  I tried fixing it, but no dice.  I still need to figure out how to do lazy syntax better.  Adding the conditions I know works when everything is not lazy breaks the action or doesn't register if I try lazy.

Share this post


Link to post
Share on other sites
15 hours ago, stuguy said:

I keep seeing


_this isEqualTo _target

is _this the group argument?  I am unsure what is passed into the string section of addAction, or how _target and _ID and all those others are passed in.  I do understand params aand how it can be used to pull out variables.  So my guess is that addAction passes in certain criteria in a certain order, though I am unsure what that is.

_this is the user of the action and _target is the object the action is on. The wiki page for addAction has a very good explanation of what is available in each section of the command.

 

8 hours ago, stuguy said:

Do you have documentation on lazy eval?

Under Conditions on the Code optimisation page. It is nothing more than wrapping the second part of an evaluation in code braces {}. For example an AND (&&) evaluation means both sides of the evaluation need to be true. In Arma..

A && B

if A is false then B will also be evaluated even though there is not much point in checking B as A is false so we know the condition is going to be false. Doing..

A && { B }

here if A is false then B is not checked and the condition will immediately exit with false.

 

13 hours ago, stuguy said:

I do, however, want all units being added individually to the group check their ranks

No need for your Switch statement, the command rankID will return a units rank as a enum.

_posLeaders = units _group select{
    !( leader _x isEqualTo _x ) && { rankId _x > rankId leader _group }
}apply{ [ rankId _x,  _x ] };
if ( count _posLeaders > 0 ) then {
    _posLeaders sort false;
    _group selectLeader ( _posLeaders select 0 select 1 );
};

 

8 hours ago, stuguy said:

Dismiss does not function, as your conditions had a syntax error

Need to check that the myGrps index is not null.

( { !isNull ( _x select 0 ) && { group cursorTarget isEqualTo ( _x select 0 ) } }count myGrps > 0 ) 

Share this post


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

A && B

if A is false then B will also be evaluated even though there is not much point in checking B as A is false so we know the condition is going to be false. Doing..


A && { B }

here if A is false then B is not checked and the condition will immediately exit with false.

 

I saw that part, but then some of the conditions inside the brackets don't have parenthesis, and some do.  Also, when I try to cleanly expand some of the conditions to add checks for group leaders and what not, the code crashes the addAction.  Like the fn joinHCGroup. 

 

You start up the conditions with no null cursor target:

!(isnull cursortarget)

then follow that up with AND _this isEqualTo _target:

&& _this isEqualTo _target

This was evaluated not with parenthesis or brackets.  Then you moved into lazy eval and the next two conditions are not in parenthesis but inside the brackets, understandably, {} instead of ().  However, we move further into lazy eval and you start comparing two things in an OR statement, and that is inside {( A || B )}.  I can take a wild guess and say that comparing two things in a singular parenthesis would be a requirement if in this particular instance you are evaluating if the unit is either on player's side or is captive.  Then AND not cursortarget's group isEqualTo the passed in group.  That's inside of parenthesis, but I want to guess that it was required because you used the NOT wildcard to turn the expression into the opposite.  Then the last two statements are two separate conditions evaluating the alive units in the passed in group.  I am guessing we are comparing two things, the number of units alive in the pass in group and the set limit required to be evaluated.  Once again, we are using wildcards inside of a requirement, so I am guessing we have to use parenthesis.  Whereas above, some of the statements like:

 

cursorTarget isKindof 'Man'

alive cursortarget

Do not use parenthesis.  Again, I am simply guessing because the documentation Bohemia provides is not as elaborate as I would like.  Some of their examples contradict what I just said, like:

 

if (_group knowsAbout _vehicle object > 0 && {alive _object} && {canMove _object} && {count magazines _object > 0}) then {
            //custom code
};

This is lazy eval, but the statements comparing certain variables and conditions comparing the results to a number do not use parenthesis, namely:

 

_group knowsAbout _vehicle object > 0

 

What I am driving at is, I certainly understand conditions and understand the {} and () versions.  But not everything follows that criteria.  Some things just kind of free ball there and I haven't found any explanation why.  It's problematic because I get syntax errors when the code compiles, or entire segments of my action break because I am not doing something particularly correct in some positions, and that's frustrating.

 

edit: what's more, some of your conditions have semi-colon.  I have no idea why this is a thing or if it is valid syntax.

"
		!(isnull cursortarget) && _this isEqualTo _target && {
			cursorTarget isKindof 'Man' && {
				alive cursortarget && {
					( side cursortarget isEqualTo side player || captive cursorTarget ) && {
						leader group cursorTarget isEqualTo cursorTarget &&
						{ group cursorTarget isEqualTo ( _x select 0 ) }count myGrps > 0
					};
			///THIS GUY ^^^
				}
			}
		}"

Share this post


Link to post
Share on other sites

Well its just basic logic really , parenthesis are just there to stop ambiguity.

22 hours ago, stuguy said:

You start up the conditions with no null cursor target:


!(isnull cursortarget)

then follow that up with AND _this isEqualTo _target:


&& _this isEqualTo _target

This was evaluated not with parenthesis or brackets

This is basically down to my IDE and what shortcut macro/template I use and the toppings I had on my pizza the previous night. There is no reason why the isNull check should be in parenthesis as there is no ambiguity here.

 

 

22 hours ago, stuguy said:

However, we move further into lazy eval and you start comparing two things in an OR statement, and that is inside {( A || B )}.

 

22 hours ago, stuguy said:

alive cursortarget && ( side cursortarget isEqualTo side player || captive cursorTarget )

As there is ambiguity here.

A && ( B || C )

I want A AND either B OR C, without the parenthesis it could be read some other way..

A && B || C

What would this represent? I would take a guess its just left to right and precedence of && is greater than || so would be read as

( A && B ) || C

So not what is needed.

 

As for braces (lazy eval) and the difference in whether they are singularly braced or as I like to write long statements cascaded, is just down to personal preference.

I like to cascade my long statements as I find them easier to read and is similar to reading nested if statements and can easily be replaced as such e.g


!(isnull cursortarget) && _this isEqualTo _target && {
    cursorTarget isKindof 'Man' && {
        alive cursortarget && {
            ( side cursortarget isEqualTo side player || captive cursorTarget ) && {
                !(group cursortarget isEqualTo _group) && {
                    ({ alive _x } count units (_group) > 0) &&
                    ({ alive _x } count units (_group) < 12)
                }
            }
        }
    }
}
if ( !(isnull cursortarget) && _this isEqualTo _target ) then {
    if ( cursorTarget isKindof 'Man' ) then {
        if ( alive cursortarget ) then {
            if ( side cursortarget isEqualTo side player || captive cursorTarget ) then {
                if !(group cursortarget isEqualTo _group) then {
                    if ( ({ alive _x } count units (_group) > 0) &&
                        ({ alive _x } count units (_group) < 12) ) then {
                        
                    }
                }
            }
        }
    }
}

As for the semi colon that should not be there and is left over from an IDE macro and I have forgotten to delete it. Should it break the code, I suppose so. I suspect as there are no following evaluations and all that is left is the cascade back out is the reason it does not.

 

TBH I write very little code nowadays everything is macro'd or placed via templates :) Im very lazy. Its not until I visit a friend and write some code at his house that I realise how heavily I depend on macros and templates and find myself having to visit the comand page all the time << at home even this is a macro from my IDE that selects the current word at the cursor position and loads up the correct wiki page for me.

Share this post


Link to post
Share on other sites

Now I got most of the issues sorted.  Most everything works.  There is a problem with the conditions in one of the functions.  Somehow they are always true, but when tested individually, they are not.

 

function that is always true after I assign an HC squad:

Entire program, works with the exception that the group add to HC group function is true for everyone, even though the conditions specify that the guy has to be a leader and he can't join the player or same group as himself:

 

I got some sleep and followed up the next day.  I forgot a simple brace to close out some conditions.  That fixed the add action.  I posted the full script at the top of this thread.

 

 

 

Edited by stuguy
solved issue

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

×