Skip to content

Commit

Permalink
Experimental movement speed limiter
Browse files Browse the repository at this point in the history
  • Loading branch information
ulteq committed Nov 7, 2017
1 parent f2e84c9 commit 32e9989
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 16 deletions.
1 change: 1 addition & 0 deletions addons/advanced_fatigue/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ PREP(addDutyFactor);
PREP(createStaminaBar);
PREP(getAnimDuty);
PREP(getMetabolicCosts);
PREP(getMovementSpeed);
PREP(handleEffects);
PREP(handlePlayerChanged);
PREP(handleStaminaBar);
Expand Down
73 changes: 73 additions & 0 deletions addons/advanced_fatigue/functions/fnc_getMovementSpeed.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Author: BaerMitUmlaut
* Calculates the current maximum movement speed for a unit.
* Calculation is done according to the Pandolf/Wojtowicz formulas.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Power <NUMBER>
* 2: Forward Angle <NUMBER>
* 3: Side Angle <NUMBER>
*
* Return Value:
* Speed <NUMBER>
*
* Example:
* [player, 840, 0, 0] call ace_advanced_fatigue_fnc_getMovementSpeed
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_power", "_fwdAngle", "_sideAngle"];

private _gearMass = 0 max (((_unit getVariable [QEGVAR(movement,totalLoad), loadAbs _unit]) / 22.046 - 3.5) * GVAR(loadFactor));
private _terrainGradient = abs(_fwdAngle);
private _terrainFactor = 1;

private _duty = GVAR(animDuty);
{
if (_x isEqualType 0) then {
_duty = _duty * _x;
} else {
_duty = _duty * (_unit call _x);
};
} forEach (GVAR(dutyList) select 1);

if (!GVAR(isSwimming)) then {
if (_fwdAngle < 0) then {
_terrainGradient = 0.15 * _terrainGradient;
};
if ((getPosATL _unit) select 2 < 0.01) then {
private _sideGradient = abs(_sideAngle / 45) min 1;
_terrainFactor = 1 + _sideGradient ^ 4;
};
};

private _fnc_getRunningSpeed = {
params ["_power", "_gearMass", "_terrainFactor", "_terrainGradient", "_duty"];
private _numerator = 3.6 * - (_power / (0.23 * _duty));
_numerator = _numerator - 2.1 * SIM_BODYMASS;
_numerator = _numerator - 4 * (_gearMass + SIM_BODYMASS) * (_gearMass / SIM_BODYMASS) ^ 2;
private _denominator = _terrainFactor * (_gearMass + SIM_BODYMASS);
private _radicand = ((0.66 * _terrainGradient) ^ 2) - _numerator / _denominator;
private _v = -0.66 * _terrainGradient + sqrt(_radicand);
_v / 1.8
};

private _fnc_getWalkingSpeed = {
params ["_power", "_gearMass", "_terrainFactor", "_terrainGradient", "_duty"];
private _numerator = 4.6 * - (_power / (0.23 * _duty));
_numerator = _numerator - 1.05 * SIM_BODYMASS;
_numerator = _numerator - 2 * (_gearMass + SIM_BODYMASS) * (_gearMass / SIM_BODYMASS) ^ 2;
private _denominator = _terrainFactor * (_gearMass + SIM_BODYMASS);
private _radicand = ((0.66 * _terrainGradient) ^ 2) - _numerator / _denominator;
private _v = -0.66 * _terrainGradient + sqrt(_radicand);
_v / 2.3
};

private _speed = [_power, _gearMass, _terrainFactor, _terrainGradient, _duty] call _fnc_getRunningSpeed;
if (_speed < 2) then {
_speed = [_power, _gearMass, _terrainFactor, _terrainGradient, _duty] call _fnc_getWalkingSpeed;
};

_speed
34 changes: 23 additions & 11 deletions addons/advanced_fatigue/functions/fnc_handleEffects.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
* Arguments:
* 0: Unit <OBJECT>
* 1: Fatigue <NUMBER>
* 2: Speed <NUMBER>
* 3: Respiratory Rate <NUMBER>
* 4: Forward Angle <NUMBER>
* 5: Side Angle <NUMBER>
* 2: Respiratory Rate <NUMBER>
* 3: Current Speed <NUMBER>
* 4: Max Run Speed <NUMBER>
* 5: Max Sprint Speed <NUMBER>
* 6: Forward Angle <NUMBER>
* 7: Side Angle <NUMBER>
*
* Return Value:
* None
Expand All @@ -19,7 +21,7 @@
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_fatigue", "_speed", "_respiratoryRate", "_fwdAngle", "_sideAngle"];
params ["_unit", "_fatigue", "_respiratoryRate", "_currentSpeed", "_maxRunSpeed", "_maxSprintSpeed", "_fwdAngle", "_sideAngle"];

// - Audible effects ----------------------------------------------------------
GVAR(lastBreath) = GVAR(lastBreath) + 1;
Expand Down Expand Up @@ -65,20 +67,30 @@ if (GVAR(isSwimming)) exitWith {
};
};
};
if ((getAnimSpeedCoef _unit) != 1) then {
_unit setAnimSpeedCoef 1;

private _currentAnimCoef = getAnimSpeedCoef _unit;
if (_currentSpeed > 0) then {
if (_currentSpeed > 3.9 || _currentSpeed > GVAR(lastSpeed) + 0.8) then {
_unit setAnimSpeedCoef (0.60 max (_currentAnimCoef * ((_maxSprintSpeed / _currentSpeed) ^ 0.5)) min 1.0);
} else {
_unit setAnimSpeedCoef (0.70 max (_currentAnimCoef * ((_maxRunSpeed / _currentSpeed) ^ 0.5)) min 1.0);
};
GVAR(lastSpeed) = _currentSpeed;
};

if (_fatigue >= 1) then {
if ((!isForcedWalk _unit) && (_fatigue >= 1 || (_currentSpeed < 2.5 && _currentAnimCoef < 0.75))) then {
_unit setAnimSpeedCoef 1;
[_unit, "forceWalk", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
} else {
if (isForcedWalk _unit && _fatigue < 0.8) then {
if (isForcedWalk _unit && _fatigue < 0.85 && _maxRunSpeed > 2.75) then {
_unit setAnimSpeedCoef 0.80;
[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
} else {
if ((isSprintAllowed _unit) && (_fatigue > 0.7 || abs(_fwdAngle) > 20 || abs(_sideAngle) > 20)) then {
if ((isSprintAllowed _unit) && (abs(_fwdAngle) > 20 || abs(_sideAngle) > 20 || _maxSprintSpeed < 3)) then {
_unit setAnimSpeedCoef 1;
[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
} else {
if ((!isSprintAllowed _unit) && _fatigue < 0.6 && abs(_fwdAngle) < 20 && abs(_sideAngle) < 20) then {
if ((!isSprintAllowed _unit) && _fatigue < 0.6 && abs(_fwdAngle) < 20 && abs(_sideAngle) < 20 && _maxSprintSpeed > 5) 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 @@ -69,6 +69,7 @@ GVAR(anWattsPerATP) = GVAR(anPathwayPower) / AN_ATP_RELEASE_RATE;

GVAR(respiratoryBufferDivisor) = (RESPIRATORY_BUFFER - 1) / RESPIRATORY_BUFFER;
GVAR(maxPowerFatigueRatio) = 0.057 / GVAR(peakPower);
GVAR(lastSpeed) = 0;

GVAR(ppeBlackoutLast) = 100;
GVAR(lastBreath) = 0;
Expand Down
25 changes: 20 additions & 5 deletions addons/advanced_fatigue/functions/fnc_mainLoop.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ private _muscleFactor = sqrt (_muscleIntegrity);
private _ae1PathwayPowerFatigued = GVAR(ae1PathwayPower) * sqrt (GVAR(ae1Reserve) / AE1_MAXRESERVE) * _oxygen * _muscleFactor;
private _ae2PathwayPowerFatigued = GVAR(ae2PathwayPower) * sqrt (GVAR(ae2Reserve) / AE2_MAXRESERVE) * _oxygen * _muscleFactor;
private _aePathwayPowerFatigued = _ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued;

private _anPathwayPowerFatigued = GVAR(anPathwayPower) * sqrt(GVAR(anReserve) / AN_MAXRESERVE) * _oxygen * _muscleIntegrity;

// Calculate how much power is consumed from each reserve
private _ae1Power = _currentWork min _ae1PathwayPowerFatigued;
private _ae2Power = (_currentWork - _ae1Power) min _ae2PathwayPowerFatigued;
Expand All @@ -70,8 +71,8 @@ systemChat format["---- ae2: %1 ----", (GVAR(ae2Reserve) / AE2_MAXRESERVE) toFix
systemChat format["---- an: %1 ----", (GVAR(anReserve) / AN_MAXRESERVE) toFixed 2];
systemChat format["---- anFatigue: %1 ----", GVAR(anFatigue) toFixed 2];
systemChat format["---- muscleDamage: %1 ----", GVAR(muscleDamage) toFixed 2];
systemChat format["---- respiratoryRate: %1 ----", GVAR(respiratoryRate) toFixed 2];
systemChat format["---- aePower: %1 ----", _aePathwayPowerFatigued toFixed 1];
//systemChat format["---- respiratoryRate: %1 ----", GVAR(respiratoryRate) toFixed 2];
//systemChat format["---- aePower: %1 ----", _aePathwayPowerFatigued toFixed 1];
#endif

// Acidosis accumulation
Expand All @@ -83,10 +84,24 @@ GVAR(ae2Reserve) = (GVAR(ae2Reserve) + _oxygen * GVAR(recoveryFactor) * AE2_ATP_

private _aeSurplus = _ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power;
// Anaerobic ATP reserve recovery
GVAR(anReserve) = (GVAR(anReserve) + _aeSurplus / GVAR(VO2MaxPower) * AN_ATP_RECOVERY * GVAR(recoveryFactor) * GVAR(anFatigue) ^ 2) min AN_MAXRESERVE;
GVAR(anReserve) = 0 max (GVAR(anReserve) + _aeSurplus / GVAR(VO2MaxPower) * AN_ATP_RECOVERY * GVAR(recoveryFactor) * GVAR(anFatigue) ^ 2) min AN_MAXRESERVE;
// Acidosis recovery
GVAR(anFatigue) = 0 max (GVAR(anFatigue) - _aeSurplus * GVAR(maxPowerFatigueRatio) * GVAR(recoveryFactor) * GVAR(anFatigue) ^ 2) min 1;

// Anaerobic power calculation
_anPower = _anPathwayPowerFatigued * (1 - (GVAR(anFatigue) ^ 2));

// Peak fatigued power calculation
private _peakPowerFatigued = _aePathwayPowerFatigued + _anPower;

// Movement rate limits
private _maxRunSpeed = ([ACE_player, _aePathwayPowerFatigued, _fwdAngle, _sideAngle] call FUNC(getMovementSpeed)) - 0.1;
private _maxSprintSpeed = [ACE_player, _peakPowerFatigued, _fwdAngle, _sideAngle] call FUNC(getMovementSpeed);
#ifdef DEBUG_MODE_FULL
systemChat format["---- maxRunSpeed: %1 ----", _maxRunSpeed toFixed 1];
systemChat format["---- maxSprintSpeed: %1 ----", _maxSprintSpeed toFixed 1];
#endif

// Respiratory rate decrease
GVAR(respiratoryRate) = GVAR(respiratoryRate) * GVAR(respiratoryBufferDivisor);

Expand All @@ -95,7 +110,7 @@ private _aePowerRatio = (GVAR(aePathwayPower) / _aePathwayPowerFatigued) min 2;
private _respiratorySampleDivisor = 1 / (RESPIRATORY_BUFFER * 4.75 * GVAR(VO2Max));
GVAR(respiratoryRate) = (GVAR(respiratoryRate) + _currentWork * _respiratorySampleDivisor * _aePowerRatio) min 1;

[ACE_player, GVAR(anFatigue), _currentSpeed, GVAR(respiratoryRate), _fwdAngle, _sideAngle] call FUNC(handleEffects);
[ACE_player, GVAR(anFatigue), GVAR(respiratoryRate), _currentSpeed, _maxRunSpeed, _maxSprintSpeed, _fwdAngle, _sideAngle] call FUNC(handleEffects);

if (GVAR(enableStaminaBar)) then {
[GVAR(anReserve) / AN_MAXRESERVE] call FUNC(handleStaminaBar);
Expand Down

0 comments on commit 32e9989

Please sign in to comment.