diff --git a/addons/refuel/$PBOPREFIX$ b/addons/refuel/$PBOPREFIX$ new file mode 100644 index 0000000000..2a68bfaf74 --- /dev/null +++ b/addons/refuel/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\refuel \ No newline at end of file diff --git a/addons/refuel/CfgEventHandlers.hpp b/addons/refuel/CfgEventHandlers.hpp new file mode 100644 index 0000000000..b928bc2de6 --- /dev/null +++ b/addons/refuel/CfgEventHandlers.hpp @@ -0,0 +1,5 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + }; +}; diff --git a/addons/refuel/CfgVehicles.hpp b/addons/refuel/CfgVehicles.hpp new file mode 100644 index 0000000000..9cc0578f40 --- /dev/null +++ b/addons/refuel/CfgVehicles.hpp @@ -0,0 +1,346 @@ +#define REFUEL_ACTION_DISTANCE 4.5 +#define MACRO_REFUEL_ACTIONS \ + class ACE_Actions : ACE_Actions { \ + class ACE_MainActions : ACE_MainActions { \ + class GVAR(TakeNozzle) { \ + displayName = CSTRING(TakeNozzle); \ + distance = REFUEL_ACTION_DISTANCE; \ + condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTakeNozzle)); \ + statement = QUOTE([ARR_3(_player,_target,objNull)] call FUNC(TakeNozzle)); \ + exceptions[] = {"isNotInside"}; \ + icon = PATHTOF(ui\icon_refuel_interact.paa); \ + }; \ + class GVAR(CheckFuel) { \ + displayName = CSTRING(CheckFuel); \ + distance = REFUEL_ACTION_DISTANCE; \ + condition = QUOTE(([ARR_2(_player,_target)] call FUNC(getFuel) >= 0) && {(_target distance _player) < REFUEL_ACTION_DISTANCE}); \ + statement = QUOTE([ARR_2(_player,_target)] call FUNC(checkFuel)); \ + exceptions[] = {"isNotInside"}; \ + icon = PATHTOF(ui\icon_refuel_interact.paa); \ + }; \ + }; \ + }; +#define MACRO_CONNECT_ACTIONS \ + class ACE_Actions { \ + class ACE_MainActions { \ + class GVAR(connect) { \ + displayName = CSTRING(connect); \ + distance = REFUEL_ACTION_DISTANCE; \ + condition = QUOTE([ARR_2(_player,_target)] call FUNC(canConnectNozzle)); \ + statement = QUOTE([ARR_2(_player,_target)] call DFUNC(connectNozzle)); \ + exceptions[] = {"isNotInside"}; \ + icon = PATHTOF(ui\icon_refuel_interact.paa); \ + }; \ + class GVAR(Disconnect) { \ + displayName = CSTRING(Disconnect); \ + distance = REFUEL_ACTION_DISTANCE; \ + condition = QUOTE([ARR_2(_player,_target)] call FUNC(canDisconnect)); \ + statement = QUOTE([ARR_2(_player,_target)] call DFUNC(disconnect)); \ + exceptions[] = {"isNotInside"}; \ + icon = PATHTOF(ui\icon_refuel_interact.paa); \ + }; \ + class GVAR(TurnOff) { \ + displayName = CSTRING(TurnOff); \ + distance = REFUEL_ACTION_DISTANCE; \ + condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTurnOff)); \ + statement = QUOTE([ARR_2(_player,_target)] call DFUNC(turnOff)); \ + exceptions[] = {"isNotInside"}; \ + icon = PATHTOF(ui\icon_refuel_interact.paa); \ + }; \ + }; \ + }; + +// does not work +#define MACRO_NOZZLE_ACTIONS \ + class ACE_Actions { \ + class ACE_MainActions { \ + displayName = ECSTRING(interaction,MainAction); \ + selection = ""; \ + distance = 2; \ + condition = "true"; \ + class GVAR(TakeNozzle) { \ + displayName = CSTRING(TakeNozzle); \ + distance = REFUEL_ACTION_DISTANCE; \ + condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTakeNozzle)); \ + statement = QUOTE([ARR_3(_player,_target,_target)] call FUNC(TakeNozzle)); \ + exceptions[] = {"isNotInside"}; \ + icon = PATHTOF(ui\icon_refuel_interact.paa); \ + }; \ + }; \ + }; + +class CfgVehicles { + class ACE_Module; + class ACE_moduleRefuelSettings : ACE_Module { + scope = 2; + displayName = CSTRING(RefuelSettings_Module_DisplayName); + icon = QUOTE(PATHTOF(ui\icon_module_refuel.paa)); + category = "ACE"; + function = QUOTE(DFUNC(moduleRefuelSettings)); + functionPriority = 1; + isGlobal = 1; + isTriggerActivated = 0; + author = ECSTRING(common,ACETeam); + class Arguments { + class rate { + displayName = CSTRING(RefuelSettings_speed_DisplayName); + description = CSTRING(RefuelSettings_speed_Description); + typeName = "NUMBER"; + class values { + class fast { + name = CSTRING(RefuelSettings_basic); + value = 10; + }; + class realistic { + name = CSTRING(RefuelSettings_advanced); + value = 1; + default = 1; + }; + }; + }; + class civ_fuel { + displayName = CSTRING(RefuelSettings_civ_fuel_DisplayName); + description = CSTRING(RefuelSettings_civ_fuel_Description); + typeName = "NUMBER"; + defaultValue = 5000; + }; + class mil_fuel { + displayName = CSTRING(RefuelSettings_mil_fuel_DisplayName); + description = CSTRING(RefuelSettings_mil_fuel_Description); + typeName = "NUMBER"; + defaultValue = 20000; + }; + class stationary_fuel { + displayName = CSTRING(RefuelSettings_stationary_fuel_DisplayName); + description = CSTRING(RefuelSettings_stationary_fuel_Description); + typeName = "NUMBER"; + defaultValue = -1; + }; + }; + }; + + class Sign_Sphere10cm_F; + class ACE_refuel_fuelNozzle : Sign_Sphere10cm_F { + // TODO replace with custom model + }; + + // Add connect to all vehicles + class LandVehicle; + class Car : LandVehicle { + MACRO_CONNECT_ACTIONS + }; + + class Tank : LandVehicle { + MACRO_CONNECT_ACTIONS + }; + + class StaticWeapon : LandVehicle { + MACRO_CONNECT_ACTIONS + }; + + class Air; + class Helicopter : Air { + MACRO_CONNECT_ACTIONS + }; + + class Plane : Air { + MACRO_CONNECT_ACTIONS + }; + + class Ship; + class Ship_F : Ship { + MACRO_CONNECT_ACTIONS + }; + + class Car_F : Car {}; + class Offroad_01_base_f : Car_F {}; + class Truck_F : Car_F {}; + class Truck_01_base_F: Truck_F {}; + class Truck_02_base_F : Truck_F {}; + class Truck_03_base_F : Truck_F {}; + class Van_01_base_F : Truck_F {}; + class Van_01_fuel_base_F : Van_01_base_F {}; + + class Tank_F : Tank {}; + class APC_Tracked_01_base_F: Tank_F {}; + class B_APC_Tracked_01_base_F: APC_Tracked_01_base_F {}; + class B_Truck_01_transport_F : Truck_01_base_F {}; + class B_Truck_01_mover_F: B_Truck_01_transport_F {}; + + class ReammoBox_F; + class Slingload_01_Base_F : ReammoBox_F { + class ACE_Actions { // FIXME ace_interact should add interactions to "All" so we can always extend + class ACE_MainActions {}; + }; + }; + class Helicopter_Base_F : Helicopter {}; + class Helicopter_Base_H : Helicopter_Base_F {}; + class Heli_Transport_04_base_F : Helicopter_Base_H {}; + class Pod_Heli_Transport_04_base_F : StaticWeapon {}; + + // Vanilla classes + class B_APC_Tracked_01_CRV_F : B_APC_Tracked_01_base_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + + class C_Van_01_fuel_F : Van_01_fuel_base_F { + transportFuel = 0; //1k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "civ"; + }; + class I_G_Van_01_fuel_F : Van_01_fuel_base_F { + transportFuel = 0; //1k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "civ"; + }; + + class I_Truck_02_fuel_F : Truck_02_base_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + class O_Truck_02_fuel_F : Truck_02_base_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + + class B_Truck_01_fuel_F : B_Truck_01_mover_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + + class O_Truck_03_fuel_F : Truck_03_base_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + + class B_Slingload_01_Fuel_F : Slingload_01_Base_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + + class O_Heli_Transport_04_fuel_F : Heli_Transport_04_base_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + + class Land_Pod_Heli_Transport_04_fuel_F : Pod_Heli_Transport_04_base_F { + transportFuel = 0; //3k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "mil"; + }; + + class Static; + class Building : Static { + class ACE_Actions { + class ACE_MainActions {}; + }; + }; + class NonStrategic : Building {}; + class House_Base : NonStrategic {}; + class House : House_Base {}; + class House_F : House {}; + class House_Small_F : House_F {}; + class Strategic : Building {}; + // Vanilla buildings + class Land_Fuelstation_Feed_F : House_Small_F { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + class Land_fs_feed_F : House_Small_F { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + + class FuelStation : Strategic { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + class Land_Fuelstation : Strategic { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + class Land_Fuelstation_army : Strategic { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + class Land_Benzina_schnell : Strategic { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + class Land_A_FuelStation_Feed : Strategic { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + class Land_Ind_FuelStation_Feed_EP1 : Strategic { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + class Land_FuelStation_Feed_PMC : Strategic { + transportFuel = 0; //50k + MACRO_REFUEL_ACTIONS + ace_refuel_hooks[] = {{0,0,0}}; + ace_refuel_type = "stationary"; + }; + + /* // Barrels from rhs? + BarrelHelper : Misc_thing 100 + BarrelBase : BarrelHelper 100 + Barrels : BarrelBase 400 + Barrel1 : BarrelBase 100 + Barrel2 : BarrelBase 100 + Barrel3 : BarrelBase 100 + Barrel4 : BarrelBase 100 + Barrel5 : BarrelBase 100 + Barrel6 : BarrelBase 100 + Wooden_barrel : BarrelBase 100 + Wooden_barrels : Wooden_barrel 400 + + // Warfare points + Base_WarfareBVehicleServicePoint : WarfareBBaseStructure 3000 + Land_StorageBladder_01_F : StorageBladder_base_F 60000 + Land_FlexibleTank_01_F : FlexibleTank_base_F 300 + + // Mods + rhsusf_M978A2_usarmy_wd : rhsusf_M977A2_usarmy_wd 10000 + rhsusf_M978A2_CPK_usarmy_wd : rhsusf_M978A2_usarmy_wd 10000 + RHS_Ural_Fuel_MSV_01 : RHS_Ural_Support_MSV_Base_01 10000 + RHS_Ural_Fuel_VDV_01 : RHS_Ural_Fuel_MSV_01 10000 + RHS_Ural_Fuel_VMF_01 : RHS_Ural_Fuel_MSV_01 10000 + RHS_Ural_Fuel_VV_01 : RHS_Ural_Fuel_MSV_01 10000 + LOP_UA_Ural_fuel : RHS_Ural_Fuel_VV_01 10000 + */ +}; diff --git a/addons/refuel/XEH_preInit.sqf b/addons/refuel/XEH_preInit.sqf new file mode 100644 index 0000000000..7360046646 --- /dev/null +++ b/addons/refuel/XEH_preInit.sqf @@ -0,0 +1,21 @@ +#include "script_component.hpp" + +ADDON = false; + +PREP(canConnectNozzle); +PREP(canDisconnect); +PREP(canRefuel); +PREP(canTakeNozzle); +PREP(canTurnOff); +PREP(checkFuel); +PREP(connectNozzle); +PREP(connectNozzleAction); +PREP(disconnect); +PREP(getFuel); +PREP(moduleRefuelSettings); +PREP(setFuel); +PREP(takeNozzle); +PREP(turnOff); +PREP(refuel); + +ADDON = true; diff --git a/addons/refuel/config.cpp b/addons/refuel/config.cpp new file mode 100644 index 0000000000..7abfb2d645 --- /dev/null +++ b/addons/refuel/config.cpp @@ -0,0 +1,16 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + units[] = {}; + weapons[] = {"ACE_refuel_fuelNozzle"}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_interaction"}; + author[] = {"GitHawk"}; + authorUrl = ""; + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "CfgVehicles.hpp" diff --git a/addons/refuel/functions/fnc_canConnectNozzle.sqf b/addons/refuel/functions/fnc_canConnectNozzle.sqf new file mode 100644 index 0000000000..07cfabd58c --- /dev/null +++ b/addons/refuel/functions/fnc_canConnectNozzle.sqf @@ -0,0 +1,25 @@ +/* + * Author: GitHawk + * Check if a unit can connect a fuel nozzle + * + * Arguments: + * 0: The unit + * 1: The target + * + * Return Value: + * NIL + * + * Example: + * [unit, target, nozzle] call ace_refuel_fnc_connectNozzle + * + * Public: Yes + */ +#include "script_component.hpp" + +private ["_nozzle"]; +params ["_unit", "_target"]; + +_nozzle = _unit getVariable [QGVAR(nozzle), nil]; +if (isNil "_nozzle") exitWith {false}; + +true \ No newline at end of file diff --git a/addons/refuel/functions/fnc_canDisconnect.sqf b/addons/refuel/functions/fnc_canDisconnect.sqf new file mode 100644 index 0000000000..ca91f0e4a7 --- /dev/null +++ b/addons/refuel/functions/fnc_canDisconnect.sqf @@ -0,0 +1,33 @@ +/* + * Author: GitHawk + * Check if a unit can disconnect a fuel nozzle + * + * Arguments: + * 0: The unit + * 0: The object holding the nozzle + * + * Return Value: + * Can disconnect + * + * Example: + * [player, truck] call ace_refuel_fnc_canDisconnect + * + * Public: Yes + */ +#include "script_component.hpp" + +private ["_nozzle", "_sink", "_fueling"]; +params ["_unit", "_nozzleHolder"]; + +if (isNull _unit || {!(_unit isKindOf "CAManBase")} || {!local _unit} || {(_nozzleHolder distance _unit) > REFUEL_ACTION_DISTANCE}) exitWith {false}; + +_nozzle = _nozzleHolder getVariable [QGVAR(nozzle), objNull]; +if (isNull _nozzle) exitWith {false}; + +_sink = _nozzle getVariable [QGVAR(sink), objNull]; +if (isNull _sink) exitWith {false}; + +_fueling = _nozzle getVariable [QGVAR(fueling), 0]; +if (_fueling == 1) exitWith {false}; + +true \ No newline at end of file diff --git a/addons/refuel/functions/fnc_canRefuel.sqf b/addons/refuel/functions/fnc_canRefuel.sqf new file mode 100644 index 0000000000..21b856918e --- /dev/null +++ b/addons/refuel/functions/fnc_canRefuel.sqf @@ -0,0 +1,25 @@ +/* + * Author: GitHawk + * Check if a unit can refuel + * + * Arguments: + * 0: The target + * + * Return Value: + * Can refuel + * + * Example: + * [unit, target] call ace_refuel_fnc_canRefuel + * + * Public: Yes + */ +#include "script_component.hpp" +private ["_fuel"]; +params ["_unit", "_target"]; + +if (isNull _unit || {!(_unit isKindOf "CAManBase")} || {!local _unit} || { (_target distance _unit) > 7}) exitWith {false}; + +_fuel = [_unit, _target] call FUNC(getFuel); +if (_fuel > 0 || {_fuel == -1}) exitWith {true}; + +false \ No newline at end of file diff --git a/addons/refuel/functions/fnc_canTakeNozzle.sqf b/addons/refuel/functions/fnc_canTakeNozzle.sqf new file mode 100644 index 0000000000..b306c2ec37 --- /dev/null +++ b/addons/refuel/functions/fnc_canTakeNozzle.sqf @@ -0,0 +1,32 @@ +/* + * Author: GitHawk + * Check if a unit can take a fuel nozzle + * + * Arguments: + * 0: The unit + * 1: The target + * + * Return Value: + * Can connect + * + * Example: + * [player, target] call ace_refuel_fnc_canTakeNozzle + * + * Public: Yes + */ +#include "script_component.hpp" + +private ["_connected"]; +params ["_unit", "_target"]; + +if (isNull _unit || {!(_unit isKindOf "CAManBase")} || {!local _unit} || {(_target distance _unit) > 3.5}) exitWith {false}; + +// Check if the fuel source is already in use +_connected = _target getVariable [QGVAR(connected), nil]; +if !(isNil "_connected") exitWith {false}; + +// Check if the player is already carrying another fuel nozzle +_connected = _unit getVariable [QGVAR(isRefueling), nil]; +if !(isNil "_connected") exitWith {false}; + +true \ No newline at end of file diff --git a/addons/refuel/functions/fnc_canTurnOff.sqf b/addons/refuel/functions/fnc_canTurnOff.sqf new file mode 100644 index 0000000000..d08dae90bf --- /dev/null +++ b/addons/refuel/functions/fnc_canTurnOff.sqf @@ -0,0 +1,30 @@ +/* + * Author: GitHawk + * Check if a unit can turn off a fuel nozzle + * + * Arguments: + * 0: The unit + * 1: The object holding the nozzle + * + * Return Value: + * Can turn off + * + * Example: + * [player, truck] call ace_refuel_fnc_canTurnOff + * + * Public: Yes + */ +#include "script_component.hpp" + +private ["_nozzle", "_fueling"]; +params ["_unit", "_nozzleHolder"]; + +if (isNull _unit || {!(_unit isKindOf "CAManBase")} || {!local _unit} || { (_nozzleHolder distance _unit) > REFUEL_ACTION_DISTANCE}) exitWith {false}; + +_nozzle = _nozzleHolder getVariable [QGVAR(nozzle), objNull]; +if (isNull _nozzle) exitWith {false}; + +_fueling = _nozzle getVariable [QGVAR(fueling), 0]; +if (_fueling == 0) exitWith {false}; + +true \ No newline at end of file diff --git a/addons/refuel/functions/fnc_checkFuel.sqf b/addons/refuel/functions/fnc_checkFuel.sqf new file mode 100644 index 0000000000..cd3525452d --- /dev/null +++ b/addons/refuel/functions/fnc_checkFuel.sqf @@ -0,0 +1,43 @@ +/* + * Author: GitHawk + * Get the remaining fuel amount + * + * Arguments: + * 0: The unit + * 1: The target + * + * Return Value: + * nil + * + * Example: + * [unit, target] call ace_refuel_fnc_checkFuel + * + * Public: Yes + */ +#include "script_component.hpp" +private ["_fuel", "_type"]; +params ["_unit", "_target"]; + +if (isNull _unit || {!(_unit isKindOf "CAManBase")} || {!local _unit} || { (_target distance _unit) > 7}) exitWith {0}; + +_fuel = [_unit, _target] call FUNC(getFuel); + +[ + 5, + [_unit, _target, _fuel], + { + params ["_args"]; + EXPLODE_3_PVT(_args,_unit,_target,_fuel); + if (_fuel > 0 ) then { + ["displayTextStructured", [_unit], [[LSTRING(Hint_RemainingFuel), _fuel], 2, _unit]] call EFUNC(common,targetEvent); + } else { + ["displayTextStructured", [_unit], [LSTRING(Hint_Empty), 2, _unit]] call EFUNC(common,targetEvent); + }; + true + }, + {true}, + localize LSTRING(CheckFuel), + {true}, + ["isnotinside"] +] call EFUNC(common,progressBar); + diff --git a/addons/refuel/functions/fnc_connectNozzle.sqf b/addons/refuel/functions/fnc_connectNozzle.sqf new file mode 100644 index 0000000000..2b66f7e5ff --- /dev/null +++ b/addons/refuel/functions/fnc_connectNozzle.sqf @@ -0,0 +1,66 @@ +/* + * Author: GitHawk et.al. + * Connect a fuel nozzle + * With code from ace_attach + * + * Arguments: + * 0: The unit + * 1: The target + * 2: The nozzle (optional) + * + * Return Value: + * NIL + * + * Example: + * [unit, target, nozzle] call ace_refuel_fnc_connectNozzle + * + * Public: Yes + */ +#include "script_component.hpp" + +#define PLACE_WAITING -1 +#define PLACE_CANCEL 0 +#define PLACE_APPROVE 1 + +private ["_nozzle", "_actionID"]; +params ["_unit", "_target"]; + +_nozzle = _unit getVariable [QGVAR(nozzle), nil]; +if (isNil "_nozzle") exitWith {}; + +GVAR(placeAction) = PLACE_WAITING; + +[{[localize LSTRING(Connect_Action), ""] call EFUNC(interaction,showMouseHint)}, []] call EFUNC(common,execNextFrame); +_unit setVariable [QGVAR(placeActionEH), [_unit, "DefaultAction", {true}, {GVAR(placeAction) = PLACE_APPROVE;}] call EFUNC(common,AddActionEventHandler)]; + +_actionID = _unit addAction [format ["%1", localize LSTRING(Cancel)], {GVAR(placeAction) = PLACE_CANCEL;}]; + +[{ + private["_virtualPos", "_virtualPosASL", "_lineInterection"]; + params ["_args","_pfID"]; + EXPLODE_4_PVT(_args,_unit,_target,_nozzle,_actionID); + + _virtualPosASL = (eyePos _unit) vectorAdd (positionCameraToWorld [0,0,0.6]) vectorDiff (positionCameraToWorld [0,0,0]); + if (cameraView == "EXTERNAL") then { + _virtualPosASL = _virtualPosASL vectorAdd ((positionCameraToWorld [0.3,0,0]) vectorDiff (positionCameraToWorld [0,0,0])); + }; + _virtualPos = _virtualPosASL call EFUNC(common,ASLToPosition); + _lineInterection = lineIntersects [eyePos ace_player, _virtualPosASL, ace_player]; + + //Don't allow placing in a bad position: + if (_lineInterection && {GVAR(placeAction) == PLACE_APPROVE}) then {GVAR(placeAction) = PLACE_WAITING;}; + + if ((GVAR(placeAction) != PLACE_WAITING) || + {_unit != ace_player} || + {!([_unit, _target, []] call EFUNC(common,canInteractWith))}) then { + + [_pfID] call CBA_fnc_removePerFrameHandler; + [] call EFUNC(interaction,hideMouseHint); + [_unit, "DefaultAction", (_unit getVariable [QGVAR(placeActionEH), -1])] call EFUNC(common,removeActionEventHandler); + _unit removeAction _actionID; + + if (GVAR(placeAction) == PLACE_APPROVE) then { + [_unit, _target, _virtualPos, _nozzle] call FUNC(ConnectNozzleAction); + }; + }; // TODO add model like in attach/functions/fnc_attach +}, 0, [_unit, _target, _nozzle, _actionID] ] call cba_fnc_addPerFrameHandler; \ No newline at end of file diff --git a/addons/refuel/functions/fnc_connectNozzleAction.sqf b/addons/refuel/functions/fnc_connectNozzleAction.sqf new file mode 100644 index 0000000000..277478710a --- /dev/null +++ b/addons/refuel/functions/fnc_connectNozzleAction.sqf @@ -0,0 +1,109 @@ +/* + * Author: GitHawk et.al + * Calculates a connection for tilting + * With code from ace_attach + * + * Arguments: + * 0: The player + * 1: The target + * 2: The visual position + * 3: The nozzle + * + * Return Value: + * NIL + * + * Example: + * [player, tank, [0,0,0], nozzle] call ace_refuel_fnc_connectNozzleAction + * + * Public: Yes + */ +#include "script_component.hpp" +#define FLOWRATE_GND 0.165 // TODO ace_vehicles messes with fuel capacity - why? +#define FLOWRATE_AIR 0.67 +#define RATE 1 // FIXME use global var from module + +private ["_startingOffset", "_startDistanceFromCenter", "_closeInUnitVector", "_closeInMax", "_closeInMin", "_closeInDistance", "_endPosTestOffset", "_endPosTest", "_doesIntersect", "_startingPosShifted", "_endASL", "_rate", "_maxFuel"]; + +params ["_unit", "_target", "_startingPosition", "_nozzle"]; +_startingOffset = _target worldToModel _startingPosition; + +_startDistanceFromCenter = vectorMagnitude _startingOffset; +_closeInUnitVector = vectorNormalized (_startingOffset vectorFromTo [0,0,0]); + +_closeInMax = _startDistanceFromCenter; +_closeInMin = 0; + +while {(_closeInMax - _closeInMin) > 0.01} do { + _closeInDistance = (_closeInMax + _closeInMin) / 2; + _endPosTestOffset = _startingOffset vectorAdd (_closeInUnitVector vectorMultiply _closeInDistance); + _endPosTestOffset set [2, (_startingOffset select 2)]; + _endPosTest = _target modelToWorldVisual _endPosTestOffset; + + _doesIntersect = false; + { + if (_doesIntersect) exitWith {}; + _startingPosShifted = _startingPosition vectorAdd _x; + _startASL = if (surfaceIsWater _startingPosShifted) then {_startingPosShifted} else {ATLtoASL _startingPosShifted}; + { + _endPosShifted = _endPosTest vectorAdd _x; + _endASL = if (surfaceIsWater _startingPosShifted) then {_endPosShifted} else {ATLtoASL _endPosShifted}; + + //Uncomment to see the lazor show, and see how the scanning works: + // drawLine3D [_startingPosShifted, _endPosShifted, [1,0,0,1]]; + if (_target in lineIntersectsWith [_startASL, _endASL, _unit]) exitWith {_doesIntersect = true}; + } forEach [[0,0,0.045], [0,0,-0.045], [0,0.045,0], [0,-0.045,0], [0.045,0,0], [-0.045,0,0]]; + } forEach [[0,0,0], [0,0,0.05], [0,0,-0.05]]; + + if (_doesIntersect) then { + _closeInMax = _closeInDistance; + } else { + _closeInMin = _closeInDistance; + }; +}; + +_closeInDistance = (_closeInMax + _closeInMin) / 2; + +//Checks (too close to center or can't attach) +if (((_startDistanceFromCenter - _closeInDistance) < 0.1) || {!([_target, _unit, _itemClassname] call FUNC(canAttach))}) exitWith { + TRACE_2("no valid spot found",_closeInDistance,_startDistanceFromCenter); + [localize LSTRING(Failed)] call EFUNC(common,displayTextStructured); +}; + +//Move it out slightly, for visibility sake (better to look a little funny than be embedded//sunk in the hull and be useless) +_closeInDistance = (_closeInDistance - 0.0085); + +_endPosTestOffset = _startingOffset vectorAdd (_closeInUnitVector vectorMultiply _closeInDistance); +_endPosTestOffset set [2, (_startingOffset select 2)]; + +// TODO put animation and delayed connect ? + +_unit setVariable [QGVAR(nozzle), nil]; +detach _nozzle; +[_unit, QGVAR(vehAttach), false] call EFUNC(common,setForceWalkStatus); + +_weaponSelect = _unit getVariable QGVAR(selectedWeaponOnRefuel); +_unit selectWeapon _weaponSelect; +_unit setVariable [QGVAR(selectedWeaponOnRefuel), nil]; + +_source = _nozzle getVariable QGVAR(source); +if (_source == _target) exitWith { + _source setVariable [QGVAR(connected), nil, true]; + ropeDestroy (_nozzle getVariable QGVAR(rope)); + deleteVehicle _nozzle; + _unit setVariable [QGVAR(isRefueling), nil]; +}; + +_nozzle attachTo [_target, _endPosTestOffset]; +_nozzle setVariable [QGVAR(sink), _target, true]; +_nozzle setVariable [QGVAR(fueling), 1, true]; +_target setVariable [QGVAR(nozzle), _nozzle, true]; + +_rate = if (_target isKindOf "Air") then { FLOWRATE_AIR * RATE +} else { + FLOWRATE_GND * RATE +}; +_maxFuel = getNumber (configFile >> "CfgVehicles" >> (typeOf _target) >> "fuelCapacity"); + +[_unit, _target, _nozzle, _rate, _maxFuel] call FUNC(refuel); + +true \ No newline at end of file diff --git a/addons/refuel/functions/fnc_cutTiltRope.sqf b/addons/refuel/functions/fnc_cutTiltRope.sqf new file mode 100644 index 0000000000..d045b502a5 --- /dev/null +++ b/addons/refuel/functions/fnc_cutTiltRope.sqf @@ -0,0 +1,34 @@ +/* + * Author: GitHawk + * Disconnects the tilting rope + * + * Arguments: + * 0: The target + * + * Return Value: + * NIL + * + * Example: + * [player] call ace_logistics_fnc_cutTiltRope + * + * Public: Yes + */ +#include "script_component.hpp" + +private ["_rope"]; +params ["_unit"]; + +_rope = _unit getVariable [QGVAR(tiltRope), nil]; +if !(isNil "_rope") then { + ropeDestroy _rope; +}; + +(_unit getVariable QGVAR(tiltVehicle)) setVariable [QGVAR(tiltUp), nil, true]; +(_unit getVariable QGVAR(tiltVehicleTow)) setVariable [QGVAR(tiltUp), nil, true]; + +_unit setVariable [QGVAR(tiltVehicle), nil]; +_unit setVariable [QGVAR(tiltVehicleTow), nil]; +_unit setVariable [QGVAR(isTilting), nil]; +_unit setVariable [QGVAR(tiltRope), nil]; + +true \ No newline at end of file diff --git a/addons/refuel/functions/fnc_disconnect.sqf b/addons/refuel/functions/fnc_disconnect.sqf new file mode 100644 index 0000000000..12e35c3a54 --- /dev/null +++ b/addons/refuel/functions/fnc_disconnect.sqf @@ -0,0 +1,28 @@ +/* + * Author: GitHawk + * Disconnect a fuel nozzle + * + * Arguments: + * 0: The unit + * 1: The object holding the nozzle + * + * Return Value: + * NIL + * + * Example: + * [unit, truck] call ace_refuel_fnc_disconnect + * + * Public: Yes + */ +#include "script_component.hpp" + +params ["_unit", "_nozzleHolder"]; + +_nozzle = _nozzleHolder getVariable QGVAR(nozzle); + +detach _nozzle; +_nozzle setVariable [QGVAR(sink), objNull]; +_nozzleHolder setVariable [QGVAR(nozzle), objNull, true]; +_unit setVariable [QGVAR(nozzle), _nozzle]; + +[_unit, _nozzleHolder, _nozzle] call FUNC(takeNozzle); diff --git a/addons/refuel/functions/fnc_getFuel.sqf b/addons/refuel/functions/fnc_getFuel.sqf new file mode 100644 index 0000000000..5b46aafc13 --- /dev/null +++ b/addons/refuel/functions/fnc_getFuel.sqf @@ -0,0 +1,45 @@ +/* + * Author: GitHawk + * Get the remaining fuel amount + * + * Arguments: + * 0: The unit + * 1: The target + * + * Return Value: + * Number of liters left + * + * Example: + * [unit, target] call ace_refuel_fnc_getFuel + * + * Public: Yes + */ +#include "script_component.hpp" +private ["_fuel", "_type"]; +params ["_unit", "_target"]; + +if (isNull _unit || {!(_unit isKindOf "CAManBase")} || {!local _unit} || { (_target distance _unit) > 7}) exitWith {0}; + +_fuel = _target getVariable [QGVAR(fuel), -2]; +if (_fuel == -2) then { + _type = getText (configFile >> "CfgVehicles" >> typeOf _target >> "ace_refuel_type"); + if (_type == "mil") then { + //_fuel = GVAR(mil_fuel); // FIXME + _fuel = 20000; // FIXME + _target setVariable [QGVAR(fuel), _fuel, true]; + } else { + if (_type == "civ") then { + _fuel = GVAR(civ_fuel); + _target setVariable [QGVAR(fuel), _fuel, true]; + } else { + if (_type == "stationary") then { + _fuel = GVAR(stationary_fuel); + _target setVariable [QGVAR(fuel), _fuel, true]; + } else { + _fuel = 0; + }; + }; + }; +}; + +_fuel diff --git a/addons/refuel/functions/fnc_moduleRefuelSettings.sqf b/addons/refuel/functions/fnc_moduleRefuelSettings.sqf new file mode 100644 index 0000000000..e6e8fa28e7 --- /dev/null +++ b/addons/refuel/functions/fnc_moduleRefuelSettings.sqf @@ -0,0 +1,25 @@ +/* + * Author: GitHawk + * Module for adjusting the refuel settings + * + * Arguments: + * 0: The module logic + * 1: units + * 2: activated + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_logic", "_units", "_activated"]; + +if !(_activated) exitWith {}; + +[_logic, QGVAR(rate), "rate"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(civ_fuel), "civ_fuel"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(mil_fuel), "mil_fuel"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(stationary_fuel), "stationary_fuel"] call EFUNC(common,readSettingFromModule); diff --git a/addons/refuel/functions/fnc_refuel.sqf b/addons/refuel/functions/fnc_refuel.sqf new file mode 100644 index 0000000000..e147a5515f --- /dev/null +++ b/addons/refuel/functions/fnc_refuel.sqf @@ -0,0 +1,69 @@ +/* + * Author: GitHawk + * Refuels the vehicle + * + * Arguments: + * 0: The target + * 1: The rate + * + * Return Value: + * NIL + * + * Public: No + */ + +#include "script_component.hpp" + +private ["_sink"]; +params ["_unit", "_target", "_nozzle", "_rate", "_maxFuel"]; + +_sink = _nozzle getVariable [QGVAR(sink), objNull]; +if (isNull _sink) exitWith {}; + +if !(local _sink) exitWith { + [_this, QUOTE(DFUNC(refuel)), _target] call EFUNC(common,execRemoteFnc); +}; + +[{ + private ["_source", "_sink", "_fuelInSource", "_fuelInSink", "_finished", "_fueling"]; + params ["_args", "_pfID"]; + EXPLODE_5_PVT(_args,_unit,_nozzle,_rate,_startFuel,_maxFuel); + + _fueling = _nozzle getVariable [QGVAR(fueling), 0]; + _rate = _rate * 0.1; + + _source = _nozzle getVariable [QGVAR(source), objNull]; + _sink = _nozzle getVariable [QGVAR(sink), objNull]; + if (isNull _source || {isNull _sink} || {(_source distance _sink) > 20}) exitWith { + detach _nozzle; + _nozzle setPosATL [(getPosATL _nozzle) select 0,(getPosATL _nozzle) select 1, 0]; + _nozzle setVariable [QGVAR(sink), objNull]; + [_pfID] call cba_fnc_removePerFrameHandler; + }; + _fuelInSource = [_unit, _source] call FUNC(getFuel); + if (_fuelInSource == 0) exitWith { + _nozzle setVariable [QGVAR(fueling), 0, true]; + [_pfID] call cba_fnc_removePerFrameHandler; + }; + _finished = false; + _fuelInSource = _fuelInSource - _rate; + if (_fuelInSource < 0 && {_fuelInSource > -1}) then { + _fuelInSource = 0; + _finished = true; + }; + + _fuelInSink = fuel _sink + ( _rate / _maxFuel); + if (_fuelInSink > 1) then { + _fuelInSink = 1; + _finished = true; + }; + _sink setFuel _fuelInSink; + [_unit, _source, _fuelInSource] call FUNC(setFuel); + + if (_finished || {_fueling == 0}) exitWith { + _nozzle setVariable [QGVAR(fueling), 0, true]; + [_pfID] call cba_fnc_removePerFrameHandler; + }; + + // TODO display ace hint how many liters were transfered +}, 0.1, [_unit, _nozzle, _rate, fuel _target, _maxFuel]] call cba_fnc_addPerFrameHandler; diff --git a/addons/refuel/functions/fnc_setFuel.sqf b/addons/refuel/functions/fnc_setFuel.sqf new file mode 100644 index 0000000000..4bcd58163f --- /dev/null +++ b/addons/refuel/functions/fnc_setFuel.sqf @@ -0,0 +1,38 @@ +/* + * Author: GitHawk + * Set the remaining fuel amount + * + * Arguments: + * 0: The unit + * 1: The target + * 2: The amout + * + * Return Value: + * Nil + * + * Example: + * [unit, target] call ace_refuel_fnc_getFuel + * + * Public: Yes + */ +#include "script_component.hpp" +private ["_maxFuel", "_type"]; +params ["_unit", "_target", "_fuel"]; + +if (isNull _unit || {isNull _target} || {!(_unit isKindOf "CAManBase")} || {!local _unit} || { (_target distance _unit) > 7}) exitWith {0}; + +_type = getText (configFile >> "CfgVehicles" >> typeOf _target >> "ace_refuel_type"); +_maxFuel = 0; +if (_type == "mil") then { + //_maxFuel = GVAR(mil_fuel); // FIXME + _maxFuel = 20000; // FIXME +}; +if (_type == "civ") then { + _maxFuel = GVAR(civ_Fuel); +}; +if (_type == "stationary") then { + _maxFuel = GVAR(stationary_Fuel); +}; +_target setVariable [QGVAR(fuel), _maxFuel min _fuel, true]; + +nil diff --git a/addons/refuel/functions/fnc_takeNozzle.sqf b/addons/refuel/functions/fnc_takeNozzle.sqf new file mode 100644 index 0000000000..b8e0d2449a --- /dev/null +++ b/addons/refuel/functions/fnc_takeNozzle.sqf @@ -0,0 +1,62 @@ +/* + * Author: GitHawk + * Take a fuel nozzle + * + * Arguments: + * 0: The unit + * 1: The target + * 2: The nozzle (optional) + * + * Return Value: + * NIL + * + * Example: + * [unit, target, truck] call ace_refuel_fnc_takeNozzle + * + * Public: Yes + */ +#include "script_component.hpp" + +private ["_endPosOffset"], +params ["_unit", "_target", "_nozzle"]; + +[_unit, QGVAR(vehAttach), true] call EFUNC(common,setForceWalkStatus); + +_unit setVariable [QGVAR(selectedWeaponOnRefuel), currentWeapon _unit]; +_unit action ["SwitchWeapon", _unit, _unit, 99]; + +if (isNull _nozzle) then { // func is called on fuel truck + _endPosOffset = getArray (configFile >> "CfgVehicles" >> typeOf _target >> "ace_refuel_hooks") select 0; + + // TODO pfh to check distance between _unit und _target + // if too large cancel walk and drop nozzle + + // TODO add pickup animation ? + + [{ + params ["_unit", "_target", "_endPosTestOffset"]; + _newNozzle = "ACE_refuel_fuelNozzle" createVehicle position _unit; + _newNozzle attachTo [_unit, [-0.02,-0.05,0], "righthandmiddle1"]; // TODO replace with right coordinates for real model + _unit setVariable [QGVAR(nozzle), _newNozzle]; + + _rope = ropeCreate [_target, _endPosTestOffset, _newNozzle, [0, 0, 0], 12]; + + _newNozzle setVariable [QGVAR(source), _target, true]; + _newNozzle setVariable [QGVAR(rope), _rope, true]; + _target setVariable [QGVAR(connected), _newNozzle, true]; + }, [_unit, _target, _endPosOffset], 2, 0] call EFUNC(common,waitAndExecute); + + _unit setVariable [QGVAR(isRefueling), 1]; +} else { // func is called in muzzle either connected or on ground + // TODO add pickup animation ? + [{ + params ["_unit", "_target", "_nozzle"]; + + detach _nozzle; + _target setVariable [QGVAR(nozzle), objNull, true]; + _nozzle attachTo [_unit, [-0.02,-0.05,0], "righthandmiddle1"]; // TODO replace with right coordinates for real model + _unit setVariable [QGVAR(nozzle), _nozzle]; + }, [_unit, _target, _nozzle], 2, 0] call EFUNC(common,waitAndExecute); +}; + +true \ No newline at end of file diff --git a/addons/refuel/functions/fnc_turnOff.sqf b/addons/refuel/functions/fnc_turnOff.sqf new file mode 100644 index 0000000000..bb37c2c7bc --- /dev/null +++ b/addons/refuel/functions/fnc_turnOff.sqf @@ -0,0 +1,26 @@ +/* + * Author: GitHawk + * Check if a unit can turn off a fuel nozzle + * + * Arguments: + * 0: The unit + * 1: The object holding the nozzle + * + * Return Value: + * Can turn off + * + * Example: + * [player, nozzle] call ace_refuel_fnc_canTurnOff + * + * Public: Yes + */ +#include "script_component.hpp" + +params ["_unit", "_nozzleHolder"]; + +if (isNull _unit || {!(_unit isKindOf "CAManBase")} || {!local _unit} || { (_nozzleHolder distance _unit) > REFUEL_ACTION_DISTANCE}) exitWith {false}; + +_nozzle = _nozzleHolder getVariable QGVAR(nozzle); +_nozzle setVariable [QGVAR(fueling), 0]; + +true \ No newline at end of file diff --git a/addons/refuel/functions/script_component.hpp b/addons/refuel/functions/script_component.hpp new file mode 100644 index 0000000000..cb77e83d80 --- /dev/null +++ b/addons/refuel/functions/script_component.hpp @@ -0,0 +1,3 @@ +#include "\z\ace\addons\refuel\script_component.hpp" + +#define REFUEL_ACTION_DISTANCE 4.5 \ No newline at end of file diff --git a/addons/refuel/script_component.hpp b/addons/refuel/script_component.hpp new file mode 100644 index 0000000000..8d737b3f97 --- /dev/null +++ b/addons/refuel/script_component.hpp @@ -0,0 +1,4 @@ +#define COMPONENT refuel +#include "\z\ace\addons\main\script_mod.hpp" + +#include "\z\ace\addons\main\script_macros.hpp" diff --git a/addons/refuel/stringtable.xml b/addons/refuel/stringtable.xml new file mode 100644 index 0000000000..919ebcc206 --- /dev/null +++ b/addons/refuel/stringtable.xml @@ -0,0 +1,93 @@ + + + + + Refuel Settings + Tankeinstellungen + + + Flow Rate + Fließrate + + + How fast should a vehicle be refueled? + Wie schnell soll ein Fahrzeug aufgetankt sein? + + + Fast + Schnell + + + Realistic + Realistisch + + + Civilian Volume + Ziviles Volumen + + + How many liters does a civilian tank truck hold? -1 is infinite. + Wieviele Liter enthält ein ziviler Tankwagen? -1 bedeutet unendlich. + + + Military Volume + Militärisches Volumen + + + How many liters does a military tank truck hold? -1 is infinite. + Wieviele Liter enthält ein militärischer Tankwagen? -1 bedeutet unendlich. + + + Stationary Volume + Stationäres Volumen + + + How many liters does a stationary object e.g. a fuel station hold? -1 is infinite. + Wieviele Liter enthält ein stationäres Objekt z.B. eine Tankstelle? -1 bedeutet unendlich. + + + Take fuel nozzle + Zapfpistole nehmen + + + Connect fuel nozzle + Zapfpistole anschließen + + + Disconnect fuel nozzle + Zapfpistole entfernen + + + Connect + Anschließen + + + Check remaining fuel + Verbleibenden Kraftstoff überprüfen + + + There are %1 liters left. + Es sind noch %1 Liter übrig. + + + There is no fuel left. + Es ist kein Treibstoff übrig. + + + Cancel + Abbrechen + + + Failed + Gescheitert + + + Close nozzle + Hahn zudrehen + + + + + + + diff --git a/addons/refuel/ui/icon_module_refuel.paa b/addons/refuel/ui/icon_module_refuel.paa new file mode 100644 index 0000000000..2cc1a9320d Binary files /dev/null and b/addons/refuel/ui/icon_module_refuel.paa differ diff --git a/addons/refuel/ui/icon_refuel_interact.paa b/addons/refuel/ui/icon_refuel_interact.paa new file mode 100644 index 0000000000..2cc1a9320d Binary files /dev/null and b/addons/refuel/ui/icon_refuel_interact.paa differ