Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overheating - Fix issues from release #8617

Merged
merged 25 commits into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
292a9b8
move overheating cookoff into separate function
Drofseh Oct 25, 2021
78a9726
move heatCoef and require mission restart for setting change
Drofseh Oct 25, 2021
409b5a8
add exit to ammo temp loop if cookoffCoef is changed to 0 mid-mission
Drofseh Oct 25, 2021
264885d
file end new line
Drofseh Oct 25, 2021
51385df
update header for ace_overheating_fnc_cookoffWeapon
Drofseh Oct 25, 2021
cc6c353
use ambientTemperature as floor for weapon and ammo temp
Drofseh Oct 25, 2021
d6a4900
add coolingCoef setting
Drofseh Oct 25, 2021
4800c61
improve feature documentation
Drofseh Oct 25, 2021
18a4cf5
add fnc_cookoffWeapon to XEH_PREP
Drofseh Oct 26, 2021
c60ab9a
add type of jam to ace_weaponJammed local event
Drofseh Oct 27, 2021
654c1d1
fix misspelling
Drofseh Oct 28, 2021
1ceb513
clear all weapon heat on death
Drofseh Oct 28, 2021
5364e69
Update addons/overheating/functions/fnc_updateTemperature.sqf
Drofseh Oct 30, 2021
14822ba
deprecate ace_overheating_fnc_getBarrelMass, cache weapon bolt and ba…
Drofseh Oct 30, 2021
b48424c
add public functions to get and set weapon and ammo temperature
Drofseh Oct 31, 2021
9733822
Merge branch 'master' into overheating-adjustments
Drofseh Oct 31, 2021
3418448
add `canCoolWeaponWithItem` function, workaround for #8657
Drofseh Nov 1, 2021
77199dc
Apply suggestions from code review
Drofseh Nov 3, 2021
5ef3945
add coef setting for addition heat from suppressor
Drofseh Nov 3, 2021
132fb6b
Update fnc_overheat.sqf
Drofseh Nov 3, 2021
69a903f
improve fnc_canCoolWeaponWithItem
Drofseh Nov 6, 2021
8c6ed26
remove extra (
Drofseh Nov 6, 2021
f82ae7a
Move canCoolWeaponWithItem action code to function
PabstMirror Nov 7, 2021
53f4085
Use hashmaps and reset on settings change
PabstMirror Nov 7, 2021
e807650
Apply suggestions from code review
Drofseh Nov 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions addons/overheating/CfgVehicles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class CfgVehicles {
};
class GVAR(CoolWeaponWithItem) {
displayName = CSTRING(CoolWeaponWithItem);
condition = QUOTE(GVAR(enabled) && {isClass (configfile >> 'CfgPatches' >> 'acex_field_rations')});
condition = QUOTE(call FUNC(canCoolWeaponWithItem));
exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"};
statement = "true";
showDisabled = 0;
Expand Down Expand Up @@ -66,7 +66,7 @@ class CfgVehicles {
};
class GVAR(CoolWeaponWithItem) {
displayName = CSTRING(CoolWeaponWithItem);
condition = QUOTE(GVAR(enabled) && {isClass (configfile >> 'CfgPatches' >> 'acex_field_rations')});
condition = QUOTE(call FUNC(canCoolWeaponWithItem));
exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"};
statement = "true";
showDisabled = 0;
Expand Down
5 changes: 5 additions & 0 deletions addons/overheating/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@ PREP(canCheckSpareBarrelsTemperatures);
PREP(checkSpareBarrelsTemperatures);
PREP(checkTemperature);
PREP(clearJam);
PREP(cookoffWeapon);
PREP(coolWeaponWithItem);
PREP(coolWeaponWithWaterSource);
PREP(displayTemperature);
PREP(firedEH);
PREP(getAmmoTemperature);
PREP(getBarrelMass);
PREP(getConsumableChildren);
PREP(getWeaponData);
PREP(getWeaponTemperature);
PREP(handleTakeEH);
PREP(handleRespawn);
PREP(jamWeapon);
PREP(loadCoolestSpareBarrel);
PREP(overheat);
PREP(sendSpareBarrelsTemperaturesHint);
PREP(setAmmoTemperature);
PREP(setWeaponTemperature);
PREP(swapBarrel);
PREP(swapBarrelAssistant);
PREP(swapBarrelCallback);
Expand Down
17 changes: 13 additions & 4 deletions addons/overheating/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ if (hasInterface) then {

if !(hasInterface) exitWith {};

GVAR(cacheWeaponData) = call CBA_fnc_createNamespace;
GVAR(cacheAmmoData) = call CBA_fnc_createNamespace;
GVAR(cacheSilencerData) = call CBA_fnc_createNamespace;
GVAR(cacheWeaponData) = createHashMap;
GVAR(cacheAmmoData) = createHashMap;
GVAR(cacheSilencerData) = createHashMap;

//Add Take EH if required
if (GVAR(unJamOnReload) || {GVAR(cookoffCoef) > 0}) then {
Expand Down Expand Up @@ -76,8 +76,18 @@ if (hasInterface) then {
}] call CBA_fnc_addClassEventHandler;
};

// Reset all weapon heat to ambient on death to prevent cookoffs when a unit respawns.
["CAManBase", "Killed", {
params ["_unit"];
{
_unit setVariable [_x, ambientTemperature select 0];
} forEach (_unit getVariable [QGVAR(trackedWeapons), []]);
_unit setVariable [QGVAR(trackedWeapons), []];
}] call CBA_fnc_addClassEventHandler;

// Install event handler to display temp when a barrel was swapped
[QGVAR(showWeaponTemperature), DFUNC(displayTemperature)] call CBA_fnc_addEventHandler;

// Install event handler to initiate an assisted barrel swap
[QGVAR(initiateSwapBarrelAssisted), DFUNC(swapBarrel)] call CBA_fnc_addEventHandler;

Expand Down Expand Up @@ -107,5 +117,4 @@ if (hasInterface) then {
[]
] call CBA_fnc_waitUntilAndExecute;
};

}] call CBA_fnc_addEventHandler;
13 changes: 8 additions & 5 deletions addons/overheating/functions/fnc_calculateCooling.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@

params ["_temperature", "_barrelMass", "_totalTime"];

if (_temperature < 1) exitWith {0};
// The lowest temperature a weapon can reach is the ambient air temperature.
private _ambientTemperature = ambientTemperature select 0;

// 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};
if (_totalTime > 1800) exitWith {_ambientTemperature};
if (_temperature <= _ambientTemperature) exitWith {_ambientTemperature};

//AR-15 (0.00570m bullet diameter) (barrel diameter usually 0.75" or 0.008255m radius)
//Steel Denisty = 7850 m^3 / kg
Expand Down Expand Up @@ -51,15 +54,15 @@ while {true} do {
_convectionRate * _barrelSurface * _temperature
// Radiative cooling
+ 0.4 * 5.67e-8 * _barrelSurface * ((_temperature + 273.15) ^ 4 - 273.15 ^ 4)
) * _deltaTime / (_barrelMass * 466);
) * GVAR(coolingCoef) * _deltaTime / (_barrelMass * 466);

if (_temperature < 1) exitWith {0};
if (_temperature <= _ambientTemperature) exitWith {_ambientTemperature};

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 };
if (_time >= _totalTime) exitWith {_temperature max _ambientTemperature};
};
27 changes: 27 additions & 0 deletions addons/overheating/functions/fnc_canCoolWeaponWithItem.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "script_component.hpp"
/*
* Author: drofseh
* Return true if the target's weapon can be cooled with an item in the player's inventory
*
* Arguments:
* 0: Target <OBJECT>
* 1: Player <OBJECT>
*
* Return Value:
* Bool <BOOL>
*
* Example:
* [cursorObject, player] call ace_overheating_fnc_canCoolWeaponWithItem
*
* Public: No
*/

params ["_unit", "_player"];
TRACE_2("canCoolWeaponWithItem",_unit,_player);

GVAR(enabled)
&& {isClass (configfile >> "CfgPatches" >> "acex_field_rations")}
&& {!(_unit getVariable [QEGVAR(captives,isSurrendering), false])} // interaction point will overlap with ace_captives
&& {!(_unit getVariable [QEGVAR(captives,isHandcuffed), false])}
&& {[_unit, currentWeapon _unit] call FUNC(getWeaponTemperature) > (ambientTemperature select 0)}
&& {((_player call EFUNC(common,uniqueItems)) findIf {getNumber (configFile >> "CfgWeapons" >> _x >> QEXGVAR(field_rations,thirstQuenched)) > 0}) != -1}
66 changes: 66 additions & 0 deletions addons/overheating/functions/fnc_cookoffWeapon.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "script_component.hpp"
/*
* Author: drofseh
* Cookoff loaded round.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Weapon <STRING>
* 2: Is Weapon Jammed <BOOL>
* 3: Type of Jam <STRING>
*
* Return Value:
* None
*
* Example:
* [player, currentWeapon player, true, "Fire"] call ace_overheating_fnc_cookoffWeapon
*
* Public: No
*/

params ["_unit", "_weapon", "_canUnjam", "_jamType"];
TRACE_4("params",_unit,_weapon,_canUnjam,_jamType);

// a weapon with a failure to fire or dud type jam will be unjammed from cooking off
// this is first so that the fired event from the cookoff can also cause a jam
if (_canUnjam && {_jamType in ["Fire","Dud"]}) then {
[_unit, currentMuzzle _unit, true] call FUNC(clearJam);

// clearJam will remove a dud round, but so will the forced fire, so give back the lost round and shoot it
if (_jamType isEqualTo "Dud") then {
_unit setAmmo [_weapon, (_unit ammo _weapon) + 1];
};
};

// get valid mode and muzzle for the main weapon, we don't want the cookoff to come from an underbarrel launcher
([_weapon] call FUNC(getWeaponData)) params ["", "", "", "_modes", "_muzzle", "_reloadTime"];

// get an appropriate firemode and muzzle, cache the current muzzle
// trying to match firemodes and switching back to the cached muzzle will hide the change from the player and prevent unexpected mode/muzzle changes (going from full auto to semi auto, or from underbarrel GL to rifle for example)
private _muzzleCache = currentMuzzle _unit;
private _mode = currentWeaponMode _unit;
if !(_mode in _modes) then {
_mode = _modes select 0;
};

// delay cookoff to ensure any previous animation from a fired event is finished
[
{
params ["_unit", "_mode", "_muzzle", "_muzzleCache"];

// fire the cookoff
_unit forceWeaponFire [_muzzle, _mode];

// switch back to the cached muzzle if required
if (_muzzle != _muzzleCache) then {
_unit selectWeapon _muzzleCache;
};

[
[localize LSTRING(WeaponCookedOff)],
true // allows the hint to be overwritten by another hint, such as a jam or another cookoff
] call CBA_fnc_notify;
},
[_unit, _mode, _muzzle, _muzzleCache],
_reloadTime
] call CBA_fnc_waitAndExecute;
2 changes: 1 addition & 1 deletion addons/overheating/functions/fnc_coolWeaponWithItem.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private _fnc_onSuccess = {
};

// cool the weapon
private _barrelMass = _weapon call FUNC(getBarrelMass);
([_weapon] call FUNC(getWeaponData)) params ["", "", "", "", "", "", "", "_barrelMass"];
_temperature = [_temperature, _barrelMass, _liquidAmount * 10] call FUNC(calculateCooling);
[_target, _tempVarName, _temperature, TEMP_TOLERANCE] call EFUNC(common,setApproximateVariablePublic);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private _fnc_condition = {
};

//Cool the weapon down
private _barrelMass = _weapon call FUNC(getBarrelMass);
([_weapon] call FUNC(getWeaponData)) params ["", "", "", "", "", "", "", "_barrelMass"];
_temperature = [_temperature, _barrelMass, 20] call FUNC(calculateCooling);
[_player, _tempVarName, _temperature, TEMP_TOLERANCE] call EFUNC(common,setApproximateVariablePublic);

Expand Down
23 changes: 23 additions & 0 deletions addons/overheating/functions/fnc_getAmmoTemperature.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "script_component.hpp"
/*
* Author: drofseh
* Get current temperature of weapon's ammo.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Weapon <STRING>
*
* Return Value:
* Current ammunition temperature <NUMBER>
*
* Example:
* [player, currentWeapon player] call ace_overheating_fnc_getAmmoTemperature
*
* Public: Yes
*/

params ["_unit", "_weapon"];

private _ammoTempVarName = format [QGVAR(%1_ammoTemp), _weapon];

_unit getVariable [_ammoTempVarName, ambientTemperature select 0]
4 changes: 3 additions & 1 deletion addons/overheating/functions/fnc_getBarrelMass.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@

params ["_weapon"];

METAL_MASS_RATIO * (getNumber (configFile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "mass") / 22.0) max 1.0;
([_weapon] call FUNC(getWeaponData)) params ["", "", "", "", "", "", "", "_barrelMass"];

_barrelMass
18 changes: 14 additions & 4 deletions addons/overheating/functions/fnc_getWeaponData.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
* 0: weapon type <STRING>
*
* Return Value:
* 0: dispresion <NUMBER>
* 0: dispersion <NUMBER>
* 1: slowdownFactor <NUMBER>
* 2: jamChance <NUMBER>
* 3: modes <ARRAY>
* 4: muzzle <STRING>
* 5: reloadTime <NUMBER>
* 6: closedBolt <NUMBER>
* 7: barrelMass <NUMBER>
*
* Example:
* ["gun"] call ace_overheating_fnc_getWeaponData
Expand All @@ -20,7 +25,7 @@
params ["_weapon"];

// Look in the cache first
private _weaponData = GVAR(cacheWeaponData) getVariable _weapon;
private _weaponData = GVAR(cacheWeaponData) get _weapon;
if (!isNil "_weaponData") exitWith {_weaponData};

// Search the config
Expand Down Expand Up @@ -71,11 +76,16 @@ private _muzzle = getArray (configFile >> "CfgWeapons" >> _weapon >> "muzzles")
if (_muzzle == "this") then {
_muzzle = _weapon;
};

private _reloadTime = getNumber (configfile >> "CfgWeapons" >> _weapon >> (_modes select 0) >> "reloadTime");

private _closedBolt = getNumber (configFile >> "CfgWeapons" >> _weapon >> QGVAR(closedBolt));

private _barrelMass = METAL_MASS_RATIO * (getNumber (configFile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "mass") / 22.0) max 1.0;

// Cache the values
_weaponData = [_dispersion, _slowdownFactor, _jamChance, _modes, _muzzle, _reloadTime];
_weaponData = [_dispersion, _slowdownFactor, _jamChance, _modes, _muzzle, _reloadTime, _closedBolt, _barrelMass];
TRACE_2("building cache",_weapon,_weaponData);
GVAR(cacheWeaponData) setVariable [_weapon, _weaponData];
GVAR(cacheWeaponData) set [_weapon, _weaponData];

_weaponData
23 changes: 23 additions & 0 deletions addons/overheating/functions/fnc_getWeaponTemperature.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "script_component.hpp"
/*
* Author: drofseh
* Get current temperature of weapon.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Weapon <STRING>
*
* Return Value:
* Current ammunition temperature <NUMBER>
*
* Example:
* [player, currentWeapon player] call ace_overheating_fnc_getWeaponTemperature
*
* Public: Yes
*/

params ["_unit", "_weapon"];

private _weaponTempVarName = format [QGVAR(%1_temp), _weapon];

_unit getVariable [_weaponTempVarName, ambientTemperature select 0];
6 changes: 4 additions & 2 deletions addons/overheating/functions/fnc_jamWeapon.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ if (_jamTypesAllowed isEqualTo []) then {
};
};

_unit setVariable [format [QGVAR(%1_jamType), _weapon], selectRandomWeighted _jamTypesAllowed];
private _jamType = selectRandomWeighted _jamTypesAllowed;
_unit setVariable [format [QGVAR(%1_jamType), _weapon], _jamType];


// Stop current burst
_unit setAmmo [_weapon, 0];
Expand All @@ -72,7 +74,7 @@ if (_weapon == primaryWeapon _unit) then {
// only display the hint once, after you try to shoot an already jammed weapon
GVAR(knowAboutJam) = false;

["ace_weaponJammed", [_unit,_weapon]] call CBA_fnc_localEvent;
["ace_weaponJammed", [_unit, _weapon, _jamType]] call CBA_fnc_localEvent;

if (_unit getVariable [QGVAR(JammingActionID), -1] == -1) then {

Expand Down
25 changes: 12 additions & 13 deletions addons/overheating/functions/fnc_overheat.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ TRACE_4("params",_unit,_weapon,_ammo,_projectile);
BEGIN_COUNTER(overheat);

// Get bullet parameters
private _energyIncrement = GVAR(cacheAmmoData) getVariable _ammo;
private _energyIncrement = GVAR(cacheAmmoData) get _ammo;
if (isNil "_energyIncrement") then {
_bulletMass = getNumber (configFile >> "CfgAmmo" >> _ammo >> "ACE_BulletMass");
private _bulletMass = getNumber (configFile >> "CfgAmmo" >> _ammo >> "ACE_BulletMass");
if (_bulletMass == 0) then {
// If the bullet mass is not configured, estimate it
_bulletMass = 3.4334 + 0.5171 * (getNumber (configFile >> "CfgAmmo" >> _ammo >> "hit") + getNumber (configFile >> "CfgAmmo" >> _ammo >> "caliber"));
Expand All @@ -38,28 +38,27 @@ if (isNil "_energyIncrement") then {
// Ref: https://en.wikipedia.org/wiki/Physics_of_firearms
// Muzzle Engergy = 1/2 * m * v^2 = (1/2 * 0.001 g/kg * bulletMass (grams) * v^2)
// Multiple by 3 becase we only calc every 3rd bullet: (3 * 1/2 * 0.001) = 0.0015
_energyIncrement = 0.0015 * _bulletMass * (vectorMagnitudeSqr velocity _projectile);
_energyIncrement = GVAR(heatCoef) * 0.0015 * _bulletMass * (vectorMagnitudeSqr velocity _projectile);

GVAR(cacheAmmoData) setVariable [_ammo, _energyIncrement];
GVAR(cacheAmmoData) set [_ammo, _energyIncrement];
};

// Increase overheating depending on how obstrusive is the current supressor,
// if any. Typical arma supressors have visibleFire=0.5 and audibleFire=0.3,
// so they produce x2.1 overheating
private _silencer = switch (_weapon) do {
private _suppressor = switch (_weapon) do {
case (primaryWeapon _unit) : {(primaryWeaponItems _unit) select 0};
case (handgunWeapon _unit) : {(handgunItems _unit) select 0};
default {""};
};
if (_silencer != "") then {
private _silencerCoef = GVAR(cacheSilencerData) getVariable _silencer;
if (isNil "_silencerCoef") then {
_silencerCoef = 1 +
(1 - getNumber (configFile >> "CfgWeapons" >> _silencer >> "ItemInfo" >> "AmmoCoef" >> "audibleFire")) +
(1 - getNumber (configFile >> "CfgWeapons" >> _silencer >> "ItemInfo" >> "AmmoCoef" >> "visibleFire"));
GVAR(cacheSilencerData) setVariable [_silencer, _silencerCoef];
if (_suppressor != "" && {GVAR(suppressorCoef) > 0}) then {
private _suppressorCoef = GVAR(cacheSilencerData) get _suppressor;
if (isNil "_suppressorCoef") then {
private _config = configFile >> "CfgWeapons" >> _suppressor >> "ItemInfo" >> "AmmoCoef";
_suppressorCoef = GVAR(suppressorCoef) * (1 + (1 - getNumber (_config >> "audibleFire")) + (1 - getNumber (_config >> "visibleFire")));
GVAR(cacheSilencerData) set [_suppressor, _suppressorCoef];
};
_energyIncrement = _energyIncrement * _silencerCoef;
_energyIncrement = _energyIncrement * _suppressorCoef;
};

TRACE_1("heat",_energyIncrement);
Expand Down
Loading