1960 lines
49 KiB
C++
1960 lines
49 KiB
C++
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
//----------------------------------------------------------------
|
||
|
// ClientEntity.cpp
|
||
|
//----------------------------------------------------------------
|
||
|
|
||
|
#include "../precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#include "ClientEntity.h"
|
||
|
#include "../Player.h"
|
||
|
#include "../script/Script_Helper.h"
|
||
|
#include "../script/Script_ScriptObject.h"
|
||
|
#include "ClientEffect.h"
|
||
|
#include "../../decllib/declTypeHolder.h"
|
||
|
#include "../guis/UserInterfaceLocal.h"
|
||
|
#include "../guis/GuiSurface.h"
|
||
|
#include "../ContentMask.h"
|
||
|
|
||
|
ABSTRACT_DECLARATION( idClass, rvClientEntity )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::rvClientEntity
|
||
|
================
|
||
|
*/
|
||
|
rvClientEntity::rvClientEntity( void ) {
|
||
|
entityNumber = -1;
|
||
|
|
||
|
worldOrigin.Zero();
|
||
|
worldAxis.Identity();
|
||
|
|
||
|
spawnNode.SetOwner( this );
|
||
|
bindNode.SetOwner( this );
|
||
|
instanceNode.SetOwner( this );
|
||
|
|
||
|
memset ( &refSound, 0, sizeof(refSound) );
|
||
|
|
||
|
gameLocal.RegisterClientEntity ( this );
|
||
|
|
||
|
axisBind = true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::~rvClientEntity
|
||
|
================
|
||
|
*/
|
||
|
rvClientEntity::~rvClientEntity( void ) {
|
||
|
CleanUp();
|
||
|
|
||
|
gameLocal.UnregisterClientEntity( this );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::CleanUp
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::CleanUp( void ) {
|
||
|
Unbind();
|
||
|
|
||
|
RemoveClientEntities();
|
||
|
|
||
|
// Free sound emitter
|
||
|
if ( refSound.referenceSound != NULL ) {
|
||
|
refSound.referenceSound->Free( false );
|
||
|
refSound.referenceSound = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
rvClientEntity::Dispose
|
||
|
=====================
|
||
|
*/
|
||
|
void rvClientEntity::Dispose( void ) {
|
||
|
CleanUp();
|
||
|
PostEventMS( &EV_Remove, 0 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::Present
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::Present( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::Think
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::Think( void ) {
|
||
|
if ( bindMaster.IsValid() && bindMaster->IsInterpolated() ) {
|
||
|
UpdateBind( true );
|
||
|
} else {
|
||
|
UpdateBind( false );
|
||
|
}
|
||
|
|
||
|
UpdateSound();
|
||
|
Present();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::ClientUpdateView
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::ClientUpdateView( void ) {
|
||
|
UpdateBind( true );
|
||
|
Present();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::Bind
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::Bind( idEntity* master, jointHandle_t joint ) {
|
||
|
Unbind();
|
||
|
|
||
|
if ( joint != INVALID_JOINT && !master->GetAnimator() ) {
|
||
|
gameLocal.Warning( "rvClientEntity::Bind: entity '%s' cannot support skeletal models.", master->GetName() );
|
||
|
joint = INVALID_JOINT;
|
||
|
}
|
||
|
|
||
|
bindMaster = master;
|
||
|
bindJoint = joint;
|
||
|
bindOrigin = worldOrigin;
|
||
|
bindAxis = worldAxis;
|
||
|
|
||
|
bindNode.AddToEnd( bindMaster->clientEntities );
|
||
|
|
||
|
UpdateBind( false );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::Bind
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::Bind( rvClientEntity* master, jointHandle_t joint ) {
|
||
|
Unbind();
|
||
|
|
||
|
if ( joint != INVALID_JOINT && !master->GetAnimator() ) {
|
||
|
gameLocal.Warning( "rvClientEntity::Bind: entity '%s' cannot support skeletal models.", master->GetName() );
|
||
|
joint = INVALID_JOINT;
|
||
|
}
|
||
|
|
||
|
bindMasterClient = master;
|
||
|
bindJoint = joint;
|
||
|
bindOrigin = worldOrigin;
|
||
|
bindAxis = worldAxis;
|
||
|
|
||
|
bindNode.AddToEnd( bindMasterClient->clientEntities );
|
||
|
|
||
|
UpdateBind( false );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
rvClientEntity::PlayEffect
|
||
|
=====================
|
||
|
*/
|
||
|
rvClientEffect* rvClientEntity::PlayEffect( const char* effectName, const idVec3& color, const char* materialType, jointHandle_t jointHandle, bool loop, const idVec3& endOrigin ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::PlayEffect
|
||
|
================
|
||
|
*/
|
||
|
rvClientEffect* rvClientEntity::PlayEffect( const int effectHandle, const idVec3& color, jointHandle_t joint, bool loop, const idVec3& endOrigin ) {
|
||
|
if ( !gameLocal.DoClientSideStuff() ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// assert ( joint != INVALID_JOINT );
|
||
|
|
||
|
if ( effectHandle < 0 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
rvClientEffect* effect = new rvClientEffect( effectHandle );
|
||
|
effect->SetOrigin( vec3_origin );
|
||
|
effect->SetAxis( mat3_identity );
|
||
|
effect->Bind( this, joint );
|
||
|
effect->SetGravity( gameLocal.GetGravity() );
|
||
|
effect->SetMaterialColor( color );
|
||
|
|
||
|
if ( !effect->Play ( gameLocal.time, loop, endOrigin ) ) {
|
||
|
delete effect;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return effect;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::Unbind
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::Unbind ( void ) {
|
||
|
bindMaster = NULL;
|
||
|
bindMasterClient = NULL;
|
||
|
bindNode.Remove();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::SetOrigin
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::SetOrigin( const idVec3& origin ) {
|
||
|
if ( IsBound() ) {
|
||
|
bindOrigin = origin;
|
||
|
} else {
|
||
|
worldOrigin = origin;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::SetAxis
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::SetAxis ( const idMat3& axis ) {
|
||
|
if ( IsBound() && axisBind ) {
|
||
|
bindAxis = axis;
|
||
|
} else {
|
||
|
worldAxis = axis;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::IsBound
|
||
|
================
|
||
|
*/
|
||
|
bool rvClientEntity::IsBound( void ) {
|
||
|
return bindMaster != NULL || bindMasterClient != NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::UpdateBind
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::UpdateBind( bool skipModelUpdate ) {
|
||
|
if ( !IsBound() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
idMat3 tempWorldAxis;
|
||
|
if ( bindJoint != INVALID_JOINT ) {
|
||
|
if ( bindMaster.IsValid() ) {
|
||
|
if ( skipModelUpdate ) {
|
||
|
bindMaster->GetWorldOriginAxisNoUpdate( bindJoint, worldOrigin, tempWorldAxis );
|
||
|
} else {
|
||
|
bindMaster->GetAnimator()->GetJointTransform( bindJoint, gameLocal.time, worldOrigin, tempWorldAxis );
|
||
|
worldOrigin = bindMaster->GetLastPushedOrigin() + ( worldOrigin * bindMaster->GetLastPushedAxis() );
|
||
|
tempWorldAxis *= bindMaster->GetLastPushedAxis();
|
||
|
}
|
||
|
} else {
|
||
|
rvClientEntity* clientEnt = bindMasterClient;
|
||
|
|
||
|
clientEnt->GetAnimator()->GetJointTransform( bindJoint, gameLocal.time, worldOrigin, tempWorldAxis );
|
||
|
|
||
|
renderEntity_t* renderEnt = clientEnt->GetRenderEntity();
|
||
|
|
||
|
worldOrigin = renderEnt->origin + ( worldOrigin * renderEnt->axis );
|
||
|
tempWorldAxis *= renderEnt->axis;
|
||
|
}
|
||
|
} else {
|
||
|
if ( bindMaster.IsValid() ) {
|
||
|
worldOrigin = bindMaster->GetLastPushedOrigin();
|
||
|
tempWorldAxis = bindMaster->GetLastPushedAxis();
|
||
|
} else {
|
||
|
renderEntity_t* renderEnt = bindMasterClient->GetRenderEntity();
|
||
|
|
||
|
worldOrigin = renderEnt->origin;
|
||
|
tempWorldAxis = renderEnt->axis;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
worldOrigin += (bindOrigin * tempWorldAxis);
|
||
|
if ( axisBind ) {
|
||
|
worldAxis = bindAxis * tempWorldAxis;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::DrawDebugInfo
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::DrawDebugInfo ( void ) const {
|
||
|
idBounds bounds( idVec3(-8,-8,-8), idVec3(8,8,8) );
|
||
|
|
||
|
gameRenderWorld->DebugBounds( colorGreen, bounds, worldOrigin );
|
||
|
|
||
|
if ( gameLocal.GetLocalPlayer() ) {
|
||
|
gameRenderWorld->DrawText( GetClassname(), worldOrigin, 0.1f, colorWhite, gameLocal.GetLocalPlayer()->firstPersonViewAxis, 1 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::UpdateSound
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::UpdateSound( void ) {
|
||
|
if ( refSound.referenceSound ) {
|
||
|
refSound.origin = worldOrigin;
|
||
|
refSound.referenceSound->UpdateEmitter( refSound.origin, refSound.listenerId, &refSound.parms );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::StartSoundShader
|
||
|
================
|
||
|
*/
|
||
|
int rvClientEntity::StartSoundShader( const idSoundShader* shader, const soundChannel_t channel, int soundShaderFlags ) {
|
||
|
if ( !shader ) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if ( !refSound.referenceSound ) {
|
||
|
refSound.referenceSound = gameSoundWorld->AllocSoundEmitter();
|
||
|
}
|
||
|
|
||
|
UpdateSound();
|
||
|
|
||
|
return refSound.referenceSound->StartSound( shader, channel, channel, gameLocal.random.RandomFloat(), soundShaderFlags );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::GetClientMaster
|
||
|
================
|
||
|
*/
|
||
|
rvClientPhysics* rvClientEntity::GetClientMaster( void ) {
|
||
|
return gameLocal.entities[ ENTITYNUM_CLIENT ]->Cast< rvClientPhysics >();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::MakeCurrent
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::MakeCurrent( void ) {
|
||
|
rvClientPhysics* clientEnt = GetClientMaster();
|
||
|
if ( clientEnt ) {
|
||
|
clientEnt->PushCurrentClientEntity( entityNumber );
|
||
|
} else {
|
||
|
assert( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::ResetCurrent
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::ResetCurrent( void ) {
|
||
|
rvClientPhysics* clientEnt = GetClientMaster();
|
||
|
if ( clientEnt ) {
|
||
|
clientEnt->PopCurrentClientEntity();
|
||
|
} else {
|
||
|
assert( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::RunPhysics
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::RunPhysics( void ) {
|
||
|
idPhysics* physics = GetPhysics();
|
||
|
if ( physics ) {
|
||
|
MakeCurrent();
|
||
|
physics->Evaluate( gameLocal.time - gameLocal.previousTime, gameLocal.time );
|
||
|
worldOrigin = physics->GetOrigin();
|
||
|
worldAxis = physics->GetAxis();
|
||
|
ResetCurrent();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::GetPhysics
|
||
|
================
|
||
|
*/
|
||
|
idPhysics* rvClientEntity::GetPhysics( void ) const {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::Collide
|
||
|
================
|
||
|
*/
|
||
|
bool rvClientEntity::Collide( const trace_t &collision, const idVec3 &velocity ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvClientEntity::RemoveClientEntities
|
||
|
================
|
||
|
*/
|
||
|
void rvClientEntity::RemoveClientEntities( void ) {
|
||
|
rvClientEntity* cent;
|
||
|
rvClientEntity* next;
|
||
|
|
||
|
// jrad - keep client effect entities around so they can finish thinking/evaluating
|
||
|
for( cent = clientEntities.Next(); cent != NULL; cent = next ) {
|
||
|
next = cent->bindNode.Next();
|
||
|
|
||
|
rvClientEffect* effect = cent->Cast< rvClientEffect >();
|
||
|
if ( effect ) {
|
||
|
effect->Stop();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
cent->Dispose();
|
||
|
}
|
||
|
clientEntities.Clear();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
rvClientPhysics
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
extern const idEventDef EV_GetWorldOrigin;
|
||
|
|
||
|
CLASS_DECLARATION( idEntity, rvClientPhysics )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
rvClientPhysics::~rvClientPhysics
|
||
|
=====================
|
||
|
*/
|
||
|
rvClientPhysics::~rvClientPhysics( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
rvClientPhysics::Spawn
|
||
|
=====================
|
||
|
*/
|
||
|
void rvClientPhysics::Spawn( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
rvClientPhysics::CanCollide
|
||
|
=====================
|
||
|
*/
|
||
|
bool rvClientPhysics::CanCollide( const idEntity* other, int traceId ) const {
|
||
|
return GetCurrentClientEntity()->CanCollide( other, traceId );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
rvClientPhysics::Collide
|
||
|
=====================
|
||
|
*/
|
||
|
bool rvClientPhysics::Collide( const trace_t &collision, const idVec3 &velocity, int bodyId ) {
|
||
|
return GetCurrentClientEntity()->Collide( collision, velocity );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
rvClientPhysics::GetCurrentClientEntity
|
||
|
=====================
|
||
|
*/
|
||
|
rvClientEntity* rvClientPhysics::GetCurrentClientEntity( void ) const {
|
||
|
assert( activeEntities.Num() && activeEntities[ 0 ] >= 0 && activeEntities[ 0 ] < MAX_CENTITIES );
|
||
|
assert( gameLocal.clientEntities[ activeEntities[ 0 ] ] );
|
||
|
|
||
|
return gameLocal.clientEntities[ activeEntities[ 0 ] ];
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdClientScriptEntity
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
extern const idEventDef EV_GetJointHandle;
|
||
|
extern const idEventDef EV_SetState;
|
||
|
|
||
|
const idEventDef EV_Dispose( "dispose", '\0', DOC_TEXT( "Removes all allocated resources associated with the entity, and schedules it for deletion at the end of the frame." ), 0, NULL );
|
||
|
const idEventDef EV_EnableAxisBind( "enableAxisBind", '\0', DOC_TEXT( "Enables/disables orientation locked bind mode." ), 1, NULL, "b", "state", "Whether to enable or disable the mode." );
|
||
|
|
||
|
CLASS_DECLARATION( rvClientEntity, sdClientScriptEntity )
|
||
|
EVENT( EV_GetWorldOrigin, sdClientScriptEntity::Event_GetWorldOrigin )
|
||
|
EVENT( EV_GetWorldAxis, sdClientScriptEntity::Event_GetWorldAxis )
|
||
|
EVENT( EV_GetOwner, sdClientScriptEntity::Event_GetOwner )
|
||
|
EVENT( EV_IsOwner, sdClientScriptEntity::Event_IsOwner )
|
||
|
EVENT( EV_GetDamagePower, sdClientScriptEntity::Event_GetDamagePower )
|
||
|
EVENT( EV_SetState, sdClientScriptEntity::Event_SetState )
|
||
|
EVENT( EV_GetKey, sdClientScriptEntity::Event_GetKey )
|
||
|
EVENT( EV_GetIntKey, sdClientScriptEntity::Event_GetIntKey )
|
||
|
EVENT( EV_GetFloatKey, sdClientScriptEntity::Event_GetFloatKey )
|
||
|
EVENT( EV_GetVectorKey, sdClientScriptEntity::Event_GetVectorKey )
|
||
|
EVENT( EV_GetEntityKey, sdClientScriptEntity::Event_GetEntityKey )
|
||
|
EVENT( EV_PlayEffect, sdClientScriptEntity::Event_PlayEffect )
|
||
|
EVENT( EV_StopEffect, sdClientScriptEntity::Event_StopEffect )
|
||
|
EVENT( EV_StopEffectHandle, sdClientScriptEntity::Event_StopEffectHandle )
|
||
|
EVENT( EV_PlayMaterialEffect, sdClientScriptEntity::Event_PlayMaterialEffect )
|
||
|
EVENT( EV_KillEffect, sdClientScriptEntity::Event_KillEffect )
|
||
|
EVENT( EV_SetOrigin, sdClientScriptEntity::Event_SetOrigin )
|
||
|
EVENT( EV_SetAngles, sdClientScriptEntity::Event_SetAngles )
|
||
|
EVENT( EV_SetGravity, sdClientScriptEntity::Event_SetGravity )
|
||
|
EVENT( EV_SetWorldAxis, sdClientScriptEntity::Event_SetWorldAxis )
|
||
|
EVENT( EV_Bind, sdClientScriptEntity::Event_Bind )
|
||
|
EVENT( EV_BindToJoint, sdClientScriptEntity::Event_BindToJoint )
|
||
|
EVENT( EV_Unbind, sdClientScriptEntity::Event_UnBind )
|
||
|
EVENT( EV_AddCheapDecal, sdClientScriptEntity::Event_AddCheapDecal )
|
||
|
EVENT( EV_GetJointHandle, sdClientScriptEntity::Event_GetJointHandle )
|
||
|
EVENT( EV_Dispose, sdClientScriptEntity::Event_Dispose )
|
||
|
EVENT( EV_EnableAxisBind, sdClientScriptEntity::Event_EnableAxisBind )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::sdClientScriptEntity
|
||
|
=====================
|
||
|
*/
|
||
|
sdClientScriptEntity::sdClientScriptEntity( void ) {
|
||
|
scriptState = NULL;
|
||
|
scriptIdealState = NULL;
|
||
|
baseScriptThread = NULL;
|
||
|
scriptObject = NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::~sdClientScriptEntity
|
||
|
=====================
|
||
|
*/
|
||
|
sdClientScriptEntity::~sdClientScriptEntity( void ) {
|
||
|
CleanUp();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::CleanUp
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::CleanUp( void ) {
|
||
|
if ( baseScriptThread != NULL ) {
|
||
|
gameLocal.program->FreeThread( baseScriptThread );
|
||
|
baseScriptThread = NULL;
|
||
|
}
|
||
|
|
||
|
DeconstructScriptObject();
|
||
|
|
||
|
rvClientEntity::CleanUp();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Think
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Think( void ) {
|
||
|
UpdateScript();
|
||
|
rvClientEntity::Think();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Spawn
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Create( const idDict* _spawnArgs, const sdProgram::sdTypeInfo* type ) {
|
||
|
if ( _spawnArgs ) {
|
||
|
spawnArgs = *_spawnArgs;
|
||
|
} else {
|
||
|
spawnArgs.Clear();
|
||
|
}
|
||
|
|
||
|
if ( type ) {
|
||
|
scriptObject = gameLocal.program->AllocScriptObject( this, type );
|
||
|
|
||
|
baseScriptThread = ConstructScriptObject();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Spawn
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::CreateByName( const idDict* _spawnArgs, const char* scriptObjectName ) {
|
||
|
Create( _spawnArgs, gameLocal.program->FindTypeInfo( scriptObjectName ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::UpdateScript
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::UpdateScript( void ) {
|
||
|
if ( !baseScriptThread || gameLocal.IsPaused() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// a series of state changes can happen in a single frame.
|
||
|
// this loop limits them in case we've entered an infinite loop.
|
||
|
for( int i = 0; i < 20; i++ ) {
|
||
|
if ( scriptIdealState != scriptState ) {
|
||
|
SetState( scriptIdealState );
|
||
|
}
|
||
|
|
||
|
// don't call script until it's done waiting
|
||
|
if ( baseScriptThread->IsWaiting() ) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// MakeCurrent();
|
||
|
baseScriptThread->Execute();
|
||
|
// ResetCurrent();
|
||
|
|
||
|
if ( scriptIdealState == scriptState ) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::ConstructScriptObject
|
||
|
================
|
||
|
*/
|
||
|
sdProgramThread* sdClientScriptEntity::ConstructScriptObject( void ) {
|
||
|
// init the script object's data
|
||
|
scriptObject->ClearObject();
|
||
|
|
||
|
sdScriptHelper h1, h2;
|
||
|
CallNonBlockingScriptEvent( scriptObject->GetSyncFunc(), h1 );
|
||
|
CallNonBlockingScriptEvent( scriptObject->GetPreConstructor(), h2 );
|
||
|
|
||
|
sdProgramThread* thread = NULL;
|
||
|
|
||
|
// call script object's constructor
|
||
|
const sdProgram::sdFunction* constructor = scriptObject->GetConstructor();
|
||
|
if ( constructor ) {
|
||
|
// start a thread that will initialize after Spawn is done being called
|
||
|
thread = gameLocal.program->CreateThread();
|
||
|
thread->SetName( "sdClientScriptEntity" );
|
||
|
thread->CallFunction( scriptObject, constructor );
|
||
|
thread->ManualControl();
|
||
|
thread->ManualDelete();
|
||
|
}
|
||
|
|
||
|
return thread;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::DeconstructScriptObject
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::DeconstructScriptObject( void ) {
|
||
|
if ( !scriptObject ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// call script object's destructor
|
||
|
sdScriptHelper h;
|
||
|
CallNonBlockingScriptEvent( scriptObject->GetDestructor(), h );
|
||
|
|
||
|
gameLocal.program->FreeScriptObject( scriptObject );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::SetState
|
||
|
=====================
|
||
|
*/
|
||
|
bool sdClientScriptEntity::SetState( const sdProgram::sdFunction* newState ) {
|
||
|
if ( !newState ) {
|
||
|
gameLocal.Error( "sdScriptEntity::SetState NULL state" );
|
||
|
}
|
||
|
|
||
|
scriptState = newState;
|
||
|
scriptIdealState = scriptState;
|
||
|
|
||
|
baseScriptThread->CallFunction( scriptObject, scriptState );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::CallNonBlockingScriptEvent
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::CallNonBlockingScriptEvent( const sdProgram::sdFunction* function, sdScriptHelper& helper ) {
|
||
|
if ( helper.Init( scriptObject, function ) ) {
|
||
|
helper.Run();
|
||
|
if ( !helper.Done() ) {
|
||
|
gameLocal.Error( "sdClientScriptEntity::CallNonBlockingScriptEvent '%s' Cannot be Blocking", function->GetName() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::OnSetState
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::OnSetState( const char* name ) {
|
||
|
const sdProgram::sdFunction* func = scriptObject->GetFunction( name );
|
||
|
if ( !func ) {
|
||
|
gameLocal.Error( "sdScriptEntity::OnSetState Can't find function '%s' in object '%s'", name, scriptObject->GetTypeName() );
|
||
|
}
|
||
|
|
||
|
scriptIdealState = func;
|
||
|
baseScriptThread->DoneProcessing();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetKey
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetKey( const char* key ) {
|
||
|
sdProgram::ReturnString( spawnArgs.GetString( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetIntKey
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetIntKey( const char* key ) {
|
||
|
sdProgram::ReturnInteger( spawnArgs.GetInt( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetFloatKey
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetFloatKey( const char* key ) {
|
||
|
sdProgram::ReturnFloat( spawnArgs.GetFloat( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetVectorKey
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetVectorKey( const char* key ) {
|
||
|
sdProgram::ReturnVector( spawnArgs.GetVector( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetEntityKey
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetEntityKey( const char* key ) {
|
||
|
const char* entname = spawnArgs.GetString( key );
|
||
|
if ( !*entname ) {
|
||
|
sdProgram::ReturnEntity( NULL );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
idEntity* ent = gameLocal.FindEntity( entname );
|
||
|
if ( !ent ) {
|
||
|
gameLocal.Warning( "Couldn't find entity '%s' specified in '%s' key", entname, key );
|
||
|
}
|
||
|
|
||
|
sdProgram::ReturnEntity( ent );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetWorldOrigin
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetWorldOrigin( void ) {
|
||
|
sdProgram::ReturnVector( GetOrigin() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetWorldAxis
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetWorldAxis( int index ) {
|
||
|
sdProgram::ReturnVector( GetAxis()[ index ] );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetDamagePower
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetDamagePower( void ) {
|
||
|
sdProgram::ReturnFloat( 1.f );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_GetOwner
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetOwner( void ) {
|
||
|
sdProgram::ReturnEntity( GetOwner() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_IsOwner
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_IsOwner( idEntity* other ) {
|
||
|
sdProgram::ReturnBoolean( false );
|
||
|
for ( int i = 0; i < GetNumOwners(); i++ ) {
|
||
|
if ( other == GetOwner( i ) ) {
|
||
|
sdProgram::ReturnBoolean( true );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_SetState
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_SetState( const char* name ) {
|
||
|
OnSetState( name );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_PlayMaterialEffect
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_PlayMaterialEffect( const char *effectName, const idVec3& color, const char* jointName, const char* materialType, bool loop ) {
|
||
|
rvClientEntityPtr< rvClientEffect > eff;
|
||
|
eff = gameLocal.PlayEffect( spawnArgs, color, effectName, materialType, GetOrigin(), GetAxis(), loop );
|
||
|
sdProgram::ReturnHandle( eff.GetSpawnId() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_PlayEffect
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_PlayEffect( const char* effectName, const char* jointName, bool loop ) {
|
||
|
jointHandle_t joint;
|
||
|
|
||
|
joint = GetAnimator() ? GetAnimator()->GetJointHandle( jointName ) : INVALID_JOINT;
|
||
|
|
||
|
rvClientEntityPtr< rvClientEffect > eff;
|
||
|
eff = PlayEffect( effectName, colorWhite.ToVec3(), NULL, joint, loop );
|
||
|
sdProgram::ReturnHandle( eff.GetSpawnId() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientScriptEntity::Event_StopEffect
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_StopEffect( const char* effectName ) {
|
||
|
int effectIndex = gameLocal.GetEffectHandle( spawnArgs, effectName, NULL );
|
||
|
|
||
|
rvClientEntity* next;
|
||
|
for ( rvClientEntity* cent = clientEntities.Next(); cent != NULL; cent = next ) {
|
||
|
next = cent->bindNode.Next();
|
||
|
|
||
|
rvClientEffect* effect = cent->Cast< rvClientEffect >();
|
||
|
if ( effect == NULL ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( effect->GetEffectIndex() == effectIndex ) {
|
||
|
effect->Stop( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_StopEffectHandle
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_StopEffectHandle( int handle ) {
|
||
|
rvClientEntityPtr< rvClientEffect > effect;
|
||
|
effect.ForceSpawnId( handle );
|
||
|
if ( effect.GetEntity() ) {
|
||
|
effect.GetEntity()->Stop( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_KillEffect
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_KillEffect( const char *effectName ) {
|
||
|
int effectIndex = gameLocal.GetEffectHandle( spawnArgs, effectName, NULL );
|
||
|
|
||
|
rvClientEntity* next;
|
||
|
for ( rvClientEntity* cent = clientEntities.Next(); cent != NULL; cent = next ) {
|
||
|
next = cent->bindNode.Next();
|
||
|
|
||
|
rvClientEffect* effect = cent->Cast< rvClientEffect >();
|
||
|
if ( effect == NULL ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( effect->GetEffectIndex() == effectIndex ) {
|
||
|
effect->Stop( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_SetOrigin
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_SetOrigin( const idVec3& org ) {
|
||
|
SetOrigin( org );
|
||
|
|
||
|
if ( GetPhysics() != NULL ) {
|
||
|
GetPhysics()->SetOrigin( org );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_SetAngles
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_SetAngles( const idAngles& ang ) {
|
||
|
idMat3 axis = ang.ToMat3();
|
||
|
|
||
|
SetAxis( axis );
|
||
|
|
||
|
if ( GetPhysics() != NULL ) {
|
||
|
GetPhysics()->SetAxis( axis );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_SetWorldAxis
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_SetWorldAxis( const idVec3& fwd, const idVec3& right, const idVec3& up ) {
|
||
|
idMat3 axis( fwd, right, up );
|
||
|
SetAxis( axis );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_Bind
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_Bind( idEntity *bindMaster ) {
|
||
|
Bind( bindMaster );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_BindToJoint
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_BindToJoint( idEntity *bindMaster, const char *boneName, float rotateWithMaster ) {
|
||
|
if ( bindMaster == NULL ) {
|
||
|
gameLocal.Warning( "sdClientScriptEntity::Event_BindToJoint: entity is NULL" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !bindMaster->GetAnimator() ) {
|
||
|
gameLocal.Warning( "sdClientScriptEntity::Event_BindToJoint: entity '%s' cannot support skeletal models.", bindMaster->GetName() );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
EnableAxisBind( rotateWithMaster > 0.f );
|
||
|
jointHandle_t hand = bindMaster->GetAnimator()->GetJointHandle( boneName );
|
||
|
|
||
|
if ( hand == INVALID_JOINT ) {
|
||
|
gameLocal.Warning( "sdClientScriptEntity::Event_BindToJoint: invalid joint name %s.", boneName );
|
||
|
hand = INVALID_JOINT;
|
||
|
}
|
||
|
|
||
|
Bind( bindMaster, hand );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_UnBind
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_UnBind( void ) {
|
||
|
Unbind();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_AddCheapDecal
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_AddCheapDecal( idEntity *attachTo, idVec3 &origin, idVec3 &normal, const char* decalName, const char* materialName ) {
|
||
|
gameLocal.AddCheapDecal( spawnArgs, attachTo, origin, normal, INVALID_JOINT, 0, decalName, materialName );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_GetJointHandle
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_GetJointHandle( const char* jointName ) {
|
||
|
if ( GetAnimator() != NULL ) {
|
||
|
sdProgram::ReturnInteger( GetAnimator()->GetJointHandle( jointName ) );
|
||
|
} else {
|
||
|
sdProgram::ReturnInteger( INVALID_JOINT );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_Dispose
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_Dispose( void ) {
|
||
|
Dispose();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_EnableAxisBind
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_EnableAxisBind( bool enabled ) {
|
||
|
EnableAxisBind( enabled );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientScriptEntity::Event_SetGravity
|
||
|
================
|
||
|
*/
|
||
|
void sdClientScriptEntity::Event_SetGravity( const idVec3& gravity ) {
|
||
|
if ( GetPhysics() != NULL ) {
|
||
|
GetPhysics()->SetGravity( gravity );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdClientProjectile
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
CLASS_DECLARATION( sdClientScriptEntity, sdClientProjectile )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientProjectile::sdClientProjectile
|
||
|
=====================
|
||
|
*/
|
||
|
sdClientProjectile::sdClientProjectile( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientProjectile::Launch
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientProjectile::Launch( idEntity* owner, const idVec3& tracerMuzzleOrigin, const idMat3& tracerMuzzleAxis ) {
|
||
|
idAngles tracerMuzzleAngles = tracerMuzzleAxis.ToAngles();
|
||
|
idVec3 anglesVec( tracerMuzzleAngles.pitch, tracerMuzzleAngles.yaw, tracerMuzzleAngles.roll );
|
||
|
|
||
|
AddOwner( owner );
|
||
|
|
||
|
sdScriptHelper helper;
|
||
|
helper.Push( tracerMuzzleOrigin );
|
||
|
helper.Push( anglesVec );
|
||
|
CallNonBlockingScriptEvent( scriptObject->GetFunction( "OnLaunch" ), helper );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdClientProjectile_Parabolic
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
extern const idEventDef EV_SetOwner;
|
||
|
extern const idEventDef EV_AddOwner;
|
||
|
extern const idEventDef EV_Launch;
|
||
|
|
||
|
CLASS_DECLARATION( sdClientProjectile, sdClientProjectile_Parabolic )
|
||
|
EVENT( EV_SetOwner, sdClientProjectile_Parabolic::Event_SetOwner )
|
||
|
EVENT( EV_AddOwner, sdClientProjectile_Parabolic::Event_AddOwner )
|
||
|
EVENT( EV_SetTeam, sdClientProjectile_Parabolic::Event_SetGameTeam )
|
||
|
EVENT( EV_Launch, sdClientProjectile_Parabolic::Event_Launch )
|
||
|
END_CLASS
|
||
|
|
||
|
|
||
|
void Create( const idDict* _spawnArgs, const char* scriptObjectName );
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
sdClientProjectile_Parabolic::Create
|
||
|
=================
|
||
|
*/
|
||
|
void sdClientProjectile_Parabolic::Create( const idDict* _spawnArgs, const sdProgram::sdTypeInfo* type ) {
|
||
|
sdClientProjectile::Create( _spawnArgs, type );
|
||
|
|
||
|
InitPhysics();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
sdClientProjectile_Parabolic::InitPhysics
|
||
|
=================
|
||
|
*/
|
||
|
void sdClientProjectile_Parabolic::InitPhysics( void ) {
|
||
|
float gravity = spawnArgs.GetFloat( "gravity" );
|
||
|
|
||
|
idVec3 gravVec = gameLocal.GetGravity();
|
||
|
gravVec.Normalize();
|
||
|
|
||
|
physicsObj.SetSelf( gameLocal.entities[ENTITYNUM_CLIENT] );
|
||
|
|
||
|
idBounds bounds;
|
||
|
bounds[ 0 ] = spawnArgs.GetVector( "mins" );
|
||
|
bounds[ 1 ] = spawnArgs.GetVector( "mins" );
|
||
|
|
||
|
idClipModel* model = new idClipModel( idTraceModel( bounds ), false );
|
||
|
model->SetContents( 0 );
|
||
|
physicsObj.SetClipModel( model );
|
||
|
physicsObj.SetGravity( gravVec * gravity );
|
||
|
physicsObj.SetClipMask( MASK_PROJECTILE | CONTENTS_BODY | CONTENTS_SLIDEMOVER );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
sdClientProjectile_Parabolic::Think
|
||
|
=================
|
||
|
*/
|
||
|
void sdClientProjectile_Parabolic::Think( void ) {
|
||
|
RunPhysics();
|
||
|
|
||
|
sdClientProjectile::Think();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientProjectile_Parabolic::Event_Launch
|
||
|
================
|
||
|
*/
|
||
|
void sdClientProjectile_Parabolic::Event_Launch( const idVec3& velocity ) {
|
||
|
idVec3 org = GetPhysics()->GetOrigin();
|
||
|
idVec3 dir = velocity;
|
||
|
dir.Normalize();
|
||
|
|
||
|
idMat3 axes = dir.ToMat3();
|
||
|
|
||
|
physicsObj.Init( org, velocity, vec3_zero, axes, gameLocal.time, -1 );
|
||
|
|
||
|
GetPhysics()->SetOrigin( org );
|
||
|
GetPhysics()->SetAxis( axes );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientProjectile_Parabolic::Event_AddOwner
|
||
|
================
|
||
|
*/
|
||
|
void sdClientProjectile_Parabolic::Event_AddOwner( idEntity* other ) {
|
||
|
AddOwner( other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientProjectile_Parabolic::Event_SetOwner
|
||
|
================
|
||
|
*/
|
||
|
void sdClientProjectile_Parabolic::Event_SetOwner( idEntity* other ) {
|
||
|
AddOwner( other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientProjectile_Parabolic::Event_SetGameTeam
|
||
|
================
|
||
|
*/
|
||
|
void sdClientProjectile_Parabolic::Event_SetGameTeam( idScriptObject* object ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientProjectile_Parabolic::Collide
|
||
|
================
|
||
|
*/
|
||
|
bool sdClientProjectile_Parabolic::Collide( const trace_t& collision, const idVec3 &velocity ) {
|
||
|
PostEventMS( &EV_Remove, 0 );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdClientAnimated
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
extern const idEventDef EV_SetAnimFrame;
|
||
|
extern const idEventDef EV_GetNumFrames;
|
||
|
extern const idEventDef EV_SetModel;
|
||
|
extern const idEventDef EV_IsHidden;
|
||
|
extern const idEventDef EV_SetJointPos;
|
||
|
extern const idEventDef EV_SetJointAngle;
|
||
|
extern const idEventDef EV_GetJointPos;
|
||
|
extern const idEventDef EV_Show;
|
||
|
extern const idEventDef EV_Hide;
|
||
|
extern const idEventDef EV_GetAnimatingOnChannel;
|
||
|
extern const idEventDef EV_PlayAnim;
|
||
|
extern const idEventDef EV_PlayCycle;
|
||
|
extern const idEventDef EV_PlayAnimBlended;
|
||
|
extern const idEventDef EV_GetShaderParm;
|
||
|
extern const idEventDef EV_SetShaderParm;
|
||
|
extern const idEventDef EV_SetShaderParms;
|
||
|
extern const idEventDef EV_SetColor;
|
||
|
extern const idEventDef EV_GetColor;
|
||
|
|
||
|
CLASS_DECLARATION( sdClientScriptEntity, sdClientAnimated )
|
||
|
EVENT( EV_SetAnimFrame, sdClientAnimated::Event_SetAnimFrame )
|
||
|
EVENT( EV_GetNumFrames, sdClientAnimated::Event_GetNumFrames )
|
||
|
EVENT( EV_IsHidden, sdClientAnimated::Event_IsHidden )
|
||
|
EVENT( EV_SetJointPos, sdClientAnimated::Event_SetJointPos )
|
||
|
EVENT( EV_SetJointAngle, sdClientAnimated::Event_SetJointAngle )
|
||
|
EVENT( EV_GetJointPos, sdClientAnimated::Event_GetJointPos )
|
||
|
EVENT( EV_Show, sdClientAnimated::Show )
|
||
|
EVENT( EV_Hide, sdClientAnimated::Hide )
|
||
|
|
||
|
EVENT( EV_PlayAnim, sdClientAnimated::Event_PlayAnim )
|
||
|
EVENT( EV_PlayCycle, sdClientAnimated::Event_PlayCycle )
|
||
|
EVENT( EV_PlayAnimBlended, sdClientAnimated::Event_PlayAnimBlended )
|
||
|
EVENT( EV_GetAnimatingOnChannel, sdClientAnimated::Event_GetAnimatingOnChannel )
|
||
|
|
||
|
EVENT( EV_SetSkin, sdClientAnimated::Event_SetSkin )
|
||
|
EVENT( EV_SetModel, sdClientAnimated::Event_SetModel )
|
||
|
|
||
|
EVENT( EV_GetShaderParm, sdClientAnimated::Event_GetShaderParm )
|
||
|
EVENT( EV_SetShaderParm, sdClientAnimated::Event_SetShaderParm )
|
||
|
EVENT( EV_SetShaderParms, sdClientAnimated::Event_SetShaderParms )
|
||
|
EVENT( EV_SetColor, sdClientAnimated::Event_SetColor )
|
||
|
EVENT( EV_GetColor, sdClientAnimated::Event_GetColor )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::sdClientAnimated
|
||
|
=====================
|
||
|
*/
|
||
|
sdClientAnimated::sdClientAnimated( void ) {
|
||
|
renderEntityHandle = -1;
|
||
|
memset( &renderEntity, 0, sizeof( renderEntity ) );
|
||
|
|
||
|
animatedFlags.hidden = false;
|
||
|
|
||
|
animator.SetEntity( this );
|
||
|
|
||
|
lastServiceTime = 0;
|
||
|
thinkFlags = 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::~sdClientAnimated
|
||
|
=====================
|
||
|
*/
|
||
|
sdClientAnimated::~sdClientAnimated( void ) {
|
||
|
CleanUp();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::CleanUp
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientAnimated::CleanUp( void ) {
|
||
|
FreeModelDef();
|
||
|
|
||
|
sdClientScriptEntity::CleanUp();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::ModelCallback
|
||
|
================
|
||
|
*/
|
||
|
bool sdClientAnimated::ModelCallback( renderEntity_t* renderEntity, const renderView_t* renderView, int& lastGameModifiedTime ) {
|
||
|
|
||
|
rvClientEntityPtr<rvClientEntity> safeEnt;
|
||
|
#pragma warning( push )
|
||
|
#pragma warning( disable: 4311 )
|
||
|
safeEnt.SetSpawnId( (int)renderEntity->callbackData );
|
||
|
#pragma warning( pop )
|
||
|
rvClientEntity* ent = safeEnt.GetEntity();//gameLocal.clientEntities[ *(int *)renderEntity->callbackData ];
|
||
|
if ( !ent ) {
|
||
|
return false;
|
||
|
//gameLocal.Error( "sdClientAnimated::ModelCallback: callback with NULL game entity" );
|
||
|
}
|
||
|
|
||
|
return ent->UpdateRenderEntity( renderEntity, renderView, lastGameModifiedTime );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::SetStaticModel
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientAnimated::SetStaticModel( const char* modelName ) {
|
||
|
assert( modelName );
|
||
|
|
||
|
FreeModelDef();
|
||
|
|
||
|
renderEntity.hModel = renderModelManager->FindModel( modelName );
|
||
|
|
||
|
if ( renderEntity.hModel ) {
|
||
|
renderEntity.hModel->Reset();
|
||
|
}
|
||
|
|
||
|
renderEntity.callback = NULL;
|
||
|
renderEntity.numJoints = 0;
|
||
|
renderEntity.joints = NULL;
|
||
|
if ( renderEntity.hModel ) {
|
||
|
renderEntity.bounds = renderEntity.hModel->Bounds( &renderEntity );
|
||
|
} else {
|
||
|
renderEntity.bounds.Zero();
|
||
|
}
|
||
|
|
||
|
UpdateModel();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::SetModel
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientAnimated::SetModel( const char* modelName ) {
|
||
|
FreeModelDef();
|
||
|
|
||
|
renderEntity.hModel = animator.SetModel( modelName );
|
||
|
if ( renderEntity.hModel == NULL ) {
|
||
|
SetStaticModel( modelName );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
gameEdit->RefreshRenderEntity( spawnArgs, renderEntity );
|
||
|
|
||
|
if ( renderEntity.customSkin != NULL ) {
|
||
|
renderEntity.customSkin = animator.ModelDef()->GetDefaultSkin();
|
||
|
}
|
||
|
|
||
|
// set the callback to update the joints
|
||
|
renderEntity.callback = sdClientAnimated::ModelCallback;
|
||
|
animator.GetJoints( &renderEntity.numJoints, &renderEntity.joints );
|
||
|
animator.GetBounds( gameLocal.time, renderEntity.bounds );
|
||
|
|
||
|
UpdateModel();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::UpdateModel
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientAnimated::UpdateModel( void ) {
|
||
|
renderEntity.origin = GetOrigin();
|
||
|
renderEntity.axis = GetAxis();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Present
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Present( void ) {
|
||
|
UpdateModel();
|
||
|
|
||
|
if ( !renderEntity.hModel || animatedFlags.hidden ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( renderSystem->IsSMPEnabled() ) {
|
||
|
if ( animator.CreateFrame( gameLocal.time, false ) ) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// add to refresh list
|
||
|
if ( renderEntityHandle == -1 ) {
|
||
|
renderEntityHandle = gameRenderWorld->AddEntityDef( &renderEntity );
|
||
|
} else {
|
||
|
gameRenderWorld->UpdateEntityDef( renderEntityHandle, &renderEntity );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::Create
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientAnimated::Create( const idDict* _spawnArgs, const sdProgram::sdTypeInfo* type ) {
|
||
|
sdClientScriptEntity::Create( _spawnArgs, type );
|
||
|
|
||
|
gameEdit->ParseSpawnArgsToRenderEntity( spawnArgs, renderEntity );
|
||
|
rvClientEntityPtr<sdClientAnimated> safeEnt;
|
||
|
safeEnt.SetEntity( this );
|
||
|
#pragma warning( push )
|
||
|
#pragma warning( disable: 4312 )
|
||
|
renderEntity.callbackData = (void*)safeEnt.GetSpawnId();
|
||
|
#pragma warning( pop )
|
||
|
|
||
|
const char* modelName = spawnArgs.GetString( "model" );
|
||
|
if ( *modelName ) {
|
||
|
SetModel( modelName );
|
||
|
}
|
||
|
|
||
|
// spawn gui entities
|
||
|
if ( !networkSystem->IsDedicated() && renderEntity.hModel != NULL ) {
|
||
|
for ( int i = 0; i < renderEntity.hModel->NumGUISurfaces(); i++ ) {
|
||
|
const guiSurface_t* guiSurface = renderEntity.hModel->GetGUISurface( i );
|
||
|
|
||
|
const char* guiName = spawnArgs.GetString( guiSurface->guiNum == 0 ? "gui" : va( "gui%d", guiSurface->guiNum + 1 ) );
|
||
|
if ( *guiName == '\0' ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
idStr theme = spawnArgs.GetString( guiSurface->guiNum == 0 ? "gui_theme" : va( "gui%d_theme", guiSurface->guiNum + 1 ), "default" );
|
||
|
|
||
|
guiHandle_t handle = gameLocal.LoadUserInterface( guiName, true, false, theme );
|
||
|
|
||
|
if ( handle.IsValid() ) {
|
||
|
sdGuiSurface* cent = reinterpret_cast< sdGuiSurface* >( sdGuiSurface::Type.CreateInstance() );
|
||
|
|
||
|
cent->Init( this, *guiSurface, handle, 0, renderEntity.flags.weaponDepthHack );
|
||
|
|
||
|
sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle );
|
||
|
if ( ui != NULL ) {
|
||
|
ui->Activate();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::FreeModelDef
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::FreeModelDef( void ) {
|
||
|
gameEdit->DestroyRenderEntity( renderEntity );
|
||
|
if ( renderEntityHandle != -1 ) {
|
||
|
gameRenderWorld->FreeEntityDef( renderEntityHandle );
|
||
|
renderEntityHandle = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::UpdateRenderEntity
|
||
|
================
|
||
|
*/
|
||
|
bool sdClientAnimated::UpdateRenderEntity( renderEntity_t* renderEntity, const renderView_t* renderView, int& lastGameModifiedTime ) {
|
||
|
if ( !renderSystem->IsSMPEnabled() ) {
|
||
|
if ( animator.CreateFrame( gameLocal.time, false ) || lastGameModifiedTime != animator.GetTransformCount() ) {
|
||
|
lastGameModifiedTime = animator.GetTransformCount();
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::UpdateAnimation
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::UpdateAnimation( void ) {
|
||
|
// is the model an MD5?
|
||
|
if ( !animator.ModelHandle() ) {
|
||
|
// no, so nothing to do
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// call any frame commands that have happened in the past frame
|
||
|
if ( !animatedFlags.hidden ) {
|
||
|
if ( gameLocal.time > lastServiceTime ) {
|
||
|
animator.ServiceAnims( lastServiceTime, gameLocal.time );
|
||
|
lastServiceTime = gameLocal.time;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if the model is animating then we have to update it
|
||
|
if ( !animator.FrameHasChanged( gameLocal.time ) ) {
|
||
|
// still fine the way it was
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// get the latest frame bounds
|
||
|
animator.GetBounds( gameLocal.time, renderEntity.bounds );
|
||
|
|
||
|
// the animation is updated
|
||
|
animator.ClearForceUpdate();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Think
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Think( void ) {
|
||
|
if ( thinkFlags & TH_ANIMATE ) {
|
||
|
UpdateAnimation();
|
||
|
}
|
||
|
sdClientScriptEntity::Think();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::BecomeActive
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::BecomeActive( int flags, bool force ) {
|
||
|
thinkFlags |= flags;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::BecomeInactive
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::BecomeInactive( int flags, bool force ) {
|
||
|
thinkFlags &= ~flags;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Hide
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Hide( void ) {
|
||
|
|
||
|
if ( !animatedFlags.hidden ) {
|
||
|
FreeModelDef();
|
||
|
animatedFlags.hidden = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Show
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Show( void ) {
|
||
|
if ( animatedFlags.hidden ) {
|
||
|
animatedFlags.hidden = false;
|
||
|
Present();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::SetSkin
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::SetSkin( const idDeclSkin* skin ) {
|
||
|
renderEntity.customSkin = skin;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_SetAnimFrame
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_SetAnimFrame( const char* anim, animChannel_t channel, float frame ) {
|
||
|
animator.SetFrame( channel, animator.GetAnim( anim ), frame, gameLocal.time, 0 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_GetNumFrames
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_GetNumFrames( const char* animName ) {
|
||
|
int anim = animator.GetAnim( animName );
|
||
|
sdProgram::ReturnInteger( animator.NumFrames( anim ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_IsHidden
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_IsHidden( void ) {
|
||
|
sdProgram::ReturnBoolean( animatedFlags.hidden );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_SetJointAngle
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_SetJointPos( jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos ) {
|
||
|
animator.SetJointPos( jointnum, transform_type, pos );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_SetJointAngle
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_SetJointAngle( jointHandle_t joint, jointModTransform_t transformType, const idAngles& angles ) {
|
||
|
animator.SetJointAxis( joint, transformType, angles.ToMat3() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::GetJointWorldTransform
|
||
|
=====================
|
||
|
*/
|
||
|
bool sdClientAnimated::GetJointWorldTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
|
||
|
if ( !animator.GetJointTransform( jointHandle, currentTime, offset, axis ) ) {
|
||
|
offset.Zero();
|
||
|
axis.Identity();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
offset = renderEntity.origin + offset * renderEntity.axis;
|
||
|
axis *= renderEntity.axis;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_GetJointPos
|
||
|
|
||
|
returns the position of the joint in worldspace
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_GetJointPos( jointHandle_t jointnum ) {
|
||
|
idVec3 offset;
|
||
|
idMat3 axis;
|
||
|
|
||
|
if ( !GetJointWorldTransform( jointnum, gameLocal.time, offset, axis ) ) {
|
||
|
offset.Zero();
|
||
|
gameLocal.Warning( "Joint # %d out of range on client entity '%s'", jointnum, GetName() );
|
||
|
}
|
||
|
|
||
|
sdProgram::ReturnVector( offset );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_PlayAnim
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_PlayAnim( animChannel_t channel, const char *animname ) {
|
||
|
int anim = animator.GetAnim( animname );
|
||
|
|
||
|
if ( !anim ) {
|
||
|
if( anim_showMissingAnims.GetBool() ) {
|
||
|
gameLocal.Warning( "sdClientAnimated::Event_PlayAnim missing '%s' animation", animname );
|
||
|
}
|
||
|
animator.Clear( channel, gameLocal.time, 0 );
|
||
|
sdProgram::ReturnFloat( 0 );
|
||
|
} else {
|
||
|
animator.PlayAnim( channel, anim, gameLocal.time, 0 );
|
||
|
sdProgram::ReturnFloat( MS2SEC( animator.AnimLength( anim ) ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_PlayCycle
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_PlayCycle( animChannel_t channel, const char *animname ) {
|
||
|
int anim = animator.GetAnim( animname );
|
||
|
|
||
|
if ( !anim ) {
|
||
|
if( anim_showMissingAnims.GetBool() ) {
|
||
|
gameLocal.Warning( "sdClientAnimated::Event_PlayCycle missing '%s' animation", animname );
|
||
|
}
|
||
|
animator.Clear( channel, gameLocal.time, 0 );
|
||
|
sdProgram::ReturnFloat( 0.0f );
|
||
|
} else {
|
||
|
animator.CycleAnim( channel, anim, gameLocal.time, 0 );
|
||
|
sdProgram::ReturnFloat( MS2SEC( animator.AnimLength( anim ) ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_PlayAnimBlended
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_PlayAnimBlended( animChannel_t channel, const char *animname, float blendTime ) {
|
||
|
int anim = animator.GetAnim( animname );
|
||
|
|
||
|
if ( !anim ) {
|
||
|
if( anim_showMissingAnims.GetBool() ) {
|
||
|
gameLocal.Warning( "idAnimatedEntity::Event_PlayAnimBlended missing '%s' animation", animname );
|
||
|
}
|
||
|
animator.Clear( channel, gameLocal.time, 0 );
|
||
|
sdProgram::ReturnFloat( 0 );
|
||
|
} else {
|
||
|
animator.PlayAnim( channel, anim, gameLocal.time, SEC2MS( blendTime ) );
|
||
|
sdProgram::ReturnFloat( MS2SEC( animator.AnimLength( anim ) ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_GetAnimatingOnChannel
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_GetAnimatingOnChannel( animChannel_t channel ) {
|
||
|
idAnimBlend *blend = animator.CurrentAnim( channel );
|
||
|
if ( !blend ) {
|
||
|
sdProgram::ReturnString( "" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int index = blend->AnimNum();
|
||
|
const idAnim* anim = animator.GetAnim( index );
|
||
|
if ( !anim ) {
|
||
|
sdProgram::ReturnString( "" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
sdProgram::ReturnString( anim->FullName() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_SetSkin
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_SetSkin( const char* skinname ) {
|
||
|
if( !*skinname ) {
|
||
|
SetSkin( NULL );
|
||
|
} else {
|
||
|
SetSkin( gameLocal.declSkinType[ skinname ] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdClientAnimated::Event_SetModel
|
||
|
================
|
||
|
*/
|
||
|
void sdClientAnimated::Event_SetModel( const char* modelName ) {
|
||
|
SetModel( modelName );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientAnimated::PlayEffect
|
||
|
=====================
|
||
|
*/
|
||
|
rvClientEffect* sdClientAnimated::PlayEffect( const char* effectName, const idVec3& color, const char* materialType, jointHandle_t jointHandle, bool loop, const idVec3& endOrigin ) {
|
||
|
if ( animatedFlags.hidden ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return sdClientScriptEntity::PlayEffect( gameLocal.GetEffectHandle( spawnArgs, effectName, materialType ), color, jointHandle, loop, endOrigin );
|
||
|
}
|
||
|
|
||
|
void sdClientAnimated::Event_GetShaderParm( int parm ) {
|
||
|
sdProgram::ReturnFloat( renderEntity.shaderParms[ (int)parm ] );
|
||
|
}
|
||
|
|
||
|
|
||
|
void sdClientAnimated::Event_SetShaderParm( int parm, float value ) {
|
||
|
renderEntity.shaderParms[ (int)parm ] = value;
|
||
|
}
|
||
|
|
||
|
void sdClientAnimated::Event_SetShaderParms( float parm0, float parm1, float parm2, float parm3 ) {
|
||
|
renderEntity.shaderParms[ 0 ] = parm0;
|
||
|
renderEntity.shaderParms[ 1 ] = parm1;
|
||
|
renderEntity.shaderParms[ 2 ] = parm2;
|
||
|
renderEntity.shaderParms[ 3 ] = parm3;
|
||
|
}
|
||
|
|
||
|
void sdClientAnimated::Event_SetColor( float red, float green, float blue ) {
|
||
|
renderEntity.shaderParms[ SHADERPARM_RED ] = red;
|
||
|
renderEntity.shaderParms[ SHADERPARM_GREEN ] = green;
|
||
|
renderEntity.shaderParms[ SHADERPARM_BLUE ] = blue;
|
||
|
}
|
||
|
|
||
|
void sdClientAnimated::Event_GetColor() {
|
||
|
sdProgram::ReturnVector( idVec3( renderEntity.shaderParms[ SHADERPARM_RED ], renderEntity.shaderParms[ SHADERPARM_GREEN ], renderEntity.shaderParms[ SHADERPARM_BLUE ] ) );
|
||
|
}
|
||
|
|
||
|
const char * sdClientAnimated::GetName( void ) const {
|
||
|
|
||
|
return va( "sdClientAnimated %s", renderEntity.hModel ? renderEntity.hModel->Name() : "<NULL>" );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdClientLight
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
extern const idEventDef EV_TurnOn;
|
||
|
extern const idEventDef EV_TurnOff;
|
||
|
|
||
|
CLASS_DECLARATION( sdClientScriptEntity, sdClientLight )
|
||
|
EVENT( EV_TurnOn, sdClientLight::Event_On )
|
||
|
EVENT( EV_TurnOff, sdClientLight::Event_Off )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientLight::sdClientLight
|
||
|
=====================
|
||
|
*/
|
||
|
sdClientLight::sdClientLight( void ) {
|
||
|
lightDefHandle = -1;
|
||
|
on = false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientLight::~sdClientLight
|
||
|
=====================
|
||
|
*/
|
||
|
sdClientLight::~sdClientLight( void ) {
|
||
|
if ( lightDefHandle != -1 ) {
|
||
|
gameRenderWorld->FreeLightDef( lightDefHandle );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientLight::Create
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientLight::Create( const idDict* _spawnArgs, const sdProgram::sdTypeInfo* type ) {
|
||
|
sdClientScriptEntity::Create( _spawnArgs, type );
|
||
|
|
||
|
gameEdit->ParseSpawnArgsToRenderLight( spawnArgs, renderLight );
|
||
|
lightDefHandle = -1;
|
||
|
on = false;
|
||
|
|
||
|
if ( spawnArgs.GetBool( "start_off", "0" ) ) {
|
||
|
Event_Off();
|
||
|
} else {
|
||
|
Event_On();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientLight::Present
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientLight::Present( void ) {
|
||
|
float parm0, parm1, parm2;
|
||
|
|
||
|
renderLight.origin = worldOrigin;
|
||
|
renderLight.axis = worldAxis;
|
||
|
|
||
|
parm0 = renderLight.shaderParms[0];
|
||
|
parm1 = renderLight.shaderParms[1];
|
||
|
parm2 = renderLight.shaderParms[2];
|
||
|
|
||
|
if ( !on ) {
|
||
|
renderLight.shaderParms[0] = 0;
|
||
|
renderLight.shaderParms[1] = 0;
|
||
|
renderLight.shaderParms[2] = 0;
|
||
|
}
|
||
|
|
||
|
// add to refresh list
|
||
|
if ( ( lightDefHandle != -1 ) ) {
|
||
|
gameRenderWorld->UpdateLightDef( lightDefHandle, &renderLight );
|
||
|
} else {
|
||
|
lightDefHandle = gameRenderWorld->AddLightDef( &renderLight );
|
||
|
}
|
||
|
|
||
|
renderLight.shaderParms[0] = parm0;
|
||
|
renderLight.shaderParms[1] = parm1;
|
||
|
renderLight.shaderParms[2] = parm2;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientLight::Event_On
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientLight::Event_On( void ) {
|
||
|
on = true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
sdClientLight::Event_Off
|
||
|
=====================
|
||
|
*/
|
||
|
void sdClientLight::Event_Off( void ) {
|
||
|
on = false;
|
||
|
}
|