Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion addons/main/XEH_postInit.sqf
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
#include "script_component.hpp"

// don't load for HC or server
if (!hasInterface) exitWith {};
if (!hasInterface) exitWith {

// if HC, register in mission GVAR
if(!isDedicated) then {
[
{
//Race conditions?
private _hcRegister = GETMVAR(GVAR(hcRegister),createHashMap);
_hcRegister set [clientOwner, diag_fps];
SETMVAR(GVAR(hcRegister),_hcRegister);
Comment on lines +11 to +13
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, not sure if it is worth it to sync an entire hashmap across the network, compared to an array of HCs, and then use setVariable[GVAR(hcFPS), round diag_fps, true];

Or even do nested array so [[hc1,fps],[hc2,fps]...]

As I the usage would be to loop through them, not know the key of the one you want, until you have been through them all.

transmitting an entire hashmap every 5 sec, compared to a single int value, should have some impact ;-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use setVariable[GVAR(hcFPS), round diag_fps, true];

That would only work for one HC though, right? Otherwise you'd still need a mapping from HC id to fps.

Or even do nested array so [[hc1,fps],[hc2,fps]...]

Is it much faster to send a nested array than a hashmap? (It'd definitely make updating slower, because you'd have to iterate through the whole array until you found the right HC, rather than just using a key?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could simply update the register every, say, 60 seconds instead

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.

So good point that when updating the value a nested array wouldn't be quicker.

Usually I would do player setVariable[GVAR(hcFPS), round diag_fps, true]; as then any other client with a reference to that player, could use the _unit getVariable[] syntax to get the value. So if you have a list of registered HCs, you loop through it and read the public variables placed on the reference to the HC. Thus only needing a list of HCs, as you can lookup the variable saved on that player "object".

I believe that would work with the HC too, as that is the same reference you need to send spawn event to the HC with CBA events?

But I am honestly not sure if there is any real performance benefit in that compared to sending a hashmap over the network. 😅

},
5
] call CBA_fnc_addPerFrameHandler;
};
};

// globals to use if certain mods are loaded
GVAR(aceLoaded) = isClass (configFile >> "CfgPatches" >> "ace_main");
Expand All @@ -12,3 +26,6 @@ GVAR(rhsLoaded) = isClass (configfile >> "CfgPatches" >> "rhs_main");
GVAR(sogLoaded) = isClass (configfile >> "CfgMods" >> "vn");
GVAR(optreLoaded) = isClass (configfile >> "CfgMods" >> "OPTRE_Core");
GVAR(crowsEWLoaded) = isClass (configFile >> "CfgPatches" >> "crowsEW_main");

GVAR(zeiLoaded) = isClass (configfile >> "CfgPatches" >> "ZEI");
GVAR(lambsLoaded) = isClass (configfile >> "CfgPatches" >> "lambs_danger");
2 changes: 2 additions & 0 deletions addons/misc/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ PREP(spawnSupplyDrop);
PREP(stripExplosives);
PREP(stripExplosivesZeus);
PREP(suitcaseNukeZeus);
PREP(strongpoint);
PREP(strongpointZeus);
PREP(surrenderChance);
PREP(surrenderChanceZeus);
PREP(surrender);
Expand Down
1 change: 1 addition & 0 deletions addons/misc/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ private _moduleList = [
[localize "STR_CROWSZA_Misc_spawn_ied_clutter",{_this call FUNC(spawnIEDClutterZeus)}, "\a3\ui_f\data\igui\cfg\simpletasks\types\destroy_ca.paa"],
[localize "STR_CROWSZA_Misc_strip_explosives",{_this call FUNC(stripExplosivesZeus)}, "\a3\ui_f\data\igui\cfg\simpletasks\types\destroy_ca.paa"],
[localize "STR_CROWSZA_Misc_suitcaseNuke",{_this call FUNC(suitcaseNukeZeus)}, "\x\zen\addons\modules\ui\nuke_ca.paa"],
[localize "STR_CROWSZA_Misc_strongpoint",{_this call FUNC(strongpointZeus)}, "\a3\ui_f\data\igui\cfg\simpletasks\types\defend_ca.paa"],
[localize "STR_CROWSZA_Misc_surrender_chance",{_this call FUNC(surrenderChanceZeus)}, "\a3\ui_f\data\igui\cfg\holdactions\holdAction_secure_ca.paa"]
];

Expand Down
124 changes: 124 additions & 0 deletions addons/misc/functions/fnc_strongpoint.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include "script_component.hpp"
/*/////////////////////////////////////////////////
Author: Landric

File: fn_strongpoint.sqf
Parameters: _dialogResult, _in
Return: none

*///////////////////////////////////////////////
params ["_dialogResult","_in"];

_in params [["_pos",[0,0,0],[[]],3], "_unit"];

private _params = ["_composition", "_radius", "_desiredStrongpointCount", "_fill", "_sandbags", "_patrols"];
if(!isNull _unit) then { _params = _params - ["_composition"]; };
if(!EGVAR(main,zeiLoaded)) then { _params = _params - ["_sandbags"]; };

_dialogResult params _params;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be commented out when done testing ;-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully by the time I'm finished, that line will be necessary :D



private "_groupPrefab";
if(isNull _unit) then {
// TODO: actually link _composition to the UI portion
_groupPrefab = _composition;
}
else {
_groupPrefab = group _unit;
};


// If an HC is registered, spawn units directly on that. Otherwise, spawn locally
private _hcRegister = GETMVAR(EGVAR(main,hcRegister),[]);
private _client = if(count _hcRegister > 0) then {
// Get the HC(s) with the lowest fps
private _minfps = selectMin (values _hcRegister);
private _clients = (keys _hcRegister) select { _hcRegister get _x <= _minfps};
if(count _clients > 0) exitWith { selectRandom _clients };
// If we can't find a client for some reason (e.g. the register has updated since getting the fps)
// just return any HC
selectRandom (keys _hcRegister)
} else { clientOwner };

// Get all buildings in radius
// TODO: account for dispersion - i.e., cluster strongpoints together, or spread out
_buildings = ASLtoAGL _pos nearObjects ["House", _radius];
_buildings = _buildings call BIS_fnc_arrayShuffle;


private _strongpointCount = 0;
while { _strongpointCount < _desiredStrongpointCount && (count _buildings) > 0 } do {

// Calculate the desired number of units to spawn for this strongpoint,
// based on the number of available positions in the building
private _building = _buildings deleteAt 0;
private _positions = _building buildingPos -1;
if(count _positions <= 0) then { continue; };
private _desiredUnits = (round((count _positions) * _fill)) max 1;

// TODO: spawn units directly on HC if exists
// TODO: account for unit being null if we're selecting via dropdown
private _group = createGroup (side _unit);

for "_i" from 0 to _desiredUnits-1 do {
private _prefabUnit = (units _groupPrefab) select (_i % count (units _groupPrefab));
[_group , [(typeOf _prefabUnit), position _building, [], 0, "NONE"]] remoteExec ["createUnit", _client];
// private _newUnit = _group createUnit [(typeOf _prefabUnit), position _building, [], 0, "NONE"];
//_newUnit setUnitLoadout (getUnitLoadout _prefabUnit);
// How to set the unit's loadout now that we don't have a reference to it, without bundling both commands into a "call"?
};

if(EGVAR(main,lambsLoaded)) then {
[_group, _building, 1, [], true, true] call lambs_wp_fnc_taskGarrison;
} else {
// This is a very basic implementation of garrisoning strongpoints
private _units = units _group;
for "_i" from 0 to (count _units)-1 do {
_units#_i setPos _positions#_i;
_units#_i setUnitPos (selectRandom ["UP", "MIDDLE"]);
_units#_i disableAI "PATH";
}
};

if(!isNil "_sandbags" && { _sandbags }) then {
if(EGVAR(main,zeiLoaded)) then {
[_building,"mil",false,true,false,0] call ZEI_fnc_createTemplate;
} else {
// TODO: if zei not loaded, do manually (lol)
};
};

_strongpointCount = _strongpointCount + 1;
};


// Create patrols
for "_i" from 0 to _patrols-1 do {

// TODO: account for unit being null if we're selecting via dropdown
private _group = createGroup (side _unit);
private _startPos = [[[ASLtoAGL _pos, _radius]]] call BIS_fnc_randomPos;
{
[_group , [(typeOf _x), _startPos, [], 0, "NONE"]] remoteExec ["createUnit", _client];
// private _newUnit = _group createUnit [(typeOf _x), _startPos, [], 0, "NONE"];
// _newUnit setUnitLoadout (getUnitLoadout _x);
// How to set the unit's loadout now that we don't have a reference to it, without bundling both commands into a "call"?
} forEach units _groupPrefab;

if(EGVAR(main,lambsLoaded)) then {
[_group, _pos, _radius, 4, [], true, true] call lambs_wp_fnc_taskPatrol;
} else {

// This is a very basic implementation of patroling
_group setBehaviour "SAFE";
for "_i" from 0 to 4 do {
_group addWaypoint [_startPos, 200];
};
((waypoints _group) select ((count waypoints _group)-1)) setWaypointType "CYCLE";
};
};




{ deleteVehicle _x } forEach units _groupPrefab;
43 changes: 43 additions & 0 deletions addons/misc/functions/fnc_strongpointZeus.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include "script_component.hpp"
/*/////////////////////////////////////////////////
Author: Landric

File: fn_strongpointZeus.sqf
Parameters: pos, unit
Return: none

*///////////////////////////////////////////////
params [["_pos",[0,0,0],[[]],3], ["_unit",objNull,[objNull]]];

if(isNull _unit) exitWith { hint parseText (localize "STR_CROWSZA_Misc_strongpoint_error_no_unit"); }; //TODO: alternatively, add dropdown(s) with all compositions


private _controls = [];

// _controls append [
// ["COMBO", "Side", [["west"], [["BLUFOR", "", "\A3\ui_f\data\map\markers\nato\b_unknown.paa"]], 0]],
// ["COMBO", "Faction", [["1"], [["Gendarmerie"]], 0]],
// ["COMBO", "Composition", [["1"], [["Gendarmerie Patrol", "", "\A3\ui_f\data\map\markers\nato\b_inf.paa"]], 0]]
// ];

_controls append [
["SLIDER:RADIUS", localize "STR_CROWSZA_Misc_strongpoint_radius", [20, 500, 200, 0, ASLtoAGL _pos, [1, 0, 0, 0.7]]],
["SLIDER", [localize "STR_CROWSZA_Misc_strongpoint_ui_strongpoints", localize "STR_CROWSZA_Misc_strongpoint_ui_strongpoints_tooltip"], [1, 20, 6, 0]],
["SLIDER:PERCENT", [localize "STR_CROWSZA_Misc_strongpoint_ui_fill", localize "STR_CROWSZA_Misc_strongpoint_ui_fill_tooltip"], [0.1, 1, 0.8, 0]],
//["SLIDER:PERCENT", [localize "STR_CROWSZA_Misc_strongpoint_ui_dispersion", localize "STR_CROWSZA_Misc_strongpoint_ui_dispersion_tooltip"], [0, 1, 0.8, 0]],
["CHECKBOX", [localize "STR_CROWSZA_Misc_strongpoint_ui_sandbags", localize "STR_CROWSZA_Misc_strongpoint_ui_sandbags_tooltip"], true],
["SLIDER", [localize "STR_CROWSZA_Misc_strongpoint_ui_patrol", localize "STR_CROWSZA_Misc_strongpoint_ui_patrol_tooltip"], [0, 6, 2, 0]]
];

if(!EGVAR(main,zeiLoaded)) then {
_controls deleteAt 3;
};


[
localize "STR_CROWSZA_Misc_strongpoint",
_controls,
FUNC(strongpoint),
{},
_this
] call zen_dialog_fnc_create;
33 changes: 33 additions & 0 deletions addons/misc/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,39 @@
<English>Remove Explosives</English>
<Chinesesimp>移除爆炸物</Chinesesimp>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint">
<English>Strongpoint</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_error_no_unit">
<English>Module must be placed on a unit&lt;br/&gt;Unit's group determines the units placed</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_radius">
<English>Radius</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_strongpoints">
<English>Max Strongpoints</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_strongpoints_tooltip">
<English>Maximum number of buildings to turn into strongpoints</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_fill">
<English>Fill %</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_fill_tooltip">
<English>% of each building to fill with units</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_sandbags">
<English>Sandbags</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_sandbags_tooltip">
<English>Place sandbags and other defences on the strongpoint</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_patrol">
<English>Patrols</English>
</Key>
<Key ID="STR_CROWSZA_Misc_strongpoint_ui_patrol_tooltip">
<English>Number of patroling groups to place in the radius</English>
</Key>
<Key ID="STR_CROWSZA_Misc_suitcaseNuke">
<English>Suitcase Device</English>
<Chinesesimp>手提箱设备</Chinesesimp>
Expand Down