Refuel - Added ability to refuel fuel sources (#8981)

* Simplify main fuel loop

* Remove unecessary action macro

* Add container refueling

* Fuel counter behaviour is now consistent for both limited and unlimited fuel sources

* Update maxFuel and refuelContainer whenever fueling begins

* Update maxFuel and refuelContainer whenever fueling begins

* Prevent loading of fuel sources into cargo when they have a nozzle connected to them

* Added action to check how much fuel is left in a jerry can

* Prevent jerry cans from being picked up if they have a nozzle connected to them

* Added function to check if a nozzle can be connected to an object

* Prevent fuel sources which have their nozzle deployed from being loaded

* Compute both tank volumes inside of refuel instead of durring turn on

* Didn't mean to delete these

* Allow for user defined fuel capacities

* Handle more edge cases with infinite fuel sources

* Refuel - Prevent fuel sources from being dragged while they're refueling other things

* Refuel - Added flow rate multiplier for refueling fuel sources

* Refuel - Use FUNC instead of DFUNC for nozzle actions

* Refuel - getCapacity should return REFUEL_DISABLED_FUEL instead of 0 when argument is not a fuel source

* Refuel - Correctly reset fuel counter when fueling a new target

* Refuel - Implemented all suggested changes

* Refuel - Added newlines to end of files

* Refuel - Added missing newline at end of XEH_PREP

* Only setFuel once per jerry can creation

Co-authored-by: PabstMirror <pabstmirror@gmail.com>

* Calling getFuel will initialize the fuel source

* Refuel - Add newline to end of file

---------

Co-authored-by: BaerMitUmlaut <baermitumlaut@users.noreply.github.com>
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
This commit is contained in:
Samuel Deutsch 2023-02-16 18:06:11 -08:00 committed by GitHub
parent 67ebb15e07
commit edf4a70ed6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 321 additions and 142 deletions

View File

@ -145,6 +145,7 @@ PiZZADOX <509thParachuteInfantry@gmail.com>
pokertour
Professor <lukas.trneny@wo.cz>
Pterolatypus <pterolatypus@gmail.com>
QuantX
QuickDagger
rakowozz
ramius86 <pasini86@hotmail.com>
@ -182,4 +183,4 @@ wizpig64
YetheSamartaka
xrufix
Zakant <Zakant@gmx.de>
zGuba
zGuba

View File

@ -36,7 +36,9 @@ if (_item isEqualType "") then {
_validItem =
(alive _item) &&
{_ignoreInteraction || {([_item, _vehicle] call EFUNC(interaction,getInteractionDistance)) < MAX_LOAD_DISTANCE}} &&
{!(_item getVariable [QEGVAR(cookoff,isCookingOff), false])};
{!(_item getVariable [QEGVAR(cookoff,isCookingOff), false])} &&
{isNull(_item getVariable [QEGVAR(refuel,nozzle), objNull])} && // Objects which have a refueling nozzle connected to them cannot be loaded
{isNull(_item getVariable [QEGVAR(refuel,ownedNozzle), objNull])}; // Fuel sources which have their nozzle out cannot be loaded
};
_validItem &&

View File

@ -1,45 +1,3 @@
#define MACRO_NOZZLE_ACTIONS \
class ACE_Actions { \
class ACE_MainActions { \
displayName = CSTRING(Refuel); \
distance = REFUEL_ACTION_DISTANCE; \
position = "[0,-0.025,0.125]"; \
condition = "true"; \
statement = ""; \
exceptions[] = {INTERACT_EXCEPTIONS}; \
showDisabled = 0; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
class GVAR(PickUpNozzle) { \
displayName = CSTRING(TakeNozzle); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTakeNozzle)); \
statement = QUOTE([ARR_2(_player,_target)] call FUNC(takeNozzle)); \
exceptions[] = {INTERACT_EXCEPTIONS_REFUELING}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
class GVAR(TurnOn) { \
displayName = CSTRING(TurnOn); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTurnOn)); \
statement = QUOTE([ARR_2(_player,_target)] call DFUNC(turnOn)); \
exceptions[] = {INTERACT_EXCEPTIONS}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
class GVAR(TurnOff) { \
displayName = CSTRING(TurnOff); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTurnOff)); \
statement = QUOTE([ARR_2(_player,_target)] call DFUNC(turnOff)); \
exceptions[] = {INTERACT_EXCEPTIONS}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
class GVAR(Disconnect) { \
displayName = CSTRING(Disconnect); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canDisconnect)); \
statement = QUOTE([ARR_2(_player,_target)] call DFUNC(disconnect)); \
exceptions[] = {INTERACT_EXCEPTIONS_REFUELING}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
}; \
}
class CBA_Extended_EventHandlers;
class CfgNonAIVehicles {
@ -91,12 +49,59 @@ class CfgVehicles {
class CBA_Extended_EventHandlers: CBA_Extended_EventHandlers {};
};
MACRO_NOZZLE_ACTIONS;
displayName = QGVAR(fuelNozzle);
scope = 1;
scopeCurator = 1;
model = QPATHTOF(data\nozzle.p3d);
destrType = "DestructNo";
class ACE_Actions {
class ACE_MainActions {
displayName = CSTRING(Refuel);
distance = REFUEL_ACTION_DISTANCE;
position = "[0,-0.025,0.125]";
condition = "true";
statement = "";
exceptions[] = {INTERACT_EXCEPTIONS};
showDisabled = 0;
icon = QPATHTOF(ui\icon_refuel_interact.paa);
class GVAR(PickUpNozzle) {
displayName = CSTRING(TakeNozzle);
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTakeNozzle));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(takeNozzle));
exceptions[] = {INTERACT_EXCEPTIONS_REFUELING};
icon = QPATHTOF(ui\icon_refuel_interact.paa);
};
class GVAR(TurnOn) {
displayName = CSTRING(TurnOn);
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTurnOn));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(turnOn));
exceptions[] = {INTERACT_EXCEPTIONS};
icon = QPATHTOF(ui\icon_refuel_interact.paa);
};
class GVAR(TurnOn_Container) {
displayName = CSTRING(TurnOn_Container);
condition = QUOTE([ARR_3(_player,_target,true)] call FUNC(canTurnOn));
statement = QUOTE([ARR_3(_player,_target,true)] call FUNC(turnOn));
exceptions[] = {INTERACT_EXCEPTIONS};
icon = QPATHTOF(ui\icon_refuel_interact.paa);
};
class GVAR(TurnOff) {
displayName = CSTRING(TurnOff);
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTurnOff));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(turnOff));
exceptions[] = {INTERACT_EXCEPTIONS};
icon = QPATHTOF(ui\icon_refuel_interact.paa);
};
class GVAR(Disconnect) {
displayName = CSTRING(Disconnect);
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canDisconnect));
statement = QUOTE([ARR_2(_player,_target)] call FUNC(disconnect));
exceptions[] = {INTERACT_EXCEPTIONS_REFUELING};
icon = QPATHTOF(ui\icon_refuel_interact.paa);
};
};
};
};
class Rope;

View File

@ -1,4 +1,5 @@
PREP(canCheckFuel);
PREP(canConnectNozzle);
PREP(canDisconnect);
PREP(canReturnNozzle);
PREP(canTakeNozzle);
@ -8,6 +9,7 @@ PREP(checkFuel);
PREP(connectNozzleAction);
PREP(disconnect);
PREP(dropNozzle);
PREP(getCapacity);
PREP(getFuel);
PREP(handleDisconnect);
PREP(handleRespawn);

View File

@ -20,7 +20,7 @@ GVAR(mainAction) = [
{
alive _target
&& {[_player, _target, [INTERACT_EXCEPTIONS]] call EFUNC(common,canInteractWith)}
&& {REFUEL_DISABLED_FUEL != [_target] call FUNC(getFuel)}
&& {REFUEL_DISABLED_FUEL != ([_target] call FUNC(getCapacity))}
},
{}, [], [0,0,0],
REFUEL_ACTION_DISTANCE

View File

@ -8,7 +8,7 @@ class CfgPatches {
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_interaction"};
author = ECSTRING(common,ACETeam);
authors[] = {"GitHawk"};
authors[] = {"GitHawk", "QuantX"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};

View File

@ -23,4 +23,4 @@ params [["_unit", objNull, [objNull]], ["_source", objNull, [objNull]]];
{!local _unit} ||
{!alive _source} ||
{([_unit, _source] call EFUNC(interaction,getInteractionDistance)) > REFUEL_ACTION_DISTANCE} ||
{(_source call FUNC(getFuel) == REFUEL_INFINITE_FUEL)})
{(_source call FUNC(getCapacity)) in [REFUEL_INFINITE_FUEL, REFUEL_DISABLED_FUEL]})

View File

@ -0,0 +1,30 @@
#include "script_component.hpp"
/*
* Author: QuantX
* Checks if an object can have a nozzle connected to it.
*
* Arguments:
* 0: Object <OBJECT>
*
* Return Value:
* Can nozzle be connected <BOOL>
*
* Example:
* [myVehicle] call ace_refuel_fnc_canConnectNozzle;
* [myJerryCan] call ace_refuel_fnc_canConnectNozzle;
*
* Public: No
*/
params [["_object", objNull, [objNull]]];
// Make sure object doesn't already have a nozzle connected
if (isNull _object || {!isNull (_object getVariable [QGVAR(nozzle), objNull])} ) exitWith {false};
// Can't fuel a jerry can that is connected to another object
if (_object getVariable [QGVAR(jerryCan), false]) exitWith {!(_object getVariable [QGVAR(isConnected), false])};
// We need to check "canReceive" before we check if the tank can be filled
// This handles the edge case where a fuel truck has an infintite supply (i.e. the truck can be refueled, but the tank cannot)
(getNumber ((configOf _object) >> QGVAR(canReceive)) == 1) ||
{!(([_object] call FUNC(getCapacity)) in [REFUEL_INFINITE_FUEL, REFUEL_DISABLED_FUEL])}

View File

@ -22,7 +22,8 @@ if (isNull _unit ||
{!(_unit isKindOf "CAManBase")} ||
{!local _unit} ||
{!alive _object} ||
{!isNull (_unit getVariable [QGVAR(nozzle), objNull])} ||
{!isNull (_unit getVariable [QGVAR(nozzle), objNull])} || // Not already carrying a nozzle
{(_object getVariable [QGVAR(jerryCan), false]) && {!isNull (_object getVariable [QGVAR(nozzle), objNull])}} || // Prevent jerry cans from being picked up if they have a nozzle connected
{typeOf _object == QGVAR(fuelNozzle) && {!isNull (attachedTo _object)}} || // Not carried by someone else
{([_unit, _object] call EFUNC(interaction,getInteractionDistance)) > REFUEL_ACTION_DISTANCE}) exitWith {false};

View File

@ -1,11 +1,12 @@
#include "script_component.hpp"
/*
* Author: GitHawk
* Check if a unit can turn on a fuel nozzle
* Check if a unit can turn on a fuel nozzle.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Nozzle <OBJECT>
* 2: Refuel container <BOOL> (default: false)
*
* Return Value:
* Can turn on <BOOL>
@ -16,7 +17,7 @@
* Public: No
*/
params [["_unit", objNull, [objNull]], ["_nozzle", objNull, [objNull]]];
params [["_unit", objNull, [objNull]], ["_nozzle", objNull, [objNull]], ["_refuelContainer", false, [false]]];
if (isNull _unit ||
{isNull _nozzle} ||
@ -24,7 +25,18 @@ if (isNull _unit ||
{!local _unit} ||
{(_nozzle distance _unit) > REFUEL_ACTION_DISTANCE}) exitWith {false};
private _source = _nozzle getVariable [QGVAR(source), objNull];
private _sink = _nozzle getVariable [QGVAR(sink), objNull];
if (isNull _source || {isNull _sink}) exitWith {false};
private _isSinkFull = if (_refuelContainer) then {
([_sink] call FUNC(getCapacity)) in [REFUEL_DISABLED_FUEL, REFUEL_INFINITE_FUEL, [_sink] call FUNC(getFuel)]
} else {
fuel _sink == 1
};
!(_nozzle getVariable [QGVAR(isRefueling), false]) &&
{[_nozzle getVariable QGVAR(source)] call FUNC(getFuel) != 0} &&
{!isNull (_nozzle getVariable [QGVAR(sink), objNull])} &&
{(fuel (_nozzle getVariable QGVAR(sink))) < 1}
{(([_source] call FUNC(getCapacity)) == REFUEL_INFINITE_FUEL) || {[_source] call FUNC(getFuel) > 0}} && // Make sure the source has fuel
{!_isSinkFull} && // Make sure the sink isn't full
{!(_refuelContainer && {_source == _sink})}; // No endless container ot itself loop

View File

@ -72,6 +72,8 @@ private _attachPosModel = _sink worldToModel (ASLtoAGL _bestPosASL);
_args params [["_unit", objNull, [objNull]], ["_nozzle", objNull, [objNull]], ["_sink", objNull, [objNull]], ["_endPosTestOffset", [0,0,0], [[]], 3]];
_unit setVariable [QGVAR(nozzle), nil, true];
_unit setVariable [QGVAR(isRefueling), false];
private _source = _nozzle getVariable QGVAR(source);
detach _nozzle;
_nozzle attachTo [_sink, _endPosTestOffset];
@ -111,21 +113,34 @@ private _attachPosModel = _sink worldToModel (ASLtoAGL _bestPosASL);
_nozzle setVariable [QGVAR(isConnected), true, true];
_sink setVariable [QGVAR(nozzle), _nozzle, true];
_source = _nozzle getVariable QGVAR(source);
private _fuel = [_source] call FUNC(getFuel);
if (_fuel == REFUEL_INFINITE_FUEL) then {
_source setVariable [QGVAR(fuelCounter), 0, true];
} else {
_source setVariable [QGVAR(fuelCounter), _fuel, true];
};
// Reset fuel counter
_source setVariable [QGVAR(fuelCounter), 0, true];
[_unit, _sink, _nozzle, _endPosTestOffset] call FUNC(refuel);
if ([_unit, _nozzle] call FUNC(canTurnOn)) then {
_unit setVariable [QGVAR(tempFuel), nil];
[_unit, _nozzle] call FUNC(turnOn);
} else {
[localize LSTRING(CouldNotTurnOn)] call EFUNC(common,displayText);
private _canReceive = getNumber ((configOf _sink) >> QGVAR(canReceive)) == 1;
private _isContainer = ([_sink] call FUNC(getCapacity)) != REFUEL_DISABLED_FUEL;
// Decide if cargo or vehicle will be refueled
switch (true) do {
case (_canReceive && {!_isContainer || {_sink == _source}}): {
// is not a refueling vehicle or refueling vehicle tries to refuel itself
if ([_unit, _nozzle, false] call FUNC(canTurnOn)) then {
[_unit, _nozzle, false] call FUNC(turnOn);
} else {
[localize LSTRING(CouldNotTurnOn)] call EFUNC(common,displayText);
};
};
case (!_canReceive && _isContainer): {
if ([_unit, _nozzle, true] call FUNC(canTurnOn)) then {
[_unit, _nozzle, true] call FUNC(turnOn);
} else {
[localize LSTRING(CouldNotTurnOn)] call EFUNC(common,displayText);
};
};
default {
/* Target is a refueling vehicle, let user manually decide if he wants to refuel cargo or vehicle itself */
};
};
},
"",

View File

@ -1,10 +1,10 @@
#include "script_component.hpp"
/*
* Author: GitHawk
* Disconnect a fuel nozzle.
* Disconnects a fuel nozzle and makes unit pick it up.
*
* Arguments:
* 0: Unit <OBJECT>
* 0: Unit <OBJECT> (default: objNull)
* 1: Nozzle <OBJECT>
*
* Return Value:
@ -27,4 +27,6 @@ _nozzle setVariable [QGVAR(sink), nil, true];
_nozzle setVariable [QGVAR(isConnected), false, true];
[objNull, _nozzle, true] call FUNC(dropNozzle);
[_unit, _nozzle] call FUNC(takeNozzle);
if (!isNull _unit) then {
[_unit, _nozzle] call FUNC(takeNozzle);
};

View File

@ -4,7 +4,7 @@
* Detaches the fuel nozzle, drops it and removes player variables.
*
* Arguments:
* 0: Unit <OBJECT> (optional)
* 0: Unit <OBJECT> (default: objNull)
* 1: Nozzle <OBJECT>
* 2: Disconnect Only <BOOL>
*

View File

@ -0,0 +1,35 @@
#include "script_component.hpp"
/*
* Author: QuantX
* Gets the capacity of a fuel source's tank.
*
* Arguments:
* 0: Fuel Source <OBJECT>
*
* Return Value:
* Fuel capacity <NUMBER> (-10 means infinte fuel, -1 means not a fuel source, >0 is a capacity in liters)
*
* Example:
* [fuelTruck] call ace_refuel_fnc_getCapacity
*
* Public: Yes
*/
params [["_source", objNull, [objNull]]];
if (isNull _source) exitWith {REFUEL_DISABLED_FUEL};
private _capacity = _source getVariable QGVAR(capacity);
// Initialize fuel truck if needed
if (isNil "_capacity") then {
// Check if this object has a fuelCargo config entry
private _fuelCargo = configOf _source >> QGVAR(fuelCargo);
_capacity = if (isNumber _fuelCargo) then {getNumber _fuelCargo} else {REFUEL_DISABLED_FUEL};
// Set capacity even if this isn't a fuel source to save on config lookup time in the event this function is used in a loop
_source setVariable [QGVAR(capacity), _capacity, true];
[_source, _capacity] call FUNC(setFuel);
};
_capacity;

View File

@ -22,8 +22,8 @@ if (isNull _source) exitWith {0};
private _fuel = _source getVariable QGVAR(currentFuelCargo);
if (isNil "_fuel") then {
_fuel = getNumber (configOf _source >> QGVAR(fuelCargo));
_source setVariable [QGVAR(currentFuelCargo), _fuel, true];
// Calling getCapacity will initialize the fuel source and return the amount of fuel in the tank
_fuel = [_source] call FUNC(getCapacity);
};
_fuel

View File

@ -22,12 +22,12 @@ if (isNull _target ||
{_target isKindOf "AllVehicles"} ||
{_target getVariable [QGVAR(jerryCan), false]}) exitWith {};
if (isServer) then {
[_target, _fuelAmount] call FUNC(setFuel); // has global effects
};
_target setVariable [QGVAR(jerryCan), true];
_target setVariable [QGVAR(source), _target];
_target setVariable [QGVAR(capacity), _fuelAmount];
if (isServer) then { [_target, _fuelAmount] call FUNC(setFuel); };
// Main Action
private _action = [QGVAR(Refuel),
localize LSTRING(Refuel),
@ -64,6 +64,30 @@ _action = [QGVAR(TurnOn),
REFUEL_ACTION_DISTANCE] call EFUNC(interact_menu,createAction);
[_target, 0, ["ACE_MainActions", QGVAR(Refuel)], _action] call EFUNC(interact_menu,addActionToObject);
// Add turnOn container
_action = [QGVAR(TurnOn_Container),
localize LSTRING(TurnOn_Container),
QPATHTOF(ui\icon_refuel_interact.paa),
{[_player, _target, true] call FUNC(turnOn)},
{[_player, _target, true] call FUNC(canTurnOn)},
{},
[],
[0, 0, 0],
REFUEL_ACTION_DISTANCE] call EFUNC(interact_menu,createAction);
[_target, 0, ["ACE_MainActions", QGVAR(Refuel)], _action] call EFUNC(interact_menu,addActionToObject);
// Add check fuel
_action = [QGVAR(CheckFuel),
localize LSTRING(CheckFuel),
QPATHTOF(ui\icon_refuel_interact.paa),
{[_player, _target] call FUNC(checkFuel)},
{[_player, _target] call FUNC(canCheckFuel)},
{},
[],
[0,0,0],
REFUEL_ACTION_DISTANCE] call EFUNC(interact_menu,createAction),
[_target, 0, ["ACE_MainActions", QGVAR(Refuel)], _action] call EFUNC(interact_menu,addActionToObject);
// Add turnOff
_action = [QGVAR(TurnOff),
localize LSTRING(TurnOff),

View File

@ -40,10 +40,14 @@ if (
|| {_fuelCargo != 0 && {_fuelCargo == _fuelCargoConfig}}
) exitWith {};
[_source, _fuelCargo] call FUNC(setFuel);
private _capacity = if (_fuelCargo < 0) then {_fuelCargo} else {_fuelCargoConfig max _fuelCargo};
_source setVariable [QGVAR(capacity), _capacity, true];
if (_fuelCargo == REFUEL_DISABLED_FUEL) exitWith {};
[_source, _fuelCargo] call FUNC(setFuel);
if (
!isNil "_hooks"
&& {_hooks isEqualTypeAll []}

View File

@ -42,10 +42,11 @@ private _virtualPosASL = (eyePos _unit) vectorAdd (positionCameraToWorld [0,0,0.
if (cameraView == "EXTERNAL") then {
_virtualPosASL = _virtualPosASL vectorAdd ((positionCameraToWorld [0.3,0,0]) vectorDiff (positionCameraToWorld [0,0,0]));
};
if (
!isNull _cursorObject
&& {_distance < REFUEL_NOZZLE_ACTION_DISTANCE}
&& {1 == getNumber (configOf _cursorObject >> QGVAR(canReceive))}
&& {[_cursorObject] call FUNC(canConnectNozzle)}
&& {isNull (_cursorObject getVariable [QGVAR(nozzle), objNull])}
&& {!lineIntersects [eyePos _unit, _virtualPosASL, _unit]}
) then {

View File

@ -18,12 +18,6 @@
params [["_unit", objNull, [objNull]], ["_source", objNull, [objNull]]];
private _currentFuel = [_source] call FUNC(getFuel);
private _fuelCounter = if (_currentFuel == REFUEL_INFINITE_FUEL) then {
_source getVariable [QGVAR(fuelCounter), 0]
} else {
(_source getVariable [QGVAR(fuelCounter), _currentFuel]) - _currentFuel
};
private _fuelCounter = 0.01 * round (100 * _fuelCounter);
private _fuelCounter = _source getVariable [QGVAR(fuelCounter), 0];
_fuelCounter = 0.01 * round (100 * _fuelCounter);
[[LSTRING(Hint_FuelCounter), _fuelCounter], 1.5, _unit] call EFUNC(common,displayTextStructured);

View File

@ -1,6 +1,6 @@
#include "script_component.hpp"
/*
* Author: GitHawk
* Author: GitHawk, QuantX
* Refuels the vehicle.
*
* Arguments:
@ -21,93 +21,111 @@
params [["_unit", objNull, [objNull]], ["_sink", objNull, [objNull]], ["_nozzle", objNull, [objNull]], ["_connectToPoint", [0,0,0], [[]], 3]];
private _config = configOf _sink;
private _rate = if (isNumber (_config >> QGVAR(flowRate))) then {
getNumber (_config >> QGVAR(flowRate)) * GVAR(rate)
} else {
// Jerry cans for example have no flow rate defined, default to 1
GVAR(rate)
};
private _rate = getNumber (_config >> QGVAR(flowRate)) * GVAR(rate);
private _maxFuel = getNumber (_config >> QGVAR(fuelCapacity));
// How much fuel is in a vehicle's fuel tank
private _maxFuelTank = getNumber (_config >> QGVAR(fuelCapacity));
// Fall back to vanilla fuelCapacity value (only air and sea vehicles don't have this defined by default by us)
// Air and sea vehicles have that value properly defined in liters, unlike ground vehicles which is is formula of (range * tested factor) - different fuel consumption system than ground vehicles
if (_maxFuel == 0) then {
_maxFuel = getNumber (_config >> "fuelCapacity");
if (_maxFuelTank == 0) then {
_maxFuelTank = getNumber (_config >> "fuelCapacity");
};
[{
params ["_args", "_pfID"];
_args params [["_source", objNull, [objNull]], ["_sink", objNull, [objNull]], ["_unit", objNull, [objNull]], ["_nozzle", objNull, [objNull]], ["_rate", 1, [0]], ["_startFuel", 0, [0]], ["_maxFuel", 0, [0]], ["_connectFromPoint", [0,0,0], [[]], 3], ["_connectToPoint", [0,0,0], [[]], 3]];
_args params [["_source", objNull, [objNull]], ["_sink", objNull, [objNull]], ["_unit", objNull, [objNull]], ["_nozzle", objNull, [objNull]], ["_rate", 1, [0]], ["_maxFuelTank", 1, [0]], ["_connectFromPoint", [0,0,0], [[]], 3], ["_connectToPoint", [0,0,0], [[]], 3]];
if !(_nozzle getVariable [QGVAR(isConnected), false]) exitWith {
[_pfID] call CBA_fnc_removePerFrameHandler;
};
// Quit if target or fuel tank got destroyed
if (!alive _source || {!alive _sink}) exitWith {
[objNull, _nozzle] call FUNC(dropNozzle);
_nozzle setVariable [QGVAR(isConnected), false, true];
if (_nozzle isKindOf "Land_CanisterFuel_F") then { _nozzle setVariable [QEGVAR(cargo,canLoad), true, true]; };
_nozzle setVariable [QGVAR(sink), nil, true];
_sink setVariable [QGVAR(nozzle), nil, true];
[objNull, _nozzle] call FUNC(disconnect);
[_pfID] call CBA_fnc_removePerFrameHandler;
};
// Quit if hose distance was exceeded
private _hoseLength = _source getVariable [QGVAR(hoseLength), GVAR(hoseLength)];
private _tooFar = ((_sink modelToWorld _connectToPoint) distance (_source modelToWorld _connectFromPoint)) > (_hoseLength - 2);
if (_tooFar && {!(_nozzle getVariable [QGVAR(jerryCan), false])}) exitWith {
[LSTRING(Hint_TooFar), 2, _unit] call EFUNC(common,displayTextStructured);
[objNull, _nozzle] call FUNC(dropNozzle);
_nozzle setVariable [QGVAR(isConnected), false, true];
if (_nozzle isKindOf "Land_CanisterFuel_F") then { _nozzle setVariable [QEGVAR(cargo,canLoad), true, true]; };
_nozzle setVariable [QGVAR(sink), nil, true];
_sink setVariable [QGVAR(nozzle), nil, true];
[objNull, _nozzle] call FUNC(disconnect);
[_pfID] call CBA_fnc_removePerFrameHandler;
};
// Main fueling process
private _finished = false;
private _fueling = _nozzle getVariable [QGVAR(isRefueling), false];
if (_fueling) then {
private _fuelInSource = [_source] call FUNC(getFuel);
if (_fuelInSource == 0) exitWith {
[LSTRING(Hint_SourceEmpty), 2, _unit] call EFUNC(common,displayTextStructured);
_nozzle setVariable [QGVAR(lastTickMissionTime), nil];
_nozzle setVariable [QGVAR(isRefueling), false, true];
};
private _refuelContainer = _nozzle getVariable [QGVAR(refuelContainer), false];
// Use special cargo refuel rate when refueling containers
// TODO: Add flow dedicated input/output flow rates for every container and use the lower of the two instead
if (_refuelContainer) then {_rate = GVAR(cargoRate)};
// Calculate rate using mission time to take time acceleration and pause into account
private _rateTime = _rate * (CBA_missionTime - (_nozzle getVariable [QGVAR(lastTickMissionTime), CBA_missionTime]));
private _addedFuel = _rate * (CBA_missionTime - (_nozzle getVariable [QGVAR(lastTickMissionTime), CBA_missionTime]));
_nozzle setVariable [QGVAR(lastTickMissionTime), CBA_missionTime];
if (_fuelInSource != REFUEL_INFINITE_FUEL) then {
if (_rateTime > _fuelInSource) then {
_rateTime = _fuelInSource;
// Figure out exactly how much fuel to transfer while being sure not to take too much from source
private _fuelInSource = [_source] call FUNC(getFuel);
if (([_source] call FUNC(getCapacity)) != REFUEL_INFINITE_FUEL) then {
if (_addedFuel > _fuelInSource) then {
_addedFuel = _fuelInSource;
_fuelInSource = 0;
_finished = true;
[LSTRING(Hint_SourceEmpty), 2, _unit] call EFUNC(common,displayTextStructured);
} else {
_fuelInSource = _fuelInSource - _rateTime;
_fuelInSource = _fuelInSource - _addedFuel;
};
};
private _fuelInSink = (if (_refuelContainer) then {
[_sink] call FUNC(getFuel)
} else {
_source setVariable [QGVAR(fuelCounter), (_source getVariable [QGVAR(fuelCounter), 0]) + _rateTime, true];
};
if (_fuelInSource <= 0 && {_fuelInSource != REFUEL_INFINITE_FUEL}) then {
_fuelInSource = 0;
[_source, _fuelInSource] call FUNC(setFuel);
_finished = true;
[LSTRING(Hint_SourceEmpty), 2, _unit] call EFUNC(common,displayTextStructured);
};
private _fuelInSink = (_unit getVariable [QGVAR(tempFuel), _startFuel]) + ( _rateTime / _maxFuel);
if (_fuelInSink > 1) then {
_fuelInSink = 1;
// How full the gas tank is. We keep our own record, since `fuel _sink` doesn't update quick enough
(_nozzle getVariable [QGVAR(tempFuel), fuel _sink]) * _maxFuelTank
}) + _addedFuel;
// Add fuel to target while being sure not to put too much into sink
private _maxFuelContainer = [_sink] call FUNC(getCapacity);
private _maxFuel = [_maxFuelTank, _maxFuelContainer] select _refuelContainer;
if (_fuelInSink >= _maxFuel) then {
// Put any extra fuel back
_fuelInSource = _fuelInSource + (_fuelInSink - _maxFuel);
_addedFuel = _maxFuel - _fuelInSink;
// We're done
_fuelInSink = _maxFuel;
_finished = true;
[LSTRING(Hint_Completed), 2, _unit] call EFUNC(common,displayTextStructured);
};
_unit setVariable [QGVAR(tempFuel), _fuelInSink];
if (_refuelContainer) then {
[_sink, _fuelInSink] call FUNC(setFuel);
} else {
private _fillRatio = _fuelInSink / _maxFuelTank;
[QEGVAR(common,setFuel), [_sink, _fillRatio], _sink] call CBA_fnc_targetEvent;
_nozzle setVariable [QGVAR(tempFuel), _fillRatio];
};
// Increment fuel counter
_source setVariable [QGVAR(fuelCounter), (_source getVariable [QGVAR(fuelCounter), 0]) + _addedFuel, true];
[QGVAR(tick), [_source, _sink, _rateTime]] call CBA_fnc_localEvent;
[QGVAR(tick), [_source, _sink, _addedFuel, _refuelContainer]] call CBA_fnc_localEvent;
[QEGVAR(common,setFuel), [_sink, _fuelInSink], _sink] call CBA_fnc_targetEvent;
[_source, _fuelInSource] call FUNC(setFuel);
} else {
_unit setVariable [QGVAR(tempFuel), fuel _sink];
_nozzle setVariable [QGVAR(tempFuel), fuel _sink];
};
if (_finished) exitWith {
// Reset variables when done
if (_finished) then {
[QGVAR(stopped), [_source, _sink]] call CBA_fnc_localEvent;
_nozzle setVariable [QGVAR(lastTickMissionTime), nil];
_nozzle setVariable [QGVAR(isRefueling), false, true];
@ -118,8 +136,7 @@ if (_maxFuel == 0) then {
_unit,
_nozzle,
_rate,
fuel _sink,
_maxFuel,
_maxFuelTank,
_nozzle getVariable [QGVAR(attachPos), [0,0,0]],
_connectToPoint
]] call CBA_fnc_addPerFrameHandler;

View File

@ -43,6 +43,10 @@ if (isNull _nozzle || {_source != _nozzle getVariable QGVAR(source)}) exitWith {
deleteVehicle _helper;
};
deleteVehicle _nozzle;
// Restore ability to drag and carry this object
_source setVariable [QEGVAR(dragging,canCarry), _source getVariable [QGVAR(canCarryLast), false], true];
_source setVariable [QEGVAR(dragging,canDrag), _source getVariable [QGVAR(canDragLast), false], true];
[_source, "blockEngine", "ACE_Refuel", false] call EFUNC(common,statusEffect_set);
},

View File

@ -18,7 +18,12 @@
params [["_source", objNull, [objNull]], ["_fuel", nil, [0]]];
if (isNull _source ||
{isNil "_fuel"}) exitWith {};
// Ensure valid fuel quantity
if (isNull _source || {isNil "_fuel"}) exitWith {};
_source setVariable [QGVAR(currentFuelCargo), _fuel, true];
// Make sure this is actually a finite fuel source
private _capacity = [_source] call FUNC(getCapacity);
if (_capacity in [REFUEL_INFINITE_FUEL, REFUEL_DISABLED_FUEL]) exitWith {};
// Don't overfill or underfill tank
_source setVariable [QGVAR(currentFuelCargo), (_fuel min _capacity) max 0, true];

View File

@ -95,10 +95,7 @@ TRACE_2("start",_unit,_nozzle);
getCursorObjectParams params ["_cursorObject", "", "_distance"];
if (!isNull _cursorObject && {_distance < REFUEL_NOZZLE_ACTION_DISTANCE}) then {
if (
1 == getNumber (configOf _cursorObject >> QGVAR(canReceive))
&& {isNull (_cursorObject getVariable [QGVAR(nozzle), objNull])}
) then {
if ([_cursorObject] call FUNC(canConnectNozzle)) then {
_hintLMB = localize LSTRING(Connect);
};
if ([_unit, _cursorObject] call FUNC(canReturnNozzle)) then {

View File

@ -77,6 +77,13 @@ params [
[_source, "blockEngine", "ACE_Refuel", true] call EFUNC(common,statusEffect_set);
_source setVariable [QGVAR(isConnected), true, true];
_source setVariable [QGVAR(ownedNozzle), _nozzle, true];
// Prevent moving the fuel source while the hose is out
_source setVariable [QGVAR(canCarryLast), _source getVariable [QEGVAR(dragging,canCarry), false], true];
_source setVariable [QGVAR(canDragLast), _source getVariable [QEGVAR(dragging,canDrag), false], true];
_source setVariable [QEGVAR(dragging,canCarry), false, true];
_source setVariable [QEGVAR(dragging,canDrag), false, true];
};
_unit setVariable [QGVAR(nozzle), _nozzle, true];

View File

@ -6,6 +6,7 @@
* Arguments:
* 0: Unit <OBJECT>
* 1: Nozzle <OBJECT>
* 2: Refuel container <BOOL> (default: false)
*
* Return Value:
* None
@ -16,9 +17,10 @@
* Public: No
*/
params [["_unit", objNull, [objNull]], ["_nozzle", objNull, [objNull]]];
params [["_unit", objNull, [objNull]], ["_nozzle", objNull, [objNull]], ["_refuelContainer", false, [false]]];
_nozzle setVariable [QGVAR(lastTickMissionTime), CBA_missionTime];
_nozzle setVariable [QGVAR(refuelContainer), _refuelContainer];
_nozzle setVariable [QGVAR(isRefueling), true, true];
[LSTRING(Hint_Started), 1.5, _unit] call EFUNC(common,displayTextStructured);
[QGVAR(started), [_nozzle getVariable QGVAR(source), _nozzle getVariable QGVAR(sink)]] call CBA_fnc_localEvent;

View File

@ -7,6 +7,15 @@
{[QGVAR(rate), _this] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting;
[
QGVAR(cargoRate), "SLIDER",
[LSTRING(RefuelSettings_speedCargo_DisplayName), LSTRING(RefuelSettings_speedCargo_Description)],
[localize ELSTRING(OptionsMenu,CategoryLogistics), localize "str_state_refuel"],
[0,250,10,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true, // isGlobal
{[QGVAR(cargoRate), _this] call EFUNC(common,cbaSettings_settingChanged)}
] call CBA_fnc_addSetting;
[
QGVAR(hoseLength), "SLIDER",
[LSTRING(RefuelSettings_hoseLength_DisplayName)],

View File

@ -49,6 +49,12 @@
<Chinese>載具多快會加油完畢?</Chinese>
<Turkish>Bir araca ne kadar hızlı yakıt ikmali yapılmalıdır?</Turkish>
</Key>
<Key ID="STR_ACE_Refuel_RefuelSettings_speedCargo_DisplayName">
<English>Cargo Flow Rate</English>
</Key>
<Key ID="STR_ACE_Refuel_RefuelSettings_speedCargo_Description">
<English>How fast should a fuel source's tank be filled?</English>
</Key>
<Key ID="STR_ACE_Refuel_Refuel">
<English>Refuel</English>
<German>Betankung</German>
@ -289,6 +295,10 @@
<Chinese>開始加油</Chinese>
<Turkish>Yakıt Doldurmayı Başlat</Turkish>
</Key>
<Key ID="STR_ACE_Refuel_TurnOn_Container">
<English>Start fueling (container)</English>
<German>Betankung beginnen (Container)</German>
</Key>
<Key ID="STR_ACE_Refuel_CouldNotTurnOn">
<English>Couldn't turn on fuel nozzle</English>
<German>Kann Zapfpistole nicht anschalten</German>