overheating: sync weapon temperature across the net, deterministic pseudo-random bullet dispersion

This commit is contained in:
Nicolás Badano 2015-02-14 16:22:02 -03:00 committed by PabstMirror
parent 932e17cea4
commit ac67e45098
5 changed files with 204 additions and 140 deletions

View File

@ -13,7 +13,7 @@ class Extended_PostInit_EventHandlers {
class Extended_FiredBIS_EventHandlers { class Extended_FiredBIS_EventHandlers {
class CAManBase { class CAManBase {
class GVAR(Overheat) { class GVAR(Overheat) {
clientFiredBIS = QUOTE( if (_this select 0 == ACE_player) then {_this call FUNC(overheat)}; ); firedBIS = QUOTE(_this call FUNC(firedEH));
}; };
}; };
}; };

View File

@ -1,21 +1,35 @@
// by esteldunedain // by CAA-Picard
#include "script_component.hpp" #include "script_component.hpp"
if (!hasInterface) exitWith {}; GVAR(pseudoRandomList) = [];
if (isServer) then {
// Construct a list of pseudo random 2D vectors
for "_i" from 0 to 30 do {
GVAR(pseudoRandomList) pushBack [-1 + random 2, -1 + random 2];
};
publicVariable QGVAR(pseudoRandomList);
};
if !(hasInterface) exitWith {};
// Add keybinds // Add keybinds
["ACE3 Weapons", QGVAR(unjamWeapon), localize LSTRING(UnjamWeapon), ["ACE3",
{ localize "STR_ACE_Overheating_UnjamWeapon",
// Conditions: canInteract {
if !([ACE_player, objNull, ["isNotInside"]] call EFUNC(common,canInteractWith)) exitWith {false}; // Conditions: canInteract
// Conditions: specific _exceptions = [];
if !([ACE_player] call EFUNC(common,canUseWeapon) && if !(_exceptions call EGVAR(common,canInteract)) exitWith {false};
{currentWeapon ACE_player in (ACE_player getVariable [QGVAR(jammedWeapons), []])} // Conditions: specific
) exitWith {false}; if !([ACE_player] call EFUNC(common,canUseWeapon) &&
{currentWeapon ACE_player in (ACE_player getVariable [QGVAR(jammedWeapons), []])}
) exitWith {false};
// Statement // Statement
[ACE_player, currentMuzzle ACE_player, false] call FUNC(clearJam); [ACE_player, currentMuzzle ACE_player, false] call FUNC(clearJam);
true true
}, },
{false}, [19, [true, false, false]],
[19, [true, false, false]], false] call CBA_fnc_addKeybind; //R Key false,
"keydown"
] call cba_fnc_registerKeybind;

View File

@ -6,6 +6,7 @@ PREP(checkTemperature);
PREP(clearJam); PREP(clearJam);
PREP(cooldown); PREP(cooldown);
PREP(displayTemperature); PREP(displayTemperature);
PREP(firedEH);
PREP(jamWeapon); PREP(jamWeapon);
PREP(overheat); PREP(overheat);
PREP(swapBarrel); PREP(swapBarrel);

View File

@ -0,0 +1,163 @@
/*
* Author: Commy2 and CAA-Picard
* Handle weapon fire
*
* Argument:
* 0: Unit <OBJECT>
* 1: Weapon <STRING>
* 3: Muzzle <STRING>
* 4: Ammo <STRING>
* 5: Magazine <STRING>
* 6: Projectile <OBJECT>
*
* Return value:
* None
*
* Public: No
*/
#include "\z\ace\addons\overheating\script_component.hpp"
private ["_unit", "_weapon", "_ammo", "_projectile"];
_unit = _this select 0;
// Exit if the unit isn't a player
if !([_unit] call EFUNC(common,isPlayer)) exitWith {};
_weapon = _this select 1;
// Compute new temperature if the unit is the local player
if (_unit == ACE_player) then {
_this call FUNC(overheat);
};
// Get current temperature from the unit variable
_variableName = format [QGVAR(%1), _weapon];
_scaledTemperature = (((_unit getVariable [_variableName, [0,0]]) select 0) / 1000) min 1 max 0;
// Smoke SFX, beginning at TEMP 0.15
private "_intensity";
_intensity = (_scaledTemperature - 0.2) * 1.25;
if (_intensity > 0) then {
private ["_position", "_direction"];
_position = position _projectile;
_direction = (_unit weaponDirection _weapon) vectorMultiply 0.25;
drop [
"\A3\data_f\ParticleEffects\Universal\Refract",
"",
"Billboard",
1.1,
2,
_position,
_direction,
1,
1.2,
1.0,
0.1,
[0.1,0.15],
[[0.06,0.06,0.06,0.32*_scaledTemperature], [0.3,0.3,0.3,0.28*_scaledTemperature], [0.3,0.3,0.3,0.25*_scaledTemperature], [0.3,0.3,0.3,0.22*_scaledTemperature], [0.3,0.3,0.3,0.1*_scaledTemperature]],
[1,0],
0.1,
0.05,
"",
"",
""
];
_intensity = (_scaledTemperature - 0.5) * 2;
if (_intensity > 0) then {
drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 12, 1, 16],
"",
"Billboard",
1,
1.2,
_position,
[0,0,0.25],
0,
1.275,
1,
0.025,
[0.28,0.33,0.37],
[[0.6,0.6,0.6,0.3*_intensity]],
[0.2],
1,
0.04,
"",
"",
""
];
};
};
// Dispersion and bullet slow down
private ["_dispersion", "_slowdownFactor", "_count"];
_dispersion = getArray (configFile >> "CfgWeapons" >> _weapon >> "ACE_Overheating_Dispersion");
_count = count _dispersion;
if (_count > 0) then {
_dispersion = ([_dispersion, (_count - 1) * _scaledTemperature] call EFUNC(common,interpolateFromArray)) max 0;
} else {
_dispersion = 0;
};
_slowdownFactor = getArray (configFile >> "CfgWeapons" >> _weapon >> "ACE_Overheating_slowdownFactor");
_count = count _slowdownFactor;
if (_count > 0) then {
_slowdownFactor = ([_slowdownFactor, (_count - 1) * _scaledTemperature] call EFUNC(common,interpolateFromArray)) max 0;
} else {
_slowdownFactor = 1;
};
// Exit if GVAR(pseudoRandomList) isn't synced yet
if (count GVAR(pseudoRandomList) == 0) exitWith {};
// Get the pseudo random values for dispersion from the remaining ammo count
private "_pseudoRandomPair";
_pseudoRandomPair = GVAR(pseudoRandomList) select ((_unit ammo _weapon) mod count GVAR(pseudoRandomList));
[_projectile, (_pseudoRandomPair select 0) * _dispersion, (_pseudoRandomPair select 1) * _dispersion, (_slowdownFactor - 1) * vectorMagnitude _velocity] call EFUNC(common,changeProjectileDirection);
// Only compute jamming for the local player
if (_unit != ACE_player) exitWith {};
private "_jamChance";
_jamChance = getArray (configFile >> "CfgWeapons" >> _weapon >> "ACE_Overheating_jamChance");
_count = count _jamChance;
if (_count == 0) then {
_jamChance = [0];
_count = 1;
};
_jamChance = [_jamChance, (_count - 1) * _scaledTemperature] call EFUNC(common,interpolateFromArray);
// increase jam chance on dusty grounds if prone
if (stance _unit == "PRONE") then {
private "_surface";
_surface = toArray (surfaceType getPosASL _unit);
_surface deleteAt 0;
_surface = configFile >> "CfgSurfaces" >> toString _surface;
if (isClass _surface) then {
_jamChance = _jamChance + (getNumber (_surface >> "dust")) * _jamChance;
};
};
if ("Jam" in (missionNamespace getvariable ["ACE_Debug", []])) then {
_jamChance = 0.5;
};
["Overheating", [_temperature, _jamChance], {format ["Temperature: %1 - JamChance: %2", _this select 0, _this select 1]}] call EFUNC(common,log);
if (random 1 < _jamChance) then {
[_unit, _weapon] call FUNC(jamWeapon);
};

View File

@ -1,5 +1,5 @@
/* /*
* Author: Commy2 and esteldunedain * Author: Commy2 and CAA-Picard
* Handle weapon fire, heat up the weapon * Handle weapon fire, heat up the weapon
* *
* Argument: * Argument:
@ -17,8 +17,7 @@
*/ */
#include "\z\ace\addons\overheating\script_component.hpp" #include "\z\ace\addons\overheating\script_component.hpp"
private ["_unit", "_weapon", "_ammo", "_projectile", "_velocity", "_variableName", "_overheat", "_temperature", "_time", "_bulletMass", "_energyIncrement", "_barrelMass", "_scaledTemperature", "_intensity", "_position", "_direction", "_dispersion", "_count", "_slowdownFactor", "_jamChance", "_surface"]; private ["_unit", "_weapon", "_ammo", "_projectile"];
_unit = _this select 0; _unit = _this select 0;
_weapon = _this select 1; _weapon = _this select 1;
_ammo = _this select 4; _ammo = _this select 4;
@ -26,6 +25,8 @@ _projectile = _this select 6;
_velocity = velocity _projectile; _velocity = velocity _projectile;
private ["_variableName", "_overheat", "_temperature", "_time", "_energyIncrement", "_barrelMass"];
// each weapon has it's own variable. Can't store the temperature in the weapon since they are not objects unfortunately. // each weapon has it's own variable. Can't store the temperature in the weapon since they are not objects unfortunately.
_variableName = format [QGVAR(%1), _weapon]; _variableName = format [QGVAR(%1), _weapon];
@ -37,134 +38,19 @@ _time = _overheat select 1;
// Get physical parameters // Get physical parameters
_bulletMass = getNumber (configFile >> "CfgAmmo" >> _ammo >> "ACE_BulletMass"); _bulletMass = getNumber (configFile >> "CfgAmmo" >> _ammo >> "ACE_BulletMass");
if (_bulletMass == 0) then { if (_bulletMass == 0) then {
// If the bullet mass is not configured, estimate it directly in grams // If the bullet mass is not configured, estimate it
_bulletMass = 3.4334 + 0.5171 * (getNumber (configFile >> "CfgAmmo" >> _ammo >> "hit") + getNumber (configFile >> "CfgAmmo" >> _ammo >> "caliber")); _bulletMass = 3.4334 + 0.5171 * (getNumber (configFile >> "CfgAmmo" >> _ammo >> "hit") + getNumber (configFile >> "CfgAmmo" >> _ammo >> "caliber"));
}; };
_energyIncrement = 0.75 * 0.0005 * _bulletMass * (vectorMagnitudeSqr _velocity); _energyIncrement = 0.75 * 0.0005 * _bulletMass * (vectorMagnitudeSqr _velocity);
_barrelMass = 0.50 * (getNumber (configFile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "mass") / 22.0) max 1.0; _barrelMass = 0.50 * (getNumber (configFile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "mass") / 22.0) max 1.0;
// Calculate cooling // Calculate cooling
_temperature = [_temperature, _barrelMass, ACE_time - _time] call FUNC(cooldown); _temperature = [_temperature, _barrelMass, time - _time] call FUNC(cooldown);
// Calculate heating // Calculate heating
_temperature = _temperature + _energyIncrement / (_barrelMass * 466); // Steel Heat Capacity = 466 J/(Kg.K) _temperature = _temperature + _energyIncrement / (_barrelMass * 466); // Steel Heat Capacity = 466 J/(Kg.K)
// set updated values // set updated values
_time = ACE_time; _time = time;
_unit setVariable [_variableName, [_temperature, _time], false];
_scaledTemperature = (_temperature / 1000) min 1 max 0;
// Smoke SFX, beginning at TEMP 0.15 // Publish the variable
private "_intensity"; [_unit, _variableName, [_temperature, _time], 2.0] call EFUNC(common,setVariablePublic);
_intensity = (_scaledTemperature - 0.2) * 1.25;
if (_intensity > 0) then {
private ["_position", "_direction"];
_position = position _projectile;
_direction = (_unit weaponDirection _weapon) vectorMultiply 0.25;
drop [
"\A3\data_f\ParticleEffects\Universal\Refract",
"",
"Billboard",
1.1,
2,
_position,
_direction,
1,
1.2,
1.0,
0.1,
[0.1,0.15],
[[0.06,0.06,0.06,0.32*_scaledTemperature], [0.3,0.3,0.3,0.28*_scaledTemperature], [0.3,0.3,0.3,0.25*_scaledTemperature], [0.3,0.3,0.3,0.22*_scaledTemperature], [0.3,0.3,0.3,0.1*_scaledTemperature]],
[1,0],
0.1,
0.05,
"",
"",
""
];
_intensity = (_scaledTemperature - 0.5) * 2;
if (_intensity > 0) then {
drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 12, 1, 16],
"",
"Billboard",
1,
1.2,
_position,
[0,0,0.25],
0,
1.275,
1,
0.025,
[0.28,0.33,0.37],
[[0.6,0.6,0.6,0.3*_intensity]],
[0.2],
1,
0.04,
"",
"",
""
];
};
};
// dispersion and bullet slow down
private ["_dispersion", "_slowdownFactor", "_count"];
_dispersion = getArray (configFile >> "CfgWeapons" >> _weapon >> "ACE_Overheating_Dispersion");
_count = count _dispersion;
if (_count > 0) then {
_dispersion = ([_dispersion, (_count - 1) * _scaledTemperature] call EFUNC(common,interpolateFromArray)) max 0;
} else {
_dispersion = 0;
};
_slowdownFactor = getArray (configFile >> "CfgWeapons" >> _weapon >> "ACE_Overheating_slowdownFactor");
_count = count _slowdownFactor;
if (_count > 0) then {
_slowdownFactor = ([_slowdownFactor, (_count - 1) * _scaledTemperature] call EFUNC(common,interpolateFromArray)) max 0;
} else {
_slowdownFactor = 1;
};
[_projectile, _dispersion - 2 * random _dispersion, _dispersion - 2 * random _dispersion, (_slowdownFactor - 1) * vectorMagnitude _velocity] call EFUNC(common,changeProjectileDirection);
// jamming
private "_jamChance";
_jamChance = getArray (configFile >> "CfgWeapons" >> _weapon >> "ACE_Overheating_jamChance");
_count = count _jamChance;
if (_count == 0) then {
_jamChance = [0];
_count = 1;
};
_jamChance = [_jamChance, (_count - 1) * _scaledTemperature] call EFUNC(common,interpolateFromArray);
// increase jam chance on dusty grounds if prone
if (stance _unit == "PRONE") then {
private "_surface";
_surface = toArray (surfaceType getPosASL _unit);
_surface deleteAt 0;
_surface = configFile >> "CfgSurfaces" >> toString _surface;
if (isClass _surface) then {
_jamChance = _jamChance + (getNumber (_surface >> "dust")) * _jamChance;
};
};
if ("Jam" in (missionNamespace getVariable ["ACE_Debug", []])) then {
_jamChance = 0.5;
};
if (random 1 < _jamChance) then {
[_unit, _weapon] call FUNC(jamWeapon);
};