diff --git a/TO_MERGE/cse/sys_weaponheat/CfgFunctions.h b/TO_MERGE/cse/sys_weaponheat/CfgFunctions.h new file mode 100644 index 0000000000..876d69d6c6 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/CfgFunctions.h @@ -0,0 +1,27 @@ +class CfgFunctions { + class CSE { + class WeaponHeat { + file = "cse\cse_sys_weaponheat\functions"; + class canSwapBarrel_wh { recompile = 1; }; + class clearMalfunction_wh { recompile = 1; }; + class generateMalfunctions_wh { recompile = 1; }; + class generateHeatHaze_wh { recompile = 1; }; + class generateSmoke_wh { recompile = 1; }; + class getBarrelMass_wh { recompile = 1; }; + class getBarrelTemperature_wh { recompile = 1; }; + class getBulletMass_wh { recompile = 1; }; + class getIn_wh { recompile = 1; }; + class getOut_wh { recompile = 1; }; + class handleWeaponHeat_wh { recompile = 1; }; + class jamWeapon_wh { recompile = 1; }; + class put_wh { recompile = 1; }; + class registerBarrelExchangeActions_wh { recompile = 1; }; + class setBarrelTemperature_wh { recompile = 1; }; + class swapBarrel_wh { recompile = 1; }; + class take_wh { recompile = 1; }; + class removeParticleEffectHeat_WH { recompile = 1; }; + class addParticleEffectHeat_WH { recompile = 1; }; + class setParticleEffectHeat_WH { recompile = 1; }; + }; + }; +}; \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/CfgSounds.h b/TO_MERGE/cse/sys_weaponheat/CfgSounds.h new file mode 100644 index 0000000000..9e38b28878 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/CfgSounds.h @@ -0,0 +1,33 @@ +class CfgSounds +{ + class cse_weaponheat_barrel_exchange + { + name="cse_weaponheat_barrel_exchange"; + sound[]={"\cse\cse_sys_weaponheat\sound\barrel_exchange.wav",1,1}; + titles[]={}; + }; + class cse_jamming_rifle + { + name="cse_jamming_rifle"; + sound[]={"\cse\cse_sys_weaponheat\sound\jamming_rifle.wav",1,1}; + titles[]={}; + }; + class cse_jamming_pistol + { + name="cse_jamming_pistol"; + sound[]={"\cse\cse_sys_weaponheat\sound\jamming_pistol.wav",1,1}; + titles[]={}; + }; + class cse_fixing_rifle + { + name="cse_fixing_rifle"; + sound[]={"\cse\cse_sys_weaponheat\sound\fixing_rifle.wav",1,1}; + titles[]={}; + }; + class cse_fixing_pistol + { + name="cse_fixing_pistol"; + sound[]={"\cse\cse_sys_weaponheat\sound\fixing_pistol.wav",1,1}; + titles[]={}; + }; +}; \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/CfgVehicles.h b/TO_MERGE/cse/sys_weaponheat/CfgVehicles.h new file mode 100644 index 0000000000..0716bea9c5 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/CfgVehicles.h @@ -0,0 +1,46 @@ +class CfgVehicles { + class Logic; + class Module_F: Logic { + class ArgumentsBaseUnits { + }; + }; + class cse_sys_weaponheat: Module_F { + scope = 2; + displayName = "Weapon Heat [CSE]"; + icon = "\cse\cse_main\data\cse_rifle_module.paa"; + category = "cseModules"; + function = "cse_fnc_initalizeModule_F"; + functionPriority = 1; + isGlobal = 1; + isTriggerActivated = 0; + class Arguments { + class genericSpareBarrel { + displayName = "Generic Spare Barrel"; + description = "Allow players to use a generic spare barrel that fits all weapons."; + typeName = "BOOL"; + defaultValue = true; + }; + }; + class ModuleDescription { + description = "Weapon heating"; + }; + }; + + class Item_Base_F; + class cse_sparebarrelbagItem: Item_Base_F + { + scope = 2; + scopeCurator = 2; + displayName = "Spare Barrel Bag"; + author = "Combat Space Enhancement"; + vehicleClass = "Items"; + class TransportItems + { + class cse_sparebarrelbag + { + name = "cse_sparebarrelbag"; + count = 1; + }; + }; + }; +}; diff --git a/TO_MERGE/cse/sys_weaponheat/CfgWeapons.h b/TO_MERGE/cse/sys_weaponheat/CfgWeapons.h new file mode 100644 index 0000000000..361a1652c1 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/CfgWeapons.h @@ -0,0 +1,49 @@ +class CfgWeapons { + class ItemCore; + class InventoryItem_Base_F; + class cse_sparebarrelbag: ItemCore + { + scope=2; + displayName="Spare Barrel Bag"; + // TODO: Replace the place holders + model="\cse\cse_sys_weaponheat\equipment\barrel_m16.p3d"; + picture="\cse\cse_sys_weaponheat\equipment\img\barrel_m16.paa"; + descriptionShort="Spare Barrel Bag"; + class ItemInfo: InventoryItem_Base_F + { + mass=40; + type=201; + }; + }; + + class cse_barrel_m16: cse_sparebarrelbag + { + displayName="M16 Spare Barrel"; + descriptionShort="M16 Spare Barrel"; + model="\cse\cse_sys_weaponheat\equipment\barrel_m16.p3d"; + picture="\cse\cse_sys_weaponheat\equipment\img\barrel_m16.paa"; + }; + + class cse_barrel_ak74: cse_sparebarrelbag + { + displayName="AK Spare Barrel"; + descriptionShort="AK Spare Barrel"; + model="\cse\cse_sys_weaponheat\equipment\barrel_ak74.p3d"; + picture="\cse\cse_sys_weaponheat\equipment\img\barrel_ak74.paa"; + }; + + class Rifle_Base_F; + class arifle_MX_Base_F; + class arifle_MX_SW_F: arifle_MX_Base_F + { + cse_exchangeableBarrel = 1; + }; + class LMG_Zafir_F: Rifle_Base_F + { + cse_exchangeableBarrel = 1; + }; + class LMG_Mk200_F: Rifle_Base_F + { + cse_exchangeableBarrel = 1; + }; +}; \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/Combat_Space_Enhancement.h b/TO_MERGE/cse/sys_weaponheat/Combat_Space_Enhancement.h new file mode 100644 index 0000000000..70239b39c0 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/Combat_Space_Enhancement.h @@ -0,0 +1,18 @@ +class Combat_Space_Enhancement { + class CfgModules { + class cse_sys_weaponheat { + init = "call compile preprocessFile 'cse\cse_sys_weaponheat\init_sys_weaponheat.sqf';"; + name = "Weapon Heating"; + class EventHandlers { + class AllVehicles { + GetIn = "call cse_fnc_getIn_wh; false"; + GetOut = "call cse_fnc_getOut_wh; false"; + }; + + class CAManBase { + killed = "[_this select 1] call cse_fnc_removeParticleEffectHeat_WH;"; + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/config.cpp b/TO_MERGE/cse/sys_weaponheat/config.cpp new file mode 100644 index 0000000000..415f7c322a --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/config.cpp @@ -0,0 +1,25 @@ +class CfgPatches { + class cse_sys_weaponheat { + units[] = {"cse_sparebarrelbagItem"}; + weapons[] = {}; + requiredVersion = 1.0; + requiredAddons[] = {"cse_f_eh","cse_main", "A3_Weapons_F", "A3_Weapons_F_Rifles_MX"}; + version = "0.10.0_rc"; + author[] = {"Combat Space Enhancement"}; + authorUrl = "http://csemod.com"; + }; +}; + +class cse_sys_weaponheat { + class PreloadAddons { + class cse_sys_weaponheat { + list[] = {"cse_sys_weaponheat"}; + }; + }; +}; + +#include "CfgVehicles.h" +#include "CfgWeapons.h" +#include "CfgSounds.h" +#include "CfgFunctions.h" +#include "Combat_Space_Enhancement.h" \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/barrel_ak74.p3d b/TO_MERGE/cse/sys_weaponheat/equipment/barrel_ak74.p3d new file mode 100644 index 0000000000..cffce0919b Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/barrel_ak74.p3d differ diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/barrel_m16.p3d b/TO_MERGE/cse/sys_weaponheat/equipment/barrel_m16.p3d new file mode 100644 index 0000000000..ac893e24e5 Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/barrel_m16.p3d differ diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_ak74.rvmat b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_ak74.rvmat new file mode 100644 index 0000000000..b96145eaea --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_ak74.rvmat @@ -0,0 +1,22 @@ +ambient[]={0.80000001,0.80000001,0.80000001,0}; +diffuse[]={0.80000001,0.80000001,0.80000001,0}; +forcedDiffuse[]={0,0,0,0}; +emmisive[]={0,0,0,0}; +specular[]={0.2,0.2,0.2,0}; +specularPower=10.6; +renderFlags[]= +{ + "NoAlphaWrite" +}; +PixelShaderID="Glass"; +VertexShaderID="Glass"; +class Stage1 +{ + texture="#(argb,8,8,3)color(1,1,1,0.9)"; + uvSource="none"; +}; +class Stage2 +{ + texture="a3\data_f\env_chrome_co.paa"; + uvSource="none"; +}; diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_ak74_co.paa b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_ak74_co.paa new file mode 100644 index 0000000000..de0d49a31b Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_ak74_co.paa differ diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16.rvmat b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16.rvmat new file mode 100644 index 0000000000..c5b74bc7d7 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16.rvmat @@ -0,0 +1,92 @@ +ambient[]={1.000000,1.000000,1.000000,1.000000}; +diffuse[]={1.000000,1.000000,1.000000,1.000000}; +forcedDiffuse[]={0.000000,0.000000,0.000000,0.000000}; +emmisive[]={0.000000,0.000000,0.000000,1.000000}; +specular[]={0.703999,0.703999,0.703999,0.000000}; +specularPower=70.000000; +PixelShaderID="Super"; +VertexShaderID="Super"; +class Stage1 +{ + texture="cse\cse_sys_weaponheat\equipment\data\barrel_m16_nohq.paa"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage2 +{ + texture="#(argb,8,8,3)color(0.5,0.5,0.5,1,DT)"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage3 +{ + texture="#(argb,8,8,3)color(0,0,0,0,MC)"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage4 +{ + texture="#(argb,8,8,3)color(1,1,1,1,AS)"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage5 +{ + texture="#(argb,8,8,3)color(0,0.05,1,1,SMDI)"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage6 +{ + texture="#(ai,32,128,1)fresnel(0.98,1.02)"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; +class Stage7 +{ + texture="cse\cse_sys_weaponheat\equipment\data\env_co.tga"; + uvSource="tex"; + class uvTransform + { + aside[]={1.000000,0.000000,0.000000}; + up[]={0.000000,1.000000,0.000000}; + dir[]={0.000000,0.000000,0.000000}; + pos[]={0.000000,0.000000,0.000000}; + }; +}; diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16_co.paa b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16_co.paa new file mode 100644 index 0000000000..a3494a0f25 Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16_co.paa differ diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16_nohq.paa b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16_nohq.paa new file mode 100644 index 0000000000..f53a424eb6 Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/data/barrel_m16_nohq.paa differ diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/data/env_co.paa b/TO_MERGE/cse/sys_weaponheat/equipment/data/env_co.paa new file mode 100644 index 0000000000..77645347b5 Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/data/env_co.paa differ diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/img/barrel_ak74.paa b/TO_MERGE/cse/sys_weaponheat/equipment/img/barrel_ak74.paa new file mode 100644 index 0000000000..93b3b8a37c Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/img/barrel_ak74.paa differ diff --git a/TO_MERGE/cse/sys_weaponheat/equipment/img/barrel_m16.paa b/TO_MERGE/cse/sys_weaponheat/equipment/img/barrel_m16.paa new file mode 100644 index 0000000000..92b4f2fc8b Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/equipment/img/barrel_m16.paa differ diff --git a/TO_MERGE/cse/sys_weaponheat/functions/defines.h b/TO_MERGE/cse/sys_weaponheat/functions/defines.h new file mode 100644 index 0000000000..e7cf47b9d1 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/defines.h @@ -0,0 +1,16 @@ +#define PI 3.14159265 +#define ABSOLUTE_ZERO_IN_CELSIUS -273.15 +#define KELVIN(t) (t - ABSOLUTE_ZERO_IN_CELSIUS) +#define CELSIUS(t) (t + ABSOLUTE_ZERO_IN_CELSIUS) +#define CENTIMETER(i) (i * 2.54) +#define STEFAN_BOLTZMANN_CONSTANT 0.00000005670373 // W / (m^2 * K^4) +#define HEAT_TRANSFER_COEFFICIENT_STEEL 25.0 // W / (m^2 * K) +#define HEAT_CAPACITY_STEEL 0.466 // J / (g * K) + +// Source: http://www.engineeringtoolbox.com/emissivity-coefficients-d_447.html +#define EMISSIVITY_STAINLESS_STEEL 0.54 + +// Source http://www.azom.com/properties.aspx?ArticleID=965 +// We have taken the average density for this +// (7.85 + 8.06 / 2) min + max / 2 +#define DENSITY_STAINLESS_STEEL 7.955 // g / cm^3 \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_addParticleEffectHeat_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_addParticleEffectHeat_wh.sqf new file mode 100644 index 0000000000..cb324f892b --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_addParticleEffectHeat_wh.sqf @@ -0,0 +1,31 @@ +/** + * fn_addParticleEffectsHeat_wh.sqf + * @Descr: Adds a heat effect for the units weapon. + * @Author: Glowbal + * + * @Arguments: [unit OBJECT] + * @Return: PARTICLE The particleeffect object + * @PublicAPI: false + */ + +private ["_unit", "_currentParticleEffect", "_weaponDirection", "_particleEffect", "_rightHandPosition"]; +_unit = _this select 0; + +_currentParticleEffect = _unit getvariable "cse_particleEffect_Heat_WH"; +if (!isnil "_currentParticleEffect") exitwith {_currentParticleEffect}; +_rightHandPosition = ATLtoASL (_unit modelToWorld (_unit selectionPosition "RightHand")); + +_weaponDirection = _unit weaponDirection _weapon; + +_dummyObj = "cse_LogicDummy" createVehicleLocal [0,0,0]; +_dummyObj attachTo [_unit, _weaponDirection vectorMultiply 0.2, "LeftHand"]; + +_particleEffect = "#particlesource" createVehicle (getPos _dummyObj); +_particleEffect setParticleCircle [0, [0, 0, 0]]; +_particleEffect setParticleRandom [0.2, [0, 0, 0], [0.0, 0.0, 0], 0.1, 0.1, [0, 0, 0, 0], 0, 0]; +_particleEffect setParticleParams [["\A3\data_f\ParticleEffects\Universal\Refract",1, 0, 1, 0], "", "Billboard", 3, 0.1, [0, 0, 0], [0, 0, 0.0], 0, 0.5, 0.5, 0.1, [1.0], [[1, 0.7, 0.7, 0.0]], [1], 0, 0, "", "", _dummyObj]; +_particleEffect setDropInterval 0.04; + +_unit setvariable ["cse_particleEffect_Heat_WH", _particleEffect]; +_unit setvariable ["cse_particleEffect_Heat_dummyObj_WH", _dummyObj]; +_particleEffect; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_canSwapBarrel_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_canSwapBarrel_wh.sqf new file mode 100644 index 0000000000..3e1480cee4 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_canSwapBarrel_wh.sqf @@ -0,0 +1,10 @@ +private ["_unit", "_weapon"]; +_unit = _this select 0; +_weapon = _this select 1; + +if (getNumber(configFile >> "CfgWeapons" >> _weapon >> "cse_exchangeableBarrel") != 1) exitWith { false }; + +if ([_unit, getText(configFile >> "CfgWeapons" >> _weapon >> "cse_spareBarrel")] call cse_fnc_hasItem) exitWith { true }; +if (cse_genericSpareBarrel_wh && [_unit, "cse_sparebarrelbag"] call cse_fnc_hasItem) exitWith { true }; + +false diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_clearMalfunction_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_clearMalfunction_wh.sqf new file mode 100644 index 0000000000..9223a16969 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_clearMalfunction_wh.sqf @@ -0,0 +1,32 @@ +/** + * fn_jamWeapon_wh.sqf + * @Descr: Clears the malfunction of a given unit/weapon/muzzle combination + * @Author: Ruthberg + * + * @Arguments: [unit OBJECT, weapon STRING, muzzle STRING] + * @Return: nil + * @PublicAPI: true + */ + +#define SUCCESS_RATE 0.9 + +private ["_unit", "_weapon", "_muzzle"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; + +if ((currentMuzzle _unit) != _muzzle) exitWith {}; +if (_unit getVariable["CSE_ClearingMalfunction", false]) exitWith {}; +if (!(_unit getVariable[format["CSE_Malfunction_%1_%2", _weapon, _muzzle], false])) exitWith {}; + +// Beginning of the procedure to clear the malfunction +_unit setVariable["CSE_ClearingMalfunction", true, false]; + +_unit playActionNow "reloadMagazine"; +sleep 2; // TODO: This should depend on the weapon type (maybe consider the weapon mass) +if (SUCCESS_RATE > random 1) then { + _unit setVariable [format["CSE_Malfunction_%1_%2", _weapon, _muzzle], false, !(_unit isKindOf "Man")]; +}; + +// End of the procedure to clear the malfunction +_unit setVariable["CSE_ClearingMalfunction", false, false]; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_generateHeatHaze_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_generateHeatHaze_wh.sqf new file mode 100644 index 0000000000..0bcfe6e90e --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_generateHeatHaze_wh.sqf @@ -0,0 +1,35 @@ +#define MAX_TEMP_HEAT_EFFECT 1000 + +private ["_unit", "_weapon", "_muzzle", "_ammo", "_malfunctionRate"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; +_ammo = _this select 3; +_barrelTemperature = _this select 4; + +if (_unit getVariable[format["cse_weaponHeat_TemperatureEffects_%1_%2", _weapon, _muzzle], false]) exitWith {}; + +if (_barrelTemperature >= 100) then { + _unit setvariable [format["cse_weaponHeat_TemperatureEffects_%1_%2", _weapon, _muzzle], true]; + + [_unit, _weapon, _muzzle, _ammo] spawn { + _unit = _this select 0; + _weapon = _this select 1; + _muzzle = _this select 2; + _ammo = _this select 3; + + _particleEffect = [_unit] call cse_fnc_addParticleEffectHeat_WH; + _currentTemp = [_unit, _weapon, _muzzle, _ammo] call cse_fnc_getBarrelTemperature_wh; + while {_currentTemp >= 100 && alive _unit} do { + _currentTemp = [_unit, _weapon, _muzzle, _ammo] call cse_fnc_getBarrelTemperature_wh; + if (currentWeapon _unit == _weapon) then { + _percentage = 0 max (_currentTemp / MAX_TEMP_HEAT_EFFECT) min 1; + [_unit, _percentage] call cse_fnc_setParticleEffectHeat_WH; + } else { + [_unit, 0] call cse_fnc_setParticleEffectHeat_WH; + }; + sleep 1; + }; + [_unit] call cse_fnc_removeParticleEffectHeat_WH; + }; +}; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_generateMalfunctions_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_generateMalfunctions_wh.sqf new file mode 100644 index 0000000000..991e6a02cf --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_generateMalfunctions_wh.sqf @@ -0,0 +1,53 @@ +/** + * fn_generateMalfunctions_wh.sqf + * @Descr: Generates weapon malfunctions based on barrel temperature and weapon cleanness + * @Author: Ruthberg + * + * @Arguments: [unit OBJECT, weapon STRING, muzzle STRING, barrelTemperature NUMBER] + * @Return: nil + * @PublicAPI: false + */ + + +#define MALFUNCTION_BASE_RATE 0.0001 // Base rate 1 : 10000 + +private ["_unit", "_weapon", "_muzzle", "_malfunctionRate"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; +_barrelTemperature = _this select 3; + +if (_unit getVariable[format["CSE_Malfunction_%1_%2", _weapon, _muzzle], false]) exitWith { + switch (getNumber (configFile >> "CfgWeapons" >> _weapon >> "type")) do { + case 1: { + playSound3d["\cse\cse_sys_weaponheat\sound\jamming_rifle.wav", _unit, false, getPos _unit, 1.5, 1, 10]; + }; + case 2: { + playSound3d["\cse\cse_sys_weaponheat\sound\jamming_pistol.wav", _unit, false, getPos _unit, 1.5, 1, 10]; + }; + default { + + }; + }; + +}; + +_malfunctionRate = MALFUNCTION_BASE_RATE max (_barrelTemperature / 1500)^4; + +// TODO: Add consideration of weapon cleanness + +if (_malfunctionRate > random 1) then { + [_unit, _weapon, _muzzle] call cse_fnc_jamWeapon_wh; + + switch (getNumber (configFile >> "CfgWeapons" >> _weapon >> "type")) do { + case 1: { + playSound3d["\cse\cse_sys_weaponheat\sound\jamming_rifle.wav", _unit, false, getPos _unit, 15, 1, 10]; + }; + case 2: { + playSound3d["\cse\cse_sys_weaponheat\sound\jamming_pistol.wav", _unit, false, getPos _unit, 15, 1, 10]; + }; + default { + + }; + }; +}; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_generateSmoke_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_generateSmoke_wh.sqf new file mode 100644 index 0000000000..a9a7f2c048 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_generateSmoke_wh.sqf @@ -0,0 +1,29 @@ +/** + * fn_generateSmoke_wh.sqf + * @Descr: Generates a smoke effect based on barrel temperature + * @Author: Ruthberg + * + * @Arguments: [unit OBJECT, weapon STRING, muzzle STRING, _bullet OBJECT, barrelTemperature NUMBER] + * @Return: nil + * @PublicAPI: false + */ + + +private ["_unit", "_weapon", "_muzzle", "_bullet", "_bulletPosition", "_weaponDirection", "_intensity", "_particlePosition", "_distance"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; +_bullet = _this select 3; +_barrelTemperature = _this select 4; + +if (_barrelTemperature < 80) exitWith {}; + +_bulletPosition = getPosATL _bullet; +_weaponDirection = _unit weaponDirection _weapon; +_intensity = (_barrelTemperature / 2000) min 0.3; + +{ + _distance = 0.05 + random 0.27; + _particlePosition = _bulletPosition vectorAdd (_weaponDirection vectorMultiply _distance); + drop ["\A3\data_f\missileSmoke", "", "Billboard", 1, 1.5,_particlePosition, [0, 0, 0], 1, 7.0, 5.5, 0.075,[0.28, 0.33, 0.37], [[.5, .5, .5, _intensity], [.6, .6, .6,_intensity*0.2]], [random 1,random 1,random 1], 0, 0, "", "", ""]; +} forEach [0, 1]; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_getBarrelMass_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_getBarrelMass_wh.sqf new file mode 100644 index 0000000000..1c638f3ec0 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_getBarrelMass_wh.sqf @@ -0,0 +1,31 @@ +/** + * fn_getBarrelMass_wh.sqf + * @Descr: Calculates the mass of the barrel + * @Author: Ruthberg + * + * @Arguments: [unit OBJECT, weapon STRING, muzzle STRING] + * @Return: barrel mass in gramm + * @PublicAPI: false + */ + + +private ["_unit", "_weapon", "_muzzle", "_barrelMass"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; + +_barrelMass = 0.40 * (getNumber (configFile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "mass")) * 50; // estimated barrel mass in gramm +if (_barrelMass == 0) then { + // TODO: Find a way to estimate the barrel mass in this case + _barrelMass = 4000; + if (!(_unit isKindOf "Man")) then { + _barrelMass = _barrelMass * 10; + }; +}; +switch (_weapon) do { + case (primaryWeapon _unit) : { _barrelMass = 1000 max _barrelMass }; + case (secondaryWeapon _unit) : { _barrelMass = 2000 max _barrelMass }; + case (handgunWeapon _unit) : { _barrelMass = 400 max _barrelMass }; +}; + +_barrelMass diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_getBarrelTemperature_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_getBarrelTemperature_wh.sqf new file mode 100644 index 0000000000..c9c01d50b7 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_getBarrelTemperature_wh.sqf @@ -0,0 +1,62 @@ +/** + * fn_getBarrelTemperature_wh.sqf + * @Descr: Calculates the current barrel temperature + * @Author: Ruthberg + * + * @Arguments: [unit OBJECT, weapon STRING, muzzle STRING, ammo STRING] + * @Return: barrel temperature in degree celsius + * @PublicAPI: true + */ + + +#include "defines.h" + +private ["_unit", "_weapon", "_muzzle", "_ammo", "_barrelMass", "_barrelLength", "_barrelCaliber", "_area", "_barrelDiameter", "_ambientTemperature", "_barrelTemperature", "_lastUpdateTime", "_deltaTime", "_simulationStep", "_fluidVelocity", "_dynamicHeatTransferCoefficient"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; +_ammo = _this select 3; + +_barrelMass = [_unit, _weapon, _muzzle] call cse_fnc_getBarrelMass_wh; +_barrelSurface = _barrelMass * 0.00015; // Rough estimation based on barrel mass only + +_barrelLength = getNumber(configFile >> "CfgWeapons" >> _weapon >> "AB_barrelLength"); +_barrelCaliber = getNumber(configFile >> "CfgAmmo" >> _ammo >> "AB_caliber"); +if (_barrelLength > 0 && _barrelCaliber > 0) then { + // Estimate barrel surface based on barrel mass and barrel length and barrel caliber + _area = _barrelMass / (DENSITY_STAINLESS_STEEL * PI * CENTIMETER(_barrelLength)); + _barrelDiameter = sqrt(CENTIMETER(_barrelCaliber)^2 + 4 * _area); + + _barrelSurface = _barrelDiameter * PI * CENTIMETER(_barrelLength); + _barrelSurface = _barrelSurface / 10000; // convert from m^2 to cm^2 +}; + +_ambientTemperature = 15; +if (["cse_AB_moduleAdvancedBallistics"] call cse_fnc_isModuleEnabled_F) then { + _ambientTemperature = ((getPosASL _unit) select 2) call cse_ab_ballistics_fnc_get_temperature_at_height; +}; + +_barrelTemperature = _unit getVariable [format["CSE_BarrelTemperature_%1", _weapon], _ambientTemperature]; +_lastUpdateTime = _unit getVariable [format["CSE_BarrelUpdateTime_%1", _weapon], diag_tickTime]; + +_deltaTime = diag_tickTime - _lastUpdateTime; + +while {_deltaTime > 0} do { + _simulationStep = (_deltaTime min 1); // max step size 1 second + + // TODO: Do we want conductive heat transfer from the barrel to other parts of the weapon? + + // Source: https://de.wikipedia.org/wiki/W%C3%A4rme%C3%BCbergangskoeffizient + // Source: https://en.wikipedia.org/wiki/Combined_forced_and_natural_convection + _fluidVelocity = vectorMagnitude (wind vectorDiff (velocity _unit)); + _dynamicHeatTransferCoefficient = 12 * sqrt(_fluidVelocity) + 2; + // Source: https://en.wikipedia.org/wiki/Convective_heat_transfer + _barrelTemperature = _barrelTemperature - (HEAT_TRANSFER_COEFFICIENT_STEEL + _dynamicHeatTransferCoefficient) * _barrelSurface * (_barrelTemperature - _ambientTemperature) / (HEAT_CAPACITY_STEEL * _barrelMass) * _simulationStep; + + // Source: https://en.wikipedia.org/wiki/Thermal_radiation + _barrelTemperature = _barrelTemperature - EMISSIVITY_STAINLESS_STEEL * STEFAN_BOLTZMANN_CONSTANT * _barrelSurface * (KELVIN(_barrelTemperature)^4 - KELVIN(_ambientTemperature)^4) / (HEAT_CAPACITY_STEEL * _barrelMass) * _simulationStep; + + _deltaTime = _deltaTime - _simulationStep; +}; + +_barrelTemperature diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_getBulletMass_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_getBulletMass_wh.sqf new file mode 100644 index 0000000000..3075e2be18 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_getBulletMass_wh.sqf @@ -0,0 +1,25 @@ +/** + * fn_getBulletMass_wh.sqf + * @Descr: Calculates the mass of the bullet + * @Author: Ruthberg + * + * @Arguments: ammo STRING + * @Return: bullet mass in gramm + * @PublicAPI: false + */ + + +private ["_ammo", "_bulletMass", "_caliber"]; +_ammo = _this; + +_bulletMass = getNumber(configFile >> "CfgAmmo" >> _ammo >> "AB_bulletMass"); +if (_bulletMass == 0) then { + // Try to estimate the mass based on BIS caliber + // B_762x51_Ball: caliber 1.0 <--> 7.62 NATO M80: bullet mass 147 grain (9.46064086 g) + _caliber = getNumber(configFile >> "CfgAmmo" >> _ammo >> "caliber"); + _bulletMass = _muzzleVelocity / 850 * _caliber * 9.46064086; +} else { + _bulletMass = _bulletMass * 0.06479891; +}; + +_bulletMass diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_getIn_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_getIn_wh.sqf new file mode 100644 index 0000000000..000261f184 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_getIn_wh.sqf @@ -0,0 +1,9 @@ +private ["_vehicle", "_position", "_unit", "_handle"]; +_vehicle = _this select 0; +_position = _this select 1; +_unit = _this select 2; + +if (_unit != player) exitWith {}; +_handle = _vehicle addEventHandler ["Fired", {_this call cse_fnc_handleWeaponHeat_wh}]; + +_vehicle setVariable ["cse_weapon_heat_fired_event_handler", _handle]; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_getOut_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_getOut_wh.sqf new file mode 100644 index 0000000000..f734099eb7 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_getOut_wh.sqf @@ -0,0 +1,12 @@ +private ["_vehicle", "_position", "_unit", "_handle"]; +_vehicle = _this select 0; +_position = _this select 1; +_unit = _this select 2; + +if (_unit != player) exitWith {}; +_handle = _vehicle getVariable "cse_weapon_heat_fired_event_handler"; + +if (!isNil "_handle") then { + _vehicle removeEventHandler ["Fired", _handle]; + _vehicle setVariable ["cse_weapon_heat_fired_event_handler", nil]; +}; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_handleWeaponHeat_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_handleWeaponHeat_wh.sqf new file mode 100644 index 0000000000..7ac712917b --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_handleWeaponHeat_wh.sqf @@ -0,0 +1,54 @@ +/** + * fn_handleWeaponHeat_wh.sqf + * @Descr: Is expected to be triggered by the fired eventhandler from BI. + * @Author: Ruthberg + * + * @Arguments: [] + * @Return: + * @PublicAPI: false + * + * Params: + * 1. unit: Object - Object the event handler is assigned to + * 2. weapon: String - Fired weapon + * 3. muzzle: String - Muzzle that was used + * 4. mode: String - Current mode of the fired weapon + * 5. ammo: String - Ammo used + * 6. magazine: String - magazine name which was used + * 7. projectile: Object - Object of the projectile that was shot (Arma 2: OA and onwards) + */ + +#include "defines.h" + +private ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_bullet", "_barrelTemperature", "_muzzleVelocity", "_barrelMass", "_bulletMass", "_caliber", "_kineticEnergy"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; +_mode = _this select 3; +_ammo = _this select 4; +_magazine = _this select 5; +_bullet = _this select 6; + +if (!(isPlayer _unit) || !local _unit) exitWith {}; +if (!(_bullet isKindOf "BulletBase")) exitWith {}; + +_barrelTemperature = [_unit, _weapon, _muzzle, _ammo] call cse_fnc_getBarrelTemperature_wh; + +_muzzleVelocity = getNumber(configFile >> "CfgMagazines" >> _magazine >> "initSpeed"); +_barrelMass = [_unit, _weapon, _muzzle] call cse_fnc_getBarrelMass_wh; +_bulletMass = _ammo call cse_fnc_getBulletMass_wh; + +_kineticEnergy = 0.5 * (_bulletMass / 1000) * _muzzleVelocity^2; // in J + +if (_kineticEnergy > 0 && _barrelMass > 0) then { + _barrelTemperature = _barrelTemperature + _kineticEnergy / (HEAT_CAPACITY_STEEL * _barrelMass); + [_unit, _weapon, _muzzle, _barrelTemperature] call cse_fnc_setBarrelTemperature_wh; +}; + +[_unit, _weapon, _muzzle, _barrelTemperature] call cse_fnc_generateMalfunctions_wh; +[_unit, _weapon, _muzzle, _ammo, _barrelTemperature] call cse_fnc_generateHeatHaze_wh; +[_unit, _weapon, _muzzle, _bullet, _barrelTemperature] call cse_fnc_generateSmoke_wh; + +// TODO: High barrel temperature side effects +// cooking off? +// fire (particle effects)? +// glowing barrel at very high temperatures? \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_jamWeapon_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_jamWeapon_wh.sqf new file mode 100644 index 0000000000..a47e907cb8 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_jamWeapon_wh.sqf @@ -0,0 +1,38 @@ +/** + * fn_jamWeapon_wh.sqf + * @Descr: Adds a malfunction to the given unit/weapon/muzzle combination + * @Author: Ruthberg + * + * @Arguments: [unit OBJECT, weapon STRING, muzzle STRING] + * @Return: nil + * @PublicAPI: true + */ + +private ["_unit", "_weapon", "_muzzle", "_ID"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; + +_unit setVariable[format["CSE_Malfunction_%1_%2", _weapon, _muzzle], true, !(_unit isKindOf "CaManBase")]; +_ID = format["CSE_Malfunction_ID_%1_%2_%3", _unit, _weapon, _muzzle]; + +[_ID, [_unit, _weapon, _muzzle, _ID], { + private ["_unit", "_weapon", "_muzzle", "_ID"]; + _unit = _this select 0; + + // necessary to prefent weapon jam from resetting when jumping in and out of vehicles. + if (vehicle _unit == _unit) then { + _weapon = _this select 1; + _muzzle = _this select 2; + _ID = _this select 3; + + if (!(_unit getVariable[format["CSE_Malfunction_%1_%2", _weapon, _muzzle], false]) || !(_weapon in (weapons (vehicle _unit)))) exitWith { + _unit setVariable[format["CSE_Malfunction_%1_%2", _weapon, _muzzle], nil, !(_unit isKindOf "CaManBase")]; // clean up the malfunction variable. + [_ID] call cse_fnc_removeTaskFromPool_F; + }; + + if (currentWeapon _unit == _weapon && currentMuzzle _unit == _muzzle) then { + (vehicle _unit) setWeaponReloadingTime [_unit, _muzzle, 1]; + }; + }; +}] call cse_fnc_addTaskToPool_f; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_put_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_put_wh.sqf new file mode 100644 index 0000000000..1b3c28d7bf --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_put_wh.sqf @@ -0,0 +1,19 @@ +private ["_unit", "_container", "_item", "_itemCargo", "_ambientTemperature", "_spareBarrelTemperature", "_spareBarrelUpdateTime"]; +_unit = _this select 0; +_container = _this select 1; +_item = _this select 2; + +if (_unit != player) exitWith {}; +if (!([configFile >> "CfgWeapons" >> _item, "cse_sparebarrelbag"] call cse_fnc_inheritsFrom)) exitWith {}; +if (_container == uniformContainer player || _container == vestContainer player || _container == backpackContainer player) exitWith {}; + +_ambientTemperature = 15; +if (["cse_AB_moduleAdvancedBallistics"] call cse_fnc_isModuleEnabled_F) then { + _ambientTemperature = ((getPosASL _unit) select 2) call cse_ab_ballistics_fnc_get_temperature_at_height; +}; + +_spareBarrelTemperature = _unit getVariable [format["CSE_BarrelTemperature_%1", _item], _ambientTemperature]; +_spareBarrelUpdateTime = _unit getVariable [format["CSE_BarrelUpdateTime_%1", _item], diag_tickTime]; + +_container setVariable [format["CSE_BarrelTemperature_%1", _item], _spareBarrelTemperature, true]; +_container setVariable [format["CSE_BarrelUpdateTime_%1", _item], _spareBarrelUpdateTime, true]; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_registerBarrelExchangeActions_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_registerBarrelExchangeActions_wh.sqf new file mode 100644 index 0000000000..5ccdf7e726 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_registerBarrelExchangeActions_wh.sqf @@ -0,0 +1,26 @@ +if (isDedicated) exitwith{}; +CSE_ICON_PATH = "cse\cse_gui\radialmenu\data\icons\"; + +cse_exchangeBarrelDisplaySubMenu = { + [_this] call cse_fnc_Debug; + + private ["_subMenus"]; + _subMenus = []; + + if ([player, currentWeapon player, currentMuzzle player] call cse_fnc_canSwapBarrel_wh) then { + _subMenus pushBack ["Swap barrel", CSE_ICON_PATH + "icon_swap_barrels.paa", { + closeDialog 0; + [player, currentWeapon player, currentMuzzle player] spawn cse_fnc_swapBarrel_wh; + }, true, "Swaps out the barrel"]; + }; + + [_this select 3, _subMenus, _this select 1, CSE_SELECTED_RADIAL_OPTION_N_GUI, true] call cse_fnc_openRadialSecondRing_GUI; +}; + + +_entries = [ + ["Weapon", {([player, currentWeapon player, currentMuzzle player] call cse_fnc_canSwapBarrel_wh)}, CSE_ICON_PATH + "icon_lines_horizontal_s.paa", cse_exchangeBarrelDisplaySubMenu, "Shows available weapon interactions"] +]; +["ActionMenu","equipment", _entries ] call cse_fnc_addMultipleEntriesToRadialCategory_F; + + diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_removeParticleEffectHeat_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_removeParticleEffectHeat_wh.sqf new file mode 100644 index 0000000000..cda3d4b85a --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_removeParticleEffectHeat_wh.sqf @@ -0,0 +1,26 @@ +/** + * fn_removeParticleEffectHeat_wh.sqf + * @Descr: N/A + * @Author: Glowbal + * + * @Arguments: [unit OBJECT] + * @Return: BOOL Whatever or not a particle effect has been removed + * @PublicAPI: false + */ + +private ["_unit", "_currentParticleEffect"]; +_unit = _this select 0; + +_currentParticleEffect = _unit getvariable "cse_particleEffect_Heat_WH"; +if (!isnil "_currentParticleEffect") exitwith { + deleteVehicle _currentParticleEffect; + _unit setvariable ["cse_particleEffect_Heat_WH", nil]; + + _dummyObj = _unit getvariable "cse_particleEffect_Heat_dummyObj_WH"; + deleteVehicle _dummyObj; + _unit setvariable ["cse_particleEffect_Heat_dummyObj_WH", nil]; + + true +}; + +false diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_setBarrelTemperature_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_setBarrelTemperature_wh.sqf new file mode 100644 index 0000000000..ccf67a5987 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_setBarrelTemperature_wh.sqf @@ -0,0 +1,19 @@ +/** + * fn_setBarrelTemperature_wh.sqf + * @Descr: Calculates the current barrel temperature + * @Author: Ruthberg + * + * @Arguments: [unit OBJECT, weapon STRING, muzzle STRING] + * @Return: barrel temperature in degree celsius + * @PublicAPI: true + */ + + +private ["_unit", "_weapon", "_muzzle", "_barrelTemperature"]; +_unit = _this select 0; +_weapon = _this select 1; +_muzzle = _this select 2; +_barrelTemperature = _this select 3; + +_unit setVariable [format["CSE_BarrelTemperature_%1", _weapon], _barrelTemperature, !(_unit isKindOf "Man")]; +_unit setVariable [format["CSE_BarrelUpdateTime_%1" , _weapon], diag_tickTime, !(_unit isKindOf "Man")]; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_setParticleEffectHeat_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_setParticleEffectHeat_wh.sqf new file mode 100644 index 0000000000..a7735a7cdc --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_setParticleEffectHeat_wh.sqf @@ -0,0 +1,11 @@ + +private ["_unit", "_percentage", "_currentParticleEffect", "_dummyObj"]; +_unit = _this select 0; +_percentage = _this select 1; + +_currentParticleEffect = _unit getvariable "cse_particleEffect_Heat_WH"; +if (!isnil "_currentParticleEffect") then { + _dummyObj = _unit getvariable "cse_particleEffect_Heat_dummyObj_WH"; + _dummyObj attachTo [_unit, (_unit weaponDirection _weapon) vectorMultiply 0.2, "LeftHand"]; + _particleEffect setParticleParams [["\A3\data_f\ParticleEffects\Universal\Refract",1, 0, 1, 0], "", "Billboard", 1, 1.0, [0, 0, 0], [0, 0, 0.0], 0, 0.5, 0.5, 0.1, [1.0], [[1, 0.7, 0.7, 0.5 * _percentage]], [1], 0, 0, "", "", _dummyObj]; +}; diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_swapBarrel_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_swapBarrel_wh.sqf new file mode 100644 index 0000000000..f15ce020c7 --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_swapBarrel_wh.sqf @@ -0,0 +1,48 @@ +private ["_unit", "_weapon"]; +_unit = _this select 0; +_weapon = _this select 1; + +if (!([_unit, _weapon] call cse_fnc_canSwapBarrel_wh)) exitWith {}; +if (vehicle _unit != _unit && {driver (vehicle _unit) == _unit || commander (vehicle _unit) == _unit || gunner (vehicle _unit) == _unit}) exitWith {}; + +if (vehicle _unit == _unit && currentWeapon _unit != "" && !(weaponLowered _unit) && (stance _unit != "PRONE")) then { + _unit action ["WeaponOnBack", _unit]; + waitUntil { weaponLowered _unit }; // probably evil +}; + +[_unit, _weapon] spawn { + private ["_unit", "_weapon", "_spareBarrel", "_ambientTemperature", "_barrelTemperature", "_barrelUpdateTime", "_spareBarrelTemperature", "_spareBarrelUpdateTime"]; + _unit = _this select 0; + _weapon = _this select 1; + + CSE_ORIGINAL_POSITION_BARREL_EXCHANGE_EQ = getPos _unit; + // TODO: Prohibit the player from using his weapon during the barrel exchange progress + CSE_CONDITION_BARREL_EXCHANGE_EQ = {((vehicle _unit != _unit && driver (vehicle _unit) != _unit && commander (vehicle _unit) != _unit && gunner (vehicle _unit) != _unit) || (((getPos _unit) distance CSE_ORIGINAL_POSITION_BARREL_EXCHANGE_EQ) < 1 && (weaponLowered _unit || stance _unit == "PRONE")))}; + + // TODO: Play animation + playSound "cse_weaponheat_barrel_exchange"; + _barrelExchangeSuccess = [15, CSE_CONDITION_BARREL_EXCHANGE_EQ] call cse_fnc_gui_loadingBar; + + if (_barrelExchangeSuccess) then { + _spareBarrel = getText(configFile >> "CfgWeapons" >> _weapon >> "cse_spareBarrel"); + if (!([_unit, _spareBarrel] call cse_fnc_hasItem)) then { + _spareBarrel = "cse_sparebarrelbag"; + }; + _ambientTemperature = 15; + if (["cse_AB_moduleAdvancedBallistics"] call cse_fnc_isModuleEnabled_F) then { + _ambientTemperature = ((getPosASL _unit) select 2) call cse_ab_ballistics_fnc_get_temperature_at_height; + }; + + _barrelTemperature = _unit getVariable [format["CSE_BarrelTemperature_%1", _weapon], _ambientTemperature]; + _barrelUpdateTime = _unit getVariable [format["CSE_BarrelUpdateTime_%1", _weapon], diag_tickTime]; + + _spareBarrelTemperature = _unit getVariable [format["CSE_BarrelTemperature_%1", _spareBarrel], _ambientTemperature]; + _spareBarrelUpdateTime = _unit getVariable [format["CSE_BarrelUpdateTime_%1", _spareBarrel], diag_tickTime]; + + _unit setVariable [format["CSE_BarrelTemperature_%1", _weapon], _spareBarrelTemperature]; + _unit setVariable [format["CSE_BarrelUpdateTime_%1", _weapon], _spareBarrelUpdateTime]; + + _unit setVariable [format["CSE_BarrelTemperature_%1", _spareBarrel], _barrelTemperature]; + _unit setVariable [format["CSE_BarrelUpdateTime_%1", _spareBarrel], _barrelUpdateTime]; + }; +}; \ No newline at end of file diff --git a/TO_MERGE/cse/sys_weaponheat/functions/fn_take_wh.sqf b/TO_MERGE/cse/sys_weaponheat/functions/fn_take_wh.sqf new file mode 100644 index 0000000000..8052b6180d --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/functions/fn_take_wh.sqf @@ -0,0 +1,35 @@ +private ["_unit", "_container", "_item", "_itemCargo", "_spareBarrelCount", "_ambientTemperature", "_spareBarrelTemperature", "_spareBarrelUpdateTime"]; +_unit = _this select 0; +_container = _this select 1; +_item = _this select 2; + +if (_unit != player) exitWith {}; +if (!([configFile >> "CfgWeapons" >> _item, "cse_sparebarrelbag"] call cse_fnc_inheritsFrom)) exitWith {}; +if (_container == uniformContainer player || _container == vestContainer player || _container == backpackContainer player) exitWith {}; + +_itemCargo = getItemCargo _container; +_spareBarrelCount = 0; +{ + if (_x == _item) exitWith { + _spareBarrelCount = (_itemCargo select 1) select _forEachIndex; + }; +} forEach (_itemCargo select 0); + +_ambientTemperature = 15; +if (["cse_AB_moduleAdvancedBallistics"] call cse_fnc_isModuleEnabled_F) then { + _ambientTemperature = ((getPosASL _unit) select 2) call cse_ab_ballistics_fnc_get_temperature_at_height; +}; + +_spareBarrelTemperature = _ambientTemperature; +_spareBarrelUpdateTime = diag_tickTime; + +if (_spareBarrelCount == 0) then { + // Assume that we took an already used spare barrel + _spareBarrelTemperature = _container getVariable [format["CSE_BarrelTemperature_%1", _item], _ambientTemperature]; + _spareBarrelUpdateTime = _container getVariable [format["CSE_BarrelUpdateTime_%1", _item], diag_tickTime]; + _container setVariable [format["CSE_BarrelTemperature_%1", _item], nil]; + _container setVariable [format["CSE_BarrelUpdateTime_%1", _item], nil]; +}; + +_unit setVariable [format["CSE_BarrelTemperature_%1", _item], _spareBarrelTemperature]; +_unit setVariable [format["CSE_BarrelUpdateTime_%1", _item], _spareBarrelUpdateTime]; diff --git a/TO_MERGE/cse/sys_weaponheat/init_sys_weaponheat.sqf b/TO_MERGE/cse/sys_weaponheat/init_sys_weaponheat.sqf new file mode 100644 index 0000000000..3b7c664e9e --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/init_sys_weaponheat.sqf @@ -0,0 +1,31 @@ +if (!hasInterface) exitWith {}; +waitUntil {!isNil "cse_gui" && !isNil "cse_main"}; +waitUntil {!isNull player}; + +player addEventHandler ["Fired", {_this call cse_fnc_handleWeaponHeat_wh}]; +player addEventHandler ["Take", {_this call cse_fnc_take_wh}]; +player addEventHandler ["Put", {_this call cse_fnc_put_wh}]; + +cse_sys_weaponheat = true; +cse_genericSpareBarrel_wh = true; + +_args = _this; +{ + _value = _x select 1; + if (!isNil "_value") then { + _name = _x select 0; + if (_name == "genericSpareBarrel") exitWith { + cse_genericSpareBarrel_wh = _value; + }; + }; +} forEach _args; + +// Clear Malfunction +["cse_weaponheat_clear_malfunction", (["cse_weaponheat_clear_malfunction","action",[20, 0,1,0]] call cse_fnc_getKeyBindingFromProfile_F), + { + [player, currentWeapon player, currentMuzzle player] call cse_fnc_clearMalfunction_wh; + }] call cse_fnc_addKeyBindingForAction_F; + +["cse_weaponheat_clear_malfunction","action", "Clear Malfunction", "Clear Malfunction"] call cse_fnc_settingsDefineDetails_F; + +call cse_fnc_registerBarrelExchangeActions_wh; diff --git a/TO_MERGE/cse/sys_weaponheat/sound/barrel_exchange.wav b/TO_MERGE/cse/sys_weaponheat/sound/barrel_exchange.wav new file mode 100644 index 0000000000..5d3391099a Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/sound/barrel_exchange.wav differ diff --git a/TO_MERGE/cse/sys_weaponheat/sound/fixing_pistol.wav b/TO_MERGE/cse/sys_weaponheat/sound/fixing_pistol.wav new file mode 100644 index 0000000000..d765edd274 Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/sound/fixing_pistol.wav differ diff --git a/TO_MERGE/cse/sys_weaponheat/sound/fixing_rifle.wav b/TO_MERGE/cse/sys_weaponheat/sound/fixing_rifle.wav new file mode 100644 index 0000000000..7f0a640670 Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/sound/fixing_rifle.wav differ diff --git a/TO_MERGE/cse/sys_weaponheat/sound/jamming_pistol.wav b/TO_MERGE/cse/sys_weaponheat/sound/jamming_pistol.wav new file mode 100644 index 0000000000..f7b48fa3e1 Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/sound/jamming_pistol.wav differ diff --git a/TO_MERGE/cse/sys_weaponheat/sound/jamming_rifle.wav b/TO_MERGE/cse/sys_weaponheat/sound/jamming_rifle.wav new file mode 100644 index 0000000000..d44507d01c Binary files /dev/null and b/TO_MERGE/cse/sys_weaponheat/sound/jamming_rifle.wav differ diff --git a/TO_MERGE/cse/sys_weaponheat/stringtable.xml b/TO_MERGE/cse/sys_weaponheat/stringtable.xml new file mode 100644 index 0000000000..e7f8b63e1a --- /dev/null +++ b/TO_MERGE/cse/sys_weaponheat/stringtable.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file