From 997bae3b7372b2b564a48fc7c7b0ad0b5bc45143 Mon Sep 17 00:00:00 2001 From: TenuredCLOUD <85143513+TenuredCLOUD@users.noreply.github.com> Date: Fri, 26 Jun 2026 23:58:08 -0700 Subject: [PATCH] Persistence | Power | Fuel - Improve persistence - added option for saving AE3 device states - removed remoteExec in GRAD ui replaced with CBA server events - added more CBA server events for cleaner data management - removed AE3 devices being saved if they are attached to an object via carrying or in cargo to stop duplicated saves - added ACE cargo persistence AE3 objects placed in cargo of vehicles can now persist to next session with proper state values (battery life, fuel, etc...) - added ACE cargo API listener events for loaded cargo for variable tracking cargo objects - added optional ability to force a GRAD save in SP when the player presses ESC key, similar to old builds to keep SP sessions up to date in case the player forgets to save with UI menu - added optional persistence for fuel pumps making them finite fuel sources --- addons/fuel/XEH_PREP.hpp | 2 + addons/fuel/functions/fnc_applyFuelStates.sqf | 38 ++++++ addons/fuel/functions/fnc_grabFuelStates.sqf | 46 +++++++ .../functions/fnc_processTerrainPumps.sqf | 2 + addons/fuel/functions/fnc_turnOffPump.sqf | 6 + addons/fuel/functions/fnc_turnOnPump.sqf | 18 ++- addons/main/script_macros.hpp | 15 ++ addons/persistence/XEH_PREP.hpp | 3 + addons/persistence/XEH_postInit.sqf | 37 +++++ addons/persistence/functions/fnc_gradSave.sqf | 2 +- .../persistence/functions/fnc_handleGrad.sqf | 41 ++++++ addons/persistence/functions/fnc_init.sqf | 3 + .../functions/fnc_restoreCargo.sqf | 82 +++++++++++ .../persistence/functions/fnc_syncCargo.sqf | 77 +++++++++++ addons/persistence/initSettings.inc.sqf | 36 +++++ addons/persistence/stringtable.xml | 128 ++++++++++++++++++ addons/persistence/ui/grad_persistence.hpp | 4 +- addons/power/XEH_postInit.sqf | 4 - .../power/functions/fnc_grabDeviceStates.sqf | 6 + 19 files changed, 542 insertions(+), 8 deletions(-) create mode 100644 addons/fuel/functions/fnc_applyFuelStates.sqf create mode 100644 addons/fuel/functions/fnc_grabFuelStates.sqf create mode 100644 addons/persistence/functions/fnc_handleGrad.sqf create mode 100644 addons/persistence/functions/fnc_restoreCargo.sqf create mode 100644 addons/persistence/functions/fnc_syncCargo.sqf diff --git a/addons/fuel/XEH_PREP.hpp b/addons/fuel/XEH_PREP.hpp index 31928f64..4a387361 100644 --- a/addons/fuel/XEH_PREP.hpp +++ b/addons/fuel/XEH_PREP.hpp @@ -1,3 +1,5 @@ +PREP(applyFuelStates); +PREP(grabFuelStates); PREP(initFuelPumps); PREP(initRefuelRestrictions); PREP(processFuelCan); diff --git a/addons/fuel/functions/fnc_applyFuelStates.sqf b/addons/fuel/functions/fnc_applyFuelStates.sqf new file mode 100644 index 00000000..29d0e389 --- /dev/null +++ b/addons/fuel/functions/fnc_applyFuelStates.sqf @@ -0,0 +1,38 @@ +#include "..\script_component.hpp" +/* + * Author: TenuredCLOUD + * Applies saved ACE fuel station states from stored hashmap + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call misery_fuel_fnc_applyFuelStates; + */ + +if (!isServer) exitWith {}; + +private _masterFuelMap = missionNamespace getVariable [QGVAR(pumpStates), createHashMap]; + +if (count _masterFuelMap isEqualTo 0) exitWith {}; + +private _activePumps = missionNamespace getVariable [QGVAR(activeFuelPumps), []]; + +if (count _activePumps isEqualTo 0) exitWith {}; + +{ + private _pump = _x; + private _pumpPos = getPosASL _pump; + + { + _y params ["_className", "_savedFuel", "_savedPosASL"]; + + if ((typeOf _pump isEqualTo _className) && (_pumpPos distance _savedPosASL < 2)) exitWith { + + _pump setVariable [QGVAR(litreCargo), _savedFuel, true]; + }; + } forEach _masterFuelMap; +} forEach _activePumps; diff --git a/addons/fuel/functions/fnc_grabFuelStates.sqf b/addons/fuel/functions/fnc_grabFuelStates.sqf new file mode 100644 index 00000000..06e5ea32 --- /dev/null +++ b/addons/fuel/functions/fnc_grabFuelStates.sqf @@ -0,0 +1,46 @@ +#include "..\script_component.hpp" +/* + * Author: TenuredCLOUD + * Server side fuel station state grabber for ACE Refuel persistence + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call misery_fuel_fnc_grabFuelStates; + */ + +if (!isServer) exitWith {}; + +private _activePumps = missionNamespace getVariable [QGVAR(activeFuelPumps), []]; + +private _masterFuelMap = createHashMap; + +{ + private _pump = _x; + + + if (!isNull _pump && {alive _pump}) then { + + private _currentFuel = _pump getVariable [QGVAR(litreCargo), -1]; + private _aceFuel = _pump getVariable [QACEGVAR(refuel,currentFuelCargo), -1]; + + if (_aceFuel isNotEqualTo -1 && ([_pump] call AE3FUNC(power,getPowerState) isNotEqualTo "Off")) then { + _currentFuel = _aceFuel; + }; + + if (_currentFuel isEqualTo -1) then { + private _capacity = [MACRO_FUELSTATION_CAPACITIES]; + private _index = _capacity findIf { (_x select 0) isEqualTo typeOf _pump }; + _currentFuel = [1000, (_capacity select _index) select 1] select (_index isNotEqualTo -1); + }; + + private _key = _pump call BIS_fnc_objectVar; + _masterFuelMap set [_key, [typeOf _pump, _currentFuel, getPosASL _pump, [vectorDir _pump, vectorUp _pump]]]; + }; +} forEach _activePumps; + +missionNamespace setVariable [QGVAR(pumpStates), _masterFuelMap, true]; diff --git a/addons/fuel/functions/fnc_processTerrainPumps.sqf b/addons/fuel/functions/fnc_processTerrainPumps.sqf index 93844ac4..816a539f 100644 --- a/addons/fuel/functions/fnc_processTerrainPumps.sqf +++ b/addons/fuel/functions/fnc_processTerrainPumps.sqf @@ -48,3 +48,5 @@ if (isClass (missionConfigFile >> "CfgGradPersistence")) then { [_x] call GRADFUNC(persistence,blacklistObjects); } forEach _replacementPumps; }; + +missionNamespace setVariable [QGVAR(activeFuelPumps), _replacementPumps, true]; diff --git a/addons/fuel/functions/fnc_turnOffPump.sqf b/addons/fuel/functions/fnc_turnOffPump.sqf index 8f28a4e1..cf0482f1 100644 --- a/addons/fuel/functions/fnc_turnOffPump.sqf +++ b/addons/fuel/functions/fnc_turnOffPump.sqf @@ -16,6 +16,12 @@ params ["_source"]; +if (EGVAR(persistence,saveACEFuelStations)) then { + private _remainingFuel = _source getVariable [QACEGVAR(refuel,currentFuelCargo), 0]; + + _source setVariable [QGVAR(litreCargo), _remainingFuel, true]; +}; + [_source, 0] call ACEFUNC(refuel,makeSource); true diff --git a/addons/fuel/functions/fnc_turnOnPump.sqf b/addons/fuel/functions/fnc_turnOnPump.sqf index c164eba4..eecb355f 100644 --- a/addons/fuel/functions/fnc_turnOnPump.sqf +++ b/addons/fuel/functions/fnc_turnOnPump.sqf @@ -19,7 +19,23 @@ params ["_source"]; [{ params ["_source"]; - [_source, -10] call ACEFUNC(refuel,makeSource); + if (EGVAR(persistence,saveACEFuelStations)) then { + + private _currentFuel = _source getVariable [QGVAR(litreCargo), -1]; + + if (_currentFuel isEqualTo -1) then { + private _capacity = [MACRO_FUELSTATION_CAPACITIES]; + private _index = _capacity findIf { (_x select 0) isEqualTo typeOf _source }; + + _currentFuel = [1000, (_capacity select _index) select 1] select (_index isNotEqualTo -1); + + _source setVariable [QGVAR(litreCargo), _currentFuel, true]; + }; + + [_source, _currentFuel] call ACEFUNC(refuel,makeSource); + } else { + [_source, -10] call ACEFUNC(refuel,makeSource); + }; }, [_source], 1] call CBA_fnc_waitAndExecute; true diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index 038ed69c..3dfafbe6 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -152,6 +152,21 @@ // Crafting stations / Fuel stations #define MACRO_FUELSTATIONS_LAND "Land_fs_feed_F", "Land_FuelStation_Feed_F", "Land_FuelStation_03_pump_F", "Land_Ind_TankSmall2", "Land_Ind_TankSmall2_EP1", "Land_A_FuelStation_Feed", "Land_fuelstation", "Land_Ind_FuelStation_Feed_EP1" #define MACRO_FUELSTATIONS_AIR "B_Slingload_01_Fuel_F", "StorageBladder_01_fuel_forest_F", "StorageBladder_01_fuel_sand_F", "Land_Pod_Heli_Transport_04_fuel_F" + +#define MACRO_FUELSTATION_CAPACITIES \ + ["Land_fs_feed_F", 10000], \ + ["Land_FuelStation_Feed_F", 10000], \ + ["Land_FuelStation_03_pump_F", 10000], \ + ["Land_Ind_TankSmall2", 15000], \ + ["Land_Ind_TankSmall2_EP1", 15000], \ + ["Land_A_FuelStation_Feed", 10000], \ + ["Land_fuelstation", 10000], \ + ["Land_Ind_FuelStation_Feed_EP1", 10000], \ + ["B_Slingload_01_Fuel_F", 4000], \ + ["StorageBladder_01_fuel_forest_F", 2500], \ + ["StorageBladder_01_fuel_sand_F", 2500], \ + ["Land_Pod_Heli_Transport_04_fuel_F", 3000] + #define MACRO_CRAFTINGSTATIONS "Land_Workbench_01_F", "Land_PortableDesk_01_olive_F" // Radios diff --git a/addons/persistence/XEH_PREP.hpp b/addons/persistence/XEH_PREP.hpp index 70502070..ef1cf9bb 100644 --- a/addons/persistence/XEH_PREP.hpp +++ b/addons/persistence/XEH_PREP.hpp @@ -3,9 +3,12 @@ PREP(clientDataGet); PREP(clientDataSet); PREP(formatSaveName); PREP(gradSave); +PREP(handleGrad); PREP(init); PREP(loadData); PREP(multiplayerDataLoad); PREP(multiplayerDataSave); PREP(newPlayer); +PREP(restoreCargo); PREP(saveGame); +PREP(syncCargo); diff --git a/addons/persistence/XEH_postInit.sqf b/addons/persistence/XEH_postInit.sqf index bfab8b9a..fba5d39c 100644 --- a/addons/persistence/XEH_postInit.sqf +++ b/addons/persistence/XEH_postInit.sqf @@ -8,6 +8,43 @@ GVAR(saveName) = call FUNC(formatSaveName); if (isServer) then { [QGVAR(saveDataToServer), FUNC(multiplayerDataSave)] call CBA_fnc_addEventHandler; [QGVAR(loadDataFromServer), FUNC(multiplayerDataLoad)] call CBA_fnc_addEventHandler; + + [QGVAR(saveWorldState), {[GVAR(gradWarning), 0] call GRADFUNC(persistence,saveMission)}] call CBA_fnc_addEventHandler; + [QGVAR(wipeWorldState), {[GVAR(gradPersistenceTag)] call GRADFUNC(persistence,clearMissionData)}] call CBA_fnc_addEventHandler; + + if (GVAR(saveAE3States)) then { + [QGVAR(grabAE3Devices), {call EFUNC(power,grabDeviceStates)}] call CBA_fnc_addEventHandler; + + [{ + call EFUNC(power,applyStates); + }, [], 0.2] call CBA_fnc_waitAndExecute; + }; + + if (GVAR(saveACECargo)) then { + [QCLASSACE(cargoLoaded), { + params ["_item", "_vehicle"]; + _item setVariable [QGVAR(isCargo), true, true]; + }] call CBA_fnc_addEventHandler; + + [QCLASSACE(cargoUnloaded), { + params ["_item", "_vehicle"]; + _item setVariable [QGVAR(isCargo), false, true]; + }] call CBA_fnc_addEventHandler; + + [QGVAR(grabCargo), {call FUNC(syncCargo)}] call CBA_fnc_addEventHandler; + + [{ + call FUNC(restoreCargo); + }, [], 0.2] call CBA_fnc_waitAndExecute; + }; + + if (GVAR(saveACEFuelStations)) then { + [QGVAR(grabFuelStationLitres), {call EFUNC(fuel,grabFuelStates)}] call CBA_fnc_addEventHandler; + + [{ + call EFUNC(fuel,applyFuelStates); + }, [], 0.2] call CBA_fnc_waitAndExecute; + }; }; [QGVAR(loadDataFromServerCallback), { diff --git a/addons/persistence/functions/fnc_gradSave.sqf b/addons/persistence/functions/fnc_gradSave.sqf index 7f3fa6b7..bff7bea4 100644 --- a/addons/persistence/functions/fnc_gradSave.sqf +++ b/addons/persistence/functions/fnc_gradSave.sqf @@ -17,5 +17,5 @@ [] call FUNC(gradSave); }, [], GVAR(gradAutosaveTimer)] call CBA_fnc_waitAndExecute; -[GVAR(gradWarning), 0] call GRADFUNC(persistence,saveMission); +[1] call FUNC(handleGrad); diff --git a/addons/persistence/functions/fnc_handleGrad.sqf b/addons/persistence/functions/fnc_handleGrad.sqf new file mode 100644 index 00000000..22a24a73 --- /dev/null +++ b/addons/persistence/functions/fnc_handleGrad.sqf @@ -0,0 +1,41 @@ +#include "..\script_component.hpp" +/* + * Author: TenuredCLOUD + * Handles GRAD saving / wipes + * Processes other data handles prior to GRAD + * + * Arguments: + * 0: Type of process + * + * Return Value: + * None + * + * Example: + * [] call misery_persistence_fnc_handleGrad +*/ + +params ["_type"]; + +if (_type isEqualTo 1) then { + + if (GVAR(saveAE3States)) then { + [QGVAR(grabAE3Devices)] call CBA_fnc_serverEvent; + }; + + if (GVAR(saveACECargo)) then { + [QGVAR(grabCargo)] call CBA_fnc_serverEvent; + }; + + if (GVAR(saveACEFuelStations)) then { + [QGVAR(grabFuelStationLitres)] call CBA_fnc_serverEvent; + }; + + [{ + // Slight delay to ensure other persistence frameworks are cached for GRAD write + [QGVAR(saveWorldState)] call CBA_fnc_serverEvent; + }, [], 0.02] call CBA_fnc_waitAndExecute; +} else { + [QGVAR(wipeWorldState)] call CBA_fnc_serverEvent; +}; + + diff --git a/addons/persistence/functions/fnc_init.sqf b/addons/persistence/functions/fnc_init.sqf index 88c6937b..31ce41ea 100644 --- a/addons/persistence/functions/fnc_init.sqf +++ b/addons/persistence/functions/fnc_init.sqf @@ -76,6 +76,9 @@ if (isMultiplayer) exitWith { params ["", "_key"]; if (_key isEqualTo 1) then { call FUNC(saveGame); + if (GVAR(gradESCSave)) then { + [1] call FUNC(handleGrad); + }; }; }]; }] call CBA_fnc_waitUntilAndExecute; diff --git a/addons/persistence/functions/fnc_restoreCargo.sqf b/addons/persistence/functions/fnc_restoreCargo.sqf new file mode 100644 index 00000000..51509fbe --- /dev/null +++ b/addons/persistence/functions/fnc_restoreCargo.sqf @@ -0,0 +1,82 @@ +#include "..\script_component.hpp" +/* + * Author: TenuredCLOUD + * ACE Cargo API restore handle + * Also restores AE3 items states stored in Cargo + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call misery_persistence_fnc_restoreCargo +*/ + +if (!isServer) exitWith {}; + +private _masterCargoMap = missionNamespace getVariable [QGVAR(cargoStates), createHashMap]; + +if (count _masterCargoMap isEqualTo 0) exitWith {}; + +{ + _y params ["_vehicleClass", "_savedPosASL", "_savedCargoArray"]; + + private _nearVehicles = nearestObjects [ASLToAGL _savedPosASL, [_vehicleClass], 8]; + if (_nearVehicles isEqualTo []) then { continue }; + + private _vehicle = _nearVehicles select 0; + + if (!isNull _vehicle) then { + { + _x params ["_className", "_powerData"]; + _powerData params ["_powerValue", "_powerType", "_damageValue"]; + + private _spawnPos = (getPosWorld _vehicle) vectorAdd [0, 0, -100]; + + private _cargoObject = createVehicle [_className, _spawnPos, [], 0, "CAN_COLLIDE"]; + + if (_damageValue > 0) then { + _cargoObject setDamage _damageValue; + }; + + switch (_powerType) do { + case 0: { + if (_powerValue isNotEqualTo -1) then { + [{private _dummy = _this select 0 getVariable [QAE3GVAR(power,internal), objNull]; (!isNull _dummy) && {alive _dummy}}, + { + params ["_object", "_battery"]; + + private _dummy = _object getVariable [QAE3GVAR(power,internal), objNull]; + if (!isNull _dummy) then { + _dummy setVariable [QAE3GVAR(power,batteryLevel), _battery, true]; + }; + }, [_cargoObject, _powerValue], 0.5] call CBA_fnc_waitUntilAndExecute; + }; + }; + case 1: { + [{ + params ["_object", "_battery"]; + _object setVariable [QAE3GVAR(power,batteryLevel), _battery, true]; + }, [_cargoObject, _powerValue], 0.2] call CBA_fnc_waitAndExecute; + }; + case 2: { + [{ + params ["_object", "_fuelVal"]; + _object setFuel _fuelVal; + }, [_cargoObject, _powerValue], 0.2] call CBA_fnc_waitAndExecute; + }; + }; + + [{ + params ["_object", "_vehicle"]; + + if (!isNull _object && !isNull _vehicle) then { + [_object, _vehicle, true] call ACEFUNC(cargo,loadItem); + }; + }, [_cargoObject, _vehicle], 0.25] call CBA_fnc_waitAndExecute; + + } forEach _savedCargoArray; + }; +} forEach _masterCargoMap; diff --git a/addons/persistence/functions/fnc_syncCargo.sqf b/addons/persistence/functions/fnc_syncCargo.sqf new file mode 100644 index 00000000..5674210e --- /dev/null +++ b/addons/persistence/functions/fnc_syncCargo.sqf @@ -0,0 +1,77 @@ +#include "..\script_component.hpp" +/* + * Author: TenuredCLOUD + * Map scanner for ACE cargo API persistence + * Also handles AE3 items stored in Cargo + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call misery_persistence_fnc_syncCargo +*/ + +if (!isServer) exitWith {}; + +private _masterCargoMap = createHashMap; + +private _allVehicles = allMissionObjects "AllVehicles" - allMissionObjects "Man" - allMissionObjects "StaticWeapon"; + +{ + private _vehicle = _x; + + private _rawCargo = _vehicle getVariable [QACEGVAR(cargo,loaded), []]; + + if (_rawCargo isNotEqualTo []) then { + private _serializedCargo = []; + + { + if (_x isEqualType "") then { + _serializedCargo pushBack [_x, [-1, -1, 0]]; + } else { + if (!isNull _x) then { + private _classname = typeOf _x; + private _damageVal = damage _x; + private _powerData = [0, -1, _damageVal]; + + private _dummy = _x getVariable [QAE3GVAR(power,internal), objNull]; + + if (!isNull _dummy) then { + private _battery = _dummy getVariable [QAE3GVAR(power,batteryLevel), 0.1]; + + _powerData = [_battery, 0, _damageVal]; + + } else { + private _directBattery = _x getVariable [QAE3GVAR(power,batteryLevel), -1]; + + if (_directBattery isNotEqualTo -1) then { + + _powerData = [_directBattery, 1, _damageVal]; + } else { + + + if (_classname in EGVAR(power,generators)) then { + + _powerData = [fuel _x, 2, _damageVal]; + }; + }; + }; + + _serializedCargo pushBack [_classname, _powerData]; + }; + }; + } forEach _rawCargo; + + if (_serializedCargo isNotEqualTo []) then { + + private _vehicleKey = format ["%1_%2", typeOf _vehicle, getPosASL _vehicle]; + + _masterCargoMap set [_vehicleKey, [typeOf _vehicle, getPosASL _vehicle, _serializedCargo]]; + }; + }; +} forEach _allVehicles; + +missionNamespace setVariable [QGVAR(cargoStates), _masterCargoMap, true]; diff --git a/addons/persistence/initSettings.inc.sqf b/addons/persistence/initSettings.inc.sqf index bf3435dc..2527c58d 100644 --- a/addons/persistence/initSettings.inc.sqf +++ b/addons/persistence/initSettings.inc.sqf @@ -59,6 +59,15 @@ private _category = format ["Misery %1", localize LSTRING(Component)]; true ] call CBA_fnc_addSetting; +[ + QGVAR(gradESCSave), + "CHECKBOX", + [LSTRING(SaveWorldStateESC), LSTRING(SaveWorldStateESCDesc)], + _category, + false, + 1 +] call CBA_fnc_addSetting; + [ QGVAR(gradWarning), "CHECKBOX", @@ -76,3 +85,30 @@ private _category = format ["Misery %1", localize LSTRING(Component)]; false, 1 ] call CBA_fnc_addSetting; + +[ + QGVAR(saveAE3States), + "CHECKBOX", + [LSTRING(SaveAE3States), LSTRING(SaveAE3StatesDesc)], + _category, + false, + 1 +] call CBA_fnc_addSetting; + +[ + QGVAR(saveACECargo), + "CHECKBOX", + [LSTRING(SaveACECargo), LSTRING(SaveACECargoDesc)], + _category, + false, + 1 +] call CBA_fnc_addSetting; + +[ + QGVAR(saveACEFuelStations), + "CHECKBOX", + [LSTRING(SaveACEFuelingStations), LSTRING(SaveACEFuelingStationsDesc)], + _category, + false, + 1 +] call CBA_fnc_addSetting; diff --git a/addons/persistence/stringtable.xml b/addons/persistence/stringtable.xml index c070ff33..8953a016 100644 --- a/addons/persistence/stringtable.xml +++ b/addons/persistence/stringtable.xml @@ -257,6 +257,102 @@ 硬核模式已启用,您需要靠近点燃的篝火才能存档... Hardcore mod etkinleştirildi, kaydetmek için yanan bir ateşin yakınında olmalısınız... + + Save ACE cargo + Uložit náklad ACE + Sauvegarder le chargement ACE + Guardar carga de ACE + Salva carico ACE + Zapisz ładunek ACE + Salvar carga do ACE + Сохранить груз ACE + ACE-Fracht speichern + ACE 화물 저장 + ACE カーゴを保存 + 儲存 ACE 物資 + 储存 ACE 物资 + ACE Kargosunu Kaydet + + + Saves ACE cargo, and restores it on load, requires GRAD persistence + Uloží náklad ACE a obnoví jej při načtení, vyžaduje GRAD persistence + Sauvegarde le chargement ACE et le restaure au chargement, nécessite GRAD persistence + Guarda la carga de ACE y la restaura al cargar, requiere GRAD persistence + Salva il carico ACE e lo ripristina al caricamento, richiede GRAD persistence + Zapisuje ładunek ACE i przywraca go po załadowaniu, wymaga GRAD persistence + Salva a carga do ACE e a restaura ao carregar, requer GRAD persistence + Сохраняет груз ACE и восстанавливает его при загрузке, требуется GRAD persistence + Speichert ACE-Fracht und stellt sie beim Laden wieder her, erfordert GRAD persistence + ACE 화물을 저장하고 불러올 때 복원합니다. GRAD persistence가 필요합니다 + ACE カーゴを保存し、ロード時に復元します(GRAD persistence が必要) + 儲存 ACE 物資並在載入時恢復,需要 GRAD persistence + 储存 ACE 物资并在载入时恢复,需要 GRAD persistence + ACE kargosunu kaydeder ve yükleme esnasında geri yükler, GRAD persistence gerektirir + + + Save ACE fueling stations + Uložit čerpací stanice ACE + Sauvegarder les stations-service ACE + Guardar estaciones de servicio ACE + Salva stazioni di rifornimento ACE + Zapisz stacje paliw ACE + Salvar postos de combustível ACE + Сохранить заправочные станции ACE + ACE-Tankstellen speichern + ACE 주유소 저장 + ACE 給油ステーションを保存 + 儲存 ACE 加油站 + 储存 ACE 加油站 + ACE Yakıt İstasyonlarını Kaydet + + + Saves ACE fueling stations, makes it so fuel locations stay depleted after use, requires GRAD persistence + Uloží čerpací stanice ACE, zajistí, aby palivové lokace zůstaly po použití vyčerpané, vyžaduje GRAD persistence + Sauvegarde les stations-service ACE, permettant aux points de ravitaillement de rester vidés après utilisation, nécessite GRAD persistence + Guarda las estaciones de servicio ACE, hace que los puntos de combustible permanezcan agotados tras su uso, requiere GRAD persistence + Salva le stazioni di rifornimento ACE, facendo in modo che i punti di rifornimento rimangano esauriti dopo l'uso, richiede GRAD persistence + Zapisuje stacje paliw ACE, sprawia, że miejsca z paliwem pozostają wyczerpane po użyciu, wymaga GRAD persistence + Salva os postos de combustível ACE, fazendo com que os locais de combustível permaneçam esgotados após o uso, requer GRAD persistence + Сохраняет заправочные станции ACE, благодаря чему запасы топлива не восполняются после использования, требуется GRAD persistence + Speichert ACE-Tankstellen, sorgt dafür, dass Tankstellen nach der Nutzung leer bleiben, erfordert GRAD persistence + ACE 주유소를 저장하여 사용 후 주유 공간이 고갈된 상태로 유지되도록 합니다. GRAD persistence가 필요합니다 + ACE 給油ステーションを保存し、使用後に燃料スポットが枯渇したままになるようにします(GRAD persistence が必要) + 儲存 ACE 加油站,使燃料點在使用後保持枯竭狀態延續,需要 GRAD persistence + 储存 ACE 加油站,使燃料点在使用后保持枯竭状态延续,需要 GRAD persistence + ACE yakıt istasyonlarını kaydeder, yakıt noktalarının kullanıldıktan sonra boş kalmasını sağlar, GRAD persistence gerektirir + + + Save AE3 states + Uložit stavy AE3 + Sauvegarder les états AE3 + Guardar estados de AE3 + Salva stati AE3 + Zapisz stany AE3 + Salvar estados do AE3 + Сохранить состояния AE3 + AE3-Zustände speichern + AE3 상태 저장 + AE3 の状態を保存 + 儲存 AE3 狀態 + 储存 AE3 状态 + AE3 Durumlarını Kaydet + + + Saves AE3 states, battery levels, generator fuel, etc... Requires GRAD persistence + Uloží stavy AE3, úrovně baterií, palivo v generátoru atd... Vyžaduje GRAD persistence + Sauvegarde les états AE3, les niveaux de batterie, le carburant du générateur, etc. Nécessite GRAD persistence + Guarda los estados de AE3, niveles de batería, combustible del generador, etc... Requiere GRAD persistence + Salva gli stati AE3, i livelli della batteria, il carburante del generatore, ecc... Richiede GRAD persistence + Zapisuje stany AE3, poziomy baterii, paliwo generatora itp... Wymaga GRAD persistence + Salva os estados do AE3, níveis de bateria, combustível do gerador, etc... Requer GRAD persistence + Сохраняет состояния AE3, уровень заряда батарей, топливо в генераторе и т. д... Требуется GRAD persistence + Speichert AE3-Zustände, Batteriestände, Generator-Kraftstoff usw. Erfordert GRAD persistence + AE3 상태, 배터리 잔량, 발전기 연료 등을 저장합니다. GRAD persistence가 필요합니다 + AE3 の状態、バッテリー残量、発電機の燃料などを保存します(GRAD persistence が必要) + 儲存 AE3 狀態、電池電量、发電機燃料等... 需要 GRAD persistence + 储存 AE3 状态、电池电量、发电机燃料等... 需要 GRAD persistence + AE3 durumlarını, batarya seviyelerini, jeneratör yakıtını vb. kaydeder... GRAD persistence gerektirir + Save Slot Pozice pro uložení @@ -305,6 +401,38 @@ 保存世界数据 Dünyayı Kaydet + + Save World state on ESC click + Uložit stav světa při stisknutí ESC + Sauvegarder l'état du monde via la touche Échap + Guardar estado del mundo al pulsar ESC + Salva lo stato del mondo alla pressione di ESC + Zapisz stan świata po naciśnięciu ESC + Salvar estado do mundo ao apertar ESC + Сохранять состояние мира при нажатии ESC + Weltzustand bei Drücken von ESC speichern + ESC 누를 때 세계 상태 저장 + ESC キー押下時にワールドの状態を保存 + 按下 ESC 時儲存世界狀態 + 按下 ESC 时储存世界状态 + ESC tıklandığında Dünya durumunu kaydet + + + Pushes a GRAD save when ESC key is pressed, SP only, requires GRAD persistence + Vynutí uložení GRAD při stisknutí klávesy ESC, pouze pro SP, vyžaduje GRAD persistence + Force une sauvegarde GRAD lorsque la touche Échap est enfoncée, Solo uniquement, nécessite GRAD persistence + Forza un guardado de GRAD al pulsar la tecla ESC, solo para un jugador, requiere GRAD persistence + Invia un salvataggio GRAD quando viene premuto il tasto ESC, solo SP, richiede GRAD persistence + Wymusza zapis GRAD po naciśnięciu klawisza ESC, tylko SP, wymaga GRAD persistence + Força um salvamento do GRAD quando a tecla ESC é pressionada, apenas SP, requer GRAD persistence + Принудительно выполняет сохранение GRAD при нажатии клавиши ESC, только в одиночной игре, требуется GRAD persistence + Erzwingt eine GRAD-Speicherung beim Drücken der ESC-Taste, nur SP, erfordert GRAD persistence + ESC 키를 누를 때 GRAD 저장을 실행합니다. 싱글 플레이어(SP) 전용이며 GRAD persistence가 필요합니다 + ESC キーが押されたときに GRAD セーブを実行します(SP 専用、GRAD persistence が必要) + 按下 ESC 鍵時推送 GRAD 存檔,僅限單人遊戲(SP),需要 GRAD persistence + 按下 ESC 键时推送 GRAD 存档,仅限单人游戏(SP),需要 GRAD persistence + ESC tuşuna basıldığında bir GRAD kaydı tetikler, yalnızca SP, GRAD persistence gerektirir + Wipe world data Smazat data světa diff --git a/addons/persistence/ui/grad_persistence.hpp b/addons/persistence/ui/grad_persistence.hpp index a1c1f5bf..32408251 100644 --- a/addons/persistence/ui/grad_persistence.hpp +++ b/addons/persistence/ui/grad_persistence.hpp @@ -45,7 +45,7 @@ class CLASS(grad_persistence_compat_ui) { colorActive[] = {0.5, 0.5, 0.5, 0.7}; font = UI_MACRO_FONT; sizeEx = UI_MACRO_TEXTSIZE; - onButtonClick = QUOTE([ARR_2(EGVAR(persistence,gradWarning),0)] remoteExec [ARR_2('GRADFUNC(persistence,saveMission)',2)]); + onButtonClick = QUOTE([ARR_1(1)] call EFUNC(persistence,handleGrad)); }; class misery_gradPersistence_wipe: RscButton { idc = -1; @@ -60,7 +60,7 @@ class CLASS(grad_persistence_compat_ui) { colorActive[] = {0.5, 0.5, 0.5, 0.7}; font = UI_MACRO_FONT; sizeEx = UI_MACRO_TEXTSIZE; - onButtonClick = QUOTE([ARR_1(EGVAR(persistence,gradPersistenceTag))] remoteExec [ARR_2('GRADFUNC(persistence,clearMissionData)',2)]); + onButtonClick = QUOTE([ARR_1(-1)] call EFUNC(persistence,handleGrad)); }; class misery_gradPersistence_cancel_wipe: RscButton { idc = -1; diff --git a/addons/power/XEH_postInit.sqf b/addons/power/XEH_postInit.sqf index 390998e0..9bf54e3c 100644 --- a/addons/power/XEH_postInit.sqf +++ b/addons/power/XEH_postInit.sqf @@ -3,10 +3,6 @@ if (isServer) then { call FUNC(initLightSources); - [{ - call FUNC(applyStates); - }, [], 0.2] call CBA_fnc_waitAndExecute; - if (isClass (missionConfigFile >> "CfgGradPersistence")) then { { [_x] call GRADFUNC(persistence,blacklistClasses); diff --git a/addons/power/functions/fnc_grabDeviceStates.sqf b/addons/power/functions/fnc_grabDeviceStates.sqf index 3f02f593..75d2ba65 100644 --- a/addons/power/functions/fnc_grabDeviceStates.sqf +++ b/addons/power/functions/fnc_grabDeviceStates.sqf @@ -48,6 +48,8 @@ private _masterDeviceMap = createHashMap; private _device = _x; private _dummy = _device getVariable [QAE3GVAR(power,internal), objNull]; + if (_x getVariable [QEGVAR(persistence,isCargo), false]) then { continue }; + if (!isNull _dummy) then { private _powerSource = _dummy getVariable [QAE3GVAR(power,batteryLevel), 0.1]; @@ -64,6 +66,8 @@ private _masterDeviceMap = createHashMap; private _powerSource = _device getVariable [QAE3GVAR(power,batteryLevel), 1]; private _key = _device call BIS_fnc_objectVar; + if (_x getVariable [QEGVAR(persistence,isCargo), false]) then { continue }; + _masterDeviceMap set [_key, [typeOf _device, _powerSource, 1, getPosASL _device, [vectorDir _device, vectorUp _device]]]; } forEach (allMissionObjects _x); } forEach _directDevices; @@ -73,6 +77,8 @@ private _masterDeviceMap = createHashMap; private _device = _x; private _key = _device call BIS_fnc_objectVar; + if (_x getVariable [QEGVAR(persistence,isCargo), false]) then { continue }; + _masterDeviceMap set [_key, [typeOf _device, fuel _device, 2, getPosASL _device, [vectorDir _device, vectorUp _device]]]; } forEach (allMissionObjects _x); } forEach _fueledDevices;