mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Overheating - Fix issues from release (#8617)
* move overheating cookoff into separate function * move heatCoef and require mission restart for setting change - move heatCoef to a more sensible place - require mission restart for heatCoef setting change (it gets cached per ammo type) * add exit to ammo temp loop if cookoffCoef is changed to 0 mid-mission - add exit to ammo temp loop if cookoffCoef is changed to 0 mid-mission, this prevents an issue where all weapon cookoff regardless of temp, because required temp gets multiplied by cookoffCoef which has been set to 0. * file end new line * update header for ace_overheating_fnc_cookoffWeapon * use ambientTemperature as floor for weapon and ammo temp * add coolingCoef setting * improve feature documentation * add fnc_cookoffWeapon to XEH_PREP * add type of jam to ace_weaponJammed local event - add type of jam to ace_weaponJammed local event - fix #8637 * fix misspelling Co-authored-by: TyroneMF <TyroneMF@hotmail.com> * clear all weapon heat on death * Update addons/overheating/functions/fnc_updateTemperature.sqf Co-authored-by: GhostIsSpooky <69561145+Salluci@users.noreply.github.com> * deprecate ace_overheating_fnc_getBarrelMass, cache weapon bolt and barrel mass values - cache closed bolt value by moving config look up to ace_overheating_fnc_getWeaponData - cache barrel mass value by moving calculation from ace_overheating_fnc_getBarrelMass to ace_overheating_fnc_getWeaponData - deprecate ace_overheating_fnc_getBarrelMass to be a wrapper for ace_overheating_fnc_getWeaponData that only returns barrel mass * add public functions to get and set weapon and ammo temperature * add `canCoolWeaponWithItem` function, workaround for #8657 * Apply suggestions from code review Co-authored-by: PabstMirror <pabstmirror@gmail.com> * add coef setting for addition heat from suppressor * Update fnc_overheat.sqf * improve fnc_canCoolWeaponWithItem * remove extra ( * Move canCoolWeaponWithItem action code to function * Use hashmaps and reset on settings change * Apply suggestions from code review Co-authored-by: jonpas <jonpas33@gmail.com> Co-authored-by: TyroneMF <TyroneMF@hotmail.com> Co-authored-by: GhostIsSpooky <69561145+Salluci@users.noreply.github.com> Co-authored-by: PabstMirror <pabstmirror@gmail.com> Co-authored-by: jonpas <jonpas33@gmail.com>
This commit is contained in:
parent
5bad6899cb
commit
99c85e3c12
@ -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;
|
||||
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
@ -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;
|
||||
|
||||
@ -107,5 +117,4 @@ if (hasInterface) then {
|
||||
[]
|
||||
] call CBA_fnc_waitUntilAndExecute;
|
||||
};
|
||||
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
@ -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
|
||||
@ -51,9 +54,9 @@ 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];
|
||||
@ -61,5 +64,5 @@ while {true} do {
|
||||
};
|
||||
|
||||
_time = _time + _deltaTime;
|
||||
if (_time >= _totalTime) exitWith { _temperature max 0 };
|
||||
if (_time >= _totalTime) exitWith {_temperature max _ambientTemperature};
|
||||
};
|
||||
|
27
addons/overheating/functions/fnc_canCoolWeaponWithItem.sqf
Normal file
27
addons/overheating/functions/fnc_canCoolWeaponWithItem.sqf
Normal file
@ -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
addons/overheating/functions/fnc_cookoffWeapon.sqf
Normal file
66
addons/overheating/functions/fnc_cookoffWeapon.sqf
Normal file
@ -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;
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
23
addons/overheating/functions/fnc_getAmmoTemperature.sqf
Normal file
23
addons/overheating/functions/fnc_getAmmoTemperature.sqf
Normal file
@ -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]
|
@ -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
|
||||
|
@ -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
|
||||
@ -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
|
||||
@ -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
addons/overheating/functions/fnc_getWeaponTemperature.sqf
Normal file
23
addons/overheating/functions/fnc_getWeaponTemperature.sqf
Normal file
@ -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];
|
@ -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];
|
||||
@ -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 {
|
||||
|
||||
|
@ -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"));
|
||||
@ -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);
|
||||
|
24
addons/overheating/functions/fnc_setAmmoTemperature.sqf
Normal file
24
addons/overheating/functions/fnc_setAmmoTemperature.sqf
Normal file
@ -0,0 +1,24 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: drofseh
|
||||
* Set weapon's ammo to specific temperature.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Weapon <STRING>
|
||||
* 2: Temperature <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player, currentWeapon player] call ace_overheating_fnc_setAmmoTemperature
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
|
||||
params ["_unit", "_weapon", "_temp"];
|
||||
|
||||
private _ammoTempVarName = format [QGVAR(%1_ammoTemp), _weapon];
|
||||
|
||||
_unit setVariable [_ammoTempVarName, _temp];
|
24
addons/overheating/functions/fnc_setWeaponTemperature.sqf
Normal file
24
addons/overheating/functions/fnc_setWeaponTemperature.sqf
Normal file
@ -0,0 +1,24 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: drofseh
|
||||
* Set weapon to specific temperature.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Weapon <STRING>
|
||||
* 2: Temperature <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player, currentWeapon player] call ace_overheating_fnc_setWeaponTemperature
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
|
||||
params ["_unit", "_weapon", "_temp"];
|
||||
|
||||
private _ammoTempVarName = format [QGVAR(%1_ammoTemp), _weapon];
|
||||
|
||||
_unit setVariable [_ammoTempVarName, _temp];
|
@ -34,7 +34,7 @@ if (GVAR(unJamOnSwapBarrel) && {[_gunner] call FUNC(canUnjam)}) then {
|
||||
[localize LSTRING(SwappedBarrel), QPATHTOF(UI\spare_barrel_ca.paa)] call EFUNC(common,displayTextPicture);
|
||||
|
||||
private _temp = _gunner getVariable [format [QGVAR(%1_temp), _weapon], 0];
|
||||
private _barrelMass = _weapon call FUNC(getBarrelMass);
|
||||
([_weapon] call FUNC(getWeaponData)) params ["", "", "", "", "", "", "", "_barrelMass"];
|
||||
|
||||
// Instruct the server to load the coolest spare barrel into the weapon and
|
||||
// store the removed barrel with the former weapon temperature. The server
|
||||
|
@ -9,7 +9,7 @@
|
||||
* 2: Barrel Temperature <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* Current ammunition temperature <NUMBER>
|
||||
* New temperature <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* [player, currentWeapon player, 600] call ace_overheating_fnc_updateAmmoTemperature
|
||||
@ -20,23 +20,25 @@
|
||||
params ["_unit", "_weapon", "_barrelTemperature"];
|
||||
TRACE_3("params",_unit,_weapon,_barrelTemperature);
|
||||
|
||||
private _closedBolt = getNumber (configFile >> "CfgWeapons" >> _weapon >> QGVAR(closedBolt));
|
||||
([_weapon] call FUNC(getWeaponData)) params ["", "", "", "", "", "", "_closedBolt"];
|
||||
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 {
|
||||
@ -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 FUNC(cookoffWeapon);
|
||||
|
||||
// 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];
|
||||
|
@ -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];
|
||||
|
@ -9,7 +9,7 @@
|
||||
* 2: Heat increment (J) <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* Current temperature <NUMBER>
|
||||
* New temperature <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* [player, currentWeapon player, 2000] call ace_overheating_fnc_updateTemperature
|
||||
@ -27,18 +27,23 @@ private _timeVarName = format [QGVAR(%1_time), _weapon];
|
||||
private _temperature = _unit getVariable [_tempVarName, 0];
|
||||
private _lastTime = _unit getVariable [_timeVarName, 0];
|
||||
|
||||
private _barrelMass = _weapon call FUNC(getBarrelMass);
|
||||
// keep track of weapons that have heat, so they can be set to ambient temperaure on killed/respawn
|
||||
private _trackedWeapons = _unit getVariable [QGVAR(trackedWeapons), []];
|
||||
_trackedWeapons pushBackUnique _tempVarName;
|
||||
_unit setVariable [QGVAR(trackedWeapons), _trackedWeapons];
|
||||
|
||||
// Calculate cooling
|
||||
([_weapon] call FUNC(getWeaponData)) params ["", "", "", "", "", "", "", "_barrelMass"];
|
||||
_temperature = [_temperature, _barrelMass, CBA_missionTime - _lastTime] call FUNC(calculateCooling);
|
||||
|
||||
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);
|
||||
|
||||
// Store the update time locally
|
||||
_unit setVariable [_timeVarName, CBA_missionTime];
|
||||
|
||||
|
@ -15,7 +15,37 @@ private _category = format ["ACE %1", localize LSTRING(DisplayName)];
|
||||
[LSTRING(heatCoef_displayName), LSTRING(heatCoef_description)],
|
||||
_category,
|
||||
[0, 5, 1, 2],
|
||||
1
|
||||
1,
|
||||
{
|
||||
if (!GVAR(enabled)) exitWith {};
|
||||
TRACE_2("reseting cache",GVAR(heatCoef),count GVAR(cacheAmmoData));
|
||||
GVAR(cacheAmmoData) = createHashMap;
|
||||
},
|
||||
false
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(coolingCoef), "SLIDER",
|
||||
[LSTRING(coolingCoef_displayName), LSTRING(coolingCoef_description)],
|
||||
_category,
|
||||
[0, 5, 1, 2],
|
||||
1,
|
||||
{},
|
||||
true
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(suppressorCoef), "SLIDER",
|
||||
[LSTRING(suppressorCoef_displayName), LSTRING(suppressorCoef_description)],
|
||||
_category,
|
||||
[0, 5, 1, 2],
|
||||
1,
|
||||
{
|
||||
if (!GVAR(enabled)) exitWith {};
|
||||
TRACE_2("reseting cache",GVAR(suppressorCoef),count GVAR(cacheSilencerData));
|
||||
GVAR(cacheSilencerData) = createHashMap;
|
||||
},
|
||||
false
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
|
@ -62,6 +62,18 @@
|
||||
<German>Koeffizient für die Menge an Hitze, die eine Waffe pro Schuss erzeugt.\nHöhere Werte beschleunigen die Erhitzung.</German>
|
||||
<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_suppressorCoef_displayName">
|
||||
<English>Suppressor Coefficient</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Overheating_suppressorCoef_description">
|
||||
<English>Coefficient for how much additional heat is added from having a suppressor attached.\nHigher value increases heat, 0 means no additional heat from the suppressor.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Overheating_DisplayTextOnJam_displayName">
|
||||
<English>Display Text on Jam</English>
|
||||
<German>Zeige Text bei Ladehemmung</German>
|
||||
@ -274,8 +286,7 @@
|
||||
<English>Unjam on Barrel Swap</English>
|
||||
<Japanese>銃身交換で弾詰まり解消</Japanese>
|
||||
<French>Désenrayer l'arme au changement de canon</French>
|
||||
<Russian>Замена ствола устраняет заклинивание оружия.</Russian>
|
||||
<German>Ladehemmungen bei Lauf-Wechsel beheben</German>
|
||||
<Russian>Замена ствола устраняет заклинивание оружия.</Russian>
|
||||
<Polish>Usuń zacięcie przy wymianie lufy</Polish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Overheating_unJamOnSwapBarrel_description">
|
||||
|
@ -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.
|
||||
|
||||
### 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.
|
||||
|
Loading…
Reference in New Issue
Block a user