quake4-sdk/source/game/ai/Monster_RepairBot.cpp
2007-06-15 00:00:00 +00:00

376 lines
9 KiB
C++

#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "../client/ClientModel.h"
class repairBotArm_t {
public:
jointHandle_t joint;
int repairTime;
bool repairing;
rvClientEffectPtr effectRepair;
rvClientEffectPtr effectImpact;
int periodicEndTime;
repairBotArm_t () {
periodicEndTime = -1;
}
void Save ( idSaveGame* savefile ) const;
void Restore ( idRestoreGame* savefile );
};
class rvMonsterRepairBot : public idAI {
public:
CLASS_PROTOTYPE( rvMonsterRepairBot );
rvMonsterRepairBot ( void );
void InitSpawnArgsVariables( void );
void Spawn ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
virtual void Think ( void );
virtual void GetDebugInfo ( debugInfoProc_t proc, void* userData );
protected:
virtual bool CheckActions ( void );
virtual void OnDeath ( void );
int repairEndTime;
float repairEffectDist;
repairBotArm_t armLeft;
repairBotArm_t armRight;
private:
void UpdateRepairs ( repairBotArm_t& arm );
void StopRepairs ( repairBotArm_t& arm );
// Leg states
stateResult_t State_Legs_Move ( const stateParms_t& parms );
stateResult_t State_TorsoAction_Repair ( const stateParms_t& parms );
stateResult_t State_TorsoAction_RepairDone ( const stateParms_t& parms );
CLASS_STATES_PROTOTYPE ( rvMonsterRepairBot );
};
CLASS_DECLARATION( idAI, rvMonsterRepairBot )
END_CLASS
/*
================
rvMonsterRepairBot::rvMonsterRepairBot
================
*/
rvMonsterRepairBot::rvMonsterRepairBot ( ) {
}
void rvMonsterRepairBot::InitSpawnArgsVariables( void )
{
armLeft.joint = animator.GetJointHandle ( spawnArgs.GetString ( "joint_arm_left", "l_fx" ) );
armRight.joint = animator.GetJointHandle ( spawnArgs.GetString ( "joint_arm_right", "r_fx" ) );
repairEffectDist = spawnArgs.GetFloat( "repairEffectDist", "64" );
}
/*
================
rvMonsterRepairBot::Spawn
================
*/
void rvMonsterRepairBot::Spawn ( void ) {
InitSpawnArgsVariables();
}
/*
================
rvMonsterRepairBot::CheckActions
================
*/
bool rvMonsterRepairBot::CheckActions ( void ) {
return false;
}
/*
================
rvMonsterRepairBot::OnDeath
================
*/
void rvMonsterRepairBot::OnDeath ( void ) {
StopRepairs ( armLeft );
StopRepairs ( armRight );
gameLocal.PlayEffect( spawnArgs, "fx_death", GetPhysics()->GetOrigin(), viewAxis );
idAI::OnDeath ( );
}
/*
================
rvMonsterRepairBot::Save
================
*/
void rvMonsterRepairBot::Save( idSaveGame *savefile ) const {
savefile->WriteInt ( repairEndTime );
armLeft.Save ( savefile );
armRight.Save ( savefile );
}
/*
================
rvMonsterRepairBot::Restore
================
*/
void rvMonsterRepairBot::Restore( idRestoreGame *savefile ) {
savefile->ReadInt ( repairEndTime );
armLeft.Restore ( savefile );
armRight.Restore ( savefile );
InitSpawnArgsVariables();
}
/*
================
rvMonsterRepairBot::Think
================
*/
void rvMonsterRepairBot::Think ( void ) {
idAI::Think ( );
// Update repair effects? (dont worry about stopping them, the state ending will do so)
UpdateRepairs ( armLeft );
UpdateRepairs ( armRight );
}
/*
================
rvMonsterRepairBot::UpdateRepairs
================
*/
void rvMonsterRepairBot::UpdateRepairs ( repairBotArm_t& arm ) {
trace_t tr;
idVec3 origin;
idMat3 axis;
if ( arm.joint == INVALID_JOINT ) {
return;
}
if ( gameLocal.time > repairEndTime ) {
StopRepairs ( arm ) ;
return;
}
// If the repair time has been crossed we need to start/stop the repairs
if ( gameLocal.time > arm.repairTime ) {
if ( arm.repairing ) {
StopRepairs ( arm );
arm.repairTime = gameLocal.time + gameLocal.random.RandomInt ( 500 );
arm.repairing = false;
} else {
arm.repairTime = gameLocal.time + gameLocal.random.RandomInt ( 2500 );
arm.repairing = true;
}
}
if ( !arm.repairing ) {
return;
}
// Left repair effect
GetJointWorldTransform ( arm.joint, gameLocal.time, origin, axis );
gameLocal.TracePoint ( this, tr, origin, origin + axis[0] * repairEffectDist, MASK_SHOT_RENDERMODEL, this );
if ( tr.fraction >= 1.0f ) {
StopRepairs ( arm );
} else {
// Start the repair effect if not already started
if ( !arm.effectRepair ) {
arm.effectRepair = PlayEffect ( "fx_repair", arm.joint, true );
}
// If the repair effect is running then set its end origin
if ( arm.effectRepair ) {
arm.effectRepair->SetEndOrigin ( tr.endpos );
}
// Start the impact effect
if ( !arm.effectImpact ) {
arm.effectImpact = PlayEffect ( "fx_repair_impact", tr.endpos, tr.c.normal.ToMat3(), true );
} else {
// Calculate the local origin and axis from the given globals
idVec3 localOrigin = (tr.endpos - renderEntity.origin) * renderEntity.axis.Transpose ( );
idMat3 localAxis = tr.c.normal.ToMat3 ();// * renderEntity.axis.Transpose();
arm.effectImpact->SetOrigin ( localOrigin );
arm.effectImpact->SetAxis ( localAxis );
}
if( gameLocal.GetTime() > arm.periodicEndTime ) {// FIXME: Seems dumb to keep banging on this if the fx isn't defined.
gameLocal.PlayEffect( spawnArgs, "fx_repair_impact_periodic", tr.endpos, tr.c.normal.ToMat3() );
arm.periodicEndTime = gameLocal.GetTime() + SEC2MS( rvRandom::flrand(spawnArgs.GetVec2("impact_fx_delay_range", "1 1")) );
}
}
}
/*
================
rvMonsterRepairBot::StopRepairs
================
*/
void rvMonsterRepairBot::StopRepairs ( repairBotArm_t& arm ) {
if ( arm.effectImpact ) {
arm.effectImpact->Stop ( );
arm.effectImpact = NULL;
}
if ( arm.effectRepair ) {
arm.effectRepair->Stop ( );
arm.effectRepair = NULL;
}
arm.periodicEndTime = -1;
}
/*
================
rvMonsterRepairBot::GetDebugInfo
================
*/
void rvMonsterRepairBot::GetDebugInfo ( debugInfoProc_t proc, void* userData ) {
// Base class first
idAI::GetDebugInfo ( proc, userData );
}
/*
===============================================================================
States
===============================================================================
*/
CLASS_STATES_DECLARATION ( rvMonsterRepairBot )
STATE ( "Legs_Move", rvMonsterRepairBot::State_Legs_Move )
STATE ( "TorsoAction_Repair", rvMonsterRepairBot::State_TorsoAction_Repair )
STATE ( "TorsoAction_RepairDone", rvMonsterRepairBot::State_TorsoAction_RepairDone )
END_CLASS_STATES
/*
================
rvMonsterRepairBot::State_Legs_Move
================
*/
stateResult_t rvMonsterRepairBot::State_Legs_Move ( const stateParms_t& parms ) {
enum {
STAGE_START,
STAGE_START_WAIT,
STAGE_MOVE,
STAGE_MOVE_WAIT,
STAGE_STOP,
STAGE_STOP_WAIT
};
switch ( parms.stage ) {
case STAGE_START:
PlayAnim ( ANIMCHANNEL_LEGS, "idle_to_run", 4 );
return SRESULT_STAGE ( STAGE_START_WAIT );
case STAGE_START_WAIT:
if ( AnimDone ( ANIMCHANNEL_LEGS, 4 ) ) {
return SRESULT_STAGE ( STAGE_MOVE );
}
return SRESULT_WAIT;
case STAGE_MOVE:
PlayCycle ( ANIMCHANNEL_LEGS, "run", 4 );
return SRESULT_STAGE ( STAGE_MOVE_WAIT );
case STAGE_MOVE_WAIT:
if ( !move.fl.moving || !CanMove() ) {
return SRESULT_STAGE ( STAGE_STOP );
}
return SRESULT_WAIT;
case STAGE_STOP:
PlayAnim ( ANIMCHANNEL_LEGS, "run_to_idle", 4 );
return SRESULT_STAGE ( STAGE_STOP_WAIT );
case STAGE_STOP_WAIT:
if ( AnimDone ( ANIMCHANNEL_LEGS, 4 ) ) {
PostAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle", 4 );
return SRESULT_DONE;
}
return SRESULT_WAIT;
}
return SRESULT_ERROR;
}
/*
================
rvMonsterRepairBot::State_TorsoAction_Repair
================
*/
stateResult_t rvMonsterRepairBot::State_TorsoAction_Repair ( const stateParms_t& parms ) {
enum {
STAGE_INIT,
STAGE_REPAIR,
};
switch ( parms.stage ) {
case STAGE_INIT:
DisableAnimState ( ANIMCHANNEL_LEGS );
PlayCycle ( ANIMCHANNEL_TORSO, "repair", 4 );
repairEndTime = gameLocal.time + SEC2MS(scriptedActionEnt->spawnArgs.GetInt ( "duration", "5" ) );
PostAnimState ( ANIMCHANNEL_TORSO, "TorsoAction_RepairDone", 0, 0, SFLAG_ONCLEAR );
return SRESULT_STAGE(STAGE_REPAIR);
case STAGE_REPAIR:
if ( gameLocal.time > repairEndTime ) {
return SRESULT_DONE;
}
return SRESULT_WAIT;
}
return SRESULT_ERROR;
}
/*
================
rvMonsterRepairBot::State_TorsoAction_RepairDone
================
*/
stateResult_t rvMonsterRepairBot::State_TorsoAction_RepairDone ( const stateParms_t& parms ) {
StopRepairs ( armLeft );
StopRepairs ( armRight );
return SRESULT_DONE;
}
/*
================
repairBotArm_t::Save
================
*/
void repairBotArm_t::Save ( idSaveGame* savefile ) const {
savefile->WriteInt ( repairTime );
savefile->WriteBool ( repairing );
effectRepair.Save ( savefile );
effectImpact.Save ( savefile );
savefile->WriteInt ( periodicEndTime );
}
/*
================
repairBotArm_t::Restore
================
*/
void repairBotArm_t::Restore ( idRestoreGame* savefile ) {
savefile->ReadInt ( repairTime );
savefile->ReadBool ( repairing );
effectRepair.Restore ( savefile );
effectImpact.Restore ( savefile );
savefile->ReadInt ( periodicEndTime );
}