You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
5.9 KiB
251 lines
5.9 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Definition for client-side advisor. |
|
// |
|
//=====================================================================================// |
|
|
|
|
|
|
|
#include "cbase.h" |
|
// this file contains the definitions for the message ID constants (eg ADVISOR_MSG_START_BEAM etc) |
|
#include "npc_advisor_shared.h" |
|
|
|
#if NPC_ADVISOR_HAS_BEHAVIOR |
|
|
|
#include "particles_simple.h" |
|
#include "citadel_effects_shared.h" |
|
#include "particles_attractor.h" |
|
#include "clienteffectprecachesystem.h" |
|
#include "c_te_effect_dispatch.h" |
|
|
|
#include "c_ai_basenpc.h" |
|
#include "dlight.h" |
|
#include "iefx.h" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: unpack a networked entity index into a basehandle. |
|
//----------------------------------------------------------------------------- |
|
inline C_BaseEntity *IndexToEntity( int eindex ) |
|
{ |
|
return ClientEntityList().GetBaseEntityFromHandle(ClientEntityList().EntIndexToHandle(eindex)); |
|
} |
|
|
|
|
|
|
|
#define ADVISOR_ELIGHT_CVARS 1 // enable/disable tuning advisor elight with console variables |
|
|
|
#if ADVISOR_ELIGHT_CVARS |
|
ConVar advisor_elight_e("advisor_elight_e","3"); |
|
ConVar advisor_elight_rfeet("advisor_elight_rfeet","52"); |
|
#endif |
|
|
|
|
|
/*! Client-side reflection of the advisor class. |
|
*/ |
|
class C_NPC_Advisor : public C_AI_BaseNPC |
|
{ |
|
DECLARE_CLASS( C_NPC_Advisor, C_AI_BaseNPC ); |
|
DECLARE_CLIENTCLASS(); |
|
|
|
public: |
|
// Server to client message received |
|
virtual void ReceiveMessage( int classID, bf_read &msg ); |
|
virtual void ClientThink( void ); |
|
|
|
private: |
|
/* |
|
// broken into its own function so I can move it if necesasry |
|
void Initialize(); |
|
*/ |
|
|
|
// start/stop beam particle effect from me to a pelting object |
|
void StartBeamFX( C_BaseEntity *pOnEntity ); |
|
void StopBeamFX( C_BaseEntity *pOnEntity ); |
|
|
|
void StartElight(); |
|
void StopElight(); |
|
|
|
int m_ElightKey; // test using an elight to make the escape sequence more visible. 0 is invalid. |
|
|
|
}; |
|
|
|
IMPLEMENT_CLIENTCLASS_DT( C_NPC_Advisor, DT_NPC_Advisor, CNPC_Advisor ) |
|
|
|
END_RECV_TABLE() |
|
|
|
// Server to client message received |
|
void C_NPC_Advisor::ReceiveMessage( int classID, bf_read &msg ) |
|
{ |
|
if ( classID != GetClientClass()->m_ClassID ) |
|
{ |
|
// message is for subclass |
|
BaseClass::ReceiveMessage( classID, msg ); |
|
return; |
|
} |
|
|
|
int messageType = msg.ReadByte(); |
|
switch( messageType ) |
|
{ |
|
case ADVISOR_MSG_START_BEAM: |
|
{ |
|
int eindex = msg.ReadLong(); |
|
StartBeamFX(IndexToEntity(eindex)); |
|
} |
|
break; |
|
|
|
case ADVISOR_MSG_STOP_BEAM: |
|
{ |
|
int eindex = msg.ReadLong(); |
|
StopBeamFX(IndexToEntity(eindex)); |
|
|
|
} |
|
break; |
|
|
|
case ADVISOR_MSG_STOP_ALL_BEAMS: |
|
{ |
|
ParticleProp()->StopEmission(); |
|
} |
|
break; |
|
case ADVISOR_MSG_START_ELIGHT: |
|
{ |
|
StartElight(); |
|
} |
|
break; |
|
case ADVISOR_MSG_STOP_ELIGHT: |
|
{ |
|
StopElight(); |
|
} |
|
break; |
|
|
|
default: |
|
AssertMsg1( false, "Received unknown message %d", messageType); |
|
} |
|
} |
|
|
|
/// only use of the clientthink on the advisor is to update the elight |
|
void C_NPC_Advisor::ClientThink( void ) |
|
{ |
|
// if the elight has gone away, bail out |
|
if (m_ElightKey == 0) |
|
{ |
|
SetNextClientThink( CLIENT_THINK_NEVER ); |
|
return; |
|
} |
|
|
|
// get the elight |
|
dlight_t * el = effects->GetElightByKey(m_ElightKey); |
|
if (!el) |
|
{ |
|
// the elight has been invalidated. bail out. |
|
m_ElightKey = 0; |
|
|
|
SetNextClientThink( CLIENT_THINK_NEVER ); |
|
return; |
|
} |
|
else |
|
{ |
|
el->origin = WorldSpaceCenter(); |
|
|
|
#if ADVISOR_ELIGHT_CVARS |
|
el->color.exponent = advisor_elight_e.GetFloat(); |
|
el->radius = advisor_elight_rfeet.GetFloat() * 12.0f; |
|
#endif |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Create a telekinetic beam effect from my head to an object |
|
// TODO: use a point attachment. |
|
//----------------------------------------------------------------------------- |
|
void C_NPC_Advisor::StartBeamFX( C_BaseEntity *pOnEntity ) |
|
{ |
|
Assert(pOnEntity); |
|
if (!pOnEntity) |
|
return; |
|
|
|
CNewParticleEffect *pEffect = ParticleProp()->Create( "Advisor_Psychic_Beam", PATTACH_ABSORIGIN_FOLLOW ); |
|
|
|
Assert(pEffect); |
|
if (!pEffect) return; |
|
|
|
ParticleProp()->AddControlPoint( pEffect, 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// terminate a telekinetic beam effect from my head to an object |
|
//----------------------------------------------------------------------------- |
|
void C_NPC_Advisor::StopBeamFX( C_BaseEntity *pOnEntity ) |
|
{ |
|
Assert(pOnEntity); |
|
if (!pOnEntity) |
|
return; |
|
|
|
ParticleProp()->StopParticlesInvolving( pOnEntity ); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
void C_NPC_Advisor::StartElight() |
|
{ |
|
AssertMsg(m_ElightKey == 0 , "Advisor trying to create new elight on top of old one!"); |
|
if ( m_ElightKey != 0 ) |
|
{ |
|
Warning("Advisor tried to start his elight when it was already one.\n"); |
|
} |
|
else |
|
{ |
|
m_ElightKey = LIGHT_INDEX_TE_DYNAMIC + this->entindex(); |
|
dlight_t * el = effects->CL_AllocElight( m_ElightKey ); |
|
|
|
if ( el ) |
|
{ |
|
// create an elight on top of me |
|
el->origin = this->WorldSpaceCenter(); |
|
|
|
el->color.r = 235; |
|
el->color.g = 255; |
|
el->color.b = 255; |
|
el->color.exponent = 3; |
|
|
|
el->radius = 52*12; |
|
el->decay = 0.0f; |
|
el->die = gpGlobals->curtime + 2000.0f; // 1000 just means " a long time " |
|
|
|
SetNextClientThink( CLIENT_THINK_ALWAYS ); |
|
} |
|
else |
|
{ // null out the light value |
|
m_ElightKey = 0; |
|
} |
|
} |
|
} |
|
|
|
void C_NPC_Advisor::StopElight() |
|
{ |
|
AssertMsg( m_ElightKey != 0, "Advisor tried to stop elight when none existed!"); |
|
dlight_t * el; |
|
// note: the following conditional sets el if not short-circuited |
|
if ( m_ElightKey == 0 || (el = effects->GetElightByKey(m_ElightKey)) == NULL ) |
|
{ |
|
Warning("Advisor tried to stop its elight when it had none.\n"); |
|
} |
|
else |
|
{ |
|
// kill the elight by setting the die value to now |
|
el->die = gpGlobals->curtime; |
|
} |
|
} |
|
|
|
|
|
#endif |
|
|
|
/****************************************************** |
|
* Tenser, said the Tensor. * |
|
* Tenser, said the Tensor. * |
|
* Tension, apprehension and dissension have begun. * |
|
******************************************************/
|
|
|