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 - Add cook off and rate of fire features and additional customization settings #8064

Merged
merged 35 commits into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6acab97
Add jamming coef to change or disable jamming.
Drofseh Jan 7, 2021
101a60c
change max to 5
Drofseh Jan 7, 2021
77f851b
add setting for overheating effects distance, unjaming on barrel swap…
Drofseh Jan 8, 2021
52fb885
little tweaks
Drofseh Jan 8, 2021
9d431b0
add overheating cookoff feature
Drofseh Jan 11, 2021
2eaf22c
Update ace3-config-entries.md
Drofseh Jan 11, 2021
28e027f
Update overheating-framework.md
Drofseh Jan 11, 2021
bb6a505
Update addons/overheating/XEH_postInit.sqf
Drofseh Jan 11, 2021
86c23a9
Update addons/overheating/XEH_postInit.sqf
Drofseh Jan 11, 2021
14d0f57
Update addons/overheating/functions/fnc_firedEH.sqf
Drofseh Jan 11, 2021
f6c1b54
Update addons/overheating/stringtable.xml
Drofseh Jan 11, 2021
88ffc0d
Update docs/wiki/feature/overheating.md
Drofseh Jan 11, 2021
cb83a7a
Update addons/overheating/stringtable.xml
Drofseh Jan 11, 2021
efe4809
Update addons/overheating/functions/fnc_jamWeapon.sqf
Drofseh Jan 11, 2021
be93626
Update addons/overheating/functions/fnc_jamWeapon.sqf
Drofseh Jan 11, 2021
9a71395
remove extra underwater cooling, make cookoffCoef enable cookoff
Drofseh Jan 13, 2021
768257c
Update stringtable.xml
Drofseh Jan 13, 2021
dbc43fd
add cookoff notification
Drofseh Jan 15, 2021
a3450d9
improvements from play testing
Drofseh Jan 18, 2021
3da9dcc
fix missing semi that I swear I already fixed before pushing
Drofseh Jan 18, 2021
f4fb843
Update overheating-framework.md
Drofseh Jan 18, 2021
d7b0eab
Update fnc_updateAmmoTemperature.sqf
Drofseh Jan 20, 2021
88334b8
include wind speed in cooling calculation
Drofseh Jan 21, 2021
a3d0132
cool with X
Drofseh Feb 27, 2021
143838a
documentation formatting
Drofseh Apr 21, 2021
60d31d1
Add config array for weapon jam types, as not all weapon can get all …
Drofseh Oct 6, 2021
d503501
remove variable that's not required
Drofseh Oct 6, 2021
9a20929
add some compat entries for RHS
Drofseh Oct 6, 2021
e53d165
fix merge conflict
Drofseh Oct 10, 2021
6a2e8b5
Merge branch 'master' into hot-hot-hot
Drofseh Oct 10, 2021
74f548a
fix a happy little accident
Drofseh Oct 13, 2021
e502f7b
move to CBA settings, minor styling.
Drofseh Oct 13, 2021
536072e
Merge branch 'master' into hot-hot-hot
Drofseh Oct 13, 2021
8ca09d0
Update error message in fnc_jamWeapon.sqf
Drofseh Oct 13, 2021
b8e9d29
Apply suggestions from code review
jonpas Oct 13, 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
20 changes: 19 additions & 1 deletion addons/overheating/ACE_Settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ class ACE_Settings {
class GVAR(enabled) {
movedToSQF = 1;
};
class GVAR(heatCoef) {
movedToSQF = 1;
};
class GVAR(showParticleEffects) {
movedToSQF = 1;
};
Expand All @@ -11,13 +14,28 @@ class ACE_Settings {
class GVAR(overheatingDispersion) {
movedToSQF = 1;
};
class GVAR(particleEffectsAndDispersionDistance) {
movedToSQF = 1;
};
class GVAR(overheatingRateOfFire) {
movedToSQF = 1;
};
class GVAR(displayTextOnJam) {
movedToSQF = 1;
};
class GVAR(unJamOnreload) {
class GVAR(jamChanceCoef) {
movedToSQF = 1;
};
class GVAR(unJamOnReload) {
movedToSQF = 1;
};
class GVAR(unJamOnSwapBarrel) {
movedToSQF = 1;
};
class GVAR(unJamFailChance) {
movedToSQF = 1;
};
class GVAR(cookoffCoef) {
movedToSQF = 1;
};
};
22 changes: 22 additions & 0 deletions addons/overheating/CfgSounds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,26 @@ class CfgSounds {
sound[]={QPATHTOF(sounds\fixing_pistol.wav),1,1};
titles[]={};
};
/* // to be added when licence compatible audio can be found or recorded
class GVAR(pouring_long) {
name= QGVAR(pouring_long);
sound[]={QPATHTOF(sounds\pouring_long.ogg),5,1};
titles[]={};
};
class GVAR(pouring_short) {
name= QGVAR(pouring_short);
sound[]={QPATHTOF(sounds\pouring_short.ogg),5,1};
titles[]={};
};
class GVAR(sizzling_long) {
name= QGVAR(sizzling_long);
sound[]={QPATHTOF(sounds\sizzling_long.ogg),5,1};
titles[]={};
};
class GVAR(sizzling_short) {
name= QGVAR(sizzling_short);
sound[]={QPATHTOF(sounds\sizzling_short.ogg),5,1};
titles[]={};
};
*/
};
18 changes: 18 additions & 0 deletions addons/overheating/CfgVehicles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ class CfgVehicles {
showDisabled = 0;
icon = QUOTE(PATHTOF(UI\temp_ca.paa));
};
class GVAR(CoolWeaponWithItem) {
displayName = CSTRING(CoolWeaponWithItem);
condition = QUOTE(GVAR(enabled) && {isClass(configfile >> 'CfgPatches' >> 'acex_field_rations')});
exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"};
statement = "true";
showDisabled = 0;
insertChildren = QUOTE(_player call FUNC(getConsumableChildren));
icon = QPATHTOF(UI\pour_water_ca.paa);
};
};
};

Expand All @@ -55,6 +64,15 @@ class CfgVehicles {
statement = QUOTE( [ARR_3(_player, _target, currentWeapon _target)] call FUNC(checkTemperature); );
icon = QUOTE(PATHTOF(UI\temp_ca.paa));
};
class GVAR(CoolWeaponWithItem) {
displayName = CSTRING(CoolWeaponWithItem);
condition = QUOTE(GVAR(enabled) && {isClass(configfile >> 'CfgPatches' >> 'acex_field_rations')});
exceptions[] = {"isNotInside", "isNotSwimming", "isNotSitting"};
statement = "true";
showDisabled = 0;
insertChildren = QUOTE(_player call FUNC(getConsumableChildren));
icon = QPATHTOF(UI\pour_water_ca.paa);
};
};
};
};
Expand Down
56 changes: 56 additions & 0 deletions addons/overheating/CfgWeapons.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
class CfgWeapons {
class PistolCore;
class Pistol : PistolCore {
//Closed Bolt (Closed Bolt will cook off if too hot)
//Pistols are nearly universally closed bolt.
GVAR(closedBolt) = 1;
};

class Pistol_Base_F : Pistol {};
class hgun_Pistol_heavy_02_F : Pistol_Base_F {
GVAR(jamTypesAllowed) = ["Fire","Dud"];
};
class hgun_Pistol_Signal_F : Pistol_Base_F {
GVAR(jamTypesAllowed) = ["Fire","Dud"];
};

class RifleCore;
class Rifle: RifleCore {
//Mean Rounds Between Stoppages (this will be scaled based on the barrel temp)
Expand All @@ -9,10 +24,17 @@ class CfgWeapons {

//Slowdown Factor (this will be scaled based on the barrel temp)
GVAR(slowdownFactor) = 1;

//Closed Bolt, most weapons are closed bolt
GVAR(closedBolt) = 1;
};
class Rifle_Base_F;
class Rifle_Long_Base_F: Rifle_Base_F {
GVAR(dispersion) = 0.75;

// Open Bolt, most machine guns are open bolt, which cannot normally cook off, and use this as a parent class
// A lot of sniper rifles also use this as a parent class, they will need to be indivisually set to closed bolt, but it's probably not an issue as they are unlikely to overheat
GVAR(closedBolt) = 0;
};

class arifle_MX_Base_F: Rifle_Base_F {
Expand All @@ -26,6 +48,36 @@ class CfgWeapons {
GVAR(allowSwapBarrel) = 1;
GVAR(dispersion) = 0.75;
};
class DMR_01_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class DMR_02_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class DMR_03_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class DMR_04_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class DMR_05_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class DMR_06_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class DMR_07_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class EBR_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class GM6_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class LRR_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
};
class MMG_01_base_F: Rifle_Long_Base_F {
GVAR(allowSwapBarrel) = 1;
};
Expand All @@ -41,6 +93,10 @@ class CfgWeapons {
class LMG_03_Base_F: Rifle_Long_Base_F {
GVAR(allowSwapBarrel) = 1;
};
class sgun_HunterShotgun_01_base_F : Rifle_Long_Base_F {
GVAR(closedBolt) = 1;
GVAR(jamTypesAllowed) = ["Fire","Dud"];
};
class ACE_ItemCore;
class CBA_MiscItem_ItemInfo;
class ACE_SpareBarrel_Item: ACE_ItemCore {
Expand Down
Binary file added addons/overheating/UI/pour_water_ca.paa
Binary file not shown.
6 changes: 6 additions & 0 deletions addons/overheating/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ PREP(canCheckSpareBarrelsTemperatures);
PREP(checkSpareBarrelsTemperatures);
PREP(checkTemperature);
PREP(clearJam);
PREP(coolWeaponWithItem);
PREP(coolWeaponWithWaterSource);
PREP(displayTemperature);
PREP(firedEH);
PREP(getBarrelMass);
PREP(getConsumableChildren);
PREP(getWeaponData);
PREP(handleTakeEH);
PREP(handleRespawn);
Expand All @@ -18,6 +22,8 @@ PREP(sendSpareBarrelsTemperaturesHint);
PREP(swapBarrel);
PREP(swapBarrelAssistant);
PREP(swapBarrelCallback);
PREP(updateAmmoTemperature);
PREP(updateAmmoTemperatureThread);
PREP(updateSpareBarrelsTemperaturesThread);
PREP(updateTemperature);
PREP(updateTemperatureThread);
48 changes: 45 additions & 3 deletions addons/overheating/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,64 @@ if (hasInterface) then {
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;
//Add Take EH if required
if (GVAR(unJamOnReload) || {GVAR(cookoffCoef) > 0}) then {
["CAManBase", "Take", {_this call FUNC(handleTakeEH);}] call CBA_fnc_addClassEventHandler;
};

// Register fire event handler
["ace_firedPlayer", DFUNC(firedEH)] call CBA_fnc_addEventHandler;
// Only add eh to non local players if dispersion is enabled
if (GVAR(overheatingDispersion)) then {
if (GVAR(overheatingDispersion) || {GVAR(showParticleEffectsForEveryone)}) then {
["ace_firedPlayerNonLocal", DFUNC(firedEH)] call CBA_fnc_addEventHandler;
};

// Schedule cool down calculation of player weapons at (infrequent) regular intervals
[] call FUNC(updateTemperatureThread);

//Add event handlers and start ammo heating loop for cookoff
if (GVAR(cookoffCoef) > 0) then {
[] call FUNC(updateAmmoTemperatureThread);

// Reset ammo temperature on reload, unless the reload is a second muzzle.
["CAManBase", "Reloaded", {
params ["_unit", "_weapon", "_muzzle"];
if (_muzzle == _weapon) then {
_unit setVariable [format [QGVAR(%1_ammoTemp), _weapon], 0];
};
}] 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;

// Add an action to allow hot weapons to be cooled off in AceX Field Rations water sources
Drofseh marked this conversation as resolved.
Show resolved Hide resolved
if (isClass(configfile >> "CfgPatches" >> "acex_field_rations")) then {
[
{acex_field_rations_enabled || CBA_missionTime > 1},
{
if (!acex_field_rations_enabled) exitWith {};

_CoolWeaponWithWaterSourceAction = [
QGVAR(CoolWeaponWithWaterSource),
LLSTRING(CoolWeaponWithWaterSource),
"\z\acex\addons\field_rations\ui\icon_water_tap.paa",
{
private _waterSource = _target getVariable ["acex_field_rations_waterSource", objNull];
[_player, _waterSource] call FUNC(coolWeaponWithWaterSource);
},
{
private _waterSource = _target getVariable ["acex_field_rations_waterSource", objNull];
[_player, _waterSource] call acex_field_rations_fnc_canDrinkFromSource;
}
] call EFUNC(interact_menu,createAction);

["acex_field_rations_helper", 0, ["acex_field_rations_waterSource"], _CoolWeaponWithWaterSourceAction] call EFUNC(interact_menu,addActionToClass);
},
[]
] call CBA_fnc_waitUntilAndExecute;
};

}] call CBA_fnc_addEventHandler;
20 changes: 13 additions & 7 deletions addons/overheating/functions/fnc_calculateCooling.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ if (_totalTime > 1800) exitWith {0};
//So Area = 210 * 1.1 * (mass / 7850) = mass * 0.029427 (for steel near that diameter)

private _barrelSurface = _barrelMass * 0.029427;
private _convectionRate = 25;

//provide additional cooling if swimming or raining or windy
if (ACE_player call EFUNC(common,isSwimming)) then {
_convectionRate = 500;
} else {
// this will give a convection rate between 25 (no wind or rain) and 125 (max rain and >=50 m/s wind)
_convectionRate = _convectionRate * ((linearConversion [0,1,rain,1,5,true] + (5 min (vectorMagnitude wind / 10))) / 2);
};

TRACE_4("cooling",_temperature,_totalTime,_barrelMass,_barrelSurface);

Expand All @@ -38,13 +47,10 @@ 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 )
// Convective cooling
_convectionRate * _barrelSurface * _temperature
// Radiative cooling
+ 0.4 * 5.67e-8 * _barrelSurface * ((_temperature + 273.15) ^ 4 - 273.15 ^ 4)
) * _deltaTime / (_barrelMass * 466);

if (_temperature < 1) exitWith {0};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ params ["_player"];
//Get the classname of the spare barrel for the weapon
private _weaponBarrelClass = getText (configFile >> 'CfgWeapons' >> currentWeapon _player >> QGVAR(barrelClassname));
//If the weapon has no defined classname then use the ACE one
if(_weaponBarrelClass == "") then {
if (_weaponBarrelClass == "") then {
_weaponBarrelClass = "ACE_SpareBarrel";
};
//Check if the player has the barrel and the weapon can have its barrel swapped
Expand Down
4 changes: 2 additions & 2 deletions addons/overheating/functions/fnc_canSwapBarrel.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
params ["_unit","_weapon"];

//Check if weapon can have its barrel swapped. If not exit out of function
if( !GVAR(enabled) || {getNumber (configFile >> 'CfgWeapons' >> _weapon >> QGVAR(allowSwapBarrel)) != 1}) exitWith{false};
if ( !GVAR(enabled) || {getNumber (configFile >> 'CfgWeapons' >> _weapon >> QGVAR(allowSwapBarrel)) != 1}) exitWith{false};

//Get the classname of the spare barrel for the weapon
private _weaponBarrelClass = getText (configFile >> 'CfgWeapons' >> _weapon >> QGVAR(barrelClassname));
//If the weapon has no defined classname then use the ACE one
if(_weaponBarrelClass == "") then {
if (_weaponBarrelClass == "") then {
_weaponBarrelClass = "ACE_SpareBarrel";
};
//If the player has the spare barrel then it can be swapped
Expand Down
2 changes: 1 addition & 1 deletion addons/overheating/functions/fnc_checkTemperature.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* None
*
* Example:
* [player, currentWeapon player] call ace_overheating_fnc_checkTemperature
* [player, player, currentWeapon player] call ace_overheating_fnc_checkTemperature
*
* Public: No
*/
Expand Down
37 changes: 25 additions & 12 deletions addons/overheating/functions/fnc_clearJam.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ if (_weapon in _jammedWeapons) then {
};

[_unit, _clearJamAction, 1] call EFUNC(common,doGesture);

if (_weapon == primaryWeapon _unit) then {
playSound QGVAR(fixing_rifle);
} else {
Expand All @@ -42,21 +43,33 @@ if (_weapon in _jammedWeapons) then {
};
};

// Check if the jam will be successfull
// Check if the jam clearing will be successfull
if (random 1 > GVAR(unJamFailChance)) then {
// Success
_jammedWeapons = _jammedWeapons - [_weapon];
_unit setVariable [QGVAR(jammedWeapons), _jammedWeapons];
if (_jammedWeapons isEqualTo []) then {
private _id = _unit getVariable [QGVAR(JammingActionID), -1];
[_unit, "DefaultAction", _id] call EFUNC(common,removeActionEventHandler);
_unit setVariable [QGVAR(JammingActionID), -1];
};
if (GVAR(DisplayTextOnJam)) then {
[{

[{
params ["_unit", "_weapon", "_jammedWeapons"];
_jammedWeapons = _jammedWeapons - [_weapon];
_unit setVariable [QGVAR(jammedWeapons), _jammedWeapons];

// If the round is a dud eject the round
if (_unit getVariable [format [QGVAR(%1_jamType), _weapon], "None"] isEqualTo "Dud") then {
private _ammo = _unit ammo _weapon;
_unit setAmmo [_weapon, _ammo - 1];
};

_unit setVariable [format [QGVAR(%1_jamType), _weapon], "None"];

if (_jammedWeapons isEqualTo []) then {
private _id = _unit getVariable [QGVAR(JammingActionID), -1];
[_unit, "DefaultAction", _id] call EFUNC(common,removeActionEventHandler);
_unit setVariable [QGVAR(JammingActionID), -1];
};

if (GVAR(DisplayTextOnJam)) then {
[localize LSTRING(WeaponUnjammed)] call EFUNC(common,displayTextStructured);
}, [], _delay] call CBA_fnc_waitAndExecute;
};
};
}, [_unit, _weapon, _jammedWeapons], _delay] call CBA_fnc_waitAndExecute;
} else {
// Failure
if (GVAR(DisplayTextOnJam)) then {
Expand Down
Loading