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 10 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
1 change: 1 addition & 0 deletions addons/overheating/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ PREP(canCheckSpareBarrelsTemperatures);
PREP(checkSpareBarrelsTemperatures);
PREP(checkTemperature);
PREP(clearJam);
PREP(cookoffWeapon);
PREP(coolWeaponWithItem);
PREP(coolWeaponWithWaterSource);
PREP(displayTemperature);
Expand Down
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 temperaure a weapon can reach is the ambient air temperature.
Drofseh marked this conversation as resolved.
Show resolved Hide resolved
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};
};
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", "_muzzleCache", "_mode", "_muzzle"];

// 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, _muzzleCache, _mode, _muzzle],
_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 @@ -95,4 +95,4 @@ private _fnc_condition = {
{}, //_fnc_onFailure,
_consumeText,
_fnc_condition
] call EFUNC(common,progressBar);
] call EFUNC(common,progressBar);
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
12 changes: 7 additions & 5 deletions addons/overheating/functions/fnc_overheat.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ BEGIN_COUNTER(overheat);
// Get bullet parameters
private _energyIncrement = GVAR(cacheAmmoData) getVariable _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,7 +38,7 @@ 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];
};
Expand All @@ -54,9 +54,11 @@ private _silencer = switch (_weapon) do {
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"));
_silencerCoef = 1 + (
1 - getNumber (configFile >> "CfgWeapons" >> _silencer >> "ItemInfo" >> "AmmoCoef" >> "audibleFire")
) + (
1 - getNumber (configFile >> "CfgWeapons" >> _silencer >> "ItemInfo" >> "AmmoCoef" >> "visibleFire")
);
GVAR(cacheSilencerData) setVariable [_silencer, _silencerCoef];
};
_energyIncrement = _energyIncrement * _silencerCoef;
Expand Down
66 changes: 11 additions & 55 deletions addons/overheating/functions/fnc_updateAmmoTemperature.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,23 @@ TRACE_3("params",_unit,_weapon,_barrelTemperature);

private _closedBolt = getNumber (configFile >> "CfgWeapons" >> _weapon >> QGVAR(closedBolt));
Drofseh marked this conversation as resolved.
Show resolved Hide resolved
private _canUnjam = [_unit] call FUNC(canUnjam);
private _jamType = _unit getVariable [format [QGVAR(%1_jamType), _weapon], "None"];

// Skip if no ammo in chamber
if (
_unit ammo _weapon < 1
// closed bolt, and jammed and type not failure to fire
|| {_closedBolt == 1 && {_canUnjam} && {!(_unit getVariable [format [QGVAR(%1_jamType), _weapon], "None"] in ["Fire","Dud"])}}
|| {_closedBolt == 1 && {_canUnjam} && {!(_jamType in ["Fire","Dud"])}}
// open bolt, and not jammed, or jammed and type not failure to fire
|| {_closedBolt == 0 && {!_canUnjam || {_canUnjam && {!(_unit getVariable [format [QGVAR(%1_jamType), _weapon], "None"] in ["Fire","Dud"])}}}}
|| {_closedBolt == 0 && {!_canUnjam || {_canUnjam && {!(_jamType in ["Fire","Dud"])}}}}
) exitWith {
_unit setVariable [format [QGVAR(%1_ammoTemp), _weapon], 0];
0
private _ambientTemperature = ambientTemperature select 0;
_unit setVariable [format [QGVAR(%1_ammoTemp), _weapon], _ambientTemperature];
_ambientTemperature
};

private _ammoTempVarName = format [QGVAR(%1_ammoTemp), _weapon];
private _ammoTemperature = _unit getVariable [_ammoTempVarName, 0];
private _ammoTemperature = _unit getVariable [_ammoTempVarName, ambientTemperature select 0];

// heat or cool the ammo
if (_ammoTemperature < _barrelTemperature) then {
Expand All @@ -47,58 +49,12 @@ if (_ammoTemperature < _barrelTemperature) then {
_ammoTemperature = _barrelTemperature;
};

// check for cook off
// cookoff if too hot
if (_ammoTemperature > (GUNPOWDER_IGNITION_TEMP * GVAR(cookoffCoef))) then {
[_unit, _weapon, _canUnjam, _jamType] call ace_overheating_fnc_cookoffWeapon;
Drofseh marked this conversation as resolved.
Show resolved Hide resolved

// 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
private _jamType = _unit getVariable [format [QGVAR(%1_jamType), _weapon], "None"];
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 {
private _ammo = _unit ammo _weapon;
_unit setAmmo [_weapon, _ammo + 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", "_muzzleCache", "_mode", "_muzzle"];

// 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, _muzzleCache, _mode, _muzzle],
_reloadTime
] call CBA_fnc_waitAndExecute;

// if the cookoff happened then the next round should start at 0
_ammoTemperature = 0;
// since a cookoff happened then the next round should start at the ambient temperature.
_ammoTemperature = ambientTemperature select 0;
};

_unit setVariable [_ammoTempVarName, _ammoTemperature];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
* Public: No
*/

// If the ace_overheating_cookoffCoef setting is set to 0 mid mission we want to exit right away or it will immediate cause all player weapons to cook off.
if (GVAR(cookoffCoef) isEqualTo 0) exitWith {
WARNING_1("'%1' has been set to 0 mid mission. Changing this setting requires mission restart.",GVAR(cookoffCoef));
};

private _currentWeapon = currentWeapon ACE_player;
if ((_currentWeapon != "") && {_currentWeapon == primaryWeapon ACE_player || {_currentWeapon == handgunWeapon ACE_player}}) then {
private _temperature = ACE_player getVariable [format [QGVAR(%1_temp), _currentWeapon], 0];
Expand Down
2 changes: 1 addition & 1 deletion addons/overheating/functions/fnc_updateTemperature.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ _temperature = [_temperature, _barrelMass, CBA_missionTime - _lastTime] call FUN
TRACE_1("cooledTo",_temperature);
// Calculate heating
// Steel Heat Capacity = 466 J/(Kg.K)
_temperature = _temperature + _heatIncrement * GVAR(heatCoef) / (_barrelMass * 466);
_temperature = _temperature + _heatIncrement / (_barrelMass * 466);

// Publish the temperature variable
[_unit, _tempVarName, _temperature, TEMP_TOLERANCE] call EFUNC(common,setApproximateVariablePublic);
Expand Down
14 changes: 13 additions & 1 deletion addons/overheating/initSettings.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,19 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)];
[LSTRING(heatCoef_displayName), LSTRING(heatCoef_description)],
_category,
[0, 5, 1, 2],
1
1,
{},
true
] call CBA_fnc_addSetting;

[
QGVAR(coolingCoef), "SLIDER",
[LSTRING(coolingCoef_displayName), LSTRING(coolingCoef_description)],
_category,
[0, 5, 1, 2],
1,
{},
true
] call CBA_fnc_addSetting;

[
Expand Down
8 changes: 7 additions & 1 deletion addons/overheating/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
<Russian>Коэффициент количества тепла, выделяемого оружием за выстрел. \nБольшие значения увеличивают нагрев.</Russian>
<Polish>Współczynnik wpływający na ilość ciepła generowanego przez broń przy każdym strzale.</Polish>
</Key>
<Key ID="STR_ACE_Overheating_coolingCoef_displayName">
<English>Cooling Coefficient</English>
</Key>
<Key ID="STR_ACE_Overheating_coolingCoef_description">
<English>Coefficient for how quickly a weapon cools down.\nHigher value increases cooling speed.</English>
</Key>
<Key ID="STR_ACE_Overheating_DisplayTextOnJam_displayName">
<English>Display Text on Jam</English>
<German>Zeige Text bei Ladehemmung</German>
Expand Down Expand Up @@ -266,7 +272,7 @@
<English>Unjam on Barrel Swap</English>
<Japanese>銃身交換で弾詰まり解消</Japanese>
<French>Désenrayer l'arme au changement de canon</French>
<Russian>Замена ствола устраняет заклинивание оружия.</Russian>
<Russian>Замена ствола устраняет заклинивание оружия.</Russian>
<Polish>Usuń zacięcie przy wymianie lufy</Polish>
</Key>
<Key ID="STR_ACE_Overheating_unJamOnSwapBarrel_description">
Expand Down
5 changes: 2 additions & 3 deletions docs/wiki/feature/overheating.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,11 @@ Jams can be cleared in the following ways:
- Select `Equipment`.
- Select `Check weapon temperature`.

**NOTE** When the bar is half full (yellow) it means the barrel is around 500°c.
Your weapon will be even more prone to jams, and it'll get worse if you don't let the barrel cool down or swap it.
**NOTE** Each section on the bar represents 100°c. When the bar reaches 2 sections weapons can start to cookoff. When it is half full (yellow) it means the barrel is around 500°c. Your weapon will be even more prone to jams, and it'll get worse if you don't let the barrel cool down or swap it.
Drofseh marked this conversation as resolved.
Show resolved Hide resolved

### 2.4 Cooling your weapon

- Weapons and spare barrels will cool off over time.
- Weapons and spare barrels will cool off over time, down to the ambient temperature in the mission.
- Cooling speed of weapons in increased in windy or rainy weather, and when swimming.
- If ACE Field Rations is loaded then weapons can be cooled with canteens, water bottles, or other beverage items. This does not require the Field Rations system to be enabled.
- If ACE Field Rations is enabled then weapons can also be cooled with the same water sources used to refill canteens and water bottles.
Expand Down