diff --git a/addons/sup_artillery/ArtilleryStateMachine.hpp b/addons/sup_artillery/ArtilleryStateMachine.hpp new file mode 100644 index 000000000..3576aeb4a --- /dev/null +++ b/addons/sup_artillery/ArtilleryStateMachine.hpp @@ -0,0 +1,141 @@ +class ArtilleryStateMachine { + list = "ALIVE_sup_artillery_stateMachine_list"; + + class Idle { + onState = ""; + onStateEntered = ""; + onStateLeaving = ""; + + class HasFireMission { + targetState = "Active"; + condition = "[_this, 'hasFireMission'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + }; + + class Active { + onState = ""; + onStateEntered = "[_this, 'activate'] call ALIVE_fnc_artillery"; + onStateLeaving = ""; + + class InRange { + targetState = "Execute"; + condition = "[_this, 'inRange'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + + class NotInRange { + targetState = "Pack"; + condition = "!([_this, 'inRange'] call ALIVE_fnc_artillery)"; + onTransition = ""; + }; + }; + + class Pack { + onState = ""; + onStateEntered = "[_this, 'pack'] call ALIVE_fnc_artillery"; + onStateLeaving = ""; + + class Packed { + targetState = "Move"; + condition = "[_this, 'hasPacked'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + }; + + class Move { + onState = ""; + onStateEntered = "[_this, 'move'] call ALIVE_fnc_artillery"; + onStateLeaving = ""; + + class InPosition { + targetState = "Unpack"; + condition = "[_this, 'inPosition'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + + class Abort { + targetState = "ReturnToBase"; + condition = "!([_this, 'hasFireMission'] call ALIVE_fnc_artillery)"; + onTransition = ""; + }; + }; + + class Unpack { + onState = ""; + onStateEntered = "[_this, 'unpack'] call ALIVE_fnc_artillery"; + onStateLeaving = ""; + + class Unpacked { + targetState = "Execute"; + condition = "[_this, 'hasUnpacked'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + }; + + class Execute { + onState = ""; + onStateEntered = "[_this, 'execute'] call ALIVE_fnc_artillery"; + onStateLeaving = ""; + + class Fire { + targetState = "Fire"; + condition = "[_this, 'canFireRound'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + + class Abort { + targetState = "ReturnToBase"; + condition = "!([_this, 'hasFireMission'] call ALIVE_fnc_artillery)"; + onTransition = ""; + }; + }; + + class Fire { + onState = ""; + onStateEntered = "[_this, 'fire'] call ALIVE_fnc_artillery"; + onStateLeaving = ""; + + class FireMissionComplete { + targetState = "ReturnToBase"; + condition = "[_this, 'isFireMissionComplete'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + + class Fired { + targetState = "FireDelay"; + condition = "[_this, 'isFireMissionDelayed'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + }; + + class FireDelay { + onState = ""; + onStateEntered = ""; + onStateLeaving = ""; + + class FireMissionComplete { + targetState = "ReturnToBase"; + condition = "[_this, 'isFireMissionComplete'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + + class Continue { + targetState = "Fire"; + condition = "[_this, 'canFireRound'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + }; + + class ReturnToBase { + onState = ""; + onStateEntered = "[_this, 'returnToBase'] call ALIVE_fnc_artillery"; + onStateLeaving = ""; + + class AtBase { + targetState = "Idle"; + condition = "[_this, 'inPosition'] call ALIVE_fnc_artillery"; + onTransition = ""; + }; + }; +}; diff --git a/addons/sup_artillery/CfgFunctions.hpp b/addons/sup_artillery/CfgFunctions.hpp index 56ed2cd78..0b59b73a8 100644 --- a/addons/sup_artillery/CfgFunctions.hpp +++ b/addons/sup_artillery/CfgFunctions.hpp @@ -1,16 +1,31 @@ class cfgFunctions { - class PREFIX { - class COMPONENT { - class ARTILLERY { - description = "The main class"; - file = "\x\alive\addons\sup_artillery\fnc_artillery.sqf"; + class PREFIX { + class COMPONENT { + class ARTILLERY { + description = "The main class"; + file = "\x\alive\addons\sup_artillery\fnc_artillery.sqf"; RECOMPILE; - }; - class artilleryInit { - description = "The module initialisation function"; - file = "\x\alive\addons\sup_artillery\fnc_artilleryInit.sqf"; + }; + class artilleryInit { + description = "The module initialisation function"; + file = "\x\alive\addons\sup_artillery\fnc_artilleryInit.sqf"; RECOMPILE; - }; - }; + }; + class artillerySpawn { + description = "Spawns artillery assets"; + file = "\x\alive\addons\sup_artillery\fnc_artillerySpawn.sqf"; + RECOMPILE; + }; + class artilleryFiredEH { + description = "Handles artillery fired events"; + file = "\x\alive\addons\sup_artillery\fnc_artilleryFiredEH.sqf"; + RECOMPILE; + }; + class artilleryGetRange { + description = "Gets range of artillery asset"; + file = "\x\alive\addons\sup_artillery\fnc_artilleryGetRange.sqf"; + RECOMPILE; + }; }; + }; }; diff --git a/addons/sup_artillery/CfgVehicles.hpp b/addons/sup_artillery/CfgVehicles.hpp index 9c6ac2d26..14edc5f54 100644 --- a/addons/sup_artillery/CfgVehicles.hpp +++ b/addons/sup_artillery/CfgVehicles.hpp @@ -4,7 +4,7 @@ class CfgVehicles { { scope = 2; displayName = "$STR_ALIVE_ARTILLERY"; - function = "ALIVE_fnc_ARTILLERYInit"; + function = "ALIVE_fnc_artilleryInit"; author = MODULE_AUTHOR; functionPriority = 161; isGlobal = 2; @@ -97,4 +97,4 @@ class CfgVehicles { }; }; }; -}; \ No newline at end of file +}; diff --git a/addons/sup_artillery/config.cpp b/addons/sup_artillery/config.cpp index 6643ea355..eba9c8329 100644 --- a/addons/sup_artillery/config.cpp +++ b/addons/sup_artillery/config.cpp @@ -3,3 +3,5 @@ #include #include #include + +#include diff --git a/addons/sup_artillery/fnc_ARTILLERY.sqf b/addons/sup_artillery/fnc_ARTILLERY.sqf deleted file mode 100644 index a20a81047..000000000 --- a/addons/sup_artillery/fnc_ARTILLERY.sqf +++ /dev/null @@ -1,57 +0,0 @@ -#include <\x\alive\addons\sup_artillery\script_component.hpp> -SCRIPT(CAS); - -/* ---------------------------------------------------------------------------- -Function: ALIVE_fnc_CQB -Description: -XXXXXXXXXX - -Parameters: -Nil or Object - If Nil, return a new instance. If Object, reference an existing instance. -String - The selected function -Array - The selected parameters - -Returns: -Any - The new instance or the result of the selected function and parameters - -Attributes: -Boolean - debug - Debug enabled -Boolean - enabled - Enabled or disable module - -Parameters: -none - -Description: -CQB Module! Detailed description to follow - -Examples: -[_logic, "factions", ["OPF_F"] call ALiVE_fnc_CQB; -[_logic, "houses", _nonStrategicHouses] call ALiVE_fnc_CQB; -[_logic, "spawnDistance", 500] call ALiVE_fnc_CQB; -[_logic, "active", true] call ALiVE_fnc_CQB; - -See Also: -- - -Author: -Wolffy, Highhead ----------------------------------------------------------------------------- */ - -#define SUPERCLASS nil - -private ["_logic","_operation","_args"]; - -PARAMS_1(_logic); -DEFAULT_PARAM(1,_operation,""); -DEFAULT_PARAM(2,_args,nil); -ALIVE_coreLogic = _logic; -_position = getposATL ALIVE_coreLogic; -_callsign = _logic getvariable ["artillery_callsign","EAGLE ONE"]; -_type = _logic getvariable ["artillery_type","B_Heli_Attack_01_F"]; -_ordnace = _logic getvariable ["artillery_ordnace",["HE", 30]]; - ARTYPOS = _position; PublicVariable "ARTYPOS"; - - - - - diff --git a/addons/sup_artillery/fnc_artillery.sqf b/addons/sup_artillery/fnc_artillery.sqf new file mode 100644 index 000000000..c2e7e071a --- /dev/null +++ b/addons/sup_artillery/fnc_artillery.sqf @@ -0,0 +1,345 @@ +#include <\x\alive\addons\sup_artillery\script_component.hpp> +SCRIPT(Artillery); + +/* ---------------------------------------------------------------------------- +Function: ALIVE_fnc_artillery +Description: +Artillery module. + +Parameters: +Nil or Object - If Nil, return a new instance. If Object, reference an existing instance. +String - The selected function +Array - The selected parameters + +Returns: +Any - The new instance or the result of the selected function and parameters + +Attributes: +Boolean - debug - Debug enabled +Boolean - enabled - Enabled or disable module + +Parameters: +none + +Examples: + +See Also: + +Author: +marceldev89 +---------------------------------------------------------------------------- */ + +#define SUPERCLASS ALIVE_fnc_baseClass +#define MAINCLASS ALIVE_fnc_artillery + +private _logic = param [0, objNull, [objNull, []]]; +private _operation = param [1, "", [""]]; +private _args = param [2, [], [objNull, [], "", 0, true, false]]; + +private _result = true; + +/* diag_log format ["###### %1: _logic: %2, _operation: %3, _args: %4", "ALIVE_fnc_artillery", _logic, _operation, _args]; */ + +switch (_operation) do { + case "init": { + _logic setVariable ["super", SUPERCLASS]; + _logic setVariable ["class", MAINCLASS]; + + // Defaults + _logic setVariable ["group", grpNull]; + _logic setVariable ["moveToPos", objNull]; + _logic setVariable ["fireMission", []]; + + // Are we synced with combat support module? + if (({typeOf _x == "ALIVE_sup_combatsupport"} count (synchronizedObjects _logic)) == 0) exitWith { _result = false }; + + // Spawn and initialize artillery units + [_logic] call ALIVE_fnc_artillerySpawn; + + // Start state machine if it hasn't already + if (isNil "ALIVE_sup_artillery_stateMachine") then { + ALIVE_sup_artillery_stateMachine_list = []; + ALIVE_sup_artillery_stateMachine = [ + configFile >> "ArtilleryStateMachine" + ] call CBA_statemachine_fnc_createFromConfig; + }; + + // Add artillery module to state machine + ALIVE_sup_artillery_stateMachine_list pushBack _logic; + }; + case "getFireMission": { + _result = _logic getVariable ["fireMission", []]; + }; + case "setFireMission": { + if (count _args == 0) exitWith { _result = false }; + + private _position = _args param [0, [0,0,0], [[]], 3]; + private _roundType = _args param [1, "", [""]]; + private _roundCount = _args param [2, 1, [1]]; + private _delay = _args param [3, 5, [1]]; + private _dispersion = _args param [4, 50, [1]]; + + private _fireMission = [] call ALIVE_fnc_hashCreate; + [_fireMission, "position", _position] call ALIVE_fnc_hashSet; + [_fireMission, "roundType", _roundType] call ALIVE_fnc_hashSet; + [_fireMission, "roundCount", _roundCount] call ALIVE_fnc_hashSet; + [_fireMission, "delay", _delay] call ALIVE_fnc_hashSet; + [_fireMission, "dispersion", _dispersion] call ALIVE_fnc_hashSet; + // Fire mission state + [_fireMission, "units", []] call ALIVE_fnc_hashSet; + [_fireMission, "unitIndex", -1] call ALIVE_fnc_hashSet; + [_fireMission, "roundsShot", -1] call ALIVE_fnc_hashSet; + [_fireMission, "nextRoundTime", -1] call ALIVE_fnc_hashSet; + + _logic setVariable ["fireMission", _fireMission]; + }; + case "getRounds": { + private _rounds = [ + ["HE", parseNumber (_logic getVariable ["artillery_he", "30"])], + ["ILLUM", parseNumber (_logic getVariable ["artillery_illum", "30"])], + ["SMOKE", parseNumber (_logic getVariable ["artillery_smoke", "30"])], + ["SADARM", parseNumber (_logic getVariable ["artillery_guided", "30"])], + ["CLUSTER", parseNumber (_logic getVariable ["artillery_cluster", "30"])], + ["LASER", parseNumber (_logic getVariable ["artillery_lg", "30"])], + ["MINE", parseNumber (_logic getVariable ["artillery_mine", "30"])], + ["AT MINE", parseNumber (_logic getVariable ["artillery_atmine", "30"])], + ["ROCKETS", parseNumber (_logic getVariable ["artillery_rockets", "16"])] + ]; + + private _roundsAvailable = []; + private _roundsUnit = (typeOf (_vehicles select 0)) call ALIVE_fnc_getArtyRounds; + + { + if ((_x select 0) in _roundsUnit) then { + _roundsAvailable pushBack _x; + }; + } forEach _rounds; + + _result = _roundsAvailable; + }; + case "hasFireMission": { + private _fireMission = _logic getVariable ["fireMission", []]; + _result = (count _fireMission > 0); + }; + case "activate": { + if (!([_logic, "inRange"] call MAINCLASS)) then { + private _fireMission = _logic getVariable ["fireMission", []]; + private _position = [_fireMission, "position"] call ALIVE_fnc_hashGet; + private _roundType = [_fireMission, "roundType"] call ALIVE_fnc_hashGet; + private _group = _logic getVariable ["group", grpNull]; + private _units = (units _group) select {vehicle _x != _x && {gunner (vehicle _x) == _x}}; + + private _vehicle = vehicle (_units select 0); + private _range = [_vehicle, _roundType] call ALIVE_fnc_artilleryGetRange; + private _radius = 500; + private _newPosition = [_position, _range - _radius, _position getDir _vehicle] call BIS_fnc_relPos; + _newPosition = [_newPosition, 10, _radius, 5, 0, 0.15, 0] call BIS_fnc_findSafePos; + _logic setVariable ["moveToPos", _newPosition]; + }; + }; + case "inRange": { + private _fireMission = _logic getVariable ["fireMission", []]; + private _position = [_fireMission, "position"] call ALIVE_fnc_hashGet; + private _roundType = [_fireMission, "roundType"] call ALIVE_fnc_hashGet; + private _group = _logic getVariable ["group", grpNull]; + private _units = (units _group) select {vehicle _x != _x && {gunner (vehicle _x) == _x}}; + _result = _position inRangeOfArtillery [_units, _roundType]; + }; + case "pack": { + private _group = _logic getVariable ["group", grpNull]; + private _deployed = _group getVariable ["sup_artillery_deployed", true]; + + if (_deployed) then { + private _weapon = objNull; + + { + if (vehicle _x != _x) exitWith { _weapon = vehicle _x }; + } forEach (units _group); + + private _handle = [_group, _weapon] spawn ALIVE_fnc_packMortar; + + [_group, _handle] spawn { + private _group = _this select 0; + private _handle = _this select 1; + + waitUntil { scriptDone _handle }; + _group setVariable ["sup_artillery_deployed", false]; + }; + }; + }; + case "hasPacked": { + private _type = _logic getvariable ["type", TYPE_ARTILLERY]; + + if (_type == TYPE_MORTAR) then { + private _group = _logic getVariable ["group", grpNull]; + _result = !(_group getVariable ["sup_artillery_deployed", true]); + } else { + _result = true + }; + }; + case "move": { + private _group = _logic getVariable ["group", grpNull]; + private _position = []; + + if (count _args == 0) then { + _position = _logic getVariable ["moveToPos", objNull]; + } else { + _position = _args param [0, [0,0,0], [[]], 3]; + _logic setVariable ["moveToPos", _position]; + }; + + _group setVariable ["sup_artillery_inPosition", false]; + + private _waypoint = _group addWaypoint [_position, 0]; + _waypoint setWaypointType "MOVE"; + _waypoint setWaypointBehaviour "SAFE"; + _waypoint setWaypointForceBehaviour true; + _waypoint setWaypointSpeed "NORMAL"; + _waypoint setWaypointFormation "COLUMN"; + _waypoint setWaypointStatements [ + "true", + "(group this) setVariable ['sup_artillery_inPosition', true]" + ]; + }; + case "inPosition": { + private _group = _logic getVariable ["group", grpNull]; + _result = _group getVariable ["sup_artillery_inPosition", false]; + }; + case "unpack": { + private _group = _logic getVariable ["group", grpNull]; + private _fireMission = _logic getVariable ["fireMission", []]; + private _position = []; + + if (count _fireMission > 0) then { + _position = [_fireMission, "position"] call ALIVE_fnc_hashGet; + } else { + _position = position _logic; + }; + + private _handle = [_group, position (leader _group), _position] spawn ALIVE_fnc_unpackMortar; + + [_group, _handle] spawn { + private _group = _this select 0; + private _handle = _this select 1; + + waitUntil { scriptDone _handle }; + _group setVariable ["sup_artillery_deployed", true]; + }; + }; + case "hasUnpacked": { + private _type = _logic getvariable ["type", TYPE_ARTILLERY]; + + if (_type == TYPE_MORTAR) then { + private _group = _logic getVariable ["group", grpNull]; + _result = _group getVariable ["sup_artillery_deployed", true]; + } else { + _result = true + }; + }; + case "execute": { + private _group = _logic getVariable ["group", grpNull]; + private _units = (units _group) select {vehicle _x != _x && {gunner (vehicle _x) == _x}}; + private _fireMission = _logic getVariable ["fireMission", []]; + private _fireMissionPos = [_fireMission, "position"] call ALIVE_fnc_hashGet; + [_fireMission, "units", _units] call ALIVE_fnc_hashSet; + [_fireMission, "unitIndex", 0] call ALIVE_fnc_hashSet; + [_fireMission, "roundsShot", 0] call ALIVE_fnc_hashSet; + [_fireMission, "nextRoundTime", time] call ALIVE_fnc_hashSet; + _units doWatch _fireMissionPos; + + _logic setVariable ["fireMission", _fireMission]; + + // Attach Fired EH to all vehicles in group + { + private _vehicle = vehicle _x; + private _firedEH = _vehicle addEventHandler ["Fired", ALIVE_fnc_artilleryFiredEH]; + _vehicle setVariable ["sup_artillery_firedEH", _firedEH]; + } forEach _units; + }; + case "canFireRound": { + private _fireMission = _logic getVariable ["fireMission", []]; + private _nextRoundTime = [_fireMission, "nextRoundTime"] call ALIVE_fnc_hashGet; + _result = (_nextRoundTime != -1 && {time >= _nextRoundTime}); + }; + // TODO: Check if unit is alive, otherwise skip + case "fire": { + private _fireMission = _logic getVariable ["fireMission", []]; + private _delay = [_fireMission, "delay"] call ALIVE_fnc_hashGet; + private _units = [_fireMission, "units"] call ALIVE_fnc_hashGet; + private _position = [_fireMission, "position"] call ALIVE_fnc_hashGet; + private _roundType = [_fireMission, "roundType"] call ALIVE_fnc_hashGet; + + if (_delay > 0) then { + private _unitIndex = [_fireMission, "unitIndex"] call ALIVE_fnc_hashGet; + private _unit = _units select _unitIndex; + + _unit doArtilleryFire [ + _position, + _roundType, + 1 + ]; + } else { + { + private _roundCount = [_fireMission, "roundCount"] call ALIVE_fnc_hashGet; + + _x doArtilleryFire [ + _position, + _roundType, + floor (_roundCount / (count _units)) // TODO: Better distribution + ]; + } forEach _units; + }; + + [_fireMission, "nextRoundTime", -1] call ALIVE_fnc_hashSet; + _logic setVariable ["fireMission", _fireMission]; + }; + case "isFireMissionComplete": { + private _fireMission = _logic getVariable ["fireMission", []]; + private _roundCount = [_fireMission, "roundCount"] call ALIVE_fnc_hashGet; + private _roundsShot = [_fireMission, "roundsShot"] call ALIVE_fnc_hashGet; + _result = (_roundsShot >= _roundCount); + }; + case "isFireMissionDelayed": { + private _fireMission = _logic getVariable ["fireMission", []]; + private _delay = [_fireMission, "delay"] call ALIVE_fnc_hashGet; + _result = (_delay > 0); + }; + case "returnToBase": { + private _group = _logic getVariable ["group", grpNull]; + private _units = (units _group) select {vehicle _x != _x && {gunner (vehicle _x) == _x}}; + _units doWatch objNull; + + // Cleanup event handlers + { + private _vehicle = vehicle _x; + private _firedEH = _vehicle getVariable ["sup_artillery_firedEH", nil]; + + if (!isNil "_firedEH") then { + _vehicle removeEventHandler ["Fired", _firedEH]; + _vehicle setVariable ["sup_artillery_firedEH", nil]; + }; + } forEach _units; + + _logic setVariable ["fireMission", []]; + + [_logic] spawn { + private _logic = param [0, objNull, [objNull]]; + + [_logic, "pack"] call MAINCLASS; + waitUntil { [_logic, "hasPacked"] call MAINCLASS }; + [_logic, "move", [position _logic]] call MAINCLASS; + waitUntil { [_logic, "inPosition"] call MAINCLASS }; + [_logic, "unpack"] call MAINCLASS; + }; + }; +}; + +// TODO: Give this legacy stuff a place +ALIVE_coreLogic = _logic; +_position = getposATL ALIVE_coreLogic; +_callsign = _logic getvariable ["artillery_callsign","EAGLE ONE"]; +_type = _logic getvariable ["artillery_type","B_Heli_Attack_01_F"]; +_ordnace = _logic getvariable ["artillery_ordnace",["HE", 30]]; + ARTYPOS = _position; PublicVariable "ARTYPOS"; + + _result; diff --git a/addons/sup_artillery/fnc_artilleryFiredEH.sqf b/addons/sup_artillery/fnc_artilleryFiredEH.sqf new file mode 100644 index 000000000..48a6667e4 --- /dev/null +++ b/addons/sup_artillery/fnc_artilleryFiredEH.sqf @@ -0,0 +1,51 @@ +#include <\x\alive\addons\sup_artillery\script_component.hpp> +SCRIPT(ArtilleryFiredEH); + +/* ---------------------------------------------------------------------------- +Function: ALIVE_fnc_artilleryFiredEH +Description: +Handles the fired event for all vehicles (guns) in the artillery group. + +Parameters: +Object - The vehicle +String - The magazine type + +Returns: +Nothing + +Examples: +[_logic] call ALIVE_fnc_artillerySpawn; + +See Also: + +Author: +marceldev89 +---------------------------------------------------------------------------- */ +private _unit = param [0, objNull]; +private _magazine = param [5, ""]; + +private _logic = (group _unit) getVariable ["logic", objNull]; +private _fireMission = _logic getVariable ["fireMission", []]; +private _roundType = [_fireMission, "roundType"] call ALIVE_fnc_hashGet; +private _roundsShot = [_fireMission, "roundsShot"] call ALIVE_fnc_hashGet; + +if (_magazine == _roundType) then { + private _delay = [_fireMission, "delay"] call ALIVE_fnc_hashGet; + + if (_delay > 0) then { + private _units = [_fireMission, "units"] call ALIVE_fnc_hashGet; + private _unitIndex = [_fireMission, "unitIndex"] call ALIVE_fnc_hashGet; + + if ((_unitIndex + 1) >= count _units) then { + _unitIndex = 0; + } else { + _unitIndex = _unitIndex + 1; + }; + + [_fireMission, "unitIndex", _unitIndex] call ALIVE_fnc_hashSet; + [_fireMission, "nextRoundTime", time + _delay] call ALIVE_fnc_hashSet; + }; + + [_fireMission, "roundsShot", _roundsShot + 1] call ALIVE_fnc_hashSet; + _logic setVariable ["fireMission", _fireMission]; +}; diff --git a/addons/sup_artillery/fnc_artilleryGetRange.sqf b/addons/sup_artillery/fnc_artilleryGetRange.sqf new file mode 100644 index 000000000..c303ca69a --- /dev/null +++ b/addons/sup_artillery/fnc_artilleryGetRange.sqf @@ -0,0 +1,43 @@ +#include <\x\alive\addons\sup_artillery\script_component.hpp> +SCRIPT(ArtilleryGetRange); + +/* ---------------------------------------------------------------------------- +Function: ALIVE_fnc_artilleryGetRange +Description: +Gets the range for artillery assets + +Parameters: +Object - The artillery asset +String - The round type + +Returns: +Number - The range + +Examples: + +See Also: + +Author: +marceldev89 +---------------------------------------------------------------------------- */ +private _vehicle = param [0, objNull, [objNull]]; +private _roundType = param [1, "", [""]]; + +private _range = 0; +private _inRange = true; +private _eta = 0; +private _target = position _vehicle; + +// Figure out range by incrementing distance from asset. Configs seem unreliable. +while {_range == 0 || (_inRange && _eta != -1)} do { + _inRange = _target inRangeOfArtillery [[_vehicle], _roundType]; + _eta = _vehicle getArtilleryETA [_target, _roundType]; + + if (_inRange && _eta != -1) then { + _range = (position _vehicle) distance2D _target; + }; + + _target = [_target, 1, 0] call BIS_fnc_relPos; +}; + +_range; diff --git a/addons/sup_artillery/fnc_ARTILLERYInit.sqf b/addons/sup_artillery/fnc_artilleryInit.sqf similarity index 100% rename from addons/sup_artillery/fnc_ARTILLERYInit.sqf rename to addons/sup_artillery/fnc_artilleryInit.sqf diff --git a/addons/sup_artillery/fnc_artillerySpawn.sqf b/addons/sup_artillery/fnc_artillerySpawn.sqf new file mode 100644 index 000000000..186914388 --- /dev/null +++ b/addons/sup_artillery/fnc_artillerySpawn.sqf @@ -0,0 +1,68 @@ +#include <\x\alive\addons\sup_artillery\script_component.hpp> +SCRIPT(ArtillerySpawn); + +/* ---------------------------------------------------------------------------- +Function: ALIVE_fnc_artillerySpawn +Description: +Spawns the assets associated with the artillery module. + +Parameters: +Object - The artillery module + +Returns: +Nothing + +Examples: +[_logic] call ALIVE_fnc_artillerySpawn; + +See Also: + +Author: +marceldev89 +---------------------------------------------------------------------------- */ +private _logic = param [0, objNull, [objNull]]; + +private _position = position _logic; +private _type = _logic getVariable ["artillery_type", ""]; +private _callsign = _logic getVariable ["artillery_callsign", ""]; +private _code = _logic getVariable ["artillery_code", ""]; + +private _side = _type call ALIVE_fnc_classSide; +private _group = createGroup _side; +private _vehicles = []; + +for "_i" from 0 to 2 do { + // TODO: Spawn vehicles in proper fancy formation (see CfgFormations) + private _vehiclePosition = _position getPos [15 * _i, (getDir _logic) * _i]; + private _vehicle = createVehicle [_type, _vehiclePosition, [], 0, "NONE"]; + _vehicle setDir (getDir _logic); + _vehicle lock true; + [_vehicle, _group] call BIS_fnc_spawnCrew; + _vehicles pushBack _vehicle; +}; + +if (_type isKindOf "StaticMortar") then { + // Create group leader + private _leader = _group createUnit ["B_Soldier_F", position (leader _group), [], 0, "NONE"]; + _group selectLeader _leader; + + // Create gunner assitants + { + private _vehicle = _x param [0, objNull]; + _group createUnit ["B_Soldier_F", position _vehicle, [], 0, "NONE"]; + } forEach _vehicles; + + _logic setVariable ["type", TYPE_MORTAR]; +} else { + _logic setVariable ["type", TYPE_ARTILLERY]; +}; + +_group setVariable ["logic", _logic]; +_logic setVariable ["group", _group]; + +// Assign artillery group to NEO_radio +private _rounds = [_logic, "getRounds"] call ALIVE_fnc_artillery; +leader _group setVariable ["NEO_radioArtyBatteryRounds", _rounds, true]; +private _a = NEO_radioLogic getVariable format ["NEO_radioArtyArray_%1", _side]; +_a set [count _a, [leader _group, _group, _callsign, _vehicles, _rounds]]; +NEO_radioLogic setVariable [format ["NEO_radioArtyArray_%1", _side], _a, true]; diff --git a/addons/sup_artillery/script_component.hpp b/addons/sup_artillery/script_component.hpp index 2982f4db2..7ad752926 100644 --- a/addons/sup_artillery/script_component.hpp +++ b/addons/sup_artillery/script_component.hpp @@ -9,4 +9,7 @@ #define DEBUG_SETTINGS DEBUG_SETTINGS_sup_artillery #endif +#define TYPE_ARTILLERY 0 +#define TYPE_MORTAR 1 + #include <\x\cba\addons\main\script_macros.hpp> diff --git a/addons/sup_combatsupport/fnc_combatSupport.sqf b/addons/sup_combatsupport/fnc_combatSupport.sqf index 06e871379..1a596e76d 100644 --- a/addons/sup_combatsupport/fnc_combatSupport.sqf +++ b/addons/sup_combatsupport/fnc_combatSupport.sqf @@ -85,14 +85,11 @@ switch(_operation) do { CAS_RESPAWN_LIMIT = parsenumber(_CAS_SET_RESPAWN_LIMIT); _TRANS_SET_RESPAWN_LIMIT = NEO_radioLogic getvariable ["combatsupport_transportrespawnlimit","3"]; TRANS_RESPAWN_LIMIT = parsenumber(_TRANS_SET_RESPAWN_LIMIT); - _ARTY_SET_RESPAWN_LIMIT = NEO_radioLogic getvariable ["combatsupport_artyrespawnlimit","3"]; - ARTY_RESPAWN_LIMIT = parsenumber(_ARTY_SET_RESPAWN_LIMIT); _audio = NEO_radioLogic getvariable ["combatsupport_audio",true]; _transportArrays = []; _casArrays = []; - _artyArrays = []; _sides = [WEST,EAST,RESISTANCE,CIVILIAN]; for "_i" from 0 to ((count synchronizedObjects _logic)-1) do { @@ -176,34 +173,6 @@ switch(_operation) do { _casArrays pushback _casArray; }; }; - } else { - switch (tolower(_type)) do { - case ("arty") : { - private ["_position","_callsign","_type"]; - - _position = getposATL _entry; - _direction = getDir _entry; - _class = typeOf _entry; - - _callsign = _entry getvariable ["CS_CALLSIGN",groupID (group _entry)]; - - _he = ["HE",parsenumber(_entry getvariable ["CS_artillery_he","30"])]; - _illum = ["ILLUM",parsenumber(_entry getvariable ["CS_artillery_illum","30"])]; - _smoke = ["SMOKE",parsenumber(_entry getvariable ["CS_artillery_smoke","30"])]; - _guided = ["SADARM",parsenumber(_entry getvariable ["CS_artillery_guided","30"])]; - _cluster = ["CLUSTER",parsenumber(_entry getvariable ["CS_artillery_cluster","30"])]; - _lg = ["LASER",parsenumber(_entry getvariable ["CS_artillery_lg","30"])]; - _mine = ["MINE",parsenumber(_entry getvariable ["CS_artillery_atmine","30"])]; - _atmine = ["AT MINE",parsenumber(_entry getvariable ["CS_artillery_atmine","30"])]; - _rockets = ["ROCKETS",parsenumber(_entry getvariable ["CS_artillery_rockets","16"])]; - - _ordnance = [_he,_illum,_smoke,_guided,_cluster,_lg,_mine,_atmine, _rockets]; - _code = _entry getvariable ["CS_CODE",""]; - _code = [_code,"this","(_this select 0)"] call CBA_fnc_replace; - _artyArray = [_position,_class, _callsign,3,_ordnance,_code]; - _artyArrays pushback _artyArray; - }; - }; }; switch (typeOf ((synchronizedObjects _logic) select _i)) do { @@ -251,57 +220,11 @@ switch(_operation) do { _transportArray = [_position,_direction,_type, _callsign,_tasks,_code,_height,_slingloading, _containers]; _transportArrays pushback _transportArray; }; - case ("ALiVE_sup_artillery") : { - private ["_position","_callsign","_type"]; - - _position = getposATL ((synchronizedObjects _logic) select _i); - _callsign = ((synchronizedObjects _logic) select _i) getvariable ["artillery_callsign","FOX ONE"]; - _class = ((synchronizedObjects _logic) select _i) getvariable ["artillery_type","B_Mortar_01_F"]; - _setherounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_he","30"]; - _setillumrounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_illum","30"]; - _setsmokerounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_smoke","30"]; - _setguidedrounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_guided","30"]; - _setclusterrounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_cluster","30"]; - _setlgrounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_lg","30"]; - _setminerounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_mine","30"]; - _setatminerounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_atmine","30"]; - _setrocketrounds = ((synchronizedObjects _logic) select _i) getvariable ["artillery_rockets","16"]; - - _direction = getDir ((synchronizedObjects _logic) select _i); - _code = ((synchronizedObjects _logic) select _i) getvariable ["artillery_code",""]; - _code = [_code,"this","(_this select 0)"] call CBA_fnc_replace; - - _herounds = parsenumber(_setherounds); - _illumrounds = parsenumber(_setillumrounds); - _smokerounds = parsenumber(_setsmokerounds); - _guidedrounds = parsenumber(_setguidedrounds); - _clusterrounds = parsenumber(_setclusterrounds); - _lgrounds = parsenumber(_setlgrounds); - _minerounds = parsenumber(_setminerounds); - _atminerounds = parsenumber(_setatminerounds); - _rocketrounds = parsenumber(_setrocketrounds); - - _he = ["HE",_herounds]; - _illum = ["ILLUM",_illumrounds]; - _smoke = ["SMOKE",_smokerounds]; - _guided = ["SADARM",_guidedrounds]; - _cluster = ["CLUSTER",_clusterrounds]; - _lg = ["LASER",_lgrounds]; - _mine = ["MINE",_minerounds]; - _atmine = ["AT MINE",_atminerounds]; - _rockets = ["ROCKETS", _rocketrounds]; - - _ordnance = [_he,_illum,_smoke,_guided,_cluster,_lg,_mine,_atmine, _rockets]; - - _artyArray = [_position,_class, _callsign,3,_ordnance,_code]; - _artyArrays pushback _artyArray; - }; }; }; SUP_CASARRAYS = _casArrays; PublicVariable "SUP_CASARRAYS"; SUP_TRANSPORTARRAYS = _transportArrays; PublicVariable "SUP_TRANSPORTARRAYS"; - SUP_ARTYARRAYS = _artyArrays; PublicVariable "SUP_ARTYARRAYS"; { NEO_radioLogic setVariable [format ["NEO_radioTrasportArray_%1", _x], [],true]; @@ -547,176 +470,6 @@ switch(_operation) do { } forEach SUP_CASARRAYS; - - - // ARTY - - { - private ["_pos", "_class", "_callsign", "_unitCount", "_rounds", "_code", "_roundsUnit", "_roundsAvailable", "_canMove", "_units", "_grp", "_vehDir","_tempclass","_side","_artyBatteries"]; - _pos = _x select 0; _pos set [2, 0]; - _class = _x select 1; - _callsign = toUpper (_x select 2); - _unitCount = round (_x select 3); if (_unitCount > 4) then { _unitCount = 4 }; if (_unitCount < 1) then { _unitCount = 1 }; - _rounds = _x select 4; - _code = _x select 5; - - if (_class in ["BUS_Support_Mort","BUS_MotInf_MortTeam","OIA_MotInf_MortTeam","OI_support_Mort","HAF_MotInf_MortTeam","HAF_Support_Mort"]) then { - // Force _unitCount to 1 to prevent spawning 3x3 units when _class is from CfgGroups - _unitCount = 1; - private _letter = _class select [0,1]; - - switch (_letter) do { - case "O" : {_tempclass = "O_Mortar_01_F"}; - case "B" : {_tempclass = "B_Mortar_01_F"}; - case "H" : {_tempclass = "I_Mortar_01_F"}; - default {_tempclass = "B_Mortar_01_F"}; - }; - - _side = getNumber(configfile >> "CfgVehicles" >> _tempclass >> "side"); - } else { - _side = getNumber(configfile >> "CfgVehicles" >> _class >> "side"); - }; - - switch (_side) do { - case 0 : {_side = EAST}; - case 1 : {_side = WEST}; - case 2 : {_side = RESISTANCE}; - default {_side = EAST}; - }; - - if (!isNil "_tempclass") then { - _roundsUnit = _tempclass call ALiVE_fnc_GetArtyRounds; - } else { - _roundsUnit = _class call ALiVE_fnc_GetArtyRounds; - }; - - _roundsAvailable = []; - _canMove = if (_class in ["B_MBT_01_arty_F", "O_MBT_02_arty_F", "B_MBT_01_mlrs_F","O_Mortar_01_F", "B_Mortar_01_F","I_Mortar_01_F","BUS_Support_Mort","BUS_MotInf_MortTeam","OIA_MotInf_MortTeam","OI_support_Mort","HAF_MotInf_MortTeam","HAF_Support_Mort"]) then { true } else { false }; - _units = []; - _artyBatteries = []; - _vehDir = 0; - - private ["_veh","_grp"]; - - _veh = nearestObjects [_pos, [_class], 5]; - - if (count _veh > 0) then {_veh = _veh select 0; _grp = group _veh} else {_veh = nil; _grp = createGroup _side}; - - if (isnil "_veh") then { - private ["_vehPos","_i"]; - for "_i" from 1 to _unitCount do - { - private ["_veh","_sptarr"]; - _vehPos = _pos getPos [15, _vehDir]; _vehPos set [2, 0]; - - if (isNil "_tempclass") then { - _veh = createVehicle [_class, _vehPos, [], 0, "CAN_COLLIDE"]; - _artyBatteries pushback _veh; - } else { - _veh = createVehicle [_tempclass, _vehPos, [], 0, "CAN_COLLIDE"]; - _artyBatteries pushback _veh; - }; - _veh setDir _vehDir; - _veh setPosATL _vehPos; - _veh lock true; - _vehDir = _vehDir + 90; - - [_veh, _grp] call BIS_fnc_spawnCrew; - - // set ownership flag for other modules - _veh setVariable ["ALIVE_CombatSupport", true]; - - // Exclude CS from VCOM - // CS only runs serverside so no PV is needed - (driver _veh) setvariable ["VCOM_NOAI", true]; - - if (_i == 1) then {leader _grp setRank "CAPTAIN"}; - - // Add leader and assistant if a mortar weapon, in order to use BIS pack and unpack functions - if (_class in ["O_Mortar_01_F", "B_Mortar_01_F","I_Mortar_01_F","BUS_Support_Mort","BUS_MotInf_MortTeam","OIA_MotInf_MortTeam","OI_support_Mort","HAF_MotInf_MortTeam","HAF_Support_Mort"]) then { - private ["_tl","_sl","_newgrp","_cars"]; - private _prefix = _class select [0,1]; - - if (_prefix == "H") then { - _prefix = "I"; - }; - - _tl = format ["%1_soldier_TL_F", _prefix]; - _sl = format ["%1_soldier_F", _prefix]; - _newgrp = [_vehPos, _side, [_tl, _sl],[],[],[],[],[],_vehDir] call BIS_fnc_spawnGroup; - (units _newgrp) joinSilent _grp; - - _sptarr = _grp getVariable ["supportWeaponArray",[]]; - _sptarr pushback _veh; - _grp setvariable ["supportWeaponArray", _sptarr]; - }; - - _units pushback _veh; - }; - if (_class in ["BUS_MotInf_MortTeam","OIA_MotInf_MortTeam","HAF_MotInf_MortTeam"]) then { - _cars = [2, faction (leader _grp),"Car"] call ALiVE_fnc_findVehicleType; - if (count _cars > 0) then { - for "_i" from 1 to ceil((count (units _grp))/4) do { - private "_car"; - _car = createVehicle [_cars select 0, [position (leader _grp),1,100,1,0,4,0] call bis_fnc_findSafePos, [], 0, "NONE"]; - _grp addVehicle _car; - _artyBatteries pushback _car; - }; - }; - }; - } else { - _units pushback _veh; - _veh lock true; - - // set ownership flag for other modules - _veh setVariable ["ALIVE_CombatSupport", true]; - }; - - { _x setVariable ["NEO_radioArtyModule", [leader _grp, _callsign], true] } forEach _units; - - [_grp,0] setWaypointPosition [_pos,0]; - [[(units _grp select 0),_callsign], "fnc_setGroupID", false, false] spawn BIS_fnc_MP; - - - _codeArray = [_code, ";"] call CBA_fnc_split; - { - _vehicle = _x; - { - if (_x != "") then { - [_vehicle, _x] spawn { - private ["_vehicle", "_spawn"]; - _vehicle = _this select 0; - _spawn = compile(_this select 1); - [_vehicle] spawn _spawn; - }; - }; - } forEach _codeArray; - } forEach _artyBatteries; - - //Validate rounds - { - if ((_x select 0) in _roundsUnit) then - { - _roundsAvailable pushback _x; - }; - } forEach _rounds; - - - leader _grp setVariable ["NEO_radioArtyBatteryRounds", _roundsAvailable, true]; - - //FSM - [_units, _grp, _callsign, _pos, _roundsAvailable, _canMove, _class, leader _grp, _code, _audio] execFSM "\x\alive\addons\sup_combatSupport\scripts\NEO_radio\fsms\alivearty.fsm"; - - _a = NEO_radioLogic getVariable format ["NEO_radioArtyArray_%1", _side]; - _a pushback ([leader _grp, _grp, _callsign, _units, _roundsAvailable]); - - NEO_radioLogic setVariable [format ["NEO_radioArtyArray_%1", _side], _a, true]; - - } forEach SUP_ARTYARRAYS; - - - - for "_i" from 0 to ((count _sides)-1) do { _sideIn = _sides select _i; @@ -751,21 +504,6 @@ switch(_operation) do { } foreach _xArray; NEO_radioLogic setVariable [format ["NEO_radioCasArray_%1", _sideIn], _sideInArray + _add,true]; }; - - private ["_sideInArray","_xArray"]; - _sideInArray = NEO_radioLogic getVariable format["NEO_radioArtyArray_%1", _sideIn]; - _xArray = NEO_radioLogic getVariable format["NEO_radioArtyArray_%1", _x]; - - if (count _xArray > 0) then { - _add = []; - { - _vehicle = _x select 0; - if (({_vehicle == _x select 0} count _sideInArray) == 0) then { - _add pushback _x; - }; - } foreach _xArray; - NEO_radioLogic setVariable [format ["NEO_radioArtyArray_%1", _sideIn], _sideInArray + _add,true]; - }; }; } foreach _sides; }; diff --git a/addons/sup_combatsupport/fnc_packMortar.sqf b/addons/sup_combatsupport/fnc_packMortar.sqf index c77fdf382..5e62b70b0 100644 --- a/addons/sup_combatsupport/fnc_packMortar.sqf +++ b/addons/sup_combatsupport/fnc_packMortar.sqf @@ -14,108 +14,82 @@ SCRIPT(packMortar); _this select 0: the support team group (group) _this select 1: the weapon (option if weapon registered as "supportWeaponSetup" variable) */ -private["_group","_weapon","_position","_leader","_units","_gunner","_assistant","_type","_wait"]; +private _group = _this param [0, grpNull]; +private _weapon = _this param [1, objNull]; -_group = [_this, 0, grpNull] call bis_fnc_param; -_weapon = [_this, 1, grpNull] call bis_fnc_param; -_type = typeOf _weapon; -_position = position _weapon; -_leader = leader _group; -_gunner = gunner _weapon; -_units = (units _group) - [_leader]; -_units = _units - [_gunner]; +if (isNull _group || isNull _weapon) exitWith {}; -if (_weapon == objNull || isNil "_weapon" || _group == grpNull || _leader == objNull) exitWith {}; +private _disassembleToCfg = (configFile >> "CfgVehicles" >> typeOf _weapon >> "assembleInfo" >> "dissasembleTo"); +private _disassembleTo = _disassembleToCfg call BIS_fnc_getCfgData; -{ - // find a group member that is not in a vehicle or staticweapon and is free - if !(_x getVariable ["packAssistant",false] || (vehicle _x != _x)) exitWith { - _assistant = _x; - _assistant setVariable ["packAssistant",true]; - }; -} foreach _units; +if (isNil "_disassembleTo" || {count _disassembleTo == 0}) exitWith {}; + +private _leader = leader _group; +private _gunner = gunner _weapon; +private _units = (units _group) - [_leader] - [_gunner]; +private _assistant = _units select 0; -// diag_log format ["%1, %2, %3, %4, %5, %6, %7", _group, _weapon, _position, _leader, _gunner, _assistant, _type]; +private _primaryBag = objNull; +private _secondaryBag = objNull; + +private _timeout = -1; _gunner leaveVehicle _weapon; -_gunner addEventHandler ["WeaponDisassembled", { - _this spawn { - private ["_unit","_bag1","_bag2"]; - _unit = _this select 0; - _bag1 = _this select 1; - _bag2 = _this select 2; +private _disassembledEH = _gunner addEventHandler ["WeaponDisassembled", { + private _unit = _this param [0, objNull]; + private _primaryBag = _this param [1, objNull]; + private _secondaryBag = _this param [2, objNull]; - _unit setVariable ["supportWeaponBag1", _bag1]; - _unit setVariable ["supportWeaponBag2", _bag2]; - }; + _unit setVariable ["primaryBag", _primaryBag]; + _unit setVariable ["secondaryBag", _secondaryBag]; }]; -_gunner action ["Disassemble",_weapon]; +_gunner action ["Disassemble", _weapon]; + +_timeout = time + 5; +while {isNull _primaryBag || isNull _secondaryBag} do { + if (time >= _timeout) exitWith { + _primaryBag = createVehicle [_disassembleTo select 0, position _weapon, [], 0, "NONE"]; + _secondaryBag = createVehicle [_disassembleTo select 1, position _weapon, [], 0, "NONE"]; + + deleteVehicle _weapon; + }; + + _primaryBag = _gunner getVariable ["primaryBag", objNull]; + _secondaryBag = _gunner getVariable ["secondaryBag", objNull]; + sleep 0.1; +}; { _x enableAI "MOVE"; - _x enableAI "ANIM"; _x setUnitPos "AUTO"; } forEach [_gunner, _assistant]; -{ - [_x,position _weapon] call ALiVE_fnc_doMoveRemote; -} foreach [_gunner, _assistant]; - -[_weapon, _gunner, _assistant] spawn { - private ["_weapon","_gunner","_assistant","_position","_wait","_bag2","_bag1","_timeout","_packs"]; - _weapon = _this select 0; - _gunner = _this select 1; - _assistant = _this select 2; - _position = position _weapon; - - _timer = time; - waitUntil {sleep 0.3; _gunner call ALiVE_fnc_unitReadyRemote || (time-_timer > 30)}; - - _gunner action ["Disassemble",_weapon]; - - _wait = true; - _timeout = false; - _timer = time; - while {_wait} do { - _packs = nearestObjects [_position, ["GroundWeaponHolder"], 3]; - if (count _packs > 1) then {_wait = false}; - if ((time-_timer) > 30) exitWith {_timeout = true;}; - sleep 1; - }; +_gunner action ["takeBag", _primaryBag]; +_assistant action ["takeBag", _secondaryBag]; - if (_timeout) then { - _bag1 = format ["%1_Mortar_01_weapon_F", _weapon select [0,1]]; - _bag2 = format ["%1_Mortar_01_support_F",_weapon select [0,1]]; - deleteVehicle _weapon; - _gunner addBackpackGlobal _bag1; - _assistant addBackpackGlobal _bag2; - } else { - _bag1 = _gunner getVariable ["supportWeaponBag1", objNull]; - _bag2 = _gunner getVariable ["supportWeaponBag2", objNull]; - _gunner action ["takeBag", _bag1]; - _assistant action ["takeBag", _bag2]; +_timeout = time + 5; +while {unitBackpack _gunner != _primaryBag || unitBackpack _assistant != _secondaryBag} do { + if (time >= _timeout) exitWith { + _gunner addBackpackGlobal (typeOf _primaryBag); + _assistant addBackpackGlobal (typeOf _secondaryBag); }; + sleep 0.1; +}; - _timer = time; - waitUntil {sleep 1; (unitBackpack _gunner == _bag1 && unitBackpack _assistant == _bag2) || (time-_timer) > 30}; +// Cleanup possible remaining backpacks +private _weaponHolders = nearestObjects [position _gunner, ["GroundWeaponHolder"], 25]; - if (unitBackpack _gunner != _bag1) then { - _gunner addBackpackGlobal (typeOf _bag1); - }; - - if (unitBackpack _assistant != _bag2) then { - _assistant addBackpackGlobal (typeOf _bag2); - { - deleteVehicle _x; - }foreach _packs; - }; - - _gunner setVariable ["supportWeaponGunner", _weapon]; - _assistant setVariable ["supportWeaponAsst", _weapon]; - _weapon setVariable ["packed",true]; +{ + private _weaponHolder = _x param [0, objNull]; + private _weaponHolderBackpacks = backpackCargo _weaponHolder; + { + private _backpack = _x param [0, objNull]; -// diag_log format ["%1 packed up!",_weapon]; -}; \ No newline at end of file + if (_backpack in _weaponHolderBackpacks) exitWith { + deleteVehicle _weaponHolder; + }; + } forEach _disassembleTo; +} forEach _weaponHolders; diff --git a/addons/sup_combatsupport/fnc_unpackMortar.sqf b/addons/sup_combatsupport/fnc_unpackMortar.sqf index 6877a6e9e..2e56ff592 100644 --- a/addons/sup_combatsupport/fnc_unpackMortar.sqf +++ b/addons/sup_combatsupport/fnc_unpackMortar.sqf @@ -15,99 +15,153 @@ SCRIPT(unpackMortar); _this select 1: location to place gun (position) _this select 2: location of target (position) */ -private ["_group","_position","_targetPos","_leader","_units","_gunner","_assistant","_weapon"]; +private _group = _this param [0, grpNull]; +private _position = _this param [1, grpNull]; +private _targetPos = _this param [2, grpNull]; -//diag_log str(_this); +// TODO: Perhaps leader could pick up an other role if needed? +if (count (units _group) < 3) exitWith { + // TODO: is supportWeaponCount needed? + _sptCount = _grp getVariable ["supportWeaponCount",3]; + _grp setVariable ["supportWeaponCount", _sptCount - 1]; + + diag_log "unpackMortar: cannot assemble, requires 3 units" +}; -_group = [_this, 0, grpNull] call bis_fnc_param; -_position = [_this, 1, grpNull] call bis_fnc_param; -_targetPos = [_this, 2, grpNull] call bis_fnc_param; -_weapon = [_this, 3, grpNull] call bis_fnc_param; -_units = (units _group); +private _assembleTo = ""; +private _disassembleTo = []; +private _backpacks = []; +// TODO: Extract to seperate script? { - if (vehicle _x != _x) then { - doGetOut _x; - }; - if (_x getVariable ["supportWeaponGunner",objNull] == _weapon) then { - _gunner = _x; - }; - if (_x getVariable ["supportWeaponAsst",objNull] == _weapon) then { - _assistant = _x; - }; -} foreach _units; + private _backpack = unitBackpack _x; -if (isNil "_gunner" || isNil "_assistant") exitWith { - diag_log "Someone from the mortar team died"; - // reduce mortar count - _sptCount = _grp getVariable ["supportWeaponCount",3]; - _grp setVariable ["supportWeaponCount", _sptCount - 1]; -}; + if (!isNull _backpack) then { + private _assembleToCfg = (configFile >> "CfgVehicles" >> typeOf _backpack >> "assembleInfo" >> "assembleTo"); + private _assembleToValue = _assembleToCfg call BIS_fnc_getCfgData; -[_gunner, _assistant, _targetPos, _weapon, _group] spawn { + if (!isNil "_assembleToValue" && {count _assembleToValue > 0}) then { + private _disassembleToCfg = (configFile >> "CfgVehicles" >> _assembleToValue >> "assembleInfo" >> "dissasembleTo"); + private _disassembleToValue = _disassembleToCfg call BIS_fnc_getCfgData; + + if (!isNil "_disassembleToValue" && {count _disassembleToValue > 0}) then { + _disassembleTo = _disassembleToValue; + }; + }; - private ["_gunner","_assistant","_pos","_tPos","_wait","_dirTo","_sptarr","_weapont", "_weapon","_grp","_timein","_timer","_sptCount"]; + _backpacks pushBack (typeOf _backpack); + }; +} forEach (units _group); - _gunner = _this select 0; - _assistant = _this select 1; - _tPos = _this select 2; - _weapont = typeOf (_this select 3); - _grp = _this select 4; +private _canAssemble = true; - waitUntil{sleep 0.1; _gunner call ALiVE_fnc_unitReadyRemote}; +{ + if (!(_x in _backpacks)) exitWith { + _canAssemble = false; + }; +} forEach _disassembleTo; + +if (!_canAssemble) exitWith { diag_log format ["unpackMortar: cannot assemble %1! NEED: %2 HAS: %3", _assembleTo, _disassembleTo, _backpacks] }; + +private _weapon = objNull; +private _leader = leader _group; +private _units = (units _group) - [_leader]; +private _gunner = _units select 0; +private _assistant = _units select 1; +private _timeout = -1; + +{_x doMove ([_position, 0, 5, 0, 0, 20, 0] call BIS_fnc_findSafePos)} forEach (_units + [_leader]); + +private _unitsReady = false; +_timeout = time + 60; +while {!_unitsReady} do { + if (time >= _timeout) exitWith { + { + doStop _x; + _x setPos ([_position, 0, 5, 0, 0, 20, 0] call BIS_fnc_findSafePos); + } forEach (_units + [_leader]); + }; - _gunner disableAI "move"; + { + // Break out of forEach as soon as unit is not "ready" + if (!(_x call ALiVE_fnc_unitReadyRemote)) exitWith { + _unitsReady = false; + }; - _assistant disableAI "move"; + _unitsReady = true; + } forEach (_units + [_leader]); - _assistant setpos (position _gunner); + sleep 0.1; +}; - _assistant setUnitPos "Middle"; +// TODO: change MOVE to PATH post A3 1.62 release? +_gunner disableAI "MOVE"; +_assistant disableAI "MOVE"; - _assistant action ["PutBag",_assistant]; - _gunner action ["Assemble",unitbackpack _gunner]; +private _assistantBackpack = unitBackpack _assistant; +_assistant action ["PutBag"]; - _wait = true; - _timein = true; - _timer = time; - while {_wait && _timein} do { - _weapon = (nearestObjects [position _gunner, [_weapont], 3]) select 0; - if (!isNil "_weapon") then { - if (alive _weapon) then {_wait = false}; - }; - if (time-_timer > 60) then {_timein = false}; - sleep 1; +_timeout = time + 5; +while {!isNull (unitBackpack _assistant)} do { + if (time >= _timeout) exitWith { + _assistantBackpack = createVehicle [typeOf _assistantBackpack, position _assistant, [], 0, "NONE"]; + removeBackpackGlobal _assistant; }; + sleep 0.1; +}; + +private _assembledEH = _gunner addEventHandler ["WeaponAssembled", { + private _unit = _this param [0, objNull]; + private _weapon = _this param [1, objNull]; + + _unit setVariable ["assembledWeapon", _weapon]; +}]; + +_gunner action ["Assemble", _assistantBackpack]; - if (!_timein && _wait) then { - diag_log format["unpack timedout %1",(nearestObjects [position _gunner, [], 3])]; +_timeout = time + 5; +while {isNull _weapon} do { + if (time >= _timeout) exitWith { + _weapon = createVehicle [_assembleTo, position _gunner, [], 0, "NONE"]; removeBackpackGlobal _gunner; - removeBackpackGlobal _assistant; - _weapon = createVehicle [_weapont, position _gunner, [], 3, "NONE"]; }; - _sptarr = _grp getVariable ["supportWeaponArray",[]]; - _sptarr pushback _weapon; - _grp setvariable ["supportWeaponArray", _sptarr]; + _weapon = _gunner getVariable ["assembledWeapon", objNull]; + sleep 0.1; +}; + +_gunner removeEventHandler ["WeaponAssembled", _assembledEH]; + +// Cleanup possible remaining backpacks +private _weaponHolders = nearestObjects [position _gunner, ["GroundWeaponHolder"], 25]; - _dirTo = ((position _weapon) getDir _tPos); +{ + private _weaponHolder = _x param [0, objNull]; + private _weaponHolderBackpacks = backpackCargo _weaponHolder; + + { + private _backpack = _x param [0, objNull]; - sleep 5; - _gunner assignAsGunner _weapon; - _gunner moveInGunner _weapon; - sleep 5; + if (_backpack in _weaponHolderBackpacks) exitWith { + deleteVehicle _weaponHolder; + }; + } forEach _disassembleTo; +} forEach _weaponHolders; - _gunner commandWatch _tPos; +private _dirTo = [position _weapon, _targetPos] call BIS_fnc_dirTo; +_weapon setDir _dirTo; - _assistant selectWeapon "Binocular"; - sleep 6; - _assistant commandWatch _tPos; - _assistant setDir _dirTo; +_gunner assignAsGunner _weapon; +_gunner moveInGunner _weapon; +_gunner commandWatch _targetPos; - _gunner setVariable ["unpacked", true]; - _assistant setVariable ["packAssistant", false]; +_assistant setUnitPos "Middle"; +_assistant setDir _dirTo; +_assistant commandWatch _targetPos; -// diag_log str(_grp getVariable ["supportWeaponArray",[]]); -}; +_leader selectWeapon "Binocular"; +_leader setUnitPos "Middle"; +_leader setDir _dirTo; +_leader commandWatch _targetPos; -_gunner +_gunner; diff --git a/addons/sup_combatsupport/script_component.hpp b/addons/sup_combatsupport/script_component.hpp index 2910df7ca..7a726ce96 100644 --- a/addons/sup_combatsupport/script_component.hpp +++ b/addons/sup_combatsupport/script_component.hpp @@ -9,4 +9,4 @@ #define DEBUG_SETTINGS DEBUG_SETTINGS_SUP_COMBATSUPPORT #endif -#include <\x\cba\addons\main\script_macros.hpp> \ No newline at end of file +#include <\x\cba\addons\main\script_macros.hpp> diff --git a/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButton.sqf b/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButton.sqf index 52bf768c4..b6a944297 100644 --- a/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButton.sqf +++ b/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButton.sqf @@ -24,7 +24,8 @@ _type = "IMMEDIATE"; _ordnanceType = _artyOrdnanceTypeLb lbText (lbCurSel _artyOrdnanceTypeLb); //_ord = [_battery, _ordnanceType] CALL ALIVE_fnc_GetMagazineType; -_ord = [_battery, _ordnanceType] CALL ALIVE_fnc_getArtyMagazineType; +private _gunner = ((units _unit) select {vehicle _x != _x && {gunner (vehicle _x) == _x}}) select 0; +_ord = [_gunner, _ordnanceType] CALL ALIVE_fnc_getArtyMagazineType; _rate = switch (_artyRateOfFireLb lbText (lbCurSel _artyRateOfFireLb)) do { @@ -57,6 +58,9 @@ if (_audio) then { player kbTell [_battery, "ALIVE_SUPP_protocol", "Artillery_Request", "GROUP"]; }; +// TODO: Cleanup obsolete bits +private _logic = _unit getVariable ["logic", objNull]; +[_logic, "setFireMission", [_pos, _ord, _count, _rate, _dispersion]] call ALIVE_fnc_artillery; //NEW TASK _battery setVariable ["NEO_radioArtyNewTask", [_type, _ordnanceType, _rate, _count, _dispersion, _pos, _unit, _ord, _callsignPlayer, player], true]; diff --git a/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButtonEnable.sqf b/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButtonEnable.sqf index a2e050863..1876634a0 100644 --- a/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButtonEnable.sqf +++ b/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyConfirmButtonEnable.sqf @@ -12,6 +12,7 @@ _artyRateOfFireLb = _display displayCtrl 655603; _artyRoundCountLb = _display displayCtrl 655605; _battery = _artyArray select (lbCurSel _artyUnitLb) select 0; if (!isNil { NEO_radioLogic getVariable "NEO_radioTalkWithArty" }) then { _battery = ((NEO_radioLogic getVariable "NEO_radioTalkWithArty") getVariable "NEO_radioArtyModule") select 0 }; _status = _battery getVariable "NEO_radioArtyUnitStatus"; +_status = "NONE"; // TODO: Handle status properly if ( diff --git a/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyUnitLbSelChanged.sqf b/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyUnitLbSelChanged.sqf index f4c533cfc..dfcf4e83a 100644 --- a/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyUnitLbSelChanged.sqf +++ b/addons/sup_combatsupport/scripts/NEO_radio/functions/ui/arty/fn_artyUnitLbSelChanged.sqf @@ -31,6 +31,7 @@ _supportMarker = NEO_radioLogic getVariable "NEO_supportMarker"; _artyMarkers = NEO_radioLogic getVariable "NEO_supportArtyMarkers"; _battery = _artyArray select (lbCurSel _artyUnitLb) select 0; if (!isNil { NEO_radioLogic getVariable "NEO_radioTalkWithArty" }) then { _battery = ((NEO_radioLogic getVariable "NEO_radioTalkWithArty") getVariable "NEO_radioArtyModule") select 0 }; _status = _battery getVariable "NEO_radioArtyUnitStatus"; +_status = "NONE"; // TODO: Handle status properly _class = typeOf (((_artyArray select (lbCurSel _artyUnitLb)) select 3) select 0); if (!isNil { NEO_radioLogic getVariable "NEO_radioTalkWithArty" }) then { _class = typeOf (NEO_radioLogic getVariable "NEO_radioTalkWithArty") }; _ord = _battery getVariable "NEO_radioArtyBatteryRounds";