mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Headless - Improve group transfer and add API (#9874)
This commit is contained in:
parent
440b9d5721
commit
120589512e
@ -1,3 +1,4 @@
|
||||
ACEX_PREP(blacklist);
|
||||
ACEX_PREP(endMissionNoPlayers);
|
||||
ACEX_PREP(handleConnectHC);
|
||||
ACEX_PREP(handleDisconnect);
|
||||
|
@ -10,6 +10,21 @@
|
||||
};
|
||||
// Add disconnect EH
|
||||
addMissionEventHandler ["HandleDisconnect", {call FUNC(handleDisconnect)}];
|
||||
|
||||
[QGVAR(transferGroupsRebalance), {
|
||||
params ["_groups", "_owner", "_rebalance"];
|
||||
|
||||
if (_groups isNotEqualTo [] && {_owner > 1}) then {
|
||||
{
|
||||
_x setGroupOwner _owner;
|
||||
} forEach _groups;
|
||||
};
|
||||
|
||||
// Rebalance units
|
||||
if (_rebalance in [REBALANCE, FORCED_REBALANCE]) then {
|
||||
(_rebalance == FORCED_REBALANCE) call FUNC(rebalance);
|
||||
};
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
} else {
|
||||
// Register HC (this part happens on HC only)
|
||||
[QXGVAR(headlessClientJoined), [player]] call CBA_fnc_globalEvent; // Global event for API purposes
|
||||
|
51
addons/headless/functions/fnc_blacklist.sqf
Normal file
51
addons/headless/functions/fnc_blacklist.sqf
Normal file
@ -0,0 +1,51 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: johnb43
|
||||
* Modifies which units are blacklisted from being transferred to HCs.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Units <OBJECT, GROUP, ARRAY>
|
||||
* 1: Add (true) or remove (false) from blacklist <BOOL> (default: true)
|
||||
* 2: Owner to transfer units to <NUMBER> (default: -1)
|
||||
* 3: Rebalance <NUMBER> (default: 0)
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [cursorObject, true] call ace_headless_fnc_blacklist
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
|
||||
params [["_units", objNull, [objNull, grpNull, []]], ["_blacklist", true, [false]], ["_owner", -1, [false]], ["_rebalance", NO_REBALANCE, [0]]];
|
||||
|
||||
if !(_units isEqualType []) then {
|
||||
_units = [_units];
|
||||
};
|
||||
|
||||
// Make sure passed arguments are objects or groups
|
||||
_units = _units select {_x isEqualType objNull || {_x isEqualType grpNull}};
|
||||
_units = _units select {!isNull _x};
|
||||
|
||||
if (_units isEqualTo []) exitWith {};
|
||||
|
||||
private _transfer = _blacklist && {_owner > 1};
|
||||
private _groups = [];
|
||||
|
||||
{
|
||||
_x setVariable [QXGVAR(blacklist), _blacklist, true];
|
||||
|
||||
if (_transfer) then {
|
||||
if (_x isEqualType objNull) then {
|
||||
_groups pushBack group _x;
|
||||
} else {
|
||||
_groups pushBack _x;
|
||||
};
|
||||
};
|
||||
} forEach _units;
|
||||
|
||||
// Try to move AI to new owner; Also takes care of rebalancing groups
|
||||
if (_transfer || {_rebalance in [REBALANCE, FORCED_REBALANCE]}) then {
|
||||
[QGVAR(transferGroupsRebalance), [_groups arrayIntersect _groups, _owner, _rebalance]] call CBA_fnc_serverEvent;
|
||||
};
|
@ -17,6 +17,9 @@
|
||||
|
||||
params ["_force"];
|
||||
|
||||
// Filter out any invalid entries
|
||||
GVAR(headlessClients) = GVAR(headlessClients) select {!isNull _x};
|
||||
|
||||
GVAR(headlessClients) params [
|
||||
["_HC1", objNull, [objNull]],
|
||||
["_HC2", objNull, [objNull]],
|
||||
@ -36,12 +39,13 @@ private _idHC2 = -1;
|
||||
private _idHC3 = -1;
|
||||
private _currentHC = 0;
|
||||
|
||||
if (!local _HC1) then {
|
||||
// objNull is never local
|
||||
if (!local _HC1 && !isNull _HC1) then {
|
||||
_idHC1 = owner _HC1;
|
||||
_currentHC = 1;
|
||||
};
|
||||
|
||||
if (!local _HC2) then {
|
||||
if (!local _HC2 && !isNull _HC2) then {
|
||||
_idHC2 = owner _HC2;
|
||||
|
||||
if (_currentHC == 0) then {
|
||||
@ -49,7 +53,7 @@ if (!local _HC2) then {
|
||||
};
|
||||
};
|
||||
|
||||
if (!local _HC3) then {
|
||||
if (!local _HC3 && !isNull _HC3) then {
|
||||
_idHC3 = owner _HC3;
|
||||
|
||||
if (_currentHC == 0) then {
|
||||
@ -57,84 +61,150 @@ if (!local _HC3) then {
|
||||
};
|
||||
};
|
||||
|
||||
if (_currentHC == 0) exitWith {
|
||||
TRACE_1("No Valid HC to transfer to",_currentHC);
|
||||
|
||||
if (XGVAR(log)) then {
|
||||
INFO("No Valid HC to transfer to");
|
||||
};
|
||||
};
|
||||
|
||||
// Prepare statistics
|
||||
private _numTransferredHC1 = 0;
|
||||
private _numTransferredHC2 = 0;
|
||||
private _numTransferredHC3 = 0;
|
||||
|
||||
private _units = [];
|
||||
private _transfer = false;
|
||||
private _previousOwner = -1;
|
||||
|
||||
// Transfer AI groups
|
||||
{
|
||||
// No transfer if empty group
|
||||
private _transfer = ((units _x) isNotEqualTo []) && {!(_x getVariable [QXGVAR(blacklist), false])};
|
||||
if (_transfer) then {
|
||||
// No transfer if waypoints with synchronized triggers exist for the group
|
||||
private _allWaypointsWithTriggers = (waypoints _x) select {(synchronizedTriggers _x) isNotEqualTo []};
|
||||
if (_allWaypointsWithTriggers isNotEqualTo []) exitWith {
|
||||
_units = units _x;
|
||||
|
||||
// No transfer if empty group or if group is blacklisted
|
||||
if (_units isEqualTo [] || {_x getVariable [QXGVAR(blacklist), false]}) then {
|
||||
continue;
|
||||
};
|
||||
|
||||
// No transfer if waypoints with synchronized triggers exist for the group
|
||||
if (((waypoints _x) select {(synchronizedTriggers _x) isNotEqualTo []}) isNotEqualTo []) then {
|
||||
continue;
|
||||
};
|
||||
|
||||
{
|
||||
// No transfer if already transferred
|
||||
if (!_force && {(owner _x) in [_idHC1, _idHC2, _idHC3]}) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
|
||||
{
|
||||
// No transfer if already transferred
|
||||
if (!_force && {(owner _x) in [_idHC1, _idHC2, _idHC3]}) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
// No transfer if any unit in group is blacklisted
|
||||
if (_x getVariable [QXGVAR(blacklist), false]) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
|
||||
// No transfer if player or UAV in this group
|
||||
if (isPlayer _x || {unitIsUAV _x}) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
// No transfer if player or UAV in this group
|
||||
if (isPlayer _x || {unitIsUAV _x}) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
|
||||
// No transfer if any unit in group is blacklisted
|
||||
if (_x getVariable [QXGVAR(blacklist), false]) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
private _vehicle = objectParent _x;
|
||||
|
||||
private _vehicle = objectParent _x;
|
||||
// No transfer if the vehicle the unit is in or if the crew in that vehicle is blacklisted
|
||||
if ((_vehicle getVariable [QXGVAR(blacklist), false]) || {unitIsUAV _vehicle}) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
|
||||
// No transfer if the vehicle the unit is in or if the crew in that vehicle is blacklisted
|
||||
if ((_vehicle getVariable [QXGVAR(blacklist), false]) || {unitIsUAV _vehicle}) exitWith {
|
||||
_transfer = false;
|
||||
};
|
||||
// Save gear if unit about to be transferred with current loadout (naked unit work-around)
|
||||
if (XGVAR(transferLoadout) == 1) then {
|
||||
_x setVariable [QGVAR(loadout), _x call CBA_fnc_getLoadout, true];
|
||||
};
|
||||
} forEach _units;
|
||||
|
||||
// Save gear if unit about to be transferred with current loadout (naked unit work-around)
|
||||
if (XGVAR(transferLoadout) == 1) then {
|
||||
_x setVariable [QGVAR(loadout), _x call CBA_fnc_getLoadout, true];
|
||||
};
|
||||
} forEach (units _x);
|
||||
if (!_transfer) then {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Round robin between HCs if load balance enabled, else pass all to one HC
|
||||
if (_transfer) then {
|
||||
switch (_currentHC) do {
|
||||
case 1: {
|
||||
private _transferred = _x setGroupOwner _idHC1;
|
||||
if (_loadBalance) then {
|
||||
_currentHC = [3, 2] select (!local _HC2);
|
||||
};
|
||||
if (_transferred) then {
|
||||
_numTransferredHC1 = _numTransferredHC1 + 1;
|
||||
_previousOwner = groupOwner _x;
|
||||
|
||||
switch (_currentHC) do {
|
||||
case 1: {
|
||||
if (_loadBalance) then {
|
||||
// Find the next valid HC
|
||||
// If none are valid, _currentHC will remain the same
|
||||
if (_idHC2 != -1) then {
|
||||
_currentHC = 2;
|
||||
} else {
|
||||
if (_idHC3 != -1) then {
|
||||
_currentHC = 3;
|
||||
};
|
||||
};
|
||||
};
|
||||
case 2: {
|
||||
private _transferred = _x setGroupOwner _idHC2;
|
||||
if (_loadBalance) then {
|
||||
_currentHC = [1, 3] select (!local _HC3);
|
||||
};
|
||||
if (_transferred) then {
|
||||
_numTransferredHC2 = _numTransferredHC2 + 1;
|
||||
|
||||
// Don't transfer if it's already local to HC1
|
||||
if (_previousOwner == _idHC1) exitWith {};
|
||||
|
||||
[QGVAR(groupTransferPre), [_x, _HC1, _previousOwner, _idHC1], [_previousOwner, _idHC1]] call CBA_fnc_targetEvent; // API
|
||||
|
||||
private _transferred = _x setGroupOwner _idHC1;
|
||||
|
||||
[QGVAR(groupTransferPost), [_x, _HC1, _previousOwner, _idHC1, _transferred], [_previousOwner, _idHC1]] call CBA_fnc_targetEvent; // API
|
||||
|
||||
if (_transferred) then {
|
||||
_numTransferredHC1 = _numTransferredHC1 + 1;
|
||||
};
|
||||
};
|
||||
case 2: {
|
||||
if (_loadBalance) then {
|
||||
// Find the next valid HC
|
||||
// If none are valid, _currentHC will remain the same
|
||||
if (_idHC3 != -1) then {
|
||||
_currentHC = 3;
|
||||
} else {
|
||||
if (_idHC1 != -1) then {
|
||||
_currentHC = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
case 3: {
|
||||
private _transferred = _x setGroupOwner _idHC3;
|
||||
if (_loadBalance) then {
|
||||
_currentHC = [2, 1] select (!local _HC1);
|
||||
};
|
||||
if (_transferred) then {
|
||||
_numTransferredHC3 = _numTransferredHC3 + 1;
|
||||
|
||||
// Don't transfer if it's already local to HC2
|
||||
if (_previousOwner == _idHC2) exitWith {};
|
||||
|
||||
[QGVAR(groupTransferPre), [_x, _HC2, _previousOwner, _idHC2], [_previousOwner, _idHC2]] call CBA_fnc_targetEvent; // API
|
||||
|
||||
private _transferred = _x setGroupOwner _idHC2;
|
||||
|
||||
[QGVAR(groupTransferPost), [_x, _HC2, _previousOwner, _idHC2, _transferred], [_previousOwner, _idHC2]] call CBA_fnc_targetEvent; // API
|
||||
|
||||
if (_transferred) then {
|
||||
_numTransferredHC2 = _numTransferredHC2 + 1;
|
||||
};
|
||||
};
|
||||
case 3: {
|
||||
if (_loadBalance) then {
|
||||
// Find the next valid HC
|
||||
// If none are valid, _currentHC will remain the same
|
||||
if (_idHC1 != -1) then {
|
||||
_currentHC = 1;
|
||||
} else {
|
||||
if (_idHC2 != -1) then {
|
||||
_currentHC = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
default {
|
||||
TRACE_1("No Valid HC to transfer to",_currentHC);
|
||||
|
||||
// Don't transfer if it's already local to HC3
|
||||
if (_previousOwner == _idHC3) exitWith {};
|
||||
|
||||
[QGVAR(groupTransferPre), [_x, _HC3, _previousOwner, _idHC3], [_previousOwner, _idHC3]] call CBA_fnc_targetEvent; // API
|
||||
|
||||
private _transferred = _x setGroupOwner _idHC2;
|
||||
|
||||
[QGVAR(groupTransferPost), [_x, _HC3, _previousOwner, _idHC3, _transferred], [_previousOwner, _idHC3]] call CBA_fnc_targetEvent; // API
|
||||
|
||||
if (_transferred) then {
|
||||
_numTransferredHC3 = _numTransferredHC3 + 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -17,3 +17,7 @@
|
||||
#include "\z\ace\addons\main\script_macros.hpp"
|
||||
|
||||
#define DELAY_DEFAULT 15
|
||||
|
||||
#define NO_REBALANCE 0
|
||||
#define REBALANCE 1
|
||||
#define FORCED_REBALANCE 2
|
||||
|
@ -156,9 +156,15 @@ MenuType: 0 = Interaction, 1 = Self Interaction
|
||||
|
||||
| Event Key | Parameters | Locality | Type | Description |
|
||||
|---------- |------------|----------|------|-------------|
|
||||
|---------- |------------|----------|------|-------------|
|
||||
| `ace_interaction_doorOpeningStarted` | [_house, _door, _animations] | Local | Listen | Called when local unit starts interacting with doors
|
||||
| `ace_interaction_doorOpeningStopped` | [_house, _door, _animations] | Local | Listen | Called when local unit stopps interacting with doors
|
||||
| `ace_interaction_doorOpeningStopped` | [_house, _door, _animations] | Local | Listen | Called when local unit stops interacting with doors
|
||||
|
||||
### 2.17 Headless (`ace_headless`)
|
||||
|
||||
| Event Key | Parameters | Locality | Type | Description |
|
||||
|---------- |------------|----------|------|-------------|
|
||||
| `ace_headless_groupTransferPre` | [_group, _HC (OBJECT), _previousOwner, _idHC] | Target | Listen | Called just before a group is transferred from any machine to a HC. Called where group currently is local and on the HC, where group is going to be local.
|
||||
| `ace_headless_groupTransferPost` | [_group, _HC (OBJECT), _previousOwner, _idHC, _transferredSuccessfully] | Target | Listen | Called just after a group is transferred from a machine to a HC. Called where group was local and on the HC, where group is now local. `_transferredSuccessfully` is passed so mods can actually check if the locality was properly transferred, as ownership transfer is not guaranteed.
|
||||
|
||||
## 3. Usage
|
||||
Also Reference [CBA Events System](https://github.com/CBATeam/CBA_A3/wiki/Custom-Events-System){:target="_blank"} documentation.
|
||||
|
@ -30,14 +30,29 @@ As of ACEX v3.2.0 _(before merge into ACE3)_ this feature can also be enabled wi
|
||||
|
||||
## 2. Scripting
|
||||
|
||||
### 2.1 Disable Transferring for a Group
|
||||
### 2.1 Manipulating HC Transfers of Groups via function
|
||||
|
||||
To prevent a group from transferring to a Headless Client use the following line on a group leader (or every unit in a group in case group leader may not spawn):
|
||||
`ace_headless_fnc_blacklist`
|
||||
|
||||
| Arguments | Type | Optional (default value)
|
||||
---| --------- | ---- | ------------------------
|
||||
0 | Units | Object, Group or Array of both | Required
|
||||
1 | Add (true) or remove (false) from blacklist | Bool | Optional (default: `true`)
|
||||
2 | Owner to transfer units to | Number | Optional (default: `-1`)
|
||||
3 | Rebalance (0 = no rebalance, 1 = rebalance, 2 = force rebalance) | Number | (default: `0`)
|
||||
**R** | None | None | Return value
|
||||
|
||||
`Force rebalance` means that all units, including the ones that are on the HCs, are rebalanced amongst the HCs, whereas `rebalance` means that newly spawned units are going to be evenly distributed amongst HCs. Therefore, `rebalance` does not guarantee that the HCs will have an equal amount of groups, whereas `force rebalance` does.
|
||||
|
||||
### 2.2 Disable Transferring for a Group via variable
|
||||
|
||||
To prevent a group from transferring to a Headless Client use the following line on a unit within a group:
|
||||
|
||||
```sqf
|
||||
this setVariable ["acex_headless_blacklist", true];
|
||||
```
|
||||
|
||||
This variable can also be set on vehicles, disabling transferal of any groups having units in said vehicles.
|
||||
|
||||
## 3. Limitations
|
||||
|
||||
@ -48,3 +63,7 @@ Some Arma 3 features are incompatible, this is up to BI to add support. Disable
|
||||
Additionally, groups will not be transferred due to lack of support if they:
|
||||
|
||||
- Have waypoints with synchronized triggers (waypoint would not change status based on trigger condition) (added in ACEX v3.2.0 - _before merge into ACE3_)
|
||||
|
||||
Groups will not be transferred to avoid issues:
|
||||
- If a player is within the group.
|
||||
- If they contain UAVs.
|
||||
|
Loading…
Reference in New Issue
Block a user