Skip to content

Commit

Permalink
Advanced Fatique - Various improvements
Browse files Browse the repository at this point in the history
* Fixes fatique calculation when walking across structures (bridges, ...)
* Prevents sprinting on very steep terrain
* Adds more in-depth debug output
* Fixes the terrain gradient calculation
* Closes #4492
  • Loading branch information
ulteq committed Nov 2, 2017
1 parent 52450bc commit 147c950
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 29 deletions.
26 changes: 26 additions & 0 deletions addons/advanced_fatigue/XEH_postInit.sqf
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
#include "script_component.hpp"
if (!hasInterface) exitWith {};

#ifdef DEBUG_MODE_FULL
onEachFrame {
private _normal = surfaceNormal (getPosWorld ACE_player);
private _beg = (getPosWorld ACE_player) vectorAdd (_normal vectorMultiply 0.5);
private _end = _beg vectorAdd (_normal vectorMultiply 2.0);
drawLine3D [ASLToATL _beg, ASLToATL _end, [0,1,0,1]];

private _side = vectorNormalized (_normal vectorCrossProduct [0, 0, 1]);
private _end = _beg vectorAdd (_side vectorMultiply 2.0);
drawLine3D [ASLToATL _beg, ASLToATL _end, [0,0,1,1]];

private _up = vectorNormalized (_normal vectorCrossProduct _side);
private _end = _beg vectorAdd (_up vectorMultiply 2.0);
drawLine3D [ASLToATL _beg, ASLToATL _end, [1,0,0,1]];

private _movementVector = vectorNormalized (velocity ACE_player);
private _end = _beg vectorAdd (_movementVector vectorMultiply 2.0);
drawLine3D [ASLToATL _beg, ASLToATL _end, [1,1,0,1]];

private _sideVector = vectorNormalized (_movementVector vectorCrossProduct _normal);
_sideVector set[2, 0];
private _end = _beg vectorAdd (_sideVector vectorMultiply 2.0);
drawLine3D [ASLToATL _beg, ASLToATL _end, [0,1,1,1]];
};
#endif

["ace_settingsInitialized", {
if (!GVAR(enabled)) exitWith {};

Expand Down
2 changes: 1 addition & 1 deletion addons/advanced_fatigue/functions/fnc_getAnimDuty.sqf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Author: BaerMitUmlaut
* Calculates the duty of the current animation.
* Calculates the duty ('postureWeight') of the current animation.
*
* Arguments:
* 0: Unit <OBJECT>
Expand Down
44 changes: 31 additions & 13 deletions addons/advanced_fatigue/functions/fnc_getMetabolicCosts.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@
* Arguments:
* 0: Unit <OBJECT>
* 1: Speed <NUMBER>
* 2: Forward Angle <NUMBER>
* 3: Side Angle <NUMBER>
*
* Return Value:
* Metabolic cost <NUMBER>
*
* Example:
* [player, 3.3] call ace_advanced_fatigue_fnc_getMetabolicCosts
* [player, 3.3, 0, 0] call ace_advanced_fatigue_fnc_getMetabolicCosts
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_velocity"];
params ["_unit", "_speed", "_fwdAngle", "_sideAngle"];

private _gearMass = ((_unit getVariable [QEGVAR(movement,totalLoad), loadAbs _unit]) / 22.046) * GVAR(loadFactor);
private _terrainGradient = 1;
private _terrainFactor = 1;

private _terrainAngle = asin (1 - ((surfaceNormal getPosASL _unit) select 2));
private _terrainGradient = (_terrainAngle / 45 min 1) * 5 * GVAR(terrainGradientFactor);
private _duty = GVAR(animDuty);

{
if (_x isEqualType 0) then {
_duty = _duty * _x;
Expand All @@ -32,20 +33,37 @@ private _duty = GVAR(animDuty);
};
} forEach (GVAR(dutyList) select 1);

if (GVAR(isSwimming)) then {
_terrainGradient = 0;
if (!GVAR(isSwimming)) then {
if (_fwdAngle < 0) then {
_terrainGradient = 0.15 * abs(_fwdAngle);
} else {
_terrainGradient = _fwdAngle;
};
if ((getPosATL _unit) select 2 < 0.01) then {
private _sideGradient = abs(_sideAngle / 45) min 1;
_terrainFactor = 1 + _sideGradient ^ 4;
};
#ifdef DEBUG_MODE_FULL
systemChat format["---- gearMass: %1 ----", _gearMass toFixed 2];
// TODO: Strip this down to 'FwdAngle' and 'SideAngle' once we're convinced of the new method
private _terrainAngleBaer = asin (1 - ((surfaceNormal getPosWorld player) select 2));
private _terrainGradientBaer = (_terrainAngleBaer / 45 min 1) * 5 * GVAR(terrainGradientFactor);
private _impactBaer = (SIM_BODYMASS + _gearMass) * (0.90 * (_speed ^ 2) + 0.66 * _speed * _terrainGradientBaer);
private _impactUlteq = _terrainFactor * (SIM_BODYMASS + _gearMass) * (0.90 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient);
hintSilent format["FwdAngle: %1 | SideAngle: %2 \n Baer -> Angle: %3 | Impact: %4 \n Ulteq -> Angle: %5 | Impact: %6", _fwdAngle toFixed 1, _sideAngle toFixed 1, _terrainGradientBaer toFixed 2, _impactBaer toFixed 2, _terrainGradient toFixed 2, _impactUlteq toFixed 2];
#endif
};

if (_velocity > 2) then {
if (_speed > 2) then {
(
2.10 * SIM_BODYMASS
+ 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
+ (SIM_BODYMASS + _gearMass) * (0.90 * (_velocity ^ 2) + 0.66 * _velocity * _terrainGradient)
) * 0.23 * _duty
+ _terrainFactor * (SIM_BODYMASS + _gearMass) * (0.90 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient)
) * BIOMECH_EFFICIENCY * _duty
} else {
(
1.05 * SIM_BODYMASS
+ 4 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
+ (SIM_BODYMASS + _gearMass) * (1.15 * (_velocity ^ 2) + 0.66 * _velocity * _terrainGradient)
) * 0.23 * _duty
+ 2 * (SIM_BODYMASS + _gearMass) * ((_gearMass / SIM_BODYMASS) ^ 2)
+ _terrainFactor * (SIM_BODYMASS + _gearMass) * (1.15 * (_speed ^ 2) + 0.66 * _speed * _terrainGradient)
) * BIOMECH_EFFICIENCY * _duty
};
14 changes: 8 additions & 6 deletions addons/advanced_fatigue/functions/fnc_handleEffects.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@
* 1: Fatigue <NUMBER>
* 2: Speed <NUMBER>
* 3: Overexhausted <BOOL>
* 4: Forward Angle <NUMBER>
* 5: Side Angle <NUMBER>
*
* Return Value:
* None
*
* Example:
* [_player, 0.5, 3.3, true] call ace_advanced_fatigue_fnc_handleEffects
* [_player, 0.5, 3.3, true, 0, 0] call ace_advanced_fatigue_fnc_handleEffects
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_fatigue", "_speed", "_overexhausted"];
params ["_unit", "_fatigue", "_speed", "_overexhausted", "_fwdAngle", "_sideAngle"];

#ifdef DEBUG_MODE_FULL
systemChat str _fatigue;
systemChat str vectorMagnitude velocity _unit;
systemChat format["---- fatigue: %1 ----", _fatigue toFixed 2];
systemChat format["---- speed: %1 ----", _speed toFixed 2];
#endif

// - Audible effects ----------------------------------------------------------
Expand Down Expand Up @@ -78,10 +80,10 @@ if (_overexhausted) then {
if (isForcedWalk _unit && {_fatigue < 0.7}) then {
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
} else {
if ((isSprintAllowed _unit) && {_fatigue > 0.7}) then {
if ((isSprintAllowed _unit) && (_fatigue > 0.7 || _fwdAngle > 15 || _fwdAngle < -25 || abs(_sideAngle) > 20)) then {
[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
} else {
if ((!isSprintAllowed _unit) && {_fatigue < 0.6}) then {
if ((!isSprintAllowed _unit) && _fatigue < 0.6 && _fwdAngle > -25 && _fwdAngle < 15 && abs(_sideAngle) < 20) then {
[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ GVAR(muscleDamage) = _newUnit getVariable [QGVAR(muscleDamage), 0];
} forEach [QGVAR(ae1Reserve), QGVAR(ae2Reserve), QGVAR(anReserve), QGVAR(anFatigue), QGVAR(muscleDamage)];

GVAR(VO2Max) = 35 + 20 * (_newUnit getVariable [QGVAR(performanceFactor), GVAR(performanceFactor)]);
GVAR(VO2MaxPower) = GVAR(VO2Max) * SIM_BODYMASS * 0.23 * JOULES_PER_ML_O2 / 60;
GVAR(VO2MaxPower) = GVAR(VO2Max) * SIM_BODYMASS * BIOMECH_EFFICIENCY * JOULES_PER_ML_O2 / 60;
GVAR(peakPower) = VO2MAX_STRENGTH * GVAR(VO2MaxPower);

GVAR(ae1PathwayPower) = GVAR(peakPower) / (13.3 + 16.7 + 113.3) * 13.3 * ANTPERCENT ^ 1.28 * 1.362;
Expand Down
17 changes: 14 additions & 3 deletions addons/advanced_fatigue/functions/fnc_mainLoop.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ if (!alive ACE_player) exitWith { // Dead people don't breath, Will also handle
_staminaBarContainer ctrlCommit 1;
};

private _normal = surfaceNormal (getPosWorld ACE_player);
private _movementVector = vectorNormalized (velocity ACE_player);
private _sideVector = vectorNormalized (_movementVector vectorCrossProduct _normal);
private _fwdAngle = asin (_movementVector select 2) * GVAR(terrainGradientFactor);
private _sideAngle = asin (_sideVector select 2) * GVAR(terrainGradientFactor);

private _currentWork = REE;
private _currentSpeed = (vectorMagnitude (velocity ACE_player)) min 6;

Expand All @@ -30,8 +36,8 @@ if (GVAR(isProne)) then {
};

if ((vehicle ACE_player == ACE_player) && {_currentSpeed > 0.1} && {isTouchingGround ACE_player || {underwater ACE_player}}) then {
_currentWork = [ACE_player, _currentSpeed] call FUNC(getMetabolicCosts);
_currentWork = _currentWork max REE;
private _metabolicCost = [ACE_player, _currentSpeed, _fwdAngle, _sideAngle] call FUNC(getMetabolicCosts);
_currentWork = _metabolicCost max REE;
};

// Calculate muscle damage increase
Expand All @@ -52,6 +58,11 @@ private _anPower = (_currentWork - _ae1Power - _ae2Power) max 0;
GVAR(ae1Reserve) = GVAR(ae1Reserve) - _ae1Power / WATTSPERATP;
GVAR(ae2Reserve) = GVAR(ae2Reserve) - _ae2Power / WATTSPERATP;
GVAR(anReserve) = GVAR(anReserve) - _anPower / WATTSPERATP;
#ifdef DEBUG_MODE_FULL
systemChat format["---- ae1: %1 ----", (_ae1Power / WATTSPERATP) toFixed 2];
systemChat format["---- ae2: %1 ----", (_ae2Power / WATTSPERATP) toFixed 2];
systemChat format["---- an: %1 ----", (_anPower / WATTSPERATP) toFixed 2];
#endif
// Increase anearobic fatigue
GVAR(anFatigue) = GVAR(anFatigue) + _anPower * (0.057 / GVAR(peakPower)) * 1.1;

Expand All @@ -72,7 +83,7 @@ private _aeReservePercentage = (GVAR(ae1Reserve) / AE1_MAXRESERVE + GVAR(ae2Rese
private _anReservePercentage = GVAR(anReserve) / AN_MAXRESERVE;
private _perceivedFatigue = 1 - (_anReservePercentage min _aeReservePercentage);

[ACE_player, _perceivedFatigue, _currentSpeed, GVAR(anReserve) == 0] call FUNC(handleEffects);
[ACE_player, _perceivedFatigue, _currentSpeed, GVAR(anReserve) == 0, _fwdAngle, _sideAngle] call FUNC(handleEffects);

if (GVAR(enableStaminaBar)) then {
[GVAR(anReserve) / AN_MAXRESERVE] call FUNC(handleStaminaBar);
Expand Down
11 changes: 6 additions & 5 deletions addons/advanced_fatigue/script_component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define COMPONENT_BEAUTIFIED Advanced Fatigue
#include "\z\ace\addons\main\script_mod.hpp"

// #define DEBUG_MODE_FULL
#define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS

Expand All @@ -20,10 +20,11 @@
#define SIM_BODYMASS 70
#define JOULES_PER_ML_O2 20.9
#define VO2MAX_STRENGTH 4.1
#define REE 18.83 //((0.5617 * SIM_BODYMASS + 42.57) * 0.23)
#define BIOMECH_EFFICIENCY 0.23
#define REE 18.83 //((0.5617 * SIM_BODYMASS + 42.57) * BIOMECH_EFFICIENCY)
#define OXYGEN 0.9
#define WATTSPERATP 7

#define AE1_MAXRESERVE 4000000
#define AE2_MAXRESERVE 84000
#define AN_MAXRESERVE 2300
#define AE1_MAXRESERVE 4000000 // mmol
#define AE2_MAXRESERVE 84000 // mmol
#define AN_MAXRESERVE 2300 // mmol

0 comments on commit 147c950

Please sign in to comment.