210 lines
5.4 KiB
C++
210 lines
5.4 KiB
C++
|
#include "../idlib/precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "Game_local.h"
|
||
|
#include "Healing_Station.h"
|
||
|
|
||
|
CLASS_DECLARATION( idAnimatedEntity, rvHealingStation )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::Think
|
||
|
================
|
||
|
*/
|
||
|
void rvHealingStation::Think ( void ) {
|
||
|
// TODO: I'm guessing this is bad, but I wanted to get this in so that people could start
|
||
|
// placing it. The entity decided to stop thinking and I didn't have time to debug it.
|
||
|
BecomeActive( TH_ALL );
|
||
|
|
||
|
stateThread.Execute();
|
||
|
UpdateAnimation();
|
||
|
|
||
|
if ( thinkFlags & TH_UPDATEVISUALS ) {
|
||
|
if ( healthDispensed > 0 ) {
|
||
|
CreateFrame( float( healthDispensed ) / maxHealth );
|
||
|
}
|
||
|
Present();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::Spawn
|
||
|
================
|
||
|
*/
|
||
|
void rvHealingStation::Spawn ( void ) {
|
||
|
entityToHeal = 0;
|
||
|
nextHealTime = 0;
|
||
|
healFrequency = spawnArgs.GetInt( "heal_frequency", "24" );
|
||
|
healAmount = spawnArgs.GetInt( "heal_amount", "1" );
|
||
|
|
||
|
healthDispensed = 0;
|
||
|
soundStartTime = 0;
|
||
|
soundLength = 0;
|
||
|
maxHealth = spawnArgs.GetInt( "max_health", "100" );
|
||
|
|
||
|
dispenseAnim = GetAnimator()->GetAnim( spawnArgs.GetString( "dispense_anim", "dispense" ) );
|
||
|
|
||
|
CreateFrame( 0 );
|
||
|
|
||
|
stateThread.SetOwner( this );
|
||
|
stateThread.SetName( GetName() );
|
||
|
GetAnimator()->CycleAnim( ANIMCHANNEL_ALL, GetAnimator()->GetAnim( spawnArgs.GetString( "anim", "idle" ) ), gameLocal.time, 4 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::Save
|
||
|
================
|
||
|
*/
|
||
|
void rvHealingStation::Save ( idSaveGame *savefile ) const {
|
||
|
stateThread.Save( savefile );
|
||
|
entityToHeal.Save ( savefile );
|
||
|
savefile->WriteInt( nextHealTime );
|
||
|
savefile->WriteInt( healFrequency );
|
||
|
savefile->WriteInt( healAmount );
|
||
|
savefile->WriteInt( healthDispensed );
|
||
|
savefile->WriteInt( maxHealth );
|
||
|
savefile->WriteInt( dispenseAnim );
|
||
|
savefile->WriteInt( soundStartTime );
|
||
|
savefile->WriteInt( soundLength );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::Restore
|
||
|
================
|
||
|
*/
|
||
|
void rvHealingStation::Restore ( idRestoreGame *savefile ) {
|
||
|
stateThread.Restore( savefile, this );
|
||
|
entityToHeal.Restore ( savefile );
|
||
|
savefile->ReadInt( nextHealTime );
|
||
|
savefile->ReadInt( healFrequency );
|
||
|
savefile->ReadInt( healAmount );
|
||
|
savefile->ReadInt( healthDispensed );
|
||
|
savefile->ReadInt( maxHealth );
|
||
|
savefile->ReadInt( dispenseAnim );
|
||
|
savefile->ReadInt( soundStartTime );
|
||
|
savefile->ReadInt( soundLength );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::BeginHealing
|
||
|
================
|
||
|
*/
|
||
|
void rvHealingStation::BeginHealing ( idEntity *toHeal ) {
|
||
|
entityToHeal = toHeal;
|
||
|
stateThread.SetState( "Healing" );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::EndHealing
|
||
|
================
|
||
|
*/
|
||
|
void rvHealingStation::EndHealing ( void ) {
|
||
|
entityToHeal = NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::CreateFrame
|
||
|
================
|
||
|
*/
|
||
|
void rvHealingStation::CreateFrame ( float station_health ) {
|
||
|
// Update the GUI
|
||
|
if ( renderEntity.gui[ 0 ] ) {
|
||
|
renderEntity.gui[ 0 ]->SetStateFloat( "station_health", 1.0f - station_health );
|
||
|
renderEntity.gui[ 0 ]->StateChanged( gameLocal.time, true );
|
||
|
}
|
||
|
|
||
|
// Update the Animation
|
||
|
int numFrames = GetAnimator()->GetAnim( dispenseAnim )->NumFrames();
|
||
|
float lerp = numFrames * station_health;
|
||
|
int frame = lerp;
|
||
|
lerp = lerp - frame;
|
||
|
frameBlend_t frameBlend = { 0, frame, frame + 1, 1.0f - lerp, lerp };
|
||
|
GetAnimator()->SetFrame( ANIMCHANNEL_ALL, dispenseAnim, frameBlend );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::IsPlaying
|
||
|
================
|
||
|
*/
|
||
|
bool rvHealingStation::IsPlaying ( void ) {
|
||
|
idSoundEmitter* emitter = soundSystem->EmitterForIndex ( SOUNDWORLD_GAME, GetSoundEmitter ( ) );
|
||
|
if( emitter ) {
|
||
|
return ( emitter->CurrentlyPlaying ( ) );
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
States
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
CLASS_STATES_DECLARATION ( rvHealingStation )
|
||
|
STATE ( "Healing", rvHealingStation::State_Healing )
|
||
|
END_CLASS_STATES
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvHealingStation::State_Healing
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvHealingStation::State_Healing ( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
STAGE_INIT,
|
||
|
STAGE_WAIT,
|
||
|
STAGE_DISPENSE,
|
||
|
};
|
||
|
|
||
|
if ( entityToHeal.IsValid() ) {
|
||
|
idPlayer* player = static_cast<idPlayer*>( entityToHeal.GetEntity( ) );
|
||
|
const int entityMaxHealth = player->inventory.maxHealth;
|
||
|
|
||
|
if ( healthDispensed < maxHealth && // and we have health to dispense...
|
||
|
entityToHeal->health < entityMaxHealth && // and the entity needs health.
|
||
|
entityToHeal->health > 0 ) // and he's still alive.
|
||
|
{
|
||
|
switch ( parms.stage ) {
|
||
|
case STAGE_INIT:
|
||
|
soundStartTime = gameLocal.time;
|
||
|
StartSound( "snd_start", SND_CHANNEL_ANY, 0, false, &soundLength );
|
||
|
return SRESULT_STAGE ( STAGE_WAIT );
|
||
|
|
||
|
case STAGE_WAIT:
|
||
|
if ( gameLocal.time > soundStartTime + soundLength ) {
|
||
|
soundStartTime = 0;
|
||
|
soundLength = 0;
|
||
|
return SRESULT_STAGE ( STAGE_DISPENSE );
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
|
||
|
case STAGE_DISPENSE:
|
||
|
if ( gameLocal.time > nextHealTime ) { // If it's time to heal...
|
||
|
int healthGiven = Min( maxHealth - healthDispensed, Min( healAmount, entityMaxHealth - entityToHeal->health ) );
|
||
|
entityToHeal->health += healthGiven;
|
||
|
healthDispensed += healthGiven;
|
||
|
nextHealTime = gameLocal.time + healFrequency;
|
||
|
}
|
||
|
if ( !IsPlaying ( ) ) {
|
||
|
StartSound( "snd_loop", SND_CHANNEL_ANY, 0, false, NULL );
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StopSound ( SND_CHANNEL_ANY, 0 );
|
||
|
StartSound ( "snd_stop", SND_CHANNEL_ANY, 0, false, NULL );
|
||
|
return SRESULT_DONE;
|
||
|
}
|