commit 75b737230e1bd4dac7b198df0eae2a1291708228 Author: Clarky77 Date: Sat Aug 8 17:42:15 2026 +1000 Initial upload. Not currently functional as a mod. Includes some slightly refactored source code as well as the original mission this was debuted in zipped up as reference + example of usage. diff --git a/cfgFunctions.hpp b/cfgFunctions.hpp new file mode 100644 index 0000000..e69de29 diff --git a/cfgVehicles.hpp b/cfgVehicles.hpp new file mode 100644 index 0000000..e69de29 diff --git a/config.cpp b/config.cpp new file mode 100644 index 0000000..d498298 --- /dev/null +++ b/config.cpp @@ -0,0 +1,30 @@ +/* + Author: Clarky + + + +*/ + +// config.cpp only relevent to modmaking, so I have discovered. Yippee + +/* +class CfgPatches +{ + class LogisticsVehicles + { + units[] = {"SPEX_CW_M5_Halftrack_Ammo"}; + weapons[] = {}; + requiredAddons[] = {"A3_Soft_F"}; + }; +}; + +class CfgVehicles +{ + class SPEX_CW_M5_Halftrack_Ammo; + + class SUPPLY_SPEX_CW_M5_Halftrack_Ammo : SPEX_CW_M5_Halftrack_Ammo + { + displayName = "M3 Half-Track (Supply)"; + } +} + */ \ No newline at end of file diff --git a/config/buildableVehicles.sqf b/config/buildableVehicles.sqf new file mode 100644 index 0000000..53a2903 --- /dev/null +++ b/config/buildableVehicles.sqf @@ -0,0 +1,61 @@ +// Each vehicle array needs to be define as per below within each category +// ["Class_Name", Cost, BuildTime, "Specialisation", [maxMateriel, transferRate]] +// Specialisation options are currently: +// 0 NONE, 1 SUPPLY, 2 BUILD +// maxMateriel and transferRate only need to be provided for SUPPLY and CONSTRUCTION vehicles + + +// Unarmed Vehicles +CLF_Category1 = [ + ["SPEX_CW_G503_MB_Open", 75, 10, "NONE", []], + ["SPEX_CW_G503_MB", 75, 10, "NONE", []], + ["SPEX_CW_G503_MB_Ambulance", 100, 10, "NONE", []], + + ["SPEX_CW_Bedford_MWD_Open", 150, 10, "NONE", []], + ["SPEX_CW_Bedford_MWD", 150, 10, "NONE", []], + ["SPEX_CW_Bedford_MWD_Ammo", 200, 10, "NONE", []], + ["SPEX_CW_Bedford_MWD_Fuel", 200, 10, "NONE", []], + ["SPEX_CW_Bedford_MWD_Repair", 200, 10, "NONE", []], + ["SPEX_CW_Bedford_MWD_Ammo", 300, 15, "SUPPLY", [300, 50]], + + ["SPEX_CW_M5_Halftrack_Unarmed_Open", 250, 15, "NONE", []], + ["SPEX_CW_M5_Halftrack_Unarmed", 250, 15, "NONE", []], + ["SPEX_CW_M5_Halftrack_Ambulance", 275, 15, "NONE", []], + ["SPEX_CW_M5_Halftrack_Ammo", 350, 15, "NONE", []], + ["SPEX_CW_M5_Halftrack_Fuel", 350, 15, "NONE", []], + ["SPEX_CW_M5_Halftrack_Repair", 350, 15, "NONE", []], + ["SPEX_CW_M5_Halftrack_Ammo", 400, 20, "SUPPLY", [500, 100]] + //["SPEX_CW_M5_Halftrack_Repair", 400, 20, "BUILD", [500, 100]] +]; + +// Armed Vehicles +CLF_Category2 = [ + ["SPEX_CW_G503_MB_M2", 150, 15, "NONE", []], + ["SPEX_CW_M5_Halftrack", 325, 20, "NONE", []], + + ["SPEX_CW_Humber_MkII", 500, 30, "NONE", []], + ["SPEX_CW_Humber_LRC", 450, 30, "NONE", []], + ["SPEX_CW_Humber_MkIV", 600, 30, "NONE", []], + ["SPEX_CW_Humber_MkIV_PLM", 750, 30, "NONE", []], + + ["SPEX_CW_M8_LAC", 750, 30, "NONE", []], + ["SPEX_CW_M8_LAC_ringMount", 800, 30, "NONE", []], + + ["SPEX_CW_Cromwell_Mk5", 900, 45, "NONE", []], + ["SPEX_CW_Cromwell_Mk6", 950, 45, "NONE", []], + ["SPEX_CW_Sherman_V", 1000, 55, "NONE", []], + ["SPEX_CW_Sherman_Ic_Hybrid", 1100, 60, "NONE", []], + ["SPEX_CW_Sherman_Vc", 1200, 60, "NONE", []], + ["SPEX_CW_M10", 1050, 50, "NONE", []] +]; + +// Support +CLF_Category3 = [ + ["SPEX_CW_QF_6_Pounder", 300, 20, "NONE", []], + ["SPE_M45_Quadmount", 325, 20, "NONE", []], + ["ACE_Wheel", 5, 5, "NONE", []], + ["ACE_Track", 15, 5, "NONE", []] +]; + + + diff --git a/eventHandlers/fn_registerClientEvents.sqf b/eventHandlers/fn_registerClientEvents.sqf new file mode 100644 index 0000000..7c5f190 --- /dev/null +++ b/eventHandlers/fn_registerClientEvents.sqf @@ -0,0 +1,102 @@ +/* + +// Handler for reacting to a supply vehicle creation, thus creating the required interactable actions on that vehicle +[ + "CLF_SupplyVehicleCreated", + { + params ["_vehicle"]; + [_vehicle] call CLF_fnc_initSupplyVehicleInteractions; + } +] call CBA_fnc_addEventHandler; + +// Handler for reacting to a supply depot creation, thus creating the required interactable actions on that depot +[ + "CLF_SupplyDepotCreated", + { + params ["_depot"]; + [_depot] call CLF_fnc_initSupplyDepotInteractions; + } +] call CBA_fnc_addEventHandler; + +*/ + +// Handler for confirming construction of a vehicle at a factory for the client +[ + "CLF_ConfirmFactoryVehicleClient", + { + params ["_hq", "_vehicle", "_cost", "_buildTime", "_player"]; + [_hq, _vehicle, _cost, _buildTime, _player] call CLF_fnc_factoryBuildConfirmClient; + } +] call CBA_fnc_addEventHandler; + +// Handler for displaying a message local to one player. Message can be SUCCESS (0), WARNING (1), ALERT (2), or INFO (3) with different appearances based on message type +[ + "CLF_ShowMessage", + { + params ["_type", "_size", "_message"]; + + private _fontsize = ""; + private _ypos = ""; + private _prefix = ""; + private _color = ""; + + + switch (_size) do { + case 0: { + _fontsize = 1; + _ypos = 0.3 + }; + + case 1: { + _fontsize = 0.8; + _ypos = 0.65 + }; + + default { + _fontsize = 0.8; + _ypos = 0.65 + }; + }; + + switch (_type) do { + case 0: { + _prefix = "SUCCESS"; + _color = "#00FF00"; + }; + + case 1: { + _prefix = "WARNING"; + _color = "#FFFF00"; + }; + + case 2: { + _prefix = "ALERT"; + _color = "#FF0000"; + }; + + case 3: { + _prefix = "INFO"; + _color = "#5979FF"; + }; + + default { + _prefix = "INFO"; + _color = "#5979FF"; + }; + }; + + [ + format [ + "%3: %4", + _fontsize, + _color, + _prefix, + _message + ], + 0, // X position (centre) + _ypos, // Y position + 4, // duration + 0.3 // fade time + ] spawn BIS_fnc_dynamicText; + } +] call CBA_fnc_addEventHandler; diff --git a/eventHandlers/fn_registerServerEvents.sqf b/eventHandlers/fn_registerServerEvents.sqf new file mode 100644 index 0000000..27681c7 --- /dev/null +++ b/eventHandlers/fn_registerServerEvents.sqf @@ -0,0 +1,62 @@ +// Handler for running the VehicleLoaded function +[ + "CLF_VehicleLoaded", + { + params ["_vehicle", "_player", "_depot"]; + [_vehicle, _player, _depot] call CLF_fnc_vehicleLoad; + } +] call CBA_fnc_addEventHandler; + +// Handler for running the VehicleUnloaded function +[ + "CLF_VehicleUnloaded", + { + params ["_vehicle", "_player", "_depot"]; + [_vehicle, _player, _depot] call CLF_fnc_vehicleUnload; + } +] call CBA_fnc_addEventHandler; + +// Handler for confirming factory vehicle construction on the server +[ + "CLF_ConfirmFactoryBuildServer", + { + params ["_hq", "_player", "_vehicleClass", "_vehiclePreviewLocation", "_rotation", "_vectorUp", "_cost", "_buildTime", "_specialisation", "_specialisationData"]; + [_hq, _player, _vehicleClass, _vehiclePreviewLocation, _rotation, _vectorUp, _cost, _buildTime, _specialisation, _specialisationData] spawn CLF_fnc_factoryBuildConfirmServer; + } +] call CBA_fnc_addEventHandler; + +// Handler for cancelling factory vehicle construction on the server +[ + "CLF_CancelFactoryBuildServer", + { + params ["_hq", "_vehicle", "_cost", "_player"]; + [_hq, _vehicle, _cost, _player ] call CLF_fnc_cancelFactoryBuildServer; + } +] call CBA_fnc_addEventHandler; + +// Handler for running the function which consumes materiel at ab ase +[ + "CLF_MaterielConsume", + { + params ["_hq", "_amount", "_player"]; + [_hq, _amount, _player] call CLF_fnc_materielConsume; + } +] call CBA_fnc_addEventHandler; + +// Handler for adding materiel back to a base +[ + "CLF_MaterielAdd", + { + params ["_hq", "_amount", "_player"]; + [_hq, _amount, _player ] call CLF_fnc_materielAdd; + } +] call CBA_fnc_addEventHandler; + +// Handler for adding fortify budget +[ + "CLF_FortifyBudgetAdd", + { + params ["_side", "_amount"]; + [_side, _amount, true] call ace_fortify_fnc_updateBudget; + } +] call CBA_fnc_addEventHandler; \ No newline at end of file diff --git a/functions/build/fn_cancelFactoryBuildClient.sqf b/functions/build/fn_cancelFactoryBuildClient.sqf new file mode 100644 index 0000000..a613306 --- /dev/null +++ b/functions/build/fn_cancelFactoryBuildClient.sqf @@ -0,0 +1,11 @@ +/* + * + * + * + * + */ + +// params ["_hq", "_vehicle", "_cost", "_buildTime", ]; + +// missionNamespace setVariable ["buildActive",false]; + diff --git a/functions/build/fn_cancelFactoryBuildServer.sqf b/functions/build/fn_cancelFactoryBuildServer.sqf new file mode 100644 index 0000000..2d6e0fc --- /dev/null +++ b/functions/build/fn_cancelFactoryBuildServer.sqf @@ -0,0 +1,19 @@ +/* + * + * + * + * + */ + +params ["_hq", "_vehicle", "_cost", "_player"]; + +deleteVehicle _vehicle; + +[ + "CLF_MaterielAdd", + [ + _hq, + _cost, + _player + ] +] call CBA_fnc_serverEvent; \ No newline at end of file diff --git a/functions/build/fn_factoryBuild.sqf b/functions/build/fn_factoryBuild.sqf new file mode 100644 index 0000000..3a6c4c6 --- /dev/null +++ b/functions/build/fn_factoryBuild.sqf @@ -0,0 +1,309 @@ +/* + * Author: Clarky + * Usage: + * [_class, _cost, _buildTime, _specialisation] call CLF_fnc_factoryBuild; + * + * Intended to be called via the factoryConfirmSelection function + * + * Purpose: + * Begins the process of building a vehicle with player selection on the VehicleFactory dialog + * + */ + +params ["_player", "_vehicleClass", "_cost", "_buildTime", "_specialisation", "_specialisationData"]; + +// Stow weapon at start of process +player action ["SWITCHWEAPON", player, player, -1]; + +private _rotation = getDir player; +missionNamespace setVariable ["previewRotation", _rotation]; +private _confirm = false; +private _cancel = false; + +private _hq = uiNamespace getVariable ["localHQ", ""]; +if (_hq isEqualTo "") exitWith { hint "No local HQ"; }; + +// Spawn the vehicle locally - only player who clicked the dialog will see it at this stage +private _vehiclePreview = createVehicleLocal [ + _vehicleClass, + [0, 0, 0], + [], + 0, + "NONE" +]; + +_vehiclePreview disableCollisionWith _player; + +//waitUntil { _vehiclePreview == _vehiclePreview }; + +// Disable all damage and simulation until build is confirmed +_vehiclePreview enableSimulation false; +_vehiclePreview enableSimulationGlobal false; +_vehiclePreview allowDamage false; +//_vehiclePreview setPhysicsCollisionFlag false; +removeAllActions _vehiclePreview; +_vehiclePreview setVehicleLock "LOCKED"; +_vehiclePreview lockInventory true; + +// Apply a slight tint/texture which will be used to show the player if it can be placed or not +_vehiclePreview setObjectTextureGlobal [0, "#(argb,8,8,3)color(0,1,0,0.35,ca)"]; + +// Load the 'display' handling input events +private _display = findDisplay 46; + +private _mouseScroll = _display displayAddEventHandler [ + // Handle mouse scroll wheel axis input + "MouseZChanged", + { + params ["_display", "_scroll"]; + private _dir = missionNamespace getVariable ["previewRotation", 0]; + _dir = _dir + (_scroll * 5); + missionNamespace setVariable ["previewRotation", _dir]; + } +]; + +private _mouseInput = _display displayAddEventHandler [ + // Handle LMB/RMB click + "MouseButtonDown", + { + params ["", "_button"]; + + switch (_button) do + { + case 0: // LMB + { + missionNamespace setVariable [ + "confirmPlacement", + true + ]; + }; + + case 1: // RMB + { + missionNamespace setVariable [ + "cancelPlacement", + true + ]; + }; + }; + false; + } +]; + +private _keyboardInput = _display displayAddEventHandler [ + // Handle keyboard clicks as extra verification tools + "KeyDown", + { + params ["", "_key"]; + + switch (_key) do + { + case 28: // Enter + { + missionNamespace setVariable [ + "confirmPlacement", + true + ]; + }; + + case 1: // Escape + { + missionNamespace setVariable [ + "cancelPlacement", + true + ]; + }; + }; + false; + } +]; + +// Load up variables for closing out the build preview one way or the other +missionNamespace setVariable ["confirmPlacement",false]; +missionNamespace setVariable ["cancelPlacement",false]; + + _previewUI = addMissionEventHandler [ + "Draw3D", + { + //hint "sucessfully spawned preview"; + if (missionNamespace getVariable ["confirmPlacement", false]) exitWith {}; + if (missionNamespace getVariable ["cancelPlacement", false]) exitWith { hintSilent ""; }; + + hintSilent "VEHICLE CONSTRUCTION\n\nLMB: Confirm\nRMB: Cancel\nScrollwheel: Rotate"; + + /* + drawIcon3D [ + "", + [1, 1, 1, 1], + positionCameraToWorld [0, 3, 0], + 0, + 0, + 0, + "LMB: Place | RMB: Cancel | Scroll: Rotate", + 2, + 0.04, + "PuristaMedium" + ];*/ + } + ]; + +// Spawn code that runs until the player +while { (player call ace_medical_fnc_isInStableCondition) && !_confirm && !_cancel } do +{ + private _rotation = missionNamespace getVariable ["previewRotation", 0]; + + // Raycast out from player perspective to find location to place the preview vehicle + private _maxDistance = 15; + private _start = eyePos player; + private _direction = getCameraViewDirection player; + private _end = _start vectorAdd ( + _direction vectorMultiply _maxDistance + ); + + private _hits = lineIntersectsSurfaces [ + _start, + _end, + player, + _vehiclePreview, + true, + 1, + "GEOM", + "NONE" + ]; + + ///////////////////////////////////////////////////////////////////// + // Validation on placement + ///////////////////////////////////////////////////////////////////// + + private _valid = false; + + // Only proceed with updates to vehicle pos if we get a result back from the raycast + if (_hits isNotEqualTo []) then + { + private _groundPos = (_hits select 0) select 0; + + //hint format ["Raycast Hit: %1", str _groundPos]; + + _vehiclePreview setDir _rotation; + _vehiclePreview setPosASL _groundPos; + _vehiclePreview setVectorUp surfaceNormal position _vehiclePreview; + + private _nearbyObjects = _vehiclePreview nearObjects 7; + + _nearbyObjects = _nearbyObjects - [_vehiclePreview]; + + { + if ( + !(_x isKindOf "Man") && + !(_x isKindOf "Items_base_F") && + !(_x isKindOf "LandVehicle") && + !(_x isKindOf "Air") && + !(_x isKindOf "Ship") && + !(_x isKindOf "Building") && + !(_x isKindOf "StaticWeapon") + ) then { + _nearbyObjects = _nearbyObjects - [_x]; + } + } forEach _nearbyObjects; + + //hint str _nearbyObjects; + + private _collision = false; + // Bit quick and dirty but this should get the job done for now - checking for nearby objects near the preview vehicle + { + if (_vehiclePreview distance _x < 7) exitWith { + _collision = true; + } + } forEach _nearbyObjects; + + //hint format ["%1", _nearbyObjects]; + + // If the raycast returns a point on terrain, and we reach this point and confirm there is no nearby objects going to potentially cause issues, mark _valid as true + if (!_collision) then { + _valid = true; + }; + }; + +// else +// { +// private _terrainInferrence = screenToWorld [0.5, 0.5]; +// _vehiclePreview setDir _rotation; +// _vehiclePreview setPosASL _terrainInferrence; +// } + + ///////////////////////////////////////////////////////////////////// + // Update texture according to current validity + ///////////////////////////////////////////////////////////////////// + if (_valid) then + { + _vehiclePreview setObjectTextureGlobal [ + 0, + "#(argb,8,8,3)color(0,1,0,0.35,ca)" + ]; + } + else + { + _vehiclePreview setObjectTextureGlobal [ + 0, + "#(argb,8,8,3)color(1,0,0,0.35,ca)" + ]; + }; + + ///////////////////////////////////////////////////////////////////// + // Check for updated input variables + ///////////////////////////////////////////////////////////////////// + if (missionNamespace getVariable ["confirmPlacement", false]) then + { + if (_valid) then + { + _confirm = true; + } else { + // Reset confirm variable back to false, as otherwise this code will fire off at next available 'valid' opportunity + missionNamespace setVariable [ + "confirmPlacement", + false + ]; + + } + + }; + + if (missionNamespace getVariable ["cancelPlacement", false]) then + { + _cancel = true; + }; + + uiSleep 0.01; +}; + +// Remove display eventhandlers to stop capturing inputs needlessly +_display displayRemoveEventHandler ["onMouseButtonDown", _mouseInput]; +_display displayRemoveEventHandler ["MouseZChanged", _mouseScroll]; +_display displayRemoveEventHandler ["KeyDown", _keyboardInput]; +removeMissionEventHandler ["Draw3D", _previewUI]; + +private _pos = getPosATL _vehiclePreview; +private _up = surfaceNormal position _vehiclePreview; +// Cleanup _vehiclePreview +deleteVehicle _vehiclePreview; + +// Proceed to call the build confirm function if valid from checks above +if (_confirm) then +{ + [ + "CLF_ConfirmFactoryBuildServer", + [ + _hq, + _player, + _vehicleClass, + _pos, + missionNamespace getVariable ["previewRotation", 0], + _up, + _cost, + _buildTime, + _specialisation, + _specialisationData + ] + ] call CBA_fnc_serverEvent; +}; + diff --git a/functions/build/fn_factoryBuildConfirmClient.sqf b/functions/build/fn_factoryBuildConfirmClient.sqf new file mode 100644 index 0000000..d245f51 --- /dev/null +++ b/functions/build/fn_factoryBuildConfirmClient.sqf @@ -0,0 +1,111 @@ +/* + * Author: Clarky + * Usage: + * [_hq, _vehicle, _cost, _buildTime] call CLF_fnc_factoryBuildConfirmClient; + * + * + * + * Purpose: + * + * + */ + +params ["_hq", "_vehicle", "_cost", "_buildTime", "_player"]; + +missionNamespace setVariable ["buildActive", true]; +missionNamespace setVariable ["cancelBuild", false]; + +_player playMoveNow "Acts_carFixingWheel"; + +private _endTime = time + _buildTime; + +[_hq, _vehicle, _cost, _buildTime, _endTime, _player] spawn { + params ["_hq", "_vehicle", "_cost", "_buildTime", "_endTime", "_player"]; + + // Load the 'display' handling input events + private _display = findDisplay 46; + // Add an event handler to be able to cancel the build + private _keyboardCancel = _display displayAddEventHandler [ + // Handle keyboard clicks as extra verification tools + "KeyDown", + { + params ["", "_key"]; + + switch (_key) do + { + case 1: // Escape + { + missionNamespace setVariable [ + "cancelBuild", + true + ]; + }; + }; + false; + } + ]; + + private _mouseCancel = _display displayAddEventHandler [ + // Handle LMB/RMB click + "MouseButtonDown", + { + params ["", "_button"]; + + switch (_button) do + { + case 1: // RMB + { + missionNamespace setVariable [ + "cancelBuild", + true + ]; + }; + }; + false; + } + ]; + + waitUntil { animationState player == "Acts_carFixingWheel" }; + while { missionNamespace getVariable ["buildActive", false]; } do { + + private _remainingTIme = ceil (_endTime - time); + + hintSilent format ["Remaining Build Time: %1\n\nRMB or ESC to cancel", _remainingTime max 0]; + + if (animationState player != "Acts_carFixingWheel" && (missionNamespace getVariable ["buildActive", false]) && (_vehicle getVariable "buildComplete")) then { + player playMoveNow "Acts_carFixingWheel"; + }; + + if ((missionNamespace getVariable "cancelBuild") || !(alive _vehicle)) then { + [ + "CLF_CancelFactoryBuildServer", + [ + _hq, + _vehicle, + _cost, + _player + ] + ] call CBA_fnc_serverEvent; + + missionNamespace setVariable ["buildActive", false]; + }; + + if (_vehicle getVariable "buildComplete") then { + missionNamespace setVariable ["buildActive", false]; + }; + + sleep 0.2; + + if (!(missionNamespace getVariable ["buildActive", false])) then { + + hintSilent ""; + + if (animationState player == "Acts_carFixingWheel") then { + player switchMove ""; + }; + + _display displayRemoveEventHandler ["MouseButtonDown", _mouseCancel]; + _display displayRemoveEventHandler ["KeyDown", _keyboardCancel]; + } + }; +}; diff --git a/functions/build/fn_factoryBuildConfirmServer.sqf b/functions/build/fn_factoryBuildConfirmServer.sqf new file mode 100644 index 0000000..8f61bf9 --- /dev/null +++ b/functions/build/fn_factoryBuildConfirmServer.sqf @@ -0,0 +1,95 @@ +/* + * Author: Clarky + * Usage: + * [] call CLF_fnc_factoryBuildConfirm; + * + * Intended to be called via the factoryBuild function once player confirms BIS_fnc_locations + * + * Purpose: + * Concludes the process of building a vehicle with player selection on the VehicleFactory dialog + * + */ + +params ["_hq", "_player", "_vehicleClass", "_vehiclePreviewLocation", "_rotation", "_vectorUp", "_cost", "_buildTime", "_specialisation", "_specialisationData"]; + +// Check current materiel available at this base +private _currentMateriel = [_hq, _player] call CLF_fnc_materielCheck; + +if (_currentMateriel > _cost) then { + // Function runs and consumes the required supplies, returns true if successful, OR returns false after giving a 'not enough supplies' message to the player (theoretically) + //[_hq, _cost, _player] remoteExec ["CLF_fnc_materielConsume", 2]; + + [ + "CLF_MaterielConsume", + [ + _hq, + _cost, + _player + ] + ] call CBA_fnc_serverEvent; + + private _vehicle = createVehicle [_vehicleClass, _vehiclePreviewLocation, [], 0, "CAN_COLLIDE"]; + waitUntil { _vehicle == _vehicle }; + _vehicle allowDamage false; + _vehicle enableSimulationGlobal false; + _vehicle setDir _rotation; + _vehicle setVectorUp _vectorUp; + _vehicle setVehicleLock "LOCKED"; + _vehicle lockInventory true; + _vehicle setVariable ["buildComplete", false, true]; + + [ + "CLF_ConfirmFactoryVehicleClient", + [ + _hq, + _vehicle, + _cost, + _buildTime, + _player + ], + _player + ] call CBA_fnc_targetEvent; + + + + [ + _vehicle, + _buildTime, + _specialisation, + _specialisationData + ] spawn { + params ["_vehicle", "_buildTime", "_specialisation", "_specialisationData"]; + + sleep _buildTime; + + if (isNull _vehicle) exitWith {}; + + _vehicle allowDamage true; + _vehicle enableSimulationGlobal true; + _vehicle setVehicleLock "UNLOCKED"; + _vehicle lockInventory false; + _vehicle setVariable ["buildComplete", true, true]; + + switch (_specialisation) do { + case "SUPPLY": { + [ + _vehicle, + _specialisationData select 0, + 0, + _specialisationData select 1 + ] call CLF_fnc_initSupplyVehicle; + } + }; + }; +} else { + hintSilent ""; + [ + "CLF_ShowMessage", + [ + 1, + 0, + "Not enough materiel." + ], + _player + ] call CBA_fnc_targetEvent; +} \ No newline at end of file diff --git a/functions/build/fn_factoryConfirmSelection.sqf b/functions/build/fn_factoryConfirmSelection.sqf new file mode 100644 index 0000000..683fc9d --- /dev/null +++ b/functions/build/fn_factoryConfirmSelection.sqf @@ -0,0 +1,52 @@ +/* + Author: Clarky + Usage: + [_class, _cost, _buildTime, _specialisation] call CLF_fnc_factoryConfirmSelection; + + Intended to be called locally using the CONFIRM button in the VehicleFactory dialog + + Purpose: + Confirms whether or not the build of a vehicle can commence +*/ + +//params ["_class", "_cost", "_buildTime", "_specialisation", "_specialisationData"]; + +// Fetch the display and listbox to find the selected row so we can reference its data +private _display = findDisplay 9999; +private _listBox = _display displayCtrl 1500; +private _row = lnbCurSelRow _listBox; + +if (_row < 0) exitWith {hint "No vehicle was selected.";}; +if (isNull player) exitWith {hint "ERR: No player found"}; + +if !(([player] call ace_common_fnc_isEngineer) || (missionNamespace getVariable "allCanUseLogistics")) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 1, + "No engineer privileges found." + ], + player + ] call CBA_fnc_targetEvent; +}; + +// Fetch vehicle data from the selected row and compile it so we can access it and pass it through to the build function +private _vehicleData = + call compile (_listBox lnbData [_row,0]); + +_vehicleData params [ + "_class", + "_cost", + "_buildTime", + "_specialisation", + "_specialisationData" + ]; + +[player, _class, _cost, _buildTime, _specialisation, _specialisationData] spawn CLF_fnc_factoryBuild; + +//hint str (_listBox lnbData [_row,0]); + +//private _camera = "camera" camCreate getPosATL player; +//_camera cameraEffect ["internal", "back"]; +//showCinemaBorder false; \ No newline at end of file diff --git a/functions/fn_canUseLogisticsSystem.sqf b/functions/fn_canUseLogisticsSystem.sqf new file mode 100644 index 0000000..9670043 --- /dev/null +++ b/functions/fn_canUseLogisticsSystem.sqf @@ -0,0 +1,12 @@ +/* + Author: Clarky + Usage: + [_caller] call CLF_fnc_canUseLogisticsSystem; + + Intended to be run to return a true/false to check if a player can interact with the logistics system +*/ + +params ["_caller"]; + +private _isEngineer = (_caller getVariable ["ACE_isEngineer", 0]) > 0; +_isEngineer; \ No newline at end of file diff --git a/functions/fn_convertSuppliesToFortify.sqf b/functions/fn_convertSuppliesToFortify.sqf new file mode 100644 index 0000000..e69de29 diff --git a/functions/fn_initBase.sqf b/functions/fn_initBase.sqf new file mode 100644 index 0000000..a06edc9 --- /dev/null +++ b/functions/fn_initBase.sqf @@ -0,0 +1,34 @@ +/* + Author: Clarky + Usage: + ["hq", "side"] call CLF_fnc_initBase; + + Intended to run on the server to initialise a new base object - Typically when a new HQ is placed in the world + + // DEPRECATED // + +*/ + +/* +params ["_hq", "_side"]; + +waitUntil { !isNull _hq; }; + +private _baseID = format [ + "BASE_%1", + diag_tickTime +]; + +_bases = missionNamespace getVariable "LogisticsBases"; + +_bases set [ + _baseID, + createHashMapFromArray [ + ["id", _baseID], + ["hq", _hq], + ["buildings", []], + ["depots", []], + ["side", _side] + ] +]; +*/ \ No newline at end of file diff --git a/functions/fn_initBaseHQ.sqf b/functions/fn_initBaseHQ.sqf new file mode 100644 index 0000000..f712c1c --- /dev/null +++ b/functions/fn_initBaseHQ.sqf @@ -0,0 +1,67 @@ +/* + Author: Clarky + Usage: + [this, side] call CLF_fnc_initBaseHQ; + + Intended to run on the server, which calls a CBA event handler that runs a client-level script for adding relevant interactions + + Purpose: + Initialises a logistics base HQ. Adds the new base to the global base hashmap. Runs a child function to intialise clientside actions. + +*/ + +params ["_hq", "_side"]; + +waitUntil { !isNull _hq; }; + +_hq setVariable ["isBaseHQ", true, true]; +// _hq setVariable []; + +// Set BaseID +private _baseID = format [ + "BASE_%1", + diag_tickTime +]; + +_hq setVariable [ + "baseID", + _baseID, + true +]; + +_hq setVariable [ + "baseDetails", + createHashMapFromArray [ + ["id", _baseID], + ["hq", _hq], + ["buildings", []], + ["depots", []], + ["side", _side] + ] +]; + +/* +// Fetch global mission Base Hashmap +private _bases = missionNamespace getVariable "LogisticsBases"; + +// Add new Base to global hashmap +_bases set [ + _baseID, + createHashMapFromArray [ + ["id", _baseID], + ["hq", _hq], + ["buildings", []], + ["depots", []], + ["side", _side] + ] +]; + +missionNamespace setVariable ["LogisticsBases", _bases, true]; +*/ + +// Initialise base HQ interactions for all clients +[_hq] remoteExecCall [ + "CLF_fnc_initBaseHQInteractions", + 0, + true +]; \ No newline at end of file diff --git a/functions/fn_initBaseHQInteractions.sqf b/functions/fn_initBaseHQInteractions.sqf new file mode 100644 index 0000000..923d6b5 --- /dev/null +++ b/functions/fn_initBaseHQInteractions.sqf @@ -0,0 +1,91 @@ +/* + * Author: Clarky + * Usage: + * [this] call CLF_fnc_initBaseHQInteractions; + *   + * Intended to run locally on each client. + * + */ + +params ["_hq"]; + +_hq addAction [ + "Check Fortify Budget", + { + params ["_target", "_caller"]; + hint format ["Current Fortify Budget: %1", [side _caller] call ace_fortify_fnc_getBudget]; + [] spawn { + sleep 3; + hintSilent ""; + } + }, + nil, + 1, + true, + false, + "", + "true", // Figure out a way to lock this to player side checks (macros?) + 6 +]; + +_hq addAction [ + "Add Fortify Budget - $100", + { + params ["_target", "_caller"]; + + // Check current materiel available at this base + private _currentMateriel = [_target, _caller] call CLF_fnc_materielCheck; + + if (_currentMateriel > 100) then { + [ + "CLF_MaterielConsume", + [ + _target, + 100, + _caller + ] + ] call CBA_fnc_serverEvent; + + [ + [ + "CLF_FortifyBudgetAdd", + side _caller, + 100 + ] + ] call CBA_fnc_serverEvent; + } else { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "Not enough materiel." + ], + _player + ] call CBA_fnc_targetEvent; + }; + }, + nil, + 1, + true, + false, + "", + "true", // Figure out a way to lock this to player side checks (macros?) + 6 +]; + +/* +if (_depots isEqualTo []) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "No connected supply depots found." + ], + _player + ] call CBA_fnc_targetEvent; + // Return false; + false; +}; +*/ diff --git a/functions/fn_initLogisticsSystem.sqf b/functions/fn_initLogisticsSystem.sqf new file mode 100644 index 0000000..6b4f7d8 --- /dev/null +++ b/functions/fn_initLogisticsSystem.sqf @@ -0,0 +1,15 @@ +/* + Author: Clarky + Usage: + call CLF_fnc_initSLogisticsSystem; + + Intended to run on the server, on mission start, to create basic variables and logistics system handling services + +*/ + +/* +// If LogisticsBases variable has not already been initialised, initalise it here +if ((missionNamespace getVariable ["LogisticsBases", ""]) isNotEqualTo "") then { + missionNamespace setVariable ["LogisticsBases", createHashMap, true]; +}; +*/ \ No newline at end of file diff --git a/functions/fn_initSupplyDepot.sqf b/functions/fn_initSupplyDepot.sqf new file mode 100644 index 0000000..c4eaf0d --- /dev/null +++ b/functions/fn_initSupplyDepot.sqf @@ -0,0 +1,65 @@ +/* + Author: Clarky + Usage: + [this, 1000, 0, false, 0] call CLF_fnc_initSupplyDepot; + + Intended to run on the server, which calls a CBA event handler that runs a client-level script for adding relevant interactions + +*/ + +params [["_hq", "", ["", objNull]], "_depot", "_maxMateriel", "_currentMateriel", "_isGenerator", "_materielRate"]; + +_depot setVariable ["isSupplyDepot", true, true]; +_depot setVariable ["maxMateriel", _maxMateriel, true]; +_depot setVariable ["currentMateriel", _currentMateriel, true]; +_depot setVariable ["isGenerator", _isGenerator, true]; +_depot setVariable ["materielRate", _materielRate, true]; + +if (_hq isNotEqualTo "") then { + _depot setVariable ["hq", _hq, true]; + private _baseDetails = _hq getVariable "baseDetails"; + private _depots = _baseDetails get "depots"; + _depots pushBack _depot; + //_hq setVariable ["baseDetails", _baseDetails]; +}; + +[_depot] remoteExecCall [ + "CLF_fnc_initSupplyDepotInteractions", + 0, + true +]; + +if (_depot getVariable "isGenerator") then { + [_depot, _materielRate] spawn { + params ["_depot", "_materielRate"]; + while {alive _depot} do { + + private _depotCurrent = + _depot getVariable "currentMateriel"; + + private _depotMax = + _depot getVariable "maxMateriel"; + + private _freeSpace = + _depotMax - _depotCurrent; + + private _amount = + (_materielRate min _freeSpace); + + _depot setVariable [ + "currentMateriel", + _depotCurrent + _amount, + true + ]; + + sleep 30; + }; + }; +}; + +/* +[ + "CLF_SupplyDepotCreated", + [_depot] +] call CBA_fnc_globalEventJIP; +*/ \ No newline at end of file diff --git a/functions/fn_initSupplyDepotInteractions.sqf b/functions/fn_initSupplyDepotInteractions.sqf new file mode 100644 index 0000000..2b8d72b --- /dev/null +++ b/functions/fn_initSupplyDepotInteractions.sqf @@ -0,0 +1,58 @@ +/* + Author: Clarky + Usage: + [this] call CLF_fnc_initSupplyDepotInteractions; +   + Intended to run locally on each client. + +*/ + +params ["_depot"]; + +if (isNull _depot) exitWith {hint "Object ain't exist";}; +if !(_depot getVariable ["isSupplyDepot", false]) exitWith {hint "Object ain't supply depot";}; + +// Prevent duplicate actions if script runs again +if (_depot getVariable ["supplyInteractionsAdded", false]) exitWith {}; + +_depot setVariable ["supplyInteractionsAdded", true]; + +////////////////////////////////////////////////////////////////// +// INIT STATUS ACTION +////////////////////////////////////////////////////////////////// + +_depot addAction [ + "Check Materiel Status", + + { + params ["_target", "_caller"]; + + private _current = + _target getVariable ["currentMateriel", 0]; + + private _max = + _target getVariable ["maxMateriel", 300]; + + [ + "CLF_ShowMessage", + [ + 3, + 1, + format + [ + "SUPPLY DEPOT STORAGE
Materiel: %1 / %2", + _current, + _max + ] + ], + _caller + ] call CBA_fnc_targetEvent; + }, + nil, + 1, + true, + false, + "", + "true", + 6 +]; \ No newline at end of file diff --git a/functions/fn_initSupplyVehicle.sqf b/functions/fn_initSupplyVehicle.sqf new file mode 100644 index 0000000..fb1ce92 --- /dev/null +++ b/functions/fn_initSupplyVehicle.sqf @@ -0,0 +1,28 @@ +/* + Author: Clarky + Usage: + [this, 300, 0, 50] call CLF_fnc_initSupplyVehicle; + + Intended to run on the server, which calls a CBA event handler that runs a client-level script for adding relevant interactions + +*/ + +params ["_vehicle", "_maxMateriel", "_currentMateriel", "_transferRate"]; + +_vehicle setVariable ["isSupplyVehicle", true, true]; +_vehicle setVariable ["maxMateriel", _maxMateriel, true]; +_vehicle setVariable ["currentMateriel", _currentMateriel, true]; +_vehicle setVariable ["transferRate", _transferRate, true]; + +[_vehicle] remoteExecCall [ + "CLF_fnc_initSupplyVehicleInteractions", + 0, + true +]; + +/* +[ + "CLF_SupplyVehicleCreated", + [_vehicle] +] call CBA_fnc_globalEventJIP; +*/ \ No newline at end of file diff --git a/functions/fn_initSupplyVehicleInteractions.sqf b/functions/fn_initSupplyVehicleInteractions.sqf new file mode 100644 index 0000000..f377f2c --- /dev/null +++ b/functions/fn_initSupplyVehicleInteractions.sqf @@ -0,0 +1,169 @@ +/* + * Author: Clarky + * Usage: + * [this] call CLF_fnc_initSupplyVehicleInteractions; + *   + * Intended to run locally on each client. + * +*/ + +params ["_vehicle"]; + +if (isNull _vehicle) exitWith {hint "Vehicle ain't exist";}; +if !(_vehicle getVariable ["isSupplyVehicle", false]) exitWith {hint "Vehicle ain't supply vehicle";}; + +// Prevent duplicate actions if script runs again +if (_vehicle getVariable ["supplyInteractionsAdded", false]) exitWith {}; + +_vehicle setVariable ["supplyInteractionsAdded", true]; + +////////////////////////////////////////////////////////////////// +// INIT STATUS ACTION +////////////////////////////////////////////////////////////////// + +_vehicle addAction [ + "Check Materiel Status", + { + params ["_target", "_caller"]; + + private _current = + _target getVariable ["currentMateriel", 0]; + + private _max = + _target getVariable ["maxMateriel", 300]; + + private _rate = + _target getVariable ["transferRate", 50]; + + [ + "CLF_ShowMessage", + [ + 3, + 1, + format + [ + "SUPPLY VEHICLE STORAGE
Materiel: %1 / %2", + _current, + _max] + ], + _caller + ] call CBA_fnc_targetEvent; + }, + nil, + 1, + true, + false, + "", + "true", + 6 +]; + +////////////////////////////////////////////////////////////////// +// INIT LOAD ACTION +////////////////////////////////////////////////////////////////// + +[ + _vehicle, // Object the action is attached to + "Load Materiel", // Title of the action + "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_loaddevice_ca.paa", // Idle icon shown on screen + "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_loaddevice_ca.paa", // Progress icon shown on screen + "(([_this] call ace_common_fnc_isEngineer) || (missionNamespace getVariable 'allCanUseLogistics')) && + ( + (nearestObjects [_target, [], 15] findIf { + _x getVariable ['isSupplyDepot', false] + }) > -1 + ) && + (_target distance _this < 7)", // Condition for the action to be shown + "alive _target", // Condition for the action to progress + {}, // Code executed when action starts + {}, // Code executed on every progress tick + { + params ["_target", "_caller"]; + + private _depot = ( + nearestObjects [_target, [], 15] + select { + _x getVariable ["isSupplyDepot", false] + } + ) param [0, objNull]; + + if (isNull _depot) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "No supply depot nearby." + ], + _caller + ] call CBA_fnc_targetEvent; + }; + + [ + "CLF_VehicleLoaded", + [_target, _caller, _depot] + ] call CBA_fnc_serverEvent; + }, // Code executed on completion + {}, // Code executed on interrupted + [], // Arguments passed to the scripts as _this select 3 + 5, // Action duration in seconds + 0, // Priority + false, // Remove on completion + false, // Show in unconscious state + true // Show on screen +] call BIS_fnc_holdActionAdd; + +////////////////////////////////////////////////////////////////// +// INIT UNLOAD ACTION +////////////////////////////////////////////////////////////////// + +[ + _vehicle, // Object the action is attached to + "Unload Materiel", // Title of the action + "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_unloaddevice_ca.paa", // Idle icon shown on screen + "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_unloaddevice_ca.paa", // Progress icon shown on screen + "(([_this] call ace_common_fnc_isEngineer) || (missionNamespace getVariable 'allCanUseLogistics')) && + ( + (nearestObjects [_target, [], 15] findIf { + _x getVariable ['isSupplyDepot', false] + }) > -1 + ) && + (_target distance _this < 7)", // Condition for the action to be shown + "alive _target", // Condition for the action to progress + {}, // Code executed when action starts + {}, // Code executed on every progress tick + { + params ["_target", "_caller"]; + + private _depot = ( + nearestObjects [_target, [], 15] + select { + _x getVariable ["isSupplyDepot", false] + } + ) param [0, objNull]; + + if (isNull _depot) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "No supply depot nearby." + ], + _caller + ] call CBA_fnc_targetEvent; + }; + + [ + "CLF_VehicleUnloaded", + [_target, _caller, _depot] + ] call CBA_fnc_serverEvent; + }, // Code executed on completion + {}, // Code executed on interrupted + [], // Arguments passed to the scripts as _this select 3 + 5, // Action duration in seconds + 0, // Priority + false, // Remove on completion + false, // Show in unconscious state + true // Show on screen +] call BIS_fnc_holdActionAdd; \ No newline at end of file diff --git a/functions/fn_initVehicleFactory.sqf b/functions/fn_initVehicleFactory.sqf new file mode 100644 index 0000000..d5c13db --- /dev/null +++ b/functions/fn_initVehicleFactory.sqf @@ -0,0 +1,28 @@ +/* + * Author: Clarky + * Usage: + * [this, 1000, 0, false, 0] call CLF_fnc_initVehicleFactory; + * + * Intended to run on the server, which calls a CBA event handler that runs a client-level script for adding relevant interactions + * +*/ + +params [["_hq", "", ["", objNull]], "_factory"]; + +waitUntil { !isNull _hq; }; + +_factory setVariable ["isVehicleFactory", true, true]; + +if (_hq isNotEqualTo "") then { + _factory setVariable ["hq", _hq, true]; + private _baseDetails = _hq getVariable "baseDetails"; + private _buildings = _baseDetails get "buildings"; + _buildings pushBack _factory; + //_hq setVariable ["baseDetails", _baseDetails]; +}; + +[_factory] remoteExecCall [ + "CLF_fnc_initVehicleFactoryInteractions", + 0, + true +]; \ No newline at end of file diff --git a/functions/fn_initVehicleFactoryInteractions.sqf b/functions/fn_initVehicleFactoryInteractions.sqf new file mode 100644 index 0000000..144e179 --- /dev/null +++ b/functions/fn_initVehicleFactoryInteractions.sqf @@ -0,0 +1,33 @@ +/* + * Author: Clarky + * Usage: + * [hq, this] call CLF_fnc_initVehicleFactoryInteractions; + *   + * Intended to run locally on each client. + * +*/ + +params ["_factory"]; + +_factory addAction [ + "Open Vehicle Factory", + + { + params ["_target", "_caller"]; + // Load up the HQ as a variable for the player to access once proceeding through to building a vehicle + private _hq = _target getVariable ["hq", ""]; + if (_hq isNotEqualTo "") then { + uiNamespace setVariable ["localHQ", _hq]; + createDialog "VehicleFactoryDialog"; + } else { + hint "No attached HQ."; + }; + }, + nil, + 1, + true, + false, + "", + "true", // Figure out a way to lock this to player side checks (macros?) + 6 +]; \ No newline at end of file diff --git a/functions/fn_materielAdd.sqf b/functions/fn_materielAdd.sqf new file mode 100644 index 0000000..5e7fbf7 --- /dev/null +++ b/functions/fn_materielAdd.sqf @@ -0,0 +1,47 @@ +/* + * Author: Clarky + * + * + * + * + */ + + params ["_hq", "_amount", "_player"]; + +// Grab all HQ/Base/Depots +private _baseDetails = _hq getVariable "baseDetails"; +private _depots = _baseDetails get "depots"; +if (_depots isEqualTo []) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "No connected supply depots found." + ], + _player + ] call CBA_fnc_targetEvent; + // Return false; + false; +}; + +// Loop through and add materiel to the depots +// Might work on a better way to do this eventually (i.e prioritising specific depots depending on reasons) +{ + // If the _amount is now at 0, exit the loop early + if (_amount <= 0) exitWith {}; + + // Get currently looped depot's materiel and draw down from it + private _depotMateriel = _x getVariable "currentMateriel"; + private _depotMax = _x getVariable "maxMateriel"; + private _freeSpace = _depotMax - _depotMateriel; + private _addAmount = _amount min _freeSpace; + + _x setVariable ["currentMateriel", _depotMateriel + _addAmount, true]; + + // Update remaining amount to reduce + _amount = _amount - _addAmount; +} forEach _depots; + +// Return true +true; \ No newline at end of file diff --git a/functions/fn_materielCheck.sqf b/functions/fn_materielCheck.sqf new file mode 100644 index 0000000..afa0a6a --- /dev/null +++ b/functions/fn_materielCheck.sqf @@ -0,0 +1,29 @@ +// temporary function - likely to be replaced in proper mod development context + +params ["_hq", "_player"]; + +// Grab all Depots at the HQ +private _baseDetails = _hq getVariable "baseDetails"; +private _depots = _baseDetails get "depots"; +if (_depots isEqualTo []) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "No connected supply depots found." + ], + _player + ] call CBA_fnc_targetEvent; + // Return false; + false; +}; + +// Check current materiel available at this base +private _currentMateriel = 0; +{ + _currentMateriel = _currentMateriel + (_x getVariable ["currentMateriel", 0]); +} forEach _depots; + +// Return result +_currentMateriel; \ No newline at end of file diff --git a/functions/fn_materielConsume.sqf b/functions/fn_materielConsume.sqf new file mode 100644 index 0000000..f6f96da --- /dev/null +++ b/functions/fn_materielConsume.sqf @@ -0,0 +1,66 @@ +/* + * Author: Clarky + * + * + * + * + */ + + params ["_hq", "_amount", "_player"]; + +// Grab all Depots at the HQ +private _baseDetails = _hq getVariable "baseDetails"; +private _depots = _baseDetails get "depots"; +if (_depots isEqualTo []) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "No connected supply depots found." + ], + _player + ] call CBA_fnc_targetEvent; + // Return false; + false; +}; + +// Check current materiel available at this base +private _currentMateriel = 0; +{ + _currentMateriel = _currentMateriel + (_x getVariable ["currentMateriel", 0]); +} forEach _depots; + +if (_currentMateriel < _amount) exitWith { + [ + "CLF_ShowMessage", + [ + 1, + 0, + "Not enough materiel." + ], + _player + ] call CBA_fnc_targetEvent; + // Return false; + false; +}; + +// Loop through and subtract materiel from the depots +// Might work on a better way to do this eventually (i.e prioritising specific depots depending on reasons) +// By this point we have 100% checked and confirmed there is enough materiel to proceed with the requested supply consumption, so this SHOULD BE SAFE AND NOT ALLOW OVERCONSUMPTION :) +{ + // If the _amount is now at 0, exit the loop early + if (_amount <= 0) exitWith {}; + + // Get currently looped depot's materiel and draw down from it + private _depotMateriel = _x getVariable "currentMateriel"; + private _reduceAmount = _depotMateriel min _amount; + + _x setVariable ["currentMateriel", _depotMateriel - _reduceAmount, true]; + + // Update remaining amount to reduce + _amount = _amount - _reduceAmount; +} forEach _depots; + +// Return true +true; \ No newline at end of file diff --git a/functions/fn_vehicleLoad.sqf b/functions/fn_vehicleLoad.sqf new file mode 100644 index 0000000..213c743 --- /dev/null +++ b/functions/fn_vehicleLoad.sqf @@ -0,0 +1,85 @@ +/* + Author: Clarky + Usage: + [ + "CLF_fnc_VehicleLoaded", + [_target, _caller, _depot] + ] call CBA_fnc_serverEvent; + + Intended to be run by an event handler call from a vehicle load action from a player on a valid supply vehicle + +*/ + +params ["_vehicle", "_player", "_depot"]; + +if (!isServer) exitWith {}; + +if (isNull _vehicle) exitWith {hint "Vehicle ain't exist";}; +if (isNull _player) exitWith {hint "Player ain't exist";}; +if (isNull _depot) exitWith {hint "Depot ain't exist";}; + +if !(_vehicle getVariable ["isSupplyVehicle", false]) exitWith {hint "Vehicle ain't supply vehicle";}; + +private _vehicleCurrent = + _vehicle getVariable ["currentMateriel", 0]; + +private _vehicleMax = + _vehicle getVariable ["maxMateriel", 300]; + +private _transferRate = + _vehicle getVariable ["transferRate", 50]; + +private _depotCurrent = + _depot getVariable ["currentMateriel", 0]; + +private _freeSpace = + _vehicleMax - _vehicleCurrent; + +if (_freeSpace <= 0) exitWith { + + [ + "CLF_ShowMessage", + [1, 0, "Vehicle is already full."], + _player + ] call CBA_fnc_targetEvent; +}; + +if (_depotCurrent <= 0) exitWith { + + [ + "CLF_ShowMessage", + [2, 0, "Depot has no materiel available."], + _player + ] call CBA_fnc_targetEvent; +}; + +private _amount = + (_transferRate min _freeSpace) + min _depotCurrent; + +_vehicle setVariable [ + "currentMateriel", + _vehicleCurrent + _amount, + true +]; + +_depot setVariable [ + "currentMateriel", + _depotCurrent - _amount, + true +]; + +[ + "CLF_ShowMessage", + [ + 0, + 0, + format [ + "Loaded %1 materiel. Vehicle now contains %2/%3.", + _amount, + _vehicle getVariable ["currentMateriel",0], + _vehicleMax + ] + ], + _player +] call CBA_fnc_targetEvent; diff --git a/functions/fn_vehicleUnload.sqf b/functions/fn_vehicleUnload.sqf new file mode 100644 index 0000000..aec4b80 --- /dev/null +++ b/functions/fn_vehicleUnload.sqf @@ -0,0 +1,93 @@ +/* + Author: Clarky + Usage: + [ + "CLF_fnc_VehicleUnloaded", + [_target, _caller, _depot] + ] call CBA_fnc_serverEvent; + + Intended to be run by an event handler call from a vehicle unload action from a player on a valid supply vehicle + +*/ + +params ["_vehicle", "_player", "_depot"]; + +if (!isServer) exitWith {}; + +if (isNull _vehicle) exitWith {hint "Vehicle ain't exist";}; +if (isNull _player) exitWith {hint "Player ain't exist";}; +if (isNull _depot) exitWith {hint "Depot ain't exist";}; + +if !(_vehicle getVariable ["isSupplyVehicle", false]) exitWith {hint "Vehicle ain't supply vehicle";}; + +private _vehicleCurrent = + _vehicle getVariable ["currentMateriel", 0]; + +private _transferRate = + _vehicle getVariable ["transferRate", 50]; + +private _depotCurrent = + _depot getVariable ["currentMateriel", 0]; + +private _depotMax = + _depot getVariable ["maxMateriel", 300]; + +private _freeSpace = + _depotMax - _depotCurrent; + +if (_freeSpace <= 0) exitWith { + + [ + "CLF_ShowMessage", + [ + 1, + 0, + "Depot is already full." + ], + _player + ] call CBA_fnc_targetEvent; +}; + +if (_vehicleCurrent <= 0) exitWith { + + [ + "CLF_ShowMessage", + [ + 2, + 0, + "Vehicle has no materiel available." + ], + _player + ] call CBA_fnc_targetEvent; +}; + +private _amount = + (_transferRate min _freeSpace) + min _vehicleCurrent; + +_vehicle setVariable [ + "currentMateriel", + _vehicleCurrent - _amount, + true +]; + +_depot setVariable [ + "currentMateriel", + _depotCurrent + _amount, + true +]; + +[ + "CLF_ShowMessage", + [ + 0, + 0, + format [ + "Unloaded %1 materiel. Depot now contains %2/%3.", + _amount, + _depot getVariable ["currentMateriel",0], + _depotMax + ] + ], + _player +] call CBA_fnc_targetEvent; diff --git a/gui/dialogs/vehicleFactoryDialog.hpp b/gui/dialogs/vehicleFactoryDialog.hpp new file mode 100644 index 0000000..02698aa --- /dev/null +++ b/gui/dialogs/vehicleFactoryDialog.hpp @@ -0,0 +1,190 @@ +/* + Author: Clarky + + Purpose: Opens a dialog which a player can use to browse supported vehicles and spend Materiel to purchase / place a vehicle into the game world. + +*/ + +#include "\a3\ui_f\hpp\definecommongrids.inc" +#include "\a3\ui_f\hpp\defineresincl.inc" +#include "\a3\ui_f\hpp\definedikcodes.inc" + +import RscStructuredText; +import RscPicture; +import RscButtonMenuOK; +import RscButtonMenuCancel; +import RscListNBox; + +class VehicleFactoryDialog +{ + idd = 9999; + movingEnable = 1; + enableSimulation = 1; + + class ControlsBackground + { + class CLF_Rsc_Text_Background: RscText + { + idc = 1103; + x = 7.25314e-07 * safezoneW; + y = 0.0247778 * safezoneH; + w = 0.340312 * safezoneW; + h = 0.481222 * safezoneH; + colorBackground[] = {0.3,0.4,0.4,0.8}; + canDrag = 1; + }; + class CLF_Rsc_Text_TopBar: RscText + { + idc = 1100; + x = -2.58163e-07 * safezoneW; + y = 1.43424e-08 * safezoneH; + w = 0.340312 * safezoneW; + h = 0.022 * safezoneH; + colorBackground[] = {0.4,0.5,0.5,1}; + canDrag = 1; + }; + class CLF_Rsc_StructuredText_Title: RscStructuredText + { + idc = 1101; + text = "Vehicle Factory"; //--- ToDo: Localize; + x = 0.00515599 * safezoneW; + y = 0.033 * safezoneH; + w = 0.324844 * safezoneW; + h = 0.022 * safezoneH; + colorText[] = {1,1,1,1}; + colorBackground[] = {-1,-1,-1,0}; + sizeEx = 1 * GUI_GRID_H; + }; + class CLF_Rsc_Text_CategoryBack: RscText + { + idc = 1102; + x = 0.015469 * safezoneW; + y = 0.066 * safezoneH; + w = 0.309375 * safezoneW; + h = 0.044 * safezoneH; + colorBackground[] = {0.2,0.23,0.23,0.6}; + }; + class CLF_Rsc_Text_ListBackground: RscText + { + idc = 1104; + x = 0.0103132 * safezoneW; + y = 0.121 * safezoneH; + w = 0.319688 * safezoneW; + h = 0.33 * safezoneH; + colorBackground[] = {0.2,0.23,0.23,0.6}; + }; + class CLF_Rsc_Text_Headers1: RscText + { + idc = 1105; + text = "Vehicle Name"; + x = 0.0113132 * safezoneW; + y = 0.124 * safezoneH; + w = 0.179688 * safezoneW; + h = 0.03 * safezoneH; + colorText[] = {1,1,1,1}; + }; + class CLF_Rsc_Text_Headers2: RscText + { + idc = 1106; + text = "Cost"; + x = 0.2633132 * safezoneW; + y = 0.124 * safezoneH; + w = 0.079688 * safezoneW; + h = 0.03 * safezoneH; + colorText[] = {1,1,1,1}; + }; + class CLF_Rsc_Text_Headers3: RscText + { + idc = 1107; + text = "Time"; + x = 0.2933132 * safezoneW; + y = 0.124 * safezoneH; + w = 0.079688 * safezoneW; + h = 0.03 * safezoneH; + colorText[] = {1,1,1,1}; + }; + }; + + + class Controls + { + //////////////////////////////////////////////////////// + // GUI EDITOR OUTPUT START (by Clarky, v1.063, #Mehomo) + //////////////////////////////////////////////////////// + + class CLF_Rsc_ButtonMenu_Cat1: RscButtonMenu + { + idc = 2400; + text = "Unarmed"; //--- ToDo: Localize; + x = 0.0154685 * safezoneW; + y = 0.077 * safezoneH; + w = 0.0670312 * safezoneW; + h = 0.022 * safezoneH; + action = "[CLF_Category1] call CLF_fnc_populateVehicleList;"; + }; + class CLF_Rsc_ButtonMenu_Cat2: RscButtonMenu + { + idc = 2401; + text = "Vehicle"; //--- ToDo: Localize; + x = 0.134062 * safezoneW; + y = 0.077 * safezoneH; + w = 0.0721875 * safezoneW; + h = 0.022 * safezoneH; + action = "[CLF_Category2] call CLF_fnc_populateVehicleList;"; + }; + class CLF_Rsc_ButtonMenu_Aircraft: RscButtonMenu + { + idc = 2402; + text = "Support"; //--- ToDo: Localize; + x = 0.257812 * safezoneW; + y = 0.077 * safezoneH; + w = 0.0670312 * safezoneW; + h = 0.022 * safezoneH; + action = "[CLF_Category3] call CLF_fnc_populateVehicleList;"; + }; + class CLF_Rsc_ListNBox_Vehicles: RscListNBox + { + idc = 1500; + x = 0.0103132 * safezoneW; + y = 0.158 * safezoneH; + w = 0.319688 * safezoneW; + h = 0.290 * safezoneH; + columns[] = { + 0.00, + 0.80, + 0.90 + }; + }; + class CLF_Rsc_ButtonMenuOK: RscButtonMenuOK + { + text = "Confirm"; //--- ToDo: Localize; + x = 0.0154695 * safezoneW; + y = 0.462 * safezoneH; + w = 0.061875 * safezoneW; + h = 0.022 * safezoneH; + tooltip = "Confirm selection."; //--- ToDo: Localize; + action = "[] call CLF_fnc_factoryConfirmSelection;"; + }; + class CLF_Rsc_ButtonMenuCancel: RscButtonMenuCancel + { + x = 0.262969 * safezoneW; + y = 0.462 * safezoneH; + w = 0.061875 * safezoneW; + h = 0.022 * safezoneH; + tooltip = "Close dialog."; //--- ToDo: Localize; + }; + /* + class CLF_Rsc_ControlsGroup_Main: RscControlsGroup + { + idc = 2300; + x = 0.329843 * safezoneW + safezoneX; + y = 0.258 * safezoneH + safezoneY; + w = 0.340312 * safezoneW; + h = 0.506 * safezoneH; + showHScrollbar = 0; + };*/ + //////////////////////////////////////////////////////// + // GUI EDITOR OUTPUT END + //////////////////////////////////////////////////////// + }; +}; \ No newline at end of file diff --git a/gui/functions/fn_populateVehicleList.sqf b/gui/functions/fn_populateVehicleList.sqf new file mode 100644 index 0000000..05045fd --- /dev/null +++ b/gui/functions/fn_populateVehicleList.sqf @@ -0,0 +1,87 @@ +/* + Author: Clarky + Usage: + [_category] call CLF_fnc_populateVehicleList; + + Intended to be called via the VehicleFactory dialog + + Purpose: + Populate's the display's listbox with relevant data from the chosen category +*/ + +// Pass in the category to load +params ["_category"]; + +// Load up the vehicle factory dialog - IDC 9999 +private _display = findDisplay 9999; +private _listBox = _display displayCtrl 1500; + +// Exit if no valid display or listbox found +if (isNull _display) exitWith {hint "Error loading Vehicle Factory Dialog";}; +if (isNull _listBox) exitWith {hint "Error loading Vehicle Factory Listbox";}; + +// Unload the current listbox if it already has data +lnbClear _listBox; + +_display setVariable [ + "CurrentCategory", + _category +]; + +{ + // Load up params from the currently looped vehicle in supplied category + _x params [ + "_class", + "_cost", + "_buildTime", + "_specialisation", + "_specialisationData" + ]; + + // Determine attributes to load into the list row + private _displayName = getText(configFile >> "CfgVehicles" >> _class >> "displayName"); + private _icon = getText(configFile >> "CfgVehicles" >> _class >> "icon"); + // private _icon = "\A3\ui_f\data\map\VehicleIcons\iconObject_1x1_ca.paa"; + + + // If vehicle is tagged with a specialisation, update display name for row + if (_specialisation == "SUPPLY") then { + private _baseDisplayName = _displayName; + _displayName = format ["[SUPPLY] %1", _baseDisplayName]; + }; + if (_specialisation == "BUILD") then { + private _baseDisplayName = _displayName; + _displayName = format ["[BUILD] %1", _baseDisplayName]; + }; + + private _row = _listBox lnbAddRow [ + _displayName, + str _cost, + str _buildTime + ]; + + _listBox lnbSetColor [[_row,0], [1,1,1,1]]; + _listBox lnbSetColor [[_row,1], [0.8,0.8,0.8,1]]; + _listBox lnbSetColor [[_row,3], [1,1,1,1]]; + //_listBox lnbSetColor [[_row,4], [0.8,0.8,0.8,1]]; + + // Store the vehicle data in the listbox row so that it can be retrieved when the Confirm button is pressed on the dialog + + private _vehicleData = [ + _class, + _cost, + _buildTime, + _specialisation, + _specialisationData + ]; + + _listBox lnbSetData [ + [_row,0], + str _vehicleData + ]; + + // Update new row's icon and set its index for retrieval later + _listBox lnbSetPicture [[_row,0], _icon]; + _listBox lnbSetValue [[_row,0], _forEachIndex]; + +} foreach _category; \ No newline at end of file diff --git a/z.Example Mission.zip b/z.Example Mission.zip new file mode 100644 index 0000000..61b3aa2 Binary files /dev/null and b/z.Example Mission.zip differ