diff --git a/addons/overheating/ACE_Settings.hpp b/addons/overheating/ACE_Settings.hpp index 6cff3268ff..abf08c9874 100644 --- a/addons/overheating/ACE_Settings.hpp +++ b/addons/overheating/ACE_Settings.hpp @@ -38,4 +38,10 @@ class ACE_Settings { displayName = CSTRING(unJamFailChance_displayName); description = CSTRING(unJamFailChance_description); }; + class GVAR(enabled) { + typeName = "BOOL"; + value = 1; + displayName = CSTRING(enabled_displayName); + description = CSTRING(enabled_description); + }; }; diff --git a/addons/overheating/CfgEventHandlers.hpp b/addons/overheating/CfgEventHandlers.hpp index 492230513f..5da5fd0dc2 100644 --- a/addons/overheating/CfgEventHandlers.hpp +++ b/addons/overheating/CfgEventHandlers.hpp @@ -16,11 +16,3 @@ class Extended_PostInit_EventHandlers { init = QUOTE( call COMPILE_FILE(XEH_postInit) ); }; }; - -class Extended_Take_EventHandlers { - class CAManBase { - class GVAR(UnjamReload) { - clientTake = QUOTE( _this call FUNC(handleTakeEH) ); - }; - }; -}; diff --git a/addons/overheating/CfgMagazines.hpp b/addons/overheating/CfgMagazines.hpp new file mode 100644 index 0000000000..cc040eca0f --- /dev/null +++ b/addons/overheating/CfgMagazines.hpp @@ -0,0 +1,11 @@ +class CfgMagazines { + class CA_Magazine; + class ACE_SpareBarrel: CA_Magazine { + displayName = CSTRING(SpareBarrelName); + descriptionshort = CSTRING(SpareBarrelDescription); + picture = QUOTE(PATHTOF(UI\spare_barrel_ca.paa)); + count = 1; + mass = 60; + ACE_isUnique = 1; + }; +}; diff --git a/addons/overheating/CfgVehicles.hpp b/addons/overheating/CfgVehicles.hpp index ec4b868b84..23a2b613f5 100644 --- a/addons/overheating/CfgVehicles.hpp +++ b/addons/overheating/CfgVehicles.hpp @@ -4,32 +4,59 @@ class CfgVehicles { class CAManBase: Man { class ACE_SelfActions { class ACE_Equipment { - class ACE_UnJam { + class GVAR(UnJam) { displayName = CSTRING(UnjamWeapon); - condition = QUOTE( [_player] call FUNC(canUnjam) ); + condition = QUOTE( GVAR(enabled) && {[_player] call FUNC(canUnjam)} ); exceptions[] = {"isNotInside", "isNotSitting"}; statement = QUOTE( [ARR_2(_player, currentMuzzle _player)] call FUNC(clearJam); ); showDisabled = 0; priority = 4; icon = QUOTE(PATHTOF(UI\unjam_ca.paa)); }; - class ACE_SwapBarrel { + class GVAR(SwapBarrel) { displayName = CSTRING(SwapBarrel); - condition = QUOTE( 'ACE_SpareBarrel' in items _player && {getNumber (configFile >> 'CfgWeapons' >> currentWeapon _player >> 'ACE_Overheating_allowSwapBarrel') == 1} ); - statement = QUOTE( [ARR_2(_player, currentWeapon _player)] call FUNC(swapBarrel); ); + condition = QUOTE( GVAR(enabled) && {'ACE_SpareBarrel' in magazines _player} && {getNumber (configFile >> 'CfgWeapons' >> currentWeapon _player >> 'ACE_Overheating_allowSwapBarrel') == 1} ); + statement = QUOTE( [ARR_3(_player, _player, currentWeapon _player)] call FUNC(swapBarrel); ); showDisabled = 0; priority = 3; icon = QUOTE(PATHTOF(UI\spare_barrel_ca.paa)); }; - class ACE_CheckTemperature { + class GVAR(CheckTemperature) { displayName = CSTRING(CheckTemperatureShort); - condition = "switch (currentWeapon _player) do {case (''): {false}; case (primaryWeapon _player); case (secondaryWeapon _player); case (handgunWeapon _player): {true}; default {false}}"; + condition = "ace_overheating_enabled && {switch (currentWeapon _player) do {case (''): {false}; case (primaryWeapon _player); case (handgunWeapon _player): {true}; default {false}}}"; exceptions[] = {"isNotInside", "isNotSitting"}; - statement = QUOTE( [ARR_2(_player, currentWeapon _player)] call FUNC(CheckTemperature); ); + statement = QUOTE( [ARR_3(_player, _player, currentWeapon _player)] call FUNC(checkTemperature); ); showDisabled = 0; priority = 2.9; icon = QUOTE(PATHTOF(UI\temp_ca.paa)); }; + class GVAR(CheckTemperatureSpareBarrels) { + displayName = CSTRING(CheckTemperatureSpareBarrelsShort); + condition = QUOTE( GVAR(enabled) && {'ACE_SpareBarrel' in magazines _player}); + exceptions[] = {"isNotInside", "isNotSitting"}; + statement = QUOTE( [_player] call FUNC(checkSpareBarrelsTemperatures); ); + showDisabled = 0; + priority = 2.8; + icon = QUOTE(PATHTOF(UI\temp_ca.paa)); + }; + }; + }; + + class ACE_Actions { + class ACE_Weapon { + class GVAR(SwapBarrel) { + displayName = CSTRING(SwapBarrel); + condition = QUOTE( GVAR(enabled) && {'ACE_SpareBarrel' in magazines _player} && {getNumber (configFile >> 'CfgWeapons' >> currentWeapon _target >> 'ACE_Overheating_allowSwapBarrel') == 1} ); + statement = QUOTE([ARR_3(_player, _target, currentWeapon _target)] call FUNC(swapBarrelAssistant);); + icon = QUOTE(PATHTOF(UI\spare_barrel_ca.paa)); + }; + class GVAR(CheckTemperature) { + displayName = CSTRING(CheckTemperatureShort); + condition = "ace_overheating_enabled && {switch (currentWeapon _target) do {case (''): {false}; case (primaryWeapon _target); case (handgunWeapon _target): {true}; default {false}}}"; + exceptions[] = {"isNotInside", "isNotSitting"}; + statement = QUOTE( [ARR_3(_player, _target, currentWeapon _target)] call FUNC(checkTemperature); ); + icon = QUOTE(PATHTOF(UI\temp_ca.paa)); + }; }; }; }; diff --git a/addons/overheating/CfgWeapons.hpp b/addons/overheating/CfgWeapons.hpp index f59c4d7911..c7a83eec6e 100644 --- a/addons/overheating/CfgWeapons.hpp +++ b/addons/overheating/CfgWeapons.hpp @@ -2,17 +2,6 @@ class CfgWeapons { class ACE_ItemCore; class InventoryItem_Base_F; - class ACE_SpareBarrel: ACE_ItemCore { - displayname = CSTRING(SpareBarrelName); - descriptionshort = CSTRING(SpareBarrelDescription); - //model = ""; - picture = QUOTE(PATHTOF(UI\spare_barrel_ca.paa)); - scope = 2; - class ItemInfo: InventoryItem_Base_F { - mass = 30; - }; - }; - class RifleCore; class Rifle: RifleCore { //Mean Rounds Between Stoppages (this will be scaled based on the barrel temp) diff --git a/addons/overheating/XEH_PREP.hpp b/addons/overheating/XEH_PREP.hpp index 312b8bb0c5..44fd931ca0 100644 --- a/addons/overheating/XEH_PREP.hpp +++ b/addons/overheating/XEH_PREP.hpp @@ -1,5 +1,7 @@ +PREP(calculateCooling); PREP(canUnjam); +PREP(checkSpareBarrelsTemperatures); PREP(checkTemperature); PREP(clearJam); PREP(displayTemperature); @@ -7,8 +9,12 @@ PREP(firedEH); PREP(getWeaponData); PREP(handleTakeEH); PREP(jamWeapon); +PREP(loadCoolestSpareBarrel); PREP(overheat); +PREP(sendSpareBarrelsTemperaturesHint); PREP(swapBarrel); +PREP(swapBarrelAssistant); PREP(swapBarrelCallback); +PREP(updateSpareBarrelsTemperaturesThread); PREP(updateTemperature); PREP(updateTemperatureThread); diff --git a/addons/overheating/XEH_postInit.sqf b/addons/overheating/XEH_postInit.sqf index 0bb2da22ca..e4935b8831 100644 --- a/addons/overheating/XEH_postInit.sqf +++ b/addons/overheating/XEH_postInit.sqf @@ -1,47 +1,69 @@ // by esteldunedain #include "script_component.hpp" -if (isServer) then { - GVAR(pseudoRandomList) = []; - // Construct a list of pseudo random 2D vectors - for "_i" from 0 to 30 do { - GVAR(pseudoRandomList) pushBack [-1 + random 2, -1 + random 2]; - }; - publicVariable QGVAR(pseudoRandomList); +if (hasInterface) then { + // Add keybinds + ["ACE3 Weapons", QGVAR(unjamWeapon), localize LSTRING(UnjamWeapon), + { + // Conditions: canInteract + if !([ACE_player, objNull, ["isNotInside"]] call EFUNC(common,canInteractWith)) exitWith {false}; + // Conditions: specific + + if !(GVAR(enabled) && {[ACE_player] call FUNC(canUnjam)}) exitWith {false}; + + // Statement + [ACE_player, currentMuzzle ACE_player, false] call FUNC(clearJam); + true + }, + {false}, + [19, [true, false, false]], false] call CBA_fnc_addKeybind; //SHIFT + R Key }; - -if !(hasInterface) exitWith {}; - -GVAR(cacheWeaponData) = call CBA_fnc_createNamespace; -GVAR(cacheAmmoData) = call CBA_fnc_createNamespace; -GVAR(cacheSilencerData) = call CBA_fnc_createNamespace; - -// Add keybinds -["ACE3 Weapons", QGVAR(unjamWeapon), localize LSTRING(UnjamWeapon), -{ - // Conditions: canInteract - if !([ACE_player, objNull, ["isNotInside"]] call EFUNC(common,canInteractWith)) exitWith {false}; - // Conditions: specific - - if !([ACE_player] call FUNC(canUnjam)) exitWith {false}; - - // Statement - [ACE_player, currentMuzzle ACE_player, false] call FUNC(clearJam); - true -}, -{false}, -[19, [true, false, false]], false] call CBA_fnc_addKeybind; //SHIFT + R Key - - -// Schedule cool down calculation of player weapons at (infrequent) regular intervals -[] call FUNC(updateTemperatureThread); - ["SettingsInitialized", { + TRACE_1("SettingsInitialized eh", GVAR(enabled)); + if (!GVAR(enabled)) exitWith {}; + + if (isServer) then { + GVAR(pseudoRandomList) = []; + // Construct a list of pseudo random 2D vectors + for "_i" from 0 to 30 do { + GVAR(pseudoRandomList) pushBack [-1 + random 2, -1 + random 2]; + }; + publicVariable QGVAR(pseudoRandomList); + + // Keep track of the temperature of stored spare barrels + GVAR(storedSpareBarrels) = [] call CBA_fnc_hashCreate; + + // Install event handlers for spare barrels + ["spareBarrelsSendTemperatureHint", FUNC(sendSpareBarrelsTemperaturesHint)] call EFUNC(common,addEventHandler); + ["spareBarrelsLoadCoolest", FUNC(loadCoolestSpareBarrel)] call EFUNC(common,addEventHandler); + + // Schedule cool down calculation of stored spare barrels + [] call FUNC(updateSpareBarrelsTemperaturesThread); + }; + + if !(hasInterface) exitWith {}; + + GVAR(cacheWeaponData) = call CBA_fnc_createNamespace; + GVAR(cacheAmmoData) = call CBA_fnc_createNamespace; + GVAR(cacheSilencerData) = call CBA_fnc_createNamespace; + + //Add Take EH (for reload) + ["CAManBase", "Take", {_this call FUNC(handleTakeEH);}] call CBA_fnc_addClassEventHandler; + // Register fire event handler ["firedPlayer", DFUNC(firedEH)] call EFUNC(common,addEventHandler); // Only add eh to non local players if dispersion is enabled if (GVAR(overheatingDispersion)) then { ["firedPlayerNonLocal", DFUNC(firedEH)] call EFUNC(common,addEventHandler); }; + + // Schedule cool down calculation of player weapons at (infrequent) regular intervals + [] call FUNC(updateTemperatureThread); + + // Install event handler to display temp when a barrel was swapped + ["showWeaponTemperature", DFUNC(displayTemperature)] call EFUNC(common,addEventHandler); + // Install event handler to initiate an assisted barrel swap + ["initiateSwapBarrelAssisted", DFUNC(swapBarrel)] call EFUNC(common,addEventHandler); + }] call EFUNC(common,addEventHandler); diff --git a/addons/overheating/XEH_preInit.sqf b/addons/overheating/XEH_preInit.sqf index a7feade1c3..cdd1fa78dd 100644 --- a/addons/overheating/XEH_preInit.sqf +++ b/addons/overheating/XEH_preInit.sqf @@ -4,4 +4,16 @@ ADDON = false; #include "XEH_PREP.hpp" +if (isNil "CBA_fnc_getMagazineIndex") then { + CBA_fnc_getMagazineIndex = { + params [["_unit", objNull, [objNull]], ["_magazine", "", [""]]]; + + private _displayName = getText (configFile >> "CfgMagazines" >> _magazine >> "displayName"); + + if (_displayName isEqualTo "") exitWith {[]}; + + (magazinesDetail _unit select {_x find _displayName == 0}) apply {_x = _x splitString "[:]"; _x select (count _x - 1)}; + }; +}; + ADDON = true; diff --git a/addons/overheating/config.cpp b/addons/overheating/config.cpp index c57e55913d..673edcf77f 100644 --- a/addons/overheating/config.cpp +++ b/addons/overheating/config.cpp @@ -18,6 +18,8 @@ class CfgPatches { #include "CfgVehicles.hpp" +#include "CfgMagazines.hpp" + #include "CfgWeapons.hpp" #include "ACE_Settings.hpp" diff --git a/addons/overheating/functions/fnc_calculateCooling.sqf b/addons/overheating/functions/fnc_calculateCooling.sqf new file mode 100644 index 0000000000..955c41441e --- /dev/null +++ b/addons/overheating/functions/fnc_calculateCooling.sqf @@ -0,0 +1,58 @@ +/* + * Author: esteldunedain + * Calculate the cooling down of a weapon over a time interval. + * + * Argument: + * 0: Initial temperature + * 1: Barrel mass + * 2: Time interval + * + * Return value: + * Final temperature + * + * Example: + * [_temperature, _barrelMass, _totalTime] call ace_overheating_fnc_calculateCooling + * + * Public: No + */ +#include "script_component.hpp" + +params ["_temperature", "_barrelMass", "_totalTime"]; + +// If a long time passed since the last shot, there's no need to calculate anything; the weapon should be cool +if (_totalTime > 1800) exitWith {0}; + +//AR-15 (0.00570m bullet diameter) (barrel diameter usually 0.75" or 0.008255m radius) +//Steel Denisty = 7850 m^3 / kg +//Area of a cylinder (2/r)*(Pi * r^3 + V) - for a 0.008255m radius barrel -> Area = 210(1/meters) * Volume +//Adjusted volume for being hollowed out is ~1.1x +//So Area = 210 * 1.1 * (mass / 7850) = mass * 0.029427 (for steel near that diameter) + +private _barrelSurface = _barrelMass * 0.029427; + +TRACE_4("cooling",_temperature,_totalTime,_barrelMass,_barrelSurface); + +private _time = 0; +while {true} do { + private _deltaTime = (_totalTime - _time) min 20; + + _temperature = _temperature - ( + // Convective cooling + 25 * _barrelSurface * _temperature + // Radiative cooling + + 0.4 * 5.67e-8 * _barrelSurface * + ( (_temperature + 273.15)*(_temperature + 273.15) + * (_temperature + 273.15)*(_temperature + 273.15) + - 273.15 * 273.15 * 273.15 *273.15 ) + ) * _deltaTime / (_barrelMass * 466); + + if (_temperature < 1) exitWith {0}; + + if (isNil "_temperature") exitWith { + diag_log text format ["[ACE] ERROR: _totalTime = %1; _time = %2; _deltaTime = %3;", _totalTime, _time, _deltaTime]; + 0 + }; + + _time = _time + _deltaTime; + if (_time >= _totalTime) exitWith { _temperature max 0 }; +}; diff --git a/addons/overheating/functions/fnc_checkSpareBarrelsTemperatures.sqf b/addons/overheating/functions/fnc_checkSpareBarrelsTemperatures.sqf new file mode 100644 index 0000000000..e8dbaabec0 --- /dev/null +++ b/addons/overheating/functions/fnc_checkSpareBarrelsTemperatures.sqf @@ -0,0 +1,38 @@ +/* + * Author: esteldunedain + * Make the player check the temperature of his spare barrels + * + * Arguments: + * 0: Player + * + * Return Value: + * None + * + * + * Public: No + */ +#include "script_component.hpp" + +params ["_player"]; + +// Check canInteractWith: +if (!([_player, objNull, ["isNotInside", "isNotSitting"]] call EFUNC(common,canInteractWith))) exitWith {}; + +// Make the unit go kneeling +[_player] call EFUNC(common,goKneeling); + +// Spawn a progress bar +[ + 5.0, + [_player], + { + params ["_args", "_elapsedTime", "_totalTime", "_errorCode"]; + _args params ["_player"]; + // Time has enlapsed, ask the server to send the hint + ['spareBarrelsSendTemperatureHint', [_player, _player]] call EFUNC(common,serverEvent); + }, + {}, + (localize LSTRING(CheckingSpareBarrelsTemperatures)), + {true}, + ["isNotInside", "isNotSitting"] +] call EFUNC(common,progressBar); diff --git a/addons/overheating/functions/fnc_checkTemperature.sqf b/addons/overheating/functions/fnc_checkTemperature.sqf index f720665620..fd2ac5f56c 100644 --- a/addons/overheating/functions/fnc_checkTemperature.sqf +++ b/addons/overheating/functions/fnc_checkTemperature.sqf @@ -3,8 +3,9 @@ * Make the player check the temperature of his weapon * * Arguments: - * 0: Player - * 1: Weapon + * 0: Unit checking + * 1: Unit that has the weapon + * 2: Weapon * * Return Value: * None @@ -16,17 +17,18 @@ */ #include "script_component.hpp" -params ["_player", "_weapon"]; -TRACE_2("params",_player,_weapon); +params ["_assistant", "_gunner", "_weapon"]; +TRACE_3("params",_assistant,_gunner,_weapon); // Play animation and report temperature -private _action = getText (configFile >> "CfgWeapons" >> _weapon >> "ACE_checkTemperatureAction"); - -if (_action == "") then { - _action = "Gear"; +private _action = "PutDown"; +if (_assistant isEqualTo _gunner) then { + _action = getText (configFile >> "CfgWeapons" >> _weapon >> "ACE_checkTemperatureAction"); + if (_action == "") then { + _action = "Gear"; + }; }; - -_player playActionNow _action; +_assistant playActionNow _action; // Waits a sec before displaying the temperature -[FUNC(displayTemperature), [_player, _weapon], 1.0] call EFUNC(common,waitAndExecute); +[FUNC(displayTemperature), [_gunner, _weapon], 1.0] call EFUNC(common,waitAndExecute); diff --git a/addons/overheating/functions/fnc_loadCoolestSpareBarrel.sqf b/addons/overheating/functions/fnc_loadCoolestSpareBarrel.sqf new file mode 100644 index 0000000000..08cb85083c --- /dev/null +++ b/addons/overheating/functions/fnc_loadCoolestSpareBarrel.sqf @@ -0,0 +1,53 @@ +/* + * Author: esteldunedain + * Collect the temperature of all the spare barrels a unit has and load the + * coolest on the unit weapon. Runs on the server. + * + * Argument: + * 0: Unit that has the spare barrels + * 1: Unit that has the weapon + * 2: Weapon + * 3: Weapon temp before switching + * 4: Mass of the removed barrel + * + * Return value: + * None + * + * + * Public: No + */ +#include "script_component.hpp" + +params ["_assistant", "_gunner", "_weapon", "_weaponTemp", "_barrelMass"]; +TRACE_5("loadCoolestSpareBarrel1",_assistant,_gunner,_weapon,_weaponTemp,_barrelMass); + +// Find all spare barrel the player has +private _allBarrels = [_assistant, "ACE_SpareBarrel"] call CBA_fnc_getMagazineIndex; +TRACE_1("_allBarrels",_allBarrels); +if ((count _allBarrels) < 1) exitWith {}; + +// Determine which on is coolest +private _coolestTemp = 10000; +private _coolestMag = _allBarrels select 0; +{ + private _temp = 0; + if ([GVAR(storedSpareBarrels), _x] call CBA_fnc_hashHasKey) then { + _temp = ([GVAR(storedSpareBarrels), _x] call CBA_fnc_hashGet) select 0; + }; + TRACE_2("loadCoolestSpareBarrel4",_x,_temp); + if (_temp < _coolestTemp) then { + _coolestTemp = _temp; + _coolestMag = _x; + }; +} forEach _allBarrels; +TRACE_3("loadCoolestSpareBarrel5",_coolestTemp,_coolestMag,_weaponTemp); + +// The new weapon temperature is similar to the coolest barrel +// Publish the new temperature value +_gunner setVariable [format [QGVAR(%1_temp), _weapon], _coolestTemp, true]; + +// Heat up the coolest barrel to the former weapon temperature +[GVAR(storedSpareBarrels), _coolestMag, [_weaponTemp, ACE_Time, _barrelMass]] call CBA_fnc_hashSet; + +// Send an event so the machines of the assistant and gunner can show the hint +["showWeaponTemperature", [_assistant, _gunner], [_gunner, _weapon]] call EFUNC(common,targetEvent); diff --git a/addons/overheating/functions/fnc_sendSpareBarrelsTemperaturesHint.sqf b/addons/overheating/functions/fnc_sendSpareBarrelsTemperaturesHint.sqf new file mode 100644 index 0000000000..2ff248016d --- /dev/null +++ b/addons/overheating/functions/fnc_sendSpareBarrelsTemperaturesHint.sqf @@ -0,0 +1,76 @@ +/* + * Author: esteldunedain + * Collect the temperature of all the spare barrels a unit has and send a hint + * to a client. Runs on the server. + * + * Argument: + * 0: Target unit of the hint + * 1: Unit that has the spare barrels + * + * Return value: + * None + * + * + * Public: No + */ +#include "script_component.hpp" + +params ["_player","_unit"]; + +// Find all spare barrel the player has +TRACE_2("sendSpareBarrelsTemperatureHunt",_player,_unit); +private _allBarrels = [_unit, "ACE_SpareBarrel"] call CBA_fnc_getMagazineIndex; +TRACE_1("_allBarrels",_allBarrels); +if ((count _allBarrels) < 1) exitWith {}; + +// Determine the temp of each barrel +private _temps = []; +{ + private _temp = 0; + if ([GVAR(storedSpareBarrels), _x] call CBA_fnc_hashHasKey) then { + _temp = ([GVAR(storedSpareBarrels), _x] call CBA_fnc_hashGet) select 0; + }; + _temps pushBack _temp; +} forEach _allBarrels; +TRACE_1("_temps",_temps); + +// Count cool +private _countCool = {_x < 20} count _temps; +private _countWarm = {(_x >= 20) && (_x < 100)} count _temps; +private _countHot = {(_x >= 100) && (_x < 200)} count _temps; +private _countVeryHot = {(_x >= 200) && (_x < 600)} count _temps; +private _countExtremelyHot = {_x >= 600} count _temps; +private _output = ["%1 %2%3%4 %5%6%7 %8%9%10 %11%12%13 %14"]; +private _size = 1.0; +if (_countCool > 0) then { + _output pushBack _countCool; + _output pushBack LSTRING(BarrelCool); + _output pushBack "
"; + _size = _size + 0.5; +}; +if (_countWarm > 0) then { + _output pushBack _countWarm; + _output pushBack LSTRING(BarrelWarm); + _output pushBack "
"; + _size = _size + 0.5; +}; +if (_countHot > 0) then { + _output pushBack _countHot; + _output pushBack LSTRING(BarrelHot); + _output pushBack "
"; + _size = _size + 0.5; +}; +if (_countVeryHot > 0) then { + _output pushBack _countVeryHot; + _output pushBack LSTRING(BarrelVeryHot); + _output pushBack "
"; + _size = _size + 0.5; +}; +if (_countExtremelyHot > 0) then { + _output pushBack _countExtremelyHot; + _output pushBack LSTRING(BarrelExtremelyHot); + _size = _size + 0.5; +}; + +TRACE_1("_output",_output); +["displayTextStructured", [_player], [_output, _size, _player]] call EFUNC(common,targetEvent); diff --git a/addons/overheating/functions/fnc_swapBarrel.sqf b/addons/overheating/functions/fnc_swapBarrel.sqf index bbdab91705..a63ef5a36a 100644 --- a/addons/overheating/functions/fnc_swapBarrel.sqf +++ b/addons/overheating/functions/fnc_swapBarrel.sqf @@ -3,29 +3,35 @@ * Make a unit start swapping it's barrel * * Argument: - * 0: Unit - * 1: Weapon + * 0: Unit initiating the action + * 1: Unit that has the weapon + * 2: Weapon * * Return value: * None * * Example: - * [player, currentWeapon player] call ace_overheating_fnc_swapBarrel + * [cursorTarget, player, currentWeapon player] call ace_overheating_fnc_swapBarrel * * Public: No */ #include "script_component.hpp" -params ["_player", "_weapon"]; -TRACE_2("params",_player,_weapon); +params ["_assistant", "_gunner", "_weapon"]; +TRACE_3("params",_assistant,_gunner,_weapon); // Make the standing player kneel down -if (stance _player != "PRONE") then { - [_player, "amovpknlmstpsraswrfldnon", 1] call EFUNC(common,doAnimation); +if (stance _gunner != "PRONE") then { + [_gunner, "amovpknlmstpsraswrfldnon", 1] call EFUNC(common,doAnimation); }; // Barrel dismount gesture -_player playActionNow QGVAR(GestureDismountMuzzle); +_gunner playActionNow QGVAR(GestureDismountMuzzle); playSound "ACE_BarrelSwap"; -[5, [_player, _weapon], {(_this select 0) call FUNC(swapBarrelCallback)}, {}, (localize LSTRING(SwappingBarrel))] call EFUNC(common,progressBar); +private _duration = 3.0; +if (_assistant isEqualTo _gunner) then { + _duration = 5.0; +}; + +[_duration, [_assistant,_gunner,_weapon], {(_this select 0) call FUNC(swapBarrelCallback)}, {}, (localize LSTRING(SwappingBarrel))] call EFUNC(common,progressBar); diff --git a/addons/overheating/functions/fnc_swapBarrelAssistant.sqf b/addons/overheating/functions/fnc_swapBarrelAssistant.sqf new file mode 100644 index 0000000000..5e3c31fc5e --- /dev/null +++ b/addons/overheating/functions/fnc_swapBarrelAssistant.sqf @@ -0,0 +1,33 @@ +/* + * Author: esteldunedain, Commy2 + * Make a unit start swapping the barrel of another unit + * + * Argument: + * 0: Unit initiating the action + * 1: Unit that has the weapon + * 2: Weapon + * + * Return value: + * None + * + * Example: + * [player, cursorTarget, currentWeapon cursorTarget] call ace_overheating_fnc_swapBarrelAssistant + * + * Public: No + */ +#include "script_component.hpp" + +params ["_assistant", "_gunner", "_weapon"]; +TRACE_3("params",_assistant,_gunner,_weapon); + +// Make the standing player kneel down +if (stance _assistant != "PRONE") then { + [_assistant, "amovpknlmstpsraswrfldnon", 1] call EFUNC(common,doAnimation); +}; + +// Barrel dismount gesture +playSound "ACE_BarrelSwap"; + +[3, [_assistant, _gunner, _weapon], {}, {}, (localize LSTRING(SwappingBarrel))] call EFUNC(common,progressBar); + +["initiateSwapBarrelAssisted", _gunner, [_assistant, _gunner, _weapon]] call EFUNC(common,objectEvent); diff --git a/addons/overheating/functions/fnc_swapBarrelCallback.sqf b/addons/overheating/functions/fnc_swapBarrelCallback.sqf index 9c62e77f21..403989deca 100644 --- a/addons/overheating/functions/fnc_swapBarrelCallback.sqf +++ b/addons/overheating/functions/fnc_swapBarrelCallback.sqf @@ -1,10 +1,11 @@ /* - * Author: Commy2 + * Author: Commy2, esteldunedain * Swap barrel callback * * Argument: - * 0: Unit - * 1: Weapon + * 0: Unit initiating the action + * 1: Unit that has the weapon + * 2: Weapon * * Return value: * None @@ -14,19 +15,26 @@ * * Public: No */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -params ["_player", "_weapon"]; -TRACE_2("params",_player,_weapon); +params ["_assistant", "_gunner", "_weapon"]; +TRACE_3("params",_assistant,_gunner,_weapon); -// Barrel mount gesture -_player playAction QGVAR(GestureMountMuzzle); -playSound "ACE_BarrelSwap"; +if (_assistant isEqualTo _gunner) then { + // Barrel mount gesture + _gunner playAction QGVAR(GestureMountMuzzle); + playSound "ACE_BarrelSwap"; +}; -// don't consume the barrel, but rotate through them. -[localize LSTRING(SwappedBarrel), QUOTE(PATHTOF(UI\spare_barrel_ca.paa))] call EFUNC(common,displayTextPicture); +private _temp = _gunner getVariable [format [QGVAR(%1_temp), _weapon], 0]; +private _barrelMass = 0.50 * (getNumber (configFile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "mass") / 22.0) max 1.0; + +// Instruct the server to load the coolest spare barrel into the weapon and +// store the removed barrel with the former weapon temperature. The server +// also updates the current weapon temperature to match that of the new +// loaded barrel. +["spareBarrelsLoadCoolest", [_assistant, _gunner, _weapon, _temp, _barrelMass]] call EFUNC(common,serverEvent); -// Publish the temperature variable -_player setVariable [format [QGVAR(%1_temp), _weapon], 0, true]; // Store the update time -_player setVariable [format [QGVAR(%1_time), _weapon], ACE_time]; +_gunner setVariable [format [QGVAR(%1_time), _weapon], ACE_time]; diff --git a/addons/overheating/functions/fnc_updateSpareBarrelsTemperaturesThread.sqf b/addons/overheating/functions/fnc_updateSpareBarrelsTemperaturesThread.sqf new file mode 100644 index 0000000000..d6b74f6769 --- /dev/null +++ b/addons/overheating/functions/fnc_updateSpareBarrelsTemperaturesThread.sqf @@ -0,0 +1,40 @@ +/* + * Author: esteldunedain + * Calculate cooldown of all the stored spare barrels. + * + * Argument: + * None + * + * Return value: + * None + * + * Example: + * [] call ace_overheating_fnc_updateSpareBarrelsTemperaturesThread + * + * Public: No + */ +// #define DEBUG_MODE_FULL +#include "script_component.hpp" + +private _pairs = []; +TRACE_1("updateSpareBarrelsTemperaturesThread1",GVAR(storedSpareBarrels)); +[GVAR(storedSpareBarrels), {_pairs pushBack [_key, _value];}] call CBA_fnc_hashEachPair; +TRACE_1("updateSpareBarrelsTemperaturesThread2",_pairs); +{ + _x params ["_barrelMagazineID","_value"]; + _value params ["_initialTemp","_initialTime", "_barrelMass"]; + + // Calculate cooling + private _finalTemp = [_initialTemp, _barrelMass, ACE_time - _initialTime] call FUNC(calculateCooling); + TRACE_4("updateSpareBarrelsTemperaturesThread3",_barrelMagazineID,_initialTemp,_finalTemp,_barrelMass); + if (_finalTemp < 5) then { + // The barrel is cool enough to keep calculating. Remove it from the hash + [GVAR(storedSpareBarrels), _barrelMagazineID] call CBA_fnc_hashRem; + } else { + // Store the new temp + [GVAR(storedSpareBarrels), _barrelMagazineID, [_finalTemp, ACE_time, _barrelMass]] call CBA_fnc_hashSet; + }; +} forEach _pairs; + +// Schedule for execution again after 10 seconds +[DFUNC(updateSpareBarrelsTemperaturesThread), [], 10] call EFUNC(common,waitAndExecute); diff --git a/addons/overheating/functions/fnc_updateTemperature.sqf b/addons/overheating/functions/fnc_updateTemperature.sqf index 89d5975024..1643fe55b4 100644 --- a/addons/overheating/functions/fnc_updateTemperature.sqf +++ b/addons/overheating/functions/fnc_updateTemperature.sqf @@ -29,50 +29,8 @@ private _lastTime = _unit getVariable [_timeVarName, 0]; private _barrelMass = 0.50 * (getNumber (configFile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "mass") / 22.0) max 1.0; -_fnc_cooling = { - params ["_temperature", "_barrelMass", "_totalTime"]; - - // If a long time passed since the last shot, there's no need to calculate anything; the weapon should be cool - if (_totalTime > 1800) exitWith {0}; - - //AR-15 (0.00570m bullet diameter) (barrel diameter usually 0.75" or 0.008255m radius) - //Steel Denisty = 7850 m^3 / kg - //Area of a cylinder (2/r)*(Pi * r^3 + V) - for a 0.008255m radius barrel -> Area = 210(1/meters) * Volume - //Adjusted volume for being hollowed out is ~1.1x - //So Area = 210 * 1.1 * (mass / 7850) = mass * 0.029427 (for steel near that diameter) - - private _barrelSurface = _barrelMass * 0.029427; - - TRACE_4("cooling",_temperature,_totalTime,_barrelMass,_barrelSurface); - - private _time = 0; - while {true} do { - private _deltaTime = (_totalTime - _time) min 20; - - _temperature = _temperature - ( - // Convective cooling - 25 * _barrelSurface * _temperature - // Radiative cooling - + 0.4 * 5.67e-8 * _barrelSurface * - ( (_temperature + 273.15)*(_temperature + 273.15) - * (_temperature + 273.15)*(_temperature + 273.15) - - 273.15 * 273.15 * 273.15 *273.15 ) - ) * _deltaTime / (_barrelMass * 466); - - if (_temperature < 1) exitWith {0}; - - if (isNil "_temperature") exitWith { - diag_log text format ["[ACE] ERROR: _totalTime = %1; _time = %2; _deltaTime = %3;", _totalTime, _time, _deltaTime]; - 0 - }; - - _time = _time + _deltaTime; - if (_time >= _totalTime) exitWith { _temperature max 0 }; - }; -}; - // Calculate cooling -_temperature = [_temperature, _barrelMass, ACE_time - _lastTime] call _fnc_cooling; +_temperature = [_temperature, _barrelMass, ACE_time - _lastTime] call FUNC(calculateCooling); TRACE_1("cooledTo",_temperature); // Calculate heating // Steel Heat Capacity = 466 J/(Kg.K) diff --git a/addons/overheating/stringtable.xml b/addons/overheating/stringtable.xml index abbf9533e7..e49ad433fc 100644 --- a/addons/overheating/stringtable.xml +++ b/addons/overheating/stringtable.xml @@ -251,6 +251,12 @@ Sto controllando la temperatura... Проверка температуры... + + Check spare barrels temperatures + + + Checking spare barrels temperatures... + Temperature Temperatur @@ -263,5 +269,28 @@ Temperatura Температура + + Cool Spare Barrel/s + + + Warm Spare Barrel/s + + + Hot Spare Barrel/s + + + Very Hot Spare Barrel/s + + + Extremely Hot Spare Barrel/s + + + Overheating Enabled + Überhitzen Aktiviert + Activada Sobrecalentamiento + + + Master enable for the overheating/jamming module + \ No newline at end of file