const string STAMINA_TIMER_CALLBACK_NAME = "STAMINA_TIMER_CALLBACK";
const string STAMINA_PLAYER_SPEED = "STAMINA_PLAYER_SPEED";
const string STAMINA_PLAYER_LENGTH = "STAMINA_PLAYER_LENGTH";
const string STAMINA_PLAYER_BREATH_SLOW = "STAMINA_PLAYER_BREATH_SLOW";
const string STAMINA_PLAYER_BREATH_SNT = "react_breath_slow.snt";
const string STAMINA_PLAYER_HEAD_BOB = "STAMINA_PLAYER_HEAD_BOB";
const float STAMINA_TIMER_SPEED_TIME = 0.5f;
const float STAMINA_PLAYER_HEAD_BOB_SPEED = 0.7f;
enum StaminaStages
{
Full,
Low,
Exhausted
}
class StaminaSystem
{
private int state;
private uint length;
private bool head_bobbing;
private bool is_running;
StaminaSystem()
{
PreloadSound(STAMINA_PLAYER_BREATH_SNT);
this.state = StaminaStages::Full;
this.length = 10;
this.head_bobbing = false;
this.is_running = false;
}
~StaminaSystem()
{
this.Stop();
}
void AddDebugMessage(string &in message, bool check, bool to_file)
{
::AddDebugMessage("Stamina system: " + message, check);
if (to_file) Print("Stamina system: " + message);
}
bool IsPlayerRunning() const
{
return this.is_running;
}
void PlayBreathSound()
{
PlaySoundAtEntity(STAMINA_PLAYER_BREATH_SLOW, STAMINA_PLAYER_BREATH_SNT, "Player", 0, false);
}
void Start()
{
SetPlayerRunSpeedMul(1);
SetPlayerMoveSpeedMul(1);
AddTimer(STAMINA_PLAYER_SPEED, STAMINA_TIMER_SPEED_TIME, STAMINA_TIMER_CALLBACK_NAME);
}
void StartPlayerHeadBob()
{
if (this.head_bobbing)
MovePlayerHeadPos(0, -0.35, 0, STAMINA_PLAYER_HEAD_BOB_SPEED, 0.6);
else
MovePlayerHeadPos(0, 0, 0, STAMINA_PLAYER_HEAD_BOB_SPEED, 0.6);
this.head_bobbing = !this.head_bobbing;
AddTimer(STAMINA_PLAYER_HEAD_BOB, 0.75f, STAMINA_TIMER_CALLBACK_NAME);
}
void StartPlayerTiredEffect()
{
this.PlayBreathSound();
AddTimer(STAMINA_PLAYER_BREATH_SLOW, 1.5f, STAMINA_TIMER_CALLBACK_NAME);
}
void Stop()
{
this.StopPlayerTiredEffect();
RemoveTimer(STAMINA_PLAYER_SPEED);
RemoveTimer(STAMINA_PLAYER_LENGTH);
SetPlayerRunSpeedMul(1);
SetPlayerMoveSpeedMul(1);
SetPlayerJumpDisabled(false);
}
void StopPlayerTiredEffect()
{
this.head_bobbing = false;
RemoveTimer(STAMINA_PLAYER_BREATH_SLOW);
RemoveTimer(STAMINA_PLAYER_HEAD_BOB);
MovePlayerHeadPos(0,0,0, 1, 1);
// StopSound(STAMINA_PLAYER_BREATH_SLOW, 1); // Crashes the game upon exit.
}
void SetStaminaLength(uint length)
{
if (length != 0)
this.length = length;
else
this.AddDebugMessage("Length cannot be 0!", false, true);
}
void Update(string &in timer_name)
{
if (timer_name == STAMINA_PLAYER_SPEED)
{
this.is_running = (GetPlayerSpeed() > 3) ? true : false;
if (this.is_running && GetTimerTimeLeft(STAMINA_PLAYER_LENGTH) == 0)
AddTimer(STAMINA_PLAYER_LENGTH, this.length, STAMINA_TIMER_CALLBACK_NAME);
else if(!this.is_running)
{
if (GetTimerTimeLeft(STAMINA_PLAYER_LENGTH) > 0 && this.state == StaminaStages::Full)
RemoveTimer(STAMINA_PLAYER_LENGTH);
else if(this.state == StaminaStages::Low)
AddTimer(STAMINA_PLAYER_LENGTH, this.length/4, STAMINA_TIMER_CALLBACK_NAME);
else if(this.state == StaminaStages::Exhausted)
AddTimer(STAMINA_PLAYER_LENGTH, this.length/2, STAMINA_TIMER_CALLBACK_NAME);
}
AddTimer(timer_name, STAMINA_TIMER_SPEED_TIME, STAMINA_TIMER_CALLBACK_NAME);
}
else if (timer_name == STAMINA_PLAYER_BREATH_SLOW)
this.StartPlayerTiredEffect();
else if (timer_name == STAMINA_PLAYER_HEAD_BOB)
this.StartPlayerHeadBob();
else if (timer_name == STAMINA_PLAYER_LENGTH)
{
if (this.is_running)
{
if (this.state == StaminaStages::Full)
{
this.state++;
SetPlayerRunSpeedMul(0.3);
}
else if (this.state == StaminaStages::Low)
{
this.state++;
SetPlayerRunSpeedMul(0);
SetPlayerMoveSpeedMul(0);
SetPlayerJumpDisabled(true);
this.StartPlayerTiredEffect();
this.StartPlayerHeadBob();
}
}
else
{
this.StopPlayerTiredEffect();
SetPlayerRunSpeedMul(1);
SetPlayerMoveSpeedMul(1);
SetPlayerJumpDisabled(false);
if (this.state == StaminaStages::Low)
this.state = StaminaStages::Full;
else if (this.state == StaminaStages::Exhausted)
this.state = StaminaStages::Full;
}
}
}
}
StaminaSystem stamina_obj;
void STAMINA_TIMER_CALLBACK(string &in timer_name)
{ stamina_obj.Update(timer_name); }