2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# pragma hdrstop
# include "Game_local.h"
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idEntity
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
idCVar net_errorSmoothingMaxDecay ( " net_errorSmoothingMaxDecay " , " 25.0 " , CVAR_FLOAT , " Max rate at which origin error smoothing decays (in units per game frame) " ) ;
idCVar net_errorSmoothingDecay ( " net_errorSmoothingDecay " , " 0.06 " , CVAR_FLOAT , " Rate at which error smoothing decays (in percent per game frame) " ) ;
// overridable events
const idEventDef EV_PostSpawn ( " <postspawn> " , NULL ) ;
const idEventDef EV_FindTargets ( " <findTargets> " , NULL ) ;
const idEventDef EV_Touch ( " <touch> " , " et " ) ;
const idEventDef EV_GetName ( " getName " , NULL , ' s ' ) ;
const idEventDef EV_SetName ( " setName " , " s " ) ;
const idEventDef EV_Activate ( " activate " , " e " ) ;
const idEventDef EV_ActivateTargets ( " activateTargets " , " e " ) ;
const idEventDef EV_NumTargets ( " numTargets " , NULL , ' f ' ) ;
const idEventDef EV_GetTarget ( " getTarget " , " f " , ' e ' ) ;
const idEventDef EV_RandomTarget ( " randomTarget " , " s " , ' e ' ) ;
const idEventDef EV_Bind ( " bind " , " e " ) ;
const idEventDef EV_BindPosition ( " bindPosition " , " e " ) ;
const idEventDef EV_BindToJoint ( " bindToJoint " , " esf " ) ;
const idEventDef EV_Unbind ( " unbind " , NULL ) ;
const idEventDef EV_RemoveBinds ( " removeBinds " ) ;
const idEventDef EV_SpawnBind ( " <spawnbind> " , NULL ) ;
const idEventDef EV_SetOwner ( " setOwner " , " e " ) ;
const idEventDef EV_SetModel ( " setModel " , " s " ) ;
const idEventDef EV_SetSkin ( " setSkin " , " s " ) ;
const idEventDef EV_GetWorldOrigin ( " getWorldOrigin " , NULL , ' v ' ) ;
const idEventDef EV_SetWorldOrigin ( " setWorldOrigin " , " v " ) ;
const idEventDef EV_GetOrigin ( " getOrigin " , NULL , ' v ' ) ;
const idEventDef EV_SetOrigin ( " setOrigin " , " v " ) ;
const idEventDef EV_GetAngles ( " getAngles " , NULL , ' v ' ) ;
const idEventDef EV_SetAngles ( " setAngles " , " v " ) ;
const idEventDef EV_GetLinearVelocity ( " getLinearVelocity " , NULL , ' v ' ) ;
const idEventDef EV_SetLinearVelocity ( " setLinearVelocity " , " v " ) ;
const idEventDef EV_GetAngularVelocity ( " getAngularVelocity " , NULL , ' v ' ) ;
const idEventDef EV_SetAngularVelocity ( " setAngularVelocity " , " v " ) ;
const idEventDef EV_GetSize ( " getSize " , NULL , ' v ' ) ;
const idEventDef EV_SetSize ( " setSize " , " vv " ) ;
const idEventDef EV_GetMins ( " getMins " , NULL , ' v ' ) ;
const idEventDef EV_GetMaxs ( " getMaxs " , NULL , ' v ' ) ;
const idEventDef EV_IsHidden ( " isHidden " , NULL , ' d ' ) ;
const idEventDef EV_Hide ( " hide " , NULL ) ;
const idEventDef EV_Show ( " show " , NULL ) ;
const idEventDef EV_Touches ( " touches " , " E " , ' d ' ) ;
const idEventDef EV_ClearSignal ( " clearSignal " , " d " ) ;
const idEventDef EV_GetShaderParm ( " getShaderParm " , " d " , ' f ' ) ;
const idEventDef EV_SetShaderParm ( " setShaderParm " , " df " ) ;
const idEventDef EV_SetShaderParms ( " setShaderParms " , " ffff " ) ;
const idEventDef EV_SetColor ( " setColor " , " fff " ) ;
const idEventDef EV_GetColor ( " getColor " , NULL , ' v ' ) ;
const idEventDef EV_CacheSoundShader ( " cacheSoundShader " , " s " ) ;
const idEventDef EV_StartSoundShader ( " startSoundShader " , " sd " , ' f ' ) ;
const idEventDef EV_StartSound ( " startSound " , " sdd " , ' f ' ) ;
const idEventDef EV_StopSound ( " stopSound " , " dd " ) ;
const idEventDef EV_FadeSound ( " fadeSound " , " dff " ) ;
const idEventDef EV_SetGuiParm ( " setGuiParm " , " ss " ) ;
const idEventDef EV_SetGuiFloat ( " setGuiFloat " , " sf " ) ;
const idEventDef EV_GetNextKey ( " getNextKey " , " ss " , ' s ' ) ;
const idEventDef EV_SetKey ( " setKey " , " ss " ) ;
const idEventDef EV_GetKey ( " getKey " , " s " , ' s ' ) ;
const idEventDef EV_GetIntKey ( " getIntKey " , " s " , ' f ' ) ;
const idEventDef EV_GetFloatKey ( " getFloatKey " , " s " , ' f ' ) ;
const idEventDef EV_GetVectorKey ( " getVectorKey " , " s " , ' v ' ) ;
const idEventDef EV_GetEntityKey ( " getEntityKey " , " s " , ' e ' ) ;
const idEventDef EV_RestorePosition ( " restorePosition " ) ;
const idEventDef EV_UpdateCameraTarget ( " <updateCameraTarget> " , NULL ) ;
const idEventDef EV_DistanceTo ( " distanceTo " , " E " , ' f ' ) ;
const idEventDef EV_DistanceToPoint ( " distanceToPoint " , " v " , ' f ' ) ;
const idEventDef EV_StartFx ( " startFx " , " s " ) ;
const idEventDef EV_HasFunction ( " hasFunction " , " s " , ' d ' ) ;
const idEventDef EV_CallFunction ( " callFunction " , " s " ) ;
const idEventDef EV_SetNeverDormant ( " setNeverDormant " , " d " ) ;
2012-11-28 15:47:07 +00:00
const idEventDef EV_SetGui ( " setGui " , " ds " ) ;
const idEventDef EV_PrecacheGui ( " precacheGui " , " s " ) ;
const idEventDef EV_GetGuiParm ( " getGuiParm " , " ds " , ' s ' ) ;
const idEventDef EV_GetGuiParmFloat ( " getGuiParmFloat " , " ds " , ' f ' ) ;
2012-11-26 18:58:24 +00:00
const idEventDef EV_MotionBlurOn ( " motionBlurOn " ) ;
const idEventDef EV_MotionBlurOff ( " motionBlurOff " ) ;
2012-11-28 15:47:07 +00:00
const idEventDef EV_GuiNamedEvent ( " guiNamedEvent " , " ds " ) ;
2012-11-26 18:58:24 +00:00
ABSTRACT_DECLARATION ( idClass , idEntity )
2012-11-28 15:47:07 +00:00
EVENT ( EV_GetName , idEntity : : Event_GetName )
EVENT ( EV_SetName , idEntity : : Event_SetName )
EVENT ( EV_FindTargets , idEntity : : Event_FindTargets )
EVENT ( EV_ActivateTargets , idEntity : : Event_ActivateTargets )
EVENT ( EV_NumTargets , idEntity : : Event_NumTargets )
EVENT ( EV_GetTarget , idEntity : : Event_GetTarget )
EVENT ( EV_RandomTarget , idEntity : : Event_RandomTarget )
EVENT ( EV_BindToJoint , idEntity : : Event_BindToJoint )
EVENT ( EV_RemoveBinds , idEntity : : Event_RemoveBinds )
EVENT ( EV_Bind , idEntity : : Event_Bind )
EVENT ( EV_BindPosition , idEntity : : Event_BindPosition )
EVENT ( EV_Unbind , idEntity : : Event_Unbind )
EVENT ( EV_SpawnBind , idEntity : : Event_SpawnBind )
EVENT ( EV_SetOwner , idEntity : : Event_SetOwner )
EVENT ( EV_SetModel , idEntity : : Event_SetModel )
EVENT ( EV_SetSkin , idEntity : : Event_SetSkin )
EVENT ( EV_GetShaderParm , idEntity : : Event_GetShaderParm )
EVENT ( EV_SetShaderParm , idEntity : : Event_SetShaderParm )
EVENT ( EV_SetShaderParms , idEntity : : Event_SetShaderParms )
EVENT ( EV_SetColor , idEntity : : Event_SetColor )
EVENT ( EV_GetColor , idEntity : : Event_GetColor )
EVENT ( EV_IsHidden , idEntity : : Event_IsHidden )
EVENT ( EV_Hide , idEntity : : Event_Hide )
EVENT ( EV_Show , idEntity : : Event_Show )
EVENT ( EV_CacheSoundShader , idEntity : : Event_CacheSoundShader )
EVENT ( EV_StartSoundShader , idEntity : : Event_StartSoundShader )
EVENT ( EV_StartSound , idEntity : : Event_StartSound )
EVENT ( EV_StopSound , idEntity : : Event_StopSound )
EVENT ( EV_FadeSound , idEntity : : Event_FadeSound )
EVENT ( EV_GetWorldOrigin , idEntity : : Event_GetWorldOrigin )
EVENT ( EV_SetWorldOrigin , idEntity : : Event_SetWorldOrigin )
EVENT ( EV_GetOrigin , idEntity : : Event_GetOrigin )
EVENT ( EV_SetOrigin , idEntity : : Event_SetOrigin )
EVENT ( EV_GetAngles , idEntity : : Event_GetAngles )
EVENT ( EV_SetAngles , idEntity : : Event_SetAngles )
EVENT ( EV_GetLinearVelocity , idEntity : : Event_GetLinearVelocity )
EVENT ( EV_SetLinearVelocity , idEntity : : Event_SetLinearVelocity )
EVENT ( EV_GetAngularVelocity , idEntity : : Event_GetAngularVelocity )
EVENT ( EV_SetAngularVelocity , idEntity : : Event_SetAngularVelocity )
EVENT ( EV_GetSize , idEntity : : Event_GetSize )
EVENT ( EV_SetSize , idEntity : : Event_SetSize )
EVENT ( EV_GetMins , idEntity : : Event_GetMins )
EVENT ( EV_GetMaxs , idEntity : : Event_GetMaxs )
EVENT ( EV_Touches , idEntity : : Event_Touches )
EVENT ( EV_SetGuiParm , idEntity : : Event_SetGuiParm )
EVENT ( EV_SetGuiFloat , idEntity : : Event_SetGuiFloat )
EVENT ( EV_GetNextKey , idEntity : : Event_GetNextKey )
EVENT ( EV_SetKey , idEntity : : Event_SetKey )
EVENT ( EV_GetKey , idEntity : : Event_GetKey )
EVENT ( EV_GetIntKey , idEntity : : Event_GetIntKey )
EVENT ( EV_GetFloatKey , idEntity : : Event_GetFloatKey )
EVENT ( EV_GetVectorKey , idEntity : : Event_GetVectorKey )
EVENT ( EV_GetEntityKey , idEntity : : Event_GetEntityKey )
EVENT ( EV_RestorePosition , idEntity : : Event_RestorePosition )
EVENT ( EV_UpdateCameraTarget , idEntity : : Event_UpdateCameraTarget )
EVENT ( EV_DistanceTo , idEntity : : Event_DistanceTo )
EVENT ( EV_DistanceToPoint , idEntity : : Event_DistanceToPoint )
EVENT ( EV_StartFx , idEntity : : Event_StartFx )
EVENT ( EV_Thread_WaitFrame , idEntity : : Event_WaitFrame )
EVENT ( EV_Thread_Wait , idEntity : : Event_Wait )
EVENT ( EV_HasFunction , idEntity : : Event_HasFunction )
EVENT ( EV_CallFunction , idEntity : : Event_CallFunction )
EVENT ( EV_SetNeverDormant , idEntity : : Event_SetNeverDormant )
EVENT ( EV_SetGui , idEntity : : Event_SetGui )
EVENT ( EV_PrecacheGui , idEntity : : Event_PrecacheGui )
EVENT ( EV_GetGuiParm , idEntity : : Event_GetGuiParm )
EVENT ( EV_GetGuiParmFloat , idEntity : : Event_GetGuiParmFloat )
EVENT ( EV_GuiNamedEvent , idEntity : : Event_GuiNamedEvent )
2012-11-26 18:58:24 +00:00
END_CLASS
/*
= = = = = = = = = = = = = = = =
UpdateGuiParms
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void UpdateGuiParms ( idUserInterface * gui , const idDict * args )
{
if ( gui = = NULL | | args = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const idKeyValue * kv = args - > MatchPrefix ( " gui_parm " , NULL ) ;
while ( kv )
{
2012-11-26 18:58:24 +00:00
gui - > SetStateString ( kv - > GetKey ( ) , kv - > GetValue ( ) ) ;
kv = args - > MatchPrefix ( " gui_parm " , kv ) ;
}
gui - > SetStateBool ( " noninteractive " , args - > GetBool ( " gui_noninteractive " ) ) ;
gui - > StateChanged ( gameLocal . time ) ;
}
/*
= = = = = = = = = = = = = = = =
AddRenderGui
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void AddRenderGui ( const char * name , idUserInterface * * gui , const idDict * args )
{
const idKeyValue * kv = args - > MatchPrefix ( " gui_parm " , NULL ) ;
2012-11-26 18:58:24 +00:00
* gui = uiManager - > FindGui ( name , true , ( kv ! = NULL ) ) ;
UpdateGuiParms ( * gui , args ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameEdit : : ParseSpawnArgsToRenderEntity
parse the static model parameters
this is the canonical renderEntity parm parsing ,
which should be used by dmap and the editor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameEdit : : ParseSpawnArgsToRenderEntity ( const idDict * args , renderEntity_t * renderEntity )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
const char * temp ;
2012-11-26 18:58:24 +00:00
idVec3 color ;
float angle ;
2012-11-28 15:47:07 +00:00
const idDeclModelDef * modelDef ;
2012-11-26 18:58:24 +00:00
memset ( renderEntity , 0 , sizeof ( * renderEntity ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = args - > GetString ( " model " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
modelDef = NULL ;
2012-11-28 15:47:07 +00:00
if ( temp [ 0 ] ! = ' \0 ' )
{
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , temp , false ) ) ;
if ( modelDef )
{
2012-11-26 18:58:24 +00:00
renderEntity - > hModel = modelDef - > ModelHandle ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! renderEntity - > hModel )
{
2012-11-26 18:58:24 +00:00
renderEntity - > hModel = renderModelManager - > FindModel ( temp ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( renderEntity - > hModel )
{
2012-11-26 18:58:24 +00:00
renderEntity - > bounds = renderEntity - > hModel - > Bounds ( renderEntity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderEntity - > bounds . Zero ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = args - > GetString ( " skin " ) ;
2012-11-28 15:47:07 +00:00
if ( temp [ 0 ] ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
renderEntity - > customSkin = declManager - > FindSkin ( temp ) ;
2012-11-28 15:47:07 +00:00
}
else if ( modelDef )
{
2012-11-26 18:58:24 +00:00
renderEntity - > customSkin = modelDef - > GetDefaultSkin ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = args - > GetString ( " shader " ) ;
2012-11-28 15:47:07 +00:00
if ( temp [ 0 ] ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
renderEntity - > customShader = declManager - > FindMaterial ( temp ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
args - > GetVector ( " origin " , " 0 0 0 " , renderEntity - > origin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the rotation matrix in either full form, or single angle form
2012-11-28 15:47:07 +00:00
if ( ! args - > GetMatrix ( " rotation " , " 1 0 0 0 1 0 0 0 1 " , renderEntity - > axis ) )
{
2012-11-26 18:58:24 +00:00
angle = args - > GetFloat ( " angle " ) ;
2012-11-28 15:47:07 +00:00
if ( angle ! = 0.0f )
{
2012-11-26 18:58:24 +00:00
renderEntity - > axis = idAngles ( 0.0f , angle , 0.0f ) . ToMat3 ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderEntity - > axis . Identity ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity - > referenceSound = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get shader parms
args - > GetVector ( " _color " , " 1 1 1 " , color ) ;
renderEntity - > shaderParms [ SHADERPARM_RED ] = color [ 0 ] ;
renderEntity - > shaderParms [ SHADERPARM_GREEN ] = color [ 1 ] ;
renderEntity - > shaderParms [ SHADERPARM_BLUE ] = color [ 2 ] ;
renderEntity - > shaderParms [ 3 ] = args - > GetFloat ( " shaderParm3 " , " 1 " ) ;
renderEntity - > shaderParms [ 4 ] = args - > GetFloat ( " shaderParm4 " , " 0 " ) ;
renderEntity - > shaderParms [ 5 ] = args - > GetFloat ( " shaderParm5 " , " 0 " ) ;
renderEntity - > shaderParms [ 6 ] = args - > GetFloat ( " shaderParm6 " , " 0 " ) ;
renderEntity - > shaderParms [ 7 ] = args - > GetFloat ( " shaderParm7 " , " 0 " ) ;
renderEntity - > shaderParms [ 8 ] = args - > GetFloat ( " shaderParm8 " , " 0 " ) ;
renderEntity - > shaderParms [ 9 ] = args - > GetFloat ( " shaderParm9 " , " 0 " ) ;
renderEntity - > shaderParms [ 10 ] = args - > GetFloat ( " shaderParm10 " , " 0 " ) ;
renderEntity - > shaderParms [ 11 ] = args - > GetFloat ( " shaderParm11 " , " 0 " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check noDynamicInteractions flag
renderEntity - > noDynamicInteractions = args - > GetBool ( " noDynamicInteractions " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check noshadows flag
renderEntity - > noShadow = args - > GetBool ( " noshadows " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check noselfshadows flag
renderEntity - > noSelfShadow = args - > GetBool ( " noselfshadows " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// init any guis, including entity-specific states
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + )
{
2012-11-26 18:58:24 +00:00
temp = args - > GetString ( i = = 0 ? " gui " : va ( " gui%d " , i + 1 ) ) ;
2012-11-28 15:47:07 +00:00
if ( temp [ 0 ] ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
AddRenderGui ( temp , & renderEntity - > gui [ i ] , args ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idGameEdit : : ParseSpawnArgsToRefSound
parse the sound parameters
this is the canonical refSound parm parsing ,
which should be used by dmap and the editor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameEdit : : ParseSpawnArgsToRefSound ( const idDict * args , refSound_t * refSound )
{
const char * temp ;
2012-11-26 18:58:24 +00:00
memset ( refSound , 0 , sizeof ( * refSound ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
refSound - > parms . minDistance = args - > GetFloat ( " s_mindistance " ) ;
refSound - > parms . maxDistance = args - > GetFloat ( " s_maxdistance " ) ;
refSound - > parms . volume = args - > GetFloat ( " s_volume " ) ;
refSound - > parms . shakes = args - > GetFloat ( " s_shakes " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
args - > GetVector ( " origin " , " 0 0 0 " , refSound - > origin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
refSound - > referenceSound = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if a diversity is not specified, every sound start will make
// a random one. Specifying diversity is usefull to make multiple
// lights all share the same buzz sound offset, for instance.
refSound - > diversity = args - > GetFloat ( " s_diversity " , " -1 " ) ;
refSound - > waitfortrigger = args - > GetBool ( " s_waitfortrigger " ) ;
2012-11-28 15:47:07 +00:00
if ( args - > GetBool ( " s_omni " ) )
{
2012-11-26 18:58:24 +00:00
refSound - > parms . soundShaderFlags | = SSF_OMNIDIRECTIONAL ;
}
2012-11-28 15:47:07 +00:00
if ( args - > GetBool ( " s_looping " ) )
{
2012-11-26 18:58:24 +00:00
refSound - > parms . soundShaderFlags | = SSF_LOOPING ;
}
2012-11-28 15:47:07 +00:00
if ( args - > GetBool ( " s_occlusion " ) )
{
2012-11-26 18:58:24 +00:00
refSound - > parms . soundShaderFlags | = SSF_NO_OCCLUSION ;
}
2012-11-28 15:47:07 +00:00
if ( args - > GetBool ( " s_global " ) )
{
2012-11-26 18:58:24 +00:00
refSound - > parms . soundShaderFlags | = SSF_GLOBAL ;
}
2012-11-28 15:47:07 +00:00
if ( args - > GetBool ( " s_unclamped " ) )
{
2012-11-26 18:58:24 +00:00
refSound - > parms . soundShaderFlags | = SSF_UNCLAMPED ;
}
refSound - > parms . soundClass = args - > GetInt ( " s_soundClass " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = args - > GetString ( " s_shader " ) ;
2012-11-28 15:47:07 +00:00
if ( temp [ 0 ] ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
refSound - > shader = declManager - > FindSound ( temp ) ;
}
}
/*
= = = = = = = = = = = = = = =
idEntity : : UpdateChangeableSpawnArgs
Any key val pair that might change during the course of the game ( via a gui or whatever )
should be initialize here so a gui or other trigger can change something and have it updated
properly . An optional source may be provided if the values reside in an outside dictionary and
first need copied over to spawnArgs
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdateChangeableSpawnArgs ( const idDict * source )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
const char * target ;
if ( ! source )
{
2012-11-26 18:58:24 +00:00
source = & spawnArgs ;
}
cameraTarget = NULL ;
target = source - > GetString ( " cameraTarget " ) ;
2012-12-11 22:48:55 +00:00
if ( target ! = NULL & & target [ 0 ] ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// update the camera taget
PostEventMS ( & EV_UpdateCameraTarget , 0 ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + )
{
2012-11-26 18:58:24 +00:00
UpdateGuiParms ( renderEntity . gui [ i ] , source ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : idEntity
= = = = = = = = = = = = = = = =
*/
idEntity : : idEntity ( ) :
useClientInterpolation ( true ) ,
predictionKey ( INVALID_PREDICTION_KEY ) ,
originDelta ( vec3_zero ) ,
axisDelta ( mat3_identity ) ,
2012-11-28 15:47:07 +00:00
interpolationBehavior ( USE_NO_INTERPOLATION )
{
2012-11-26 18:58:24 +00:00
entityNumber = ENTITYNUM_NONE ;
entityDefNumber = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnNode . SetOwner ( this ) ;
activeNode . SetOwner ( this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
snapshotNode . SetOwner ( this ) ;
snapshotChanged = - 1 ;
snapshotStale = false ;
snapshotBits = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
thinkFlags = 0 ;
dormantStart = 0 ;
cinematic = false ;
renderView = NULL ;
cameraTarget = NULL ;
health = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physics = NULL ;
bindMaster = NULL ;
bindJoint = INVALID_JOINT ;
bindBody = - 1 ;
teamMaster = NULL ;
teamChain = NULL ;
signals = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
snapshotsReceived = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( PVSAreas , 0 , sizeof ( PVSAreas ) ) ;
numPVSAreas = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( & fl , 0 , sizeof ( fl ) ) ;
fl . neverDormant = true ; // most entities never go dormant
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( & renderEntity , 0 , sizeof ( renderEntity ) ) ;
modelDefHandle = - 1 ;
memset ( & refSound , 0 , sizeof ( refSound ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mpGUIState = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( & xrayEntity , 0 , sizeof ( xrayEntity ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
timeGroup = TIME_GROUP1 ;
xrayEntityHandle = - 1 ;
xraySkin = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
noGrab = false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FixupLocalizedStrings
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : FixupLocalizedStrings ( )
{
for ( int i = 0 ; i < spawnArgs . GetNumKeyVals ( ) ; i + + )
{
const idKeyValue * kv = spawnArgs . GetKeyVal ( i ) ;
if ( idStr : : Cmpn ( kv - > GetValue ( ) , STRTABLE_ID , STRTABLE_ID_LENGTH ) = = 0 )
{
2012-11-26 18:58:24 +00:00
spawnArgs . Set ( kv - > GetKey ( ) , idLocalization : : GetString ( kv - > GetValue ( ) ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Spawn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Spawn ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
const char * temp ;
2012-11-26 18:58:24 +00:00
idVec3 origin ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
const idKeyValue * networkSync ;
const char * classname ;
const char * scriptObjectName ;
2012-11-26 18:58:24 +00:00
gameLocal . RegisterEntity ( this , - 1 , gameLocal . GetSpawnArgs ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . GetString ( " classname " , NULL , & classname ) ;
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * def = gameLocal . FindEntityDef ( classname , false ) ;
if ( def )
{
2012-11-26 18:58:24 +00:00
entityDefNumber = def - > Index ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FixupLocalizedStrings ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// parse static models the same way the editor display does
gameEdit - > ParseSpawnArgsToRenderEntity ( & spawnArgs , & renderEntity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity . entityNum = entityNumber ;
noGrab = spawnArgs . GetBool ( " noGrab " , " 0 " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
xraySkin = NULL ;
renderEntity . xrayIndex = 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStr str ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " skin_xray " , " " , str ) )
{
2012-11-26 18:58:24 +00:00
xraySkin = declManager - > FindSkin ( str . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// go dormant within 100ms so that when the map starts most monsters are dormant
dormantStart = gameLocal . time - DELAY_DORMANT_TIME + 100 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
origin = renderEntity . origin ;
axis = renderEntity . axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// do the audio parsing the same way dmap and the editor do
gameEdit - > ParseSpawnArgsToRefSound ( & spawnArgs , & refSound ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// only play SCHANNEL_PRIVATE when sndworld->PlaceListener() is called with this listenerId
// don't spatialize sounds from the same entity
refSound . listenerId = entityNumber + 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
cameraTarget = NULL ;
temp = spawnArgs . GetString ( " cameraTarget " ) ;
2012-12-11 22:48:55 +00:00
if ( temp ! = NULL & & temp [ 0 ] ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// update the camera taget
PostEventMS ( & EV_UpdateCameraTarget , 0 ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + )
{
2012-11-26 18:58:24 +00:00
UpdateGuiParms ( renderEntity . gui [ i ] , & spawnArgs ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fl . solidForTeam = spawnArgs . GetBool ( " solidForTeam " , " 0 " ) ;
fl . neverDormant = spawnArgs . GetBool ( " neverDormant " , " 0 " ) ;
fl . hidden = spawnArgs . GetBool ( " hide " , " 0 " ) ;
2012-11-28 15:47:07 +00:00
if ( fl . hidden )
{
2012-11-26 18:58:24 +00:00
// make sure we're hidden, since a spawn function might not set it up right
PostEventMS ( & EV_Hide , 0 ) ;
}
cinematic = spawnArgs . GetBool ( " cinematic " , " 0 " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
networkSync = spawnArgs . FindKey ( " networkSync " ) ;
2012-11-28 15:47:07 +00:00
if ( networkSync )
{
2012-11-26 18:58:24 +00:00
fl . networkSync = ( atoi ( networkSync - > GetValue ( ) ) ! = 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
#if 0
2012-11-28 15:47:07 +00:00
if ( ! common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
// common->DPrintf( "NET: DBG %s - %s is synced: %s\n", spawnArgs.GetString( "classname", "" ), GetType()->classname, fl.networkSync ? "true" : "false" );
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " classname " , " " ) [ 0 ] = = ' \0 ' & & ! fl . networkSync )
{
2012-11-26 18:58:24 +00:00
common - > DPrintf ( " NET: WRN %s entity, no classname, and no networkSync? \n " , GetType ( ) - > classname ) ;
}
}
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// every object will have a unique name
temp = spawnArgs . GetString ( " name " , va ( " %s_%s_%d " , GetClassname ( ) , spawnArgs . GetString ( " classname " ) , entityNumber ) ) ;
SetName ( temp ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we have targets, wait until all entities are spawned to get them
2012-11-28 15:47:07 +00:00
if ( spawnArgs . MatchPrefix ( " target " ) | | spawnArgs . MatchPrefix ( " guiTarget " ) )
{
if ( gameLocal . GameState ( ) = = GAMESTATE_STARTUP )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_FindTargets , 0 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// not during spawn, so it's ok to get the targets
FindTargets ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
health = spawnArgs . GetInt ( " health " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
InitDefaultPhysics ( origin , axis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetOrigin ( origin ) ;
SetAxis ( axis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = spawnArgs . GetString ( " model " ) ;
2012-12-11 22:48:55 +00:00
if ( temp ! = NULL & & * temp ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
SetModel ( temp ) ;
}
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " bind " , " " , & temp ) )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_SpawnBind , 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// auto-start a sound on the entity
2012-11-28 15:47:07 +00:00
if ( refSound . shader & & ! refSound . waitfortrigger )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( refSound . shader , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// setup script object
2012-11-28 15:47:07 +00:00
if ( ShouldConstructScriptObjectAtSpawn ( ) & & spawnArgs . GetString ( " scriptobject " , NULL , & scriptObjectName ) )
{
if ( ! scriptObject . SetType ( scriptObjectName ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Script object '%s' not found on entity '%s'. " , scriptObjectName , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ConstructScriptObject ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// determine time group
DetermineTimeGroup ( spawnArgs . GetBool ( " slowmo " , " 1 " ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ~ idEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity : : ~ idEntity ( )
{
2012-11-26 18:58:24 +00:00
DeconstructScriptObject ( ) ;
scriptObject . Free ( ) ;
2012-11-28 15:47:07 +00:00
if ( thinkFlags )
{
2012-11-26 18:58:24 +00:00
BecomeInactive ( thinkFlags ) ;
}
activeNode . Remove ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Signal ( SIG_REMOVED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we have to set back the default physics object before unbinding because the entity
// specific physics object might be an entity variable and as such could already be destroyed.
SetPhysics ( NULL ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove any entities that are bound to me
RemoveBinds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unbind from master
Unbind ( ) ;
QuitTeam ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . RemoveEntityFromHash ( name . c_str ( ) , this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete renderView ;
renderView = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete signals ;
signals = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FreeModelDef ( ) ;
FreeSoundEmitter ( false ) ;
2012-11-28 15:47:07 +00:00
if ( xrayEntityHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeEntityDef ( xrayEntityHandle ) ;
xrayEntityHandle = - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . UnregisterEntity ( this ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Save
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
int i , j ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( entityNumber ) ;
savefile - > WriteInt ( entityDefNumber ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// spawnNode and activeNode are restored by gameLocal
savefile - > WriteDict ( & spawnArgs ) ;
savefile - > WriteString ( name ) ;
scriptObject . Save ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( thinkFlags ) ;
savefile - > WriteInt ( dormantStart ) ;
savefile - > WriteBool ( cinematic ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteObject ( cameraTarget ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( health ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( targets . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < targets . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
targets [ i ] . Save ( savefile ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
entityFlags_s flags = fl ;
LittleBitField ( & flags , sizeof ( flags ) ) ;
savefile - > Write ( & flags , sizeof ( flags ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( timeGroup ) ;
savefile - > WriteBool ( noGrab ) ;
savefile - > WriteRenderEntity ( xrayEntity ) ;
savefile - > WriteInt ( xrayEntityHandle ) ;
savefile - > WriteSkin ( xraySkin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteRenderEntity ( renderEntity ) ;
savefile - > WriteInt ( modelDefHandle ) ;
savefile - > WriteRefSound ( refSound ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteObject ( bindMaster ) ;
savefile - > WriteJoint ( bindJoint ) ;
savefile - > WriteInt ( bindBody ) ;
savefile - > WriteObject ( teamMaster ) ;
savefile - > WriteObject ( teamChain ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteStaticObject ( defaultPhysicsObj ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( numPVSAreas ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_PVS_AREAS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( PVSAreas [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! signals )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( false ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( true ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < NUM_SIGNALS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( signals - > signal [ i ] . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < signals - > signal [ i ] . Num ( ) ; j + + )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( signals - > signal [ i ] [ j ] . threadnum ) ;
savefile - > WriteString ( signals - > signal [ i ] [ j ] . function - > Name ( ) ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( mpGUIState ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Restore
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
int i , j ;
int num ;
idStr funcname ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( entityNumber ) ;
savefile - > ReadInt ( entityDefNumber ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// spawnNode and activeNode are restored by gameLocal
savefile - > ReadDict ( & spawnArgs ) ;
savefile - > ReadString ( name ) ;
SetName ( name ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scriptObject . Restore ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( thinkFlags ) ;
savefile - > ReadInt ( dormantStart ) ;
savefile - > ReadBool ( cinematic ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( cameraTarget ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( health ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
targets . Clear ( ) ;
savefile - > ReadInt ( num ) ;
targets . SetNum ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
targets [ i ] . Restore ( savefile ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > Read ( & fl , sizeof ( fl ) ) ;
LittleBitField ( & fl , sizeof ( fl ) ) ;
savefile - > ReadInt ( timeGroup ) ;
savefile - > ReadBool ( noGrab ) ;
savefile - > ReadRenderEntity ( xrayEntity ) ;
savefile - > ReadInt ( xrayEntityHandle ) ;
2012-11-28 15:47:07 +00:00
if ( xrayEntityHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
xrayEntityHandle = gameRenderWorld - > AddEntityDef ( & xrayEntity ) ;
}
savefile - > ReadSkin ( xraySkin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadRenderEntity ( renderEntity ) ;
savefile - > ReadInt ( modelDefHandle ) ;
savefile - > ReadRefSound ( refSound ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( bindMaster ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadJoint ( bindJoint ) ;
savefile - > ReadInt ( bindBody ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( teamMaster ) ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( teamChain ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadStaticObject ( defaultPhysicsObj ) ;
RestorePhysics ( & defaultPhysicsObj ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( numPVSAreas ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_PVS_AREAS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( PVSAreas [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool readsignals ;
savefile - > ReadBool ( readsignals ) ;
2012-11-28 15:47:07 +00:00
if ( readsignals )
{
signals = new ( TAG_ENTITY ) signalList_t ;
for ( i = 0 ; i < NUM_SIGNALS ; i + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( num ) ;
signals - > signal [ i ] . SetNum ( num ) ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < num ; j + + )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( signals - > signal [ i ] [ j ] . threadnum ) ;
savefile - > ReadString ( funcname ) ;
signals - > signal [ i ] [ j ] . function = gameLocal . program . FindFunction ( funcname ) ;
2012-11-28 15:47:07 +00:00
if ( ! signals - > signal [ i ] [ j ] . function )
{
2012-11-26 18:58:24 +00:00
savefile - > Error ( " Function '%s' not found " , funcname . c_str ( ) ) ;
}
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( mpGUIState ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// restore must retrieve modelDefHandle from the renderer
2012-11-28 15:47:07 +00:00
if ( modelDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
modelDefHandle = gameRenderWorld - > AddEntityDef ( & renderEntity ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetEntityDefName
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idEntity : : GetEntityDefName ( ) const
{
if ( entityDefNumber < 0 )
{
2012-11-26 18:58:24 +00:00
return " *unknown* " ;
}
return declManager - > DeclByIndex ( DECL_ENTITYDEF , entityDefNumber , false ) - > GetName ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetName
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetName ( const char * newname )
{
if ( name . Length ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . RemoveEntityFromHash ( name . c_str ( ) , this ) ;
gameLocal . program . SetEntity ( name , NULL ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
name = newname ;
2012-11-28 15:47:07 +00:00
if ( name . Length ( ) )
{
if ( ( name = = " NULL " ) | | ( name = = " null_entity " ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Cannot name entity '%s'. '%s' is reserved for script. " , name . c_str ( ) , name . c_str ( ) ) ;
}
gameLocal . AddEntityToHash ( name . c_str ( ) , this ) ;
gameLocal . program . SetEntity ( name , this ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetName
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idEntity : : GetName ( ) const
{
2012-11-26 18:58:24 +00:00
return name . c_str ( ) ;
}
/***********************************************************************
Thinking
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : Think
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Think ( )
{
2012-11-26 18:58:24 +00:00
RunPhysics ( ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DoDormantTests
Monsters and other expensive entities that are completely closed
off from the player can skip all of their work
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : DoDormantTests ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( fl . neverDormant )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the monster area is not topologically connected to a player
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . InPlayerConnectedArea ( this ) )
{
if ( dormantStart = = 0 )
{
2012-11-26 18:58:24 +00:00
dormantStart = gameLocal . time ;
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . time - dormantStart < DELAY_DORMANT_TIME )
{
2012-11-26 18:58:24 +00:00
// just got closed off, don't go dormant yet
return false ;
}
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// the monster area is topologically connected to a player, but if
// the monster hasn't been woken up before, do the more precise PVS check
2012-11-28 15:47:07 +00:00
if ( ! fl . hasAwakened )
{
if ( ! gameLocal . InPlayerPVS ( this ) )
{
2012-11-26 18:58:24 +00:00
return true ; // stay dormant
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// wake up
dormantStart = 0 ;
fl . hasAwakened = true ; // only go dormant when area closed off now, not just out of PVS
return false ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : CheckDormant
Monsters and other expensive entities that are completely closed
off from the player can skip all of their work
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : CheckDormant ( )
{
2012-11-26 18:58:24 +00:00
bool dormant ;
dormant = DoDormantTests ( ) ;
2012-11-28 15:47:07 +00:00
if ( dormant & & ! fl . isDormant )
{
2012-11-26 18:58:24 +00:00
fl . isDormant = true ;
DormantBegin ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! dormant & & fl . isDormant )
{
2012-11-26 18:58:24 +00:00
fl . isDormant = false ;
DormantEnd ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return dormant ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DormantBegin
called when entity becomes dormant
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : DormantBegin ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DormantEnd
called when entity wakes from being dormant
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : DormantEnd ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsActive
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : IsActive ( ) const
{
2012-11-26 18:58:24 +00:00
return activeNode . InList ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BecomeActive
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : BecomeActive ( int flags )
{
if ( ( flags & TH_PHYSICS ) )
{
2012-11-26 18:58:24 +00:00
// enable the team master if this entity is part of a physics team
2012-11-28 15:47:07 +00:00
if ( teamMaster & & teamMaster ! = this )
{
2012-11-26 18:58:24 +00:00
teamMaster - > BecomeActive ( TH_PHYSICS ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! ( thinkFlags & TH_PHYSICS ) )
{
2012-11-26 18:58:24 +00:00
// if this is a pusher
2012-11-28 15:47:07 +00:00
if ( physics - > IsType ( idPhysics_Parametric : : Type ) | | physics - > IsType ( idPhysics_Actor : : Type ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . sortPushers = true ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int oldFlags = thinkFlags ;
thinkFlags | = flags ;
2012-11-28 15:47:07 +00:00
if ( thinkFlags )
{
if ( ! IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
activeNode . AddToEnd ( gameLocal . activeEntities ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! oldFlags )
{
2012-11-26 18:58:24 +00:00
// we became inactive this frame, so we have to decrease the count of entities to deactivate
gameLocal . numEntitiesToDeactivate - - ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BecomeInactive
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : BecomeInactive ( int flags )
{
if ( ( flags & TH_PHYSICS ) )
{
2012-11-26 18:58:24 +00:00
// may only disable physics on a team master if no team members are running physics or bound to a joints
2012-11-28 15:47:07 +00:00
if ( teamMaster = = this )
{
for ( idEntity * ent = teamMaster - > teamChain ; ent ; ent = ent - > teamChain )
{
if ( ( ent - > thinkFlags & TH_PHYSICS ) | | ( ( ent - > bindMaster = = this ) & & ( ent - > bindJoint ! = INVALID_JOINT ) ) )
{
2012-11-26 18:58:24 +00:00
flags & = ~ TH_PHYSICS ;
break ;
}
}
}
}
2012-11-28 15:47:07 +00:00
if ( thinkFlags )
{
2012-11-26 18:58:24 +00:00
thinkFlags & = ~ flags ;
2012-11-28 15:47:07 +00:00
if ( ! thinkFlags & & IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . numEntitiesToDeactivate + + ;
}
}
2012-11-28 15:47:07 +00:00
if ( ( flags & TH_PHYSICS ) )
{
2012-11-26 18:58:24 +00:00
// if this entity has a team master
2012-11-28 15:47:07 +00:00
if ( teamMaster & & teamMaster ! = this )
{
2012-11-26 18:58:24 +00:00
// if the team master is at rest
2012-11-28 15:47:07 +00:00
if ( teamMaster - > IsAtRest ( ) )
{
2012-11-26 18:58:24 +00:00
teamMaster - > BecomeInactive ( TH_PHYSICS ) ;
}
}
// Becoming inactive automagically turns on motion blur again
renderEntity . skipMotionBlur = false ;
BecomeActive ( TH_UPDATEVISUALS ) ;
}
}
/***********************************************************************
Visuals
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : SetShaderParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetShaderParm ( int parmnum , float value )
{
if ( ( parmnum < 0 ) | | ( parmnum > = MAX_ENTITY_SHADER_PARMS ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " shader parm index (%d) out of range " , parmnum ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity . shaderParms [ parmnum ] = value ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetColor ( float red , float green , float blue )
{
2012-11-26 18:58:24 +00:00
renderEntity . shaderParms [ SHADERPARM_RED ] = red ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = green ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = blue ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetColor ( const idVec3 & color )
{
2012-11-26 18:58:24 +00:00
SetColor ( color [ 0 ] , color [ 1 ] , color [ 2 ] ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : GetColor ( idVec3 & out ) const
{
2012-11-26 18:58:24 +00:00
out [ 0 ] = renderEntity . shaderParms [ SHADERPARM_RED ] ;
out [ 1 ] = renderEntity . shaderParms [ SHADERPARM_GREEN ] ;
out [ 2 ] = renderEntity . shaderParms [ SHADERPARM_BLUE ] ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetColor ( const idVec4 & color )
{
2012-11-26 18:58:24 +00:00
renderEntity . shaderParms [ SHADERPARM_RED ] = color [ 0 ] ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = color [ 1 ] ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = color [ 2 ] ;
renderEntity . shaderParms [ SHADERPARM_ALPHA ] = color [ 3 ] ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : GetColor ( idVec4 & out ) const
{
2012-11-26 18:58:24 +00:00
out [ 0 ] = renderEntity . shaderParms [ SHADERPARM_RED ] ;
out [ 1 ] = renderEntity . shaderParms [ SHADERPARM_GREEN ] ;
out [ 2 ] = renderEntity . shaderParms [ SHADERPARM_BLUE ] ;
out [ 3 ] = renderEntity . shaderParms [ SHADERPARM_ALPHA ] ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateAnimationControllers
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : UpdateAnimationControllers ( )
{
2012-11-26 18:58:24 +00:00
// any ragdoll and IK animation controllers should be updated here
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetModel ( const char * modelname )
{
2012-11-26 18:58:24 +00:00
assert ( modelname ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FreeModelDef ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity . hModel = renderModelManager - > FindModel ( modelname ) ;
2012-11-28 15:47:07 +00:00
if ( renderEntity . hModel )
{
2012-11-26 18:58:24 +00:00
renderEntity . hModel - > Reset ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity . callback = NULL ;
renderEntity . numJoints = 0 ;
renderEntity . joints = NULL ;
2012-11-28 15:47:07 +00:00
if ( renderEntity . hModel )
{
2012-11-26 18:58:24 +00:00
renderEntity . bounds = renderEntity . hModel - > Bounds ( & renderEntity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderEntity . bounds . Zero ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetSkin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetSkin ( const idDeclSkin * skin )
{
2012-11-26 18:58:24 +00:00
renderEntity . customSkin = skin ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetSkin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDeclSkin * idEntity : : GetSkin ( ) const
{
2012-11-26 18:58:24 +00:00
return renderEntity . customSkin ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FreeModelDef
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : FreeModelDef ( )
{
if ( modelDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeEntityDef ( modelDefHandle ) ;
modelDefHandle = - 1 ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FreeLightDef
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : FreeLightDef ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsHidden
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : IsHidden ( ) const
{
2012-11-26 18:58:24 +00:00
return fl . hidden ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Hide
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Hide ( )
{
if ( ! IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
fl . hidden = true ;
FreeModelDef ( ) ;
UpdateVisuals ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Show
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Show ( )
{
if ( IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
fl . hidden = false ;
UpdateVisuals ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateModelTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdateModelTransform ( )
{
2012-11-26 18:58:24 +00:00
idVec3 origin ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
if ( GetPhysicsToVisualTransform ( origin , axis ) )
{
2012-11-26 18:58:24 +00:00
renderEntity . axis = axis * GetPhysics ( ) - > GetAxis ( ) ;
renderEntity . origin = GetPhysics ( ) - > GetOrigin ( ) + origin * renderEntity . axis ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Add the deltas here, used for projectiles in MP. These deltas should only affect the visuals.
renderEntity . axis = GetPhysics ( ) - > GetAxis ( ) * axisDelta ;
renderEntity . origin = GetPhysics ( ) - > GetOrigin ( ) + originDelta ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdateModel ( )
{
2012-11-26 18:58:24 +00:00
renderEntity . timeGroup = timeGroup ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateModelTransform ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if the entity has an MD5 model
2012-11-28 15:47:07 +00:00
idAnimator * animator = GetAnimator ( ) ;
if ( animator ! = NULL & & animator - > ModelHandle ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
// set the callback to update the joints
renderEntity . callback = idEntity : : ModelCallback ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set to invalid number to force an update the next time the PVS areas are retrieved
ClearPVSAreas ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ensure that we call Present this frame
BecomeActive ( TH_UPDATEVISUALS ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If the entity has an xray skin, go ahead and add it
2012-11-28 15:47:07 +00:00
if ( xraySkin ! = NULL )
{
2012-11-26 18:58:24 +00:00
xrayEntity = renderEntity ;
xrayEntity . xrayIndex = 2 ;
xrayEntity . customSkin = xraySkin ;
2012-11-28 15:47:07 +00:00
if ( xrayEntityHandle = = - 1 )
{
2012-11-26 18:58:24 +00:00
xrayEntityHandle = gameRenderWorld - > AddEntityDef ( & xrayEntity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > UpdateEntityDef ( xrayEntityHandle , & xrayEntity ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateVisuals
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdateVisuals ( )
{
2012-11-26 18:58:24 +00:00
UpdateModel ( ) ;
UpdateSound ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdatePVSAreas
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdatePVSAreas ( )
{
2012-11-26 18:58:24 +00:00
int localNumPVSAreas , localPVSAreas [ 32 ] ;
idBounds modelAbsBounds ;
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
modelAbsBounds . FromTransformedBounds ( renderEntity . bounds , renderEntity . origin , renderEntity . axis ) ;
localNumPVSAreas = gameLocal . pvs . GetPVSAreas ( modelAbsBounds , localPVSAreas , sizeof ( localPVSAreas ) / sizeof ( localPVSAreas [ 0 ] ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: some particle systems may have huge bounds and end up in many PVS areas
// the first MAX_PVS_AREAS may not be visible to a network client and as a result the particle system may not show up when it should
2012-11-28 15:47:07 +00:00
if ( localNumPVSAreas > MAX_PVS_AREAS )
{
2012-11-26 18:58:24 +00:00
localNumPVSAreas = gameLocal . pvs . GetPVSAreas ( idBounds ( renderEntity . origin ) . Expand ( 64.0f ) , localPVSAreas , sizeof ( localPVSAreas ) / sizeof ( localPVSAreas [ 0 ] ) ) ;
}
2012-11-28 15:47:07 +00:00
for ( numPVSAreas = 0 ; numPVSAreas < MAX_PVS_AREAS & & numPVSAreas < localNumPVSAreas ; numPVSAreas + + )
{
2012-11-26 18:58:24 +00:00
PVSAreas [ numPVSAreas ] = localPVSAreas [ numPVSAreas ] ;
}
2012-11-28 15:47:07 +00:00
for ( i = numPVSAreas ; i < MAX_PVS_AREAS ; i + + )
{
2012-11-26 18:58:24 +00:00
PVSAreas [ i ] = 0 ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdatePVSAreas
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdatePVSAreas ( const idVec3 & pos )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numPVSAreas = gameLocal . pvs . GetPVSAreas ( idBounds ( pos ) , PVSAreas , MAX_PVS_AREAS ) ;
i = numPVSAreas ;
2012-11-28 15:47:07 +00:00
while ( i < MAX_PVS_AREAS )
{
2012-11-26 18:58:24 +00:00
PVSAreas [ i + + ] = 0 ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetNumPVSAreas
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idEntity : : GetNumPVSAreas ( )
{
if ( numPVSAreas < 0 )
{
2012-11-26 18:58:24 +00:00
UpdatePVSAreas ( ) ;
}
return numPVSAreas ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPVSAreas
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const int * idEntity : : GetPVSAreas ( )
{
if ( numPVSAreas < 0 )
{
2012-11-26 18:58:24 +00:00
UpdatePVSAreas ( ) ;
}
return PVSAreas ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClearPVSAreas
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ClearPVSAreas ( )
{
2012-11-26 18:58:24 +00:00
numPVSAreas = - 1 ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PhysicsTeamInPVS
FIXME : for networking also return true if any of the entity shadows is in the PVS
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : PhysicsTeamInPVS ( pvsHandle_t pvsHandle )
{
idEntity * part ;
if ( teamMaster )
{
for ( part = teamMaster ; part ; part = part - > teamChain )
{
if ( gameLocal . pvs . InCurrentPVS ( pvsHandle , part - > GetPVSAreas ( ) , part - > GetNumPVSAreas ( ) ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return gameLocal . pvs . InCurrentPVS ( pvsHandle , GetPVSAreas ( ) , GetNumPVSAreas ( ) ) ;
}
return false ;
}
/*
= = = = = = = = = = = = = =
idEntity : : BecomeReplicated
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : BecomeReplicated ( )
{
2012-11-26 18:58:24 +00:00
fl . skipReplication = false ;
2012-11-28 15:47:07 +00:00
if ( GetPhysics ( ) )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > ResetInterpolationState ( GetPhysics ( ) - > GetOrigin ( ) , GetPhysics ( ) - > GetAxis ( ) ) ;
}
}
/*
= = = = = = = = = = = = = =
idEntity : : ProjectOverlay
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ProjectOverlay ( const idVec3 & origin , const idVec3 & dir , float size , const char * material )
{
2012-11-26 18:58:24 +00:00
float s , c ;
idMat3 axis , axistemp ;
idVec3 localOrigin , localAxis [ 2 ] ;
idPlane localPlane [ 2 ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure the entity has a valid model handle
2012-11-28 15:47:07 +00:00
if ( modelDefHandle < 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// only do this on dynamic md5 models
2012-11-28 15:47:07 +00:00
if ( renderEntity . hModel - > IsDynamicModel ( ) ! = DM_CACHED )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idMath : : SinCos16 ( gameLocal . random . RandomFloat ( ) * idMath : : TWO_PI , s , c ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis [ 2 ] = - dir ;
axis [ 2 ] . NormalVectors ( axistemp [ 0 ] , axistemp [ 1 ] ) ;
axis [ 0 ] = axistemp [ 0 ] * c + axistemp [ 1 ] * - s ;
axis [ 1 ] = axistemp [ 0 ] * - s + axistemp [ 1 ] * - c ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity . axis . ProjectVector ( origin - renderEntity . origin , localOrigin ) ;
renderEntity . axis . ProjectVector ( axis [ 0 ] , localAxis [ 0 ] ) ;
renderEntity . axis . ProjectVector ( axis [ 1 ] , localAxis [ 1 ] ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
size = 1.0f / size ;
localAxis [ 0 ] * = size ;
localAxis [ 1 ] * = size ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
localPlane [ 0 ] = localAxis [ 0 ] ;
localPlane [ 0 ] [ 3 ] = - ( localOrigin * localAxis [ 0 ] ) + 0.5f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
localPlane [ 1 ] = localAxis [ 1 ] ;
localPlane [ 1 ] [ 3 ] = - ( localOrigin * localAxis [ 1 ] ) + 0.5f ;
2012-11-28 15:47:07 +00:00
const idMaterial * mtr = declManager - > FindMaterial ( material ) ;
2012-11-26 18:58:24 +00:00
// project an overlay onto the model
gameRenderWorld - > ProjectOverlay ( modelDefHandle , localPlane , mtr , gameLocal . slow . time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure non-animating models update their overlay
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Present
Present is called to allow entities to generate refEntities , lights , etc for the renderer .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Present ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . isNewFrame )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't present to the renderer if the entity hasn't changed
2012-11-28 15:47:07 +00:00
if ( ! ( thinkFlags & TH_UPDATEVISUALS ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
BecomeInactive ( TH_UPDATEVISUALS ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// camera target for remote render views
2012-11-28 15:47:07 +00:00
if ( cameraTarget & & gameLocal . InPlayerPVS ( this ) )
{
2012-11-26 18:58:24 +00:00
renderEntity . remoteRenderView = cameraTarget - > GetRenderView ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if set to invisible, skip
2012-11-28 15:47:07 +00:00
if ( ! renderEntity . hModel | | IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add to refresh list
2012-11-28 15:47:07 +00:00
if ( modelDefHandle = = - 1 )
{
2012-11-26 18:58:24 +00:00
modelDefHandle = gameRenderWorld - > AddEntityDef ( & renderEntity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > UpdateEntityDef ( modelDefHandle , & renderEntity ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetRenderEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
renderEntity_t * idEntity : : GetRenderEntity ( )
{
2012-11-26 18:58:24 +00:00
return & renderEntity ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetModelDefHandle
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idEntity : : GetModelDefHandle ( )
{
2012-11-26 18:58:24 +00:00
return modelDefHandle ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateRenderEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : UpdateRenderEntity ( renderEntity_s * renderEntity , const renderView_t * renderView )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idAnimator * animator = GetAnimator ( ) ;
if ( animator ! = NULL )
{
2012-11-26 18:58:24 +00:00
SetTimeState ts ( timeGroup ) ;
int currentTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
if ( renderEntity ! = NULL )
{
2012-11-26 18:58:24 +00:00
currentTime = gameLocal . GetTimeGroupTime ( renderEntity - > timeGroup ) ;
}
return animator - > CreateFrame ( currentTime , false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ModelCallback
NOTE : may not change the game state whatsoever !
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : ModelCallback ( renderEntity_s * renderEntity , const renderView_t * renderView )
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
ent = gameLocal . entities [ renderEntity - > entityNum ] ;
2012-11-28 15:47:07 +00:00
if ( ent = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " idEntity::ModelCallback: callback with NULL game entity " ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return ent - > UpdateRenderEntity ( renderEntity , renderView ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetAnimator
Subclasses will be responsible for allocating animator .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAnimator * idEntity : : GetAnimator ( )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
/*
= = = = = = = = = = = = =
idEntity : : GetRenderView
This is used by remote camera views to look from an entity
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
renderView_t * idEntity : : GetRenderView ( )
{
if ( ! renderView )
{
renderView = new ( TAG_ENTITY ) renderView_t ;
2012-11-26 18:58:24 +00:00
}
memset ( renderView , 0 , sizeof ( * renderView ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderView - > vieworg = GetPhysics ( ) - > GetOrigin ( ) ;
renderView - > fov_x = 120 ;
renderView - > fov_y = 120 ;
renderView - > viewaxis = GetPhysics ( ) - > GetAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// copy global shader parms
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_GLOBAL_SHADER_PARMS ; i + + )
{
2012-11-26 18:58:24 +00:00
renderView - > shaderParms [ i ] = gameLocal . globalShaderParms [ i ] ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderView - > globalMaterial = gameLocal . GetGlobalMaterial ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderView - > time [ 0 ] = gameLocal . slow . time ;
renderView - > time [ 1 ] = gameLocal . fast . time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return renderView ;
}
/***********************************************************************
Sound
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : CanPlayChatterSounds
Used for playing chatter sounds on monsters .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : CanPlayChatterSounds ( ) const
{
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : StartSound
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : StartSound ( const char * soundName , const s_channelType channel , int soundShaderFlags , bool broadcast , int * length )
{
const idSoundShader * shader ;
const char * sound ;
if ( length )
{
2012-11-26 18:58:24 +00:00
* length = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we should ALWAYS be playing sounds from the def.
// hardcoded sounds MUST be avoided at all times because they won't get precached.
assert ( idStr : : Icmpn ( soundName , " snd_ " , 4 ) = = 0 ) ;
2012-11-28 15:47:07 +00:00
if ( ! spawnArgs . GetString ( soundName , " " , & sound ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( sound [ 0 ] = = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . isNewFrame )
{
2012-11-26 18:58:24 +00:00
// don't play the sound, but don't report an error
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
shader = declManager - > FindSound ( sound ) ;
return StartSoundShader ( shader , channel , soundShaderFlags , broadcast , length ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : StartSoundShader
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : StartSoundShader ( const idSoundShader * shader , const s_channelType channel , int soundShaderFlags , bool broadcast , int * length )
{
2012-11-26 18:58:24 +00:00
float diversity ;
int len ;
2012-11-28 15:47:07 +00:00
if ( length )
{
2012-11-26 18:58:24 +00:00
* length = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( ! shader )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . isNewFrame )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsServer ( ) & & broadcast )
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
msg . BeginWriting ( ) ;
msg . WriteLong ( gameLocal . ServerRemapDecl ( - 1 , DECL_SOUND , shader - > Index ( ) ) ) ;
msg . WriteByte ( channel ) ;
ServerSendEvent ( EVENT_STARTSOUNDSHADER , & msg , false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set a random value for diversity unless one was parsed from the entity
2012-11-28 15:47:07 +00:00
if ( refSound . diversity < 0.0f )
{
2012-11-26 18:58:24 +00:00
diversity = gameLocal . random . RandomFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
diversity = refSound . diversity ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we don't have a soundEmitter allocated yet, get one now
2012-11-28 15:47:07 +00:00
if ( ! refSound . referenceSound )
{
2012-11-26 18:58:24 +00:00
refSound . referenceSound = gameSoundWorld - > AllocSoundEmitter ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateSound ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
len = refSound . referenceSound - > StartSound ( shader , channel , diversity , soundShaderFlags , ! timeGroup /*_D3XP*/ ) ;
2012-11-28 15:47:07 +00:00
if ( length )
{
2012-11-26 18:58:24 +00:00
* length = len ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set reference to the sound for shader synced effects
renderEntity . referenceSound = refSound . referenceSound ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : StopSound
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : StopSound ( const s_channelType channel , bool broadcast )
{
if ( ! gameLocal . isNewFrame )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsServer ( ) & & broadcast )
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
msg . BeginWriting ( ) ;
msg . WriteByte ( channel ) ;
ServerSendEvent ( EVENT_STOPSOUNDSHADER , & msg , false ) ;
}
2012-11-28 15:47:07 +00:00
if ( refSound . referenceSound )
{
2012-11-26 18:58:24 +00:00
refSound . referenceSound - > StopSound ( channel ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetSoundVolume
Must be called before starting a new sound .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetSoundVolume ( float volume )
{
2012-11-26 18:58:24 +00:00
refSound . parms . volume = volume ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateSound
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdateSound ( )
{
if ( refSound . referenceSound )
{
2012-11-26 18:58:24 +00:00
idVec3 origin ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
if ( GetPhysicsToSoundTransform ( origin , axis ) )
{
2012-11-26 18:58:24 +00:00
refSound . origin = GetPhysics ( ) - > GetOrigin ( ) + origin * axis ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
refSound . origin = GetPhysics ( ) - > GetOrigin ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
refSound . referenceSound - > UpdateEmitter ( refSound . origin , refSound . listenerId , & refSound . parms ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetListenerId
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idEntity : : GetListenerId ( ) const
{
2012-11-26 18:58:24 +00:00
return refSound . listenerId ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetSoundEmitter
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSoundEmitter * idEntity : : GetSoundEmitter ( ) const
{
2012-11-26 18:58:24 +00:00
return refSound . referenceSound ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FreeSoundEmitter
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : FreeSoundEmitter ( bool immediate )
{
if ( refSound . referenceSound )
{
2012-11-26 18:58:24 +00:00
refSound . referenceSound - > Free ( immediate ) ;
refSound . referenceSound = NULL ;
}
}
/***********************************************************************
entity binding
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : PreBind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : PreBind ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PostBind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : PostBind ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PreUnbind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : PreUnbind ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PostUnbind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : PostUnbind ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : InitBind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : InitBind ( idEntity * master )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( master = = this )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Tried to bind an object to itself. " ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
if ( this = = gameLocal . world )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Tried to bind world to another entity " ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unbind myself from my master
Unbind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add any bind constraints to an articulated figure
2012-11-28 15:47:07 +00:00
if ( master & & IsType ( idAFEntity_Base : : Type ) )
{
static_cast < idAFEntity_Base * > ( this ) - > AddBindConstraints ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ! master | | master = = gameLocal . world )
{
2012-11-26 18:58:24 +00:00
// this can happen in scripts, so safely exit out.
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FinishBind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : FinishBind ( )
{
2012-11-26 18:58:24 +00:00
// set the master on the physics object
physics - > SetMaster ( bindMaster , fl . bindOrientated ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// We are now separated from our previous team and are either
// an individual, or have a team of our own. Now we can join
// the new bindMaster's team. Bindmaster must be set before
// joining the team, or we will be placed in the wrong position
// on the team.
JoinTeam ( bindMaster ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if our bindMaster is enabled during a cinematic, we must be, too
cinematic = bindMaster - > cinematic ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure the team master is active so that physics get run
teamMaster - > BecomeActive ( TH_PHYSICS ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Bind
bind relative to the visual position of the master
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Bind ( idEntity * master , bool orientated )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! InitBind ( master ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PreBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bindJoint = INVALID_JOINT ;
bindBody = - 1 ;
bindMaster = master ;
fl . bindOrientated = orientated ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FinishBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BindToJoint
bind relative to a joint of the md5 model used by the master
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : BindToJoint ( idEntity * master , const char * jointname , bool orientated )
{
2012-11-26 18:58:24 +00:00
jointHandle_t jointnum ;
2012-11-28 15:47:07 +00:00
idAnimator * masterAnimator ;
if ( ! InitBind ( master ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
masterAnimator = master - > GetAnimator ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! masterAnimator )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idEntity::BindToJoint: entity '%s' cannot support skeletal models. " , master - > GetName ( ) ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
jointnum = masterAnimator - > GetJointHandle ( jointname ) ;
2012-11-28 15:47:07 +00:00
if ( jointnum = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idEntity::BindToJoint: joint '%s' not found on entity '%s'. " , jointname , master - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PreBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bindJoint = jointnum ;
bindBody = - 1 ;
bindMaster = master ;
fl . bindOrientated = orientated ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FinishBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BindToJoint
bind relative to a joint of the md5 model used by the master
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : BindToJoint ( idEntity * master , jointHandle_t jointnum , bool orientated )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! InitBind ( master ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PreBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bindJoint = jointnum ;
bindBody = - 1 ;
bindMaster = master ;
fl . bindOrientated = orientated ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FinishBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BindToBody
bind relative to a collision model used by the physics of the master
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : BindToBody ( idEntity * master , int bodyId , bool orientated )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! InitBind ( master ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( bodyId < 0 )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idEntity::BindToBody: body '%d' not found. " , bodyId ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PreBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bindJoint = INVALID_JOINT ;
bindBody = bodyId ;
bindMaster = master ;
fl . bindOrientated = orientated ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FinishBind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Unbind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Unbind ( )
{
idEntity * prev ;
idEntity * next ;
idEntity * last ;
idEntity * ent ;
2012-11-26 18:58:24 +00:00
// remove any bind constraints from an articulated figure
2012-11-28 15:47:07 +00:00
if ( IsType ( idAFEntity_Base : : Type ) )
{
static_cast < idAFEntity_Base * > ( this ) - > RemoveBindConstraints ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ! bindMaster )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! teamMaster )
{
2012-11-26 18:58:24 +00:00
// Teammaster already has been freed
bindMaster = NULL ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PreUnbind ( ) ;
2012-11-28 15:47:07 +00:00
if ( physics )
{
2012-11-26 18:58:24 +00:00
physics - > SetMaster ( NULL , fl . bindOrientated ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// We're still part of a team, so that means I have to extricate myself
// and any entities that are bound to me from the old team.
// Find the node previous to me in the team
prev = teamMaster ;
2012-11-28 15:47:07 +00:00
for ( ent = teamMaster - > teamChain ; ent & & ( ent ! = this ) ; ent = ent - > teamChain )
{
2012-11-26 18:58:24 +00:00
prev = ent ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ent = = this ) ; // If ent is not pointing to this, then something is very wrong.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Find the last node in my team that is bound to me.
// Also find the first node not bound to me, if one exists.
last = this ;
2012-11-28 15:47:07 +00:00
for ( next = teamChain ; next ! = NULL ; next = next - > teamChain )
{
if ( ! next - > IsBoundTo ( this ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Tell them I'm now the teamMaster
next - > teamMaster = this ;
last = next ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// disconnect the last member of our team from the old team
last - > teamChain = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// connect up the previous member of the old team to the node that
// follow the last node bound to me (if one exists).
2012-11-28 15:47:07 +00:00
if ( teamMaster ! = this )
{
2012-11-26 18:58:24 +00:00
prev - > teamChain = next ;
2012-11-28 15:47:07 +00:00
if ( ! next & & ( teamMaster = = prev ) )
{
2012-11-26 18:58:24 +00:00
prev - > teamMaster = NULL ;
}
2012-11-28 15:47:07 +00:00
}
else if ( next )
{
2012-11-26 18:58:24 +00:00
// If we were the teamMaster, then the nodes that were not bound to me are now
// a disconnected chain. Make them into their own team.
2012-11-28 15:47:07 +00:00
for ( ent = next ; ent - > teamChain ! = NULL ; ent = ent - > teamChain )
{
2012-11-26 18:58:24 +00:00
ent - > teamMaster = next ;
}
next - > teamMaster = next ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If we don't have anyone on our team, then clear the team variables.
2012-11-28 15:47:07 +00:00
if ( teamChain )
{
2012-11-26 18:58:24 +00:00
// make myself my own team
teamMaster = this ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// no longer a team
teamMaster = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bindJoint = INVALID_JOINT ;
bindBody = - 1 ;
bindMaster = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PostUnbind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RemoveBinds
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : RemoveBinds ( )
{
idEntity * ent ;
idEntity * next ;
for ( ent = teamChain ; ent ! = NULL ; ent = next )
{
2012-11-26 18:58:24 +00:00
next = ent - > teamChain ;
2012-11-28 15:47:07 +00:00
if ( ent - > bindMaster = = this )
{
2012-11-26 18:58:24 +00:00
ent - > Unbind ( ) ;
ent - > PostEventMS ( & EV_Remove , 0 ) ;
next = teamChain ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsBound
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : IsBound ( ) const
{
if ( bindMaster )
{
2012-11-26 18:58:24 +00:00
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsBoundTo
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : IsBoundTo ( idEntity * master ) const
{
idEntity * ent ;
if ( ! bindMaster )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
for ( ent = bindMaster ; ent ! = NULL ; ent = ent - > bindMaster )
{
if ( ent = = master )
{
2012-11-26 18:58:24 +00:00
return true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetBindMaster
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idEntity : : GetBindMaster ( ) const
{
2012-11-26 18:58:24 +00:00
return bindMaster ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetBindJoint
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
jointHandle_t idEntity : : GetBindJoint ( ) const
{
2012-11-26 18:58:24 +00:00
return bindJoint ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetBindBody
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idEntity : : GetBindBody ( ) const
{
2012-11-26 18:58:24 +00:00
return bindBody ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetTeamMaster
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idEntity : : GetTeamMaster ( ) const
{
2012-11-26 18:58:24 +00:00
return teamMaster ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetNextTeamEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idEntity : : GetNextTeamEntity ( ) const
{
2012-11-26 18:58:24 +00:00
return teamChain ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : ConvertLocalToWorldTransform
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ConvertLocalToWorldTransform ( idVec3 & offset , idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
UpdateModelTransform ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
offset = renderEntity . origin + offset * renderEntity . axis ;
axis * = renderEntity . axis ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetLocalVector
Takes a vector in worldspace and transforms it into the parent
object ' s localspace .
Note : Does not take origin into acount . Use getLocalCoordinate to
convert coordinates .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idVec3 idEntity : : GetLocalVector ( const idVec3 & vec ) const
{
2012-11-26 18:58:24 +00:00
idVec3 pos ;
2012-11-28 15:47:07 +00:00
if ( ! bindMaster )
{
2012-11-26 18:58:24 +00:00
return vec ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . ProjectVector ( vec , pos ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return pos ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetLocalCoordinates
Takes a vector in world coordinates and transforms it into the parent
object ' s local coordinates .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idVec3 idEntity : : GetLocalCoordinates ( const idVec3 & vec ) const
{
2012-11-26 18:58:24 +00:00
idVec3 pos ;
2012-11-28 15:47:07 +00:00
if ( ! bindMaster )
{
2012-11-26 18:58:24 +00:00
return vec ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . ProjectVector ( vec - masterOrigin , pos ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return pos ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetWorldVector
Takes a vector in the parent object ' s local coordinates and transforms
it into world coordinates .
Note : Does not take origin into acount . Use getWorldCoordinate to
convert coordinates .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idVec3 idEntity : : GetWorldVector ( const idVec3 & vec ) const
{
2012-11-26 18:58:24 +00:00
idVec3 pos ;
2012-11-28 15:47:07 +00:00
if ( ! bindMaster )
{
2012-11-26 18:58:24 +00:00
return vec ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . UnprojectVector ( vec , pos ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return pos ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetWorldCoordinates
Takes a vector in the parent object ' s local coordinates and transforms
it into world coordinates .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idVec3 idEntity : : GetWorldCoordinates ( const idVec3 & vec ) const
{
2012-11-26 18:58:24 +00:00
idVec3 pos ;
2012-11-28 15:47:07 +00:00
if ( ! bindMaster )
{
2012-11-26 18:58:24 +00:00
return vec ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . UnprojectVector ( vec , pos ) ;
pos + = masterOrigin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return pos ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetMasterPosition
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : GetMasterPosition ( idVec3 & masterOrigin , idMat3 & masterAxis ) const
{
2012-11-26 18:58:24 +00:00
idVec3 localOrigin ;
idMat3 localAxis ;
2012-11-28 15:47:07 +00:00
idAnimator * masterAnimator ;
if ( bindMaster )
{
2012-11-26 18:58:24 +00:00
// if bound to a joint of an animated model
2012-11-28 15:47:07 +00:00
if ( bindJoint ! = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
masterAnimator = bindMaster - > GetAnimator ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! masterAnimator )
{
2012-11-26 18:58:24 +00:00
masterOrigin = vec3_origin ;
masterAxis = mat3_identity ;
return false ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
masterAnimator - > GetJointTransform ( bindJoint , gameLocal . time , masterOrigin , masterAxis ) ;
masterAxis * = bindMaster - > renderEntity . axis ;
masterOrigin = bindMaster - > renderEntity . origin + masterOrigin * bindMaster - > renderEntity . axis ;
}
2012-11-28 15:47:07 +00:00
}
else if ( bindBody > = 0 & & bindMaster - > GetPhysics ( ) )
{
2012-11-26 18:58:24 +00:00
masterOrigin = bindMaster - > GetPhysics ( ) - > GetOrigin ( bindBody ) ;
masterAxis = bindMaster - > GetPhysics ( ) - > GetAxis ( bindBody ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
masterOrigin = bindMaster - > renderEntity . origin ;
masterAxis = bindMaster - > renderEntity . axis ;
}
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
masterOrigin = vec3_origin ;
masterAxis = mat3_identity ;
return false ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetWorldVelocities
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : GetWorldVelocities ( idVec3 & linearVelocity , idVec3 & angularVelocity ) const
{
2012-11-26 18:58:24 +00:00
linearVelocity = physics - > GetLinearVelocity ( ) ;
angularVelocity = physics - > GetAngularVelocity ( ) ;
2012-11-28 15:47:07 +00:00
if ( bindMaster )
{
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin , masterLinearVelocity , masterAngularVelocity ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get position of master
GetMasterPosition ( masterOrigin , masterAxis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get master velocities
bindMaster - > GetWorldVelocities ( masterLinearVelocity , masterAngularVelocity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// linear velocity relative to master plus master linear and angular velocity
linearVelocity = linearVelocity * masterAxis + masterLinearVelocity +
2012-11-28 15:47:07 +00:00
masterAngularVelocity . Cross ( GetPhysics ( ) - > GetOrigin ( ) - masterOrigin ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : JoinTeam
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : JoinTeam ( idEntity * teammember )
{
idEntity * ent ;
idEntity * master ;
idEntity * prev ;
idEntity * next ;
2012-11-26 18:58:24 +00:00
// if we're already on a team, quit it so we can join this one
2012-11-28 15:47:07 +00:00
if ( teamMaster & & ( teamMaster ! = this ) )
{
2012-11-26 18:58:24 +00:00
QuitTeam ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( teammember ) ;
2012-11-28 15:47:07 +00:00
if ( teammember = = this )
{
2012-11-26 18:58:24 +00:00
teamMaster = this ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if our new team mate is already on a team
master = teammember - > teamMaster ;
2012-11-28 15:47:07 +00:00
if ( ! master )
{
2012-11-26 18:58:24 +00:00
// he's not on a team, so he's the new teamMaster
master = teammember ;
teammember - > teamMaster = teammember ;
teammember - > teamChain = this ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make anyone who's bound to me part of the new team
2012-11-28 15:47:07 +00:00
for ( ent = teamChain ; ent ! = NULL ; ent = ent - > teamChain )
{
2012-11-26 18:58:24 +00:00
ent - > teamMaster = master ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// skip past the chain members bound to the entity we're teaming up with
prev = teammember ;
next = teammember - > teamChain ;
2012-11-28 15:47:07 +00:00
if ( bindMaster )
{
2012-11-26 18:58:24 +00:00
// if we have a bindMaster, join after any entities bound to the entity
// we're joining
2012-11-28 15:47:07 +00:00
while ( next & & next - > IsBoundTo ( teammember ) )
{
2012-11-26 18:58:24 +00:00
prev = next ;
next = next - > teamChain ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// if we're not bound to someone, then put us at the end of the team
2012-11-28 15:47:07 +00:00
while ( next )
{
2012-11-26 18:58:24 +00:00
prev = next ;
next = next - > teamChain ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make anyone who's bound to me part of the new team and
// also find the last member of my team
2012-11-28 15:47:07 +00:00
for ( ent = this ; ent - > teamChain ! = NULL ; ent = ent - > teamChain )
{
2012-11-26 18:58:24 +00:00
ent - > teamChain - > teamMaster = master ;
}
2012-11-28 15:47:07 +00:00
prev - > teamChain = this ;
2012-11-26 18:58:24 +00:00
ent - > teamChain = next ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
teamMaster = master ;
2012-11-28 15:47:07 +00:00
// reorder the active entity list
2012-11-26 18:58:24 +00:00
gameLocal . sortTeamMasters = true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : QuitTeam
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : QuitTeam ( )
{
idEntity * ent ;
if ( ! teamMaster )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if I'm the teamMaster
2012-11-28 15:47:07 +00:00
if ( teamMaster = = this )
{
2012-11-26 18:58:24 +00:00
// do we have more than one teammate?
2012-11-28 15:47:07 +00:00
if ( ! teamChain - > teamChain )
{
2012-11-26 18:58:24 +00:00
// no, break up the team
teamChain - > teamMaster = NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// yes, so make the first teammate the teamMaster
2012-11-28 15:47:07 +00:00
for ( ent = teamChain ; ent ; ent = ent - > teamChain )
{
2012-11-26 18:58:24 +00:00
ent - > teamMaster = teamChain ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
assert ( teamMaster ) ;
assert ( teamMaster - > teamChain ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the previous member of the teamChain
ent = teamMaster ;
2012-11-28 15:47:07 +00:00
while ( ent - > teamChain ! = this )
{
2012-11-26 18:58:24 +00:00
assert ( ent - > teamChain ) ; // this should never happen
ent = ent - > teamChain ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove this from the teamChain
ent - > teamChain = teamChain ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if no one is left on the team, break it up
2012-11-28 15:47:07 +00:00
if ( ! teamMaster - > teamChain )
{
2012-11-26 18:58:24 +00:00
teamMaster - > teamMaster = NULL ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
teamMaster = NULL ;
teamChain = NULL ;
}
/***********************************************************************
Physics .
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : InitDefaultPhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : InitDefaultPhysics ( const idVec3 & origin , const idMat3 & axis )
{
const char * temp ;
idClipModel * clipModel = NULL ;
2012-11-26 18:58:24 +00:00
// check if a clipmodel key/value pair is set
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " clipmodel " , " " , & temp ) )
{
if ( idClipModel : : CheckModel ( temp ) )
{
clipModel = new ( TAG_PHYSICS_CLIP_ENTITY ) idClipModel ( temp ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
if ( ! spawnArgs . GetBool ( " noclipmodel " , " 0 " ) )
{
2012-11-26 18:58:24 +00:00
// check if mins/maxs or size key/value pairs are set
2012-11-28 15:47:07 +00:00
if ( ! clipModel )
{
2012-11-26 18:58:24 +00:00
idVec3 size ;
idBounds bounds ;
bool setClipModel = false ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetVector ( " mins " , NULL , bounds [ 0 ] ) & &
spawnArgs . GetVector ( " maxs " , NULL , bounds [ 1 ] ) )
{
2012-11-26 18:58:24 +00:00
setClipModel = true ;
2012-11-28 15:47:07 +00:00
if ( bounds [ 0 ] [ 0 ] > bounds [ 1 ] [ 0 ] | | bounds [ 0 ] [ 1 ] > bounds [ 1 ] [ 1 ] | | bounds [ 0 ] [ 2 ] > bounds [ 1 ] [ 2 ] )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Invalid bounds '%s'-'%s' on entity '%s' " , bounds [ 0 ] . ToString ( ) , bounds [ 1 ] . ToString ( ) , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( spawnArgs . GetVector ( " size " , NULL , size ) )
{
if ( ( size . x < 0.0f ) | | ( size . y < 0.0f ) | | ( size . z < 0.0f ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Invalid size '%s' on entity '%s' " , size . ToString ( ) , name . c_str ( ) ) ;
}
bounds [ 0 ] . Set ( size . x * - 0.5f , size . y * - 0.5f , 0.0f ) ;
bounds [ 1 ] . Set ( size . x * 0.5f , size . y * 0.5f , size . z ) ;
setClipModel = true ;
}
2012-11-28 15:47:07 +00:00
if ( setClipModel )
{
2012-11-26 18:58:24 +00:00
int numSides ;
idTraceModel trm ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetInt ( " cylinder " , " 0 " , numSides ) & & numSides > 0 )
{
2012-11-26 18:58:24 +00:00
trm . SetupCylinder ( bounds , numSides < 3 ? 3 : numSides ) ;
2012-11-28 15:47:07 +00:00
}
else if ( spawnArgs . GetInt ( " cone " , " 0 " , numSides ) & & numSides > 0 )
{
2012-11-26 18:58:24 +00:00
trm . SetupCone ( bounds , numSides < 3 ? 3 : numSides ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
trm . SetupBox ( bounds ) ;
}
2012-11-28 15:47:07 +00:00
clipModel = new ( TAG_PHYSICS_CLIP_ENTITY ) idClipModel ( trm ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if the visual model can be used as collision model
2012-11-28 15:47:07 +00:00
if ( ! clipModel )
{
2012-11-26 18:58:24 +00:00
temp = spawnArgs . GetString ( " model " ) ;
2012-11-28 15:47:07 +00:00
if ( ( temp ! = NULL ) & & ( * temp ! = 0 ) )
{
if ( idClipModel : : CheckModel ( temp ) )
{
clipModel = new ( TAG_PHYSICS_CLIP_ENTITY ) idClipModel ( temp ) ;
2012-11-26 18:58:24 +00:00
}
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
defaultPhysicsObj . SetSelf ( this ) ;
defaultPhysicsObj . SetClipModel ( clipModel , 1.0f ) ;
defaultPhysicsObj . SetOrigin ( origin ) ;
defaultPhysicsObj . SetAxis ( axis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physics = & defaultPhysicsObj ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetPhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetPhysics ( idPhysics * phys )
{
2012-11-26 18:58:24 +00:00
// clear any contacts the current physics object has
2012-11-28 15:47:07 +00:00
if ( physics )
{
2012-11-26 18:58:24 +00:00
physics - > ClearContacts ( ) ;
}
// set new physics object or set the default physics if NULL
2012-11-28 15:47:07 +00:00
if ( phys ! = NULL )
{
2012-11-26 18:58:24 +00:00
defaultPhysicsObj . SetClipModel ( NULL , 1.0f ) ;
physics = phys ;
physics - > Activate ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
physics = & defaultPhysicsObj ;
}
physics - > UpdateTime ( gameLocal . time ) ;
physics - > SetMaster ( bindMaster , fl . bindOrientated ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RestorePhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : RestorePhysics ( idPhysics * phys )
{
2012-11-26 18:58:24 +00:00
assert ( phys ! = NULL ) ;
// restore physics pointer
physics = phys ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idPhysics * idEntity : : GetPhysics ( ) const
{
2012-11-26 18:58:24 +00:00
return physics ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RunPhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : RunPhysics ( )
{
2012-11-26 18:58:24 +00:00
int i , reachedTime ;
2012-11-28 15:47:07 +00:00
idEntity * part = NULL , * blockedPart = NULL , * blockingEntity = NULL ;
2012-11-26 18:58:24 +00:00
trace_t results ;
bool moved ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't run physics if not enabled
2012-11-28 15:47:07 +00:00
if ( ! ( thinkFlags & TH_PHYSICS ) )
{
2012-11-26 18:58:24 +00:00
// however do update any animation controllers
2012-11-28 15:47:07 +00:00
if ( UpdateAnimationControllers ( ) )
{
2012-11-26 18:58:24 +00:00
BecomeActive ( TH_ANIMATE ) ;
}
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if this entity is a team slave don't do anything because the team master will handle everything
2012-11-28 15:47:07 +00:00
if ( teamMaster & & teamMaster ! = this )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int startTime = gameLocal . previousTime ;
const int endTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . push . InitSavingPushedEntityPositions ( ) ;
blockedPart = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save the physics state of the whole team and disable the team for collision detection
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
if ( ! part - > fl . solidForTeam )
{
2012-11-26 18:58:24 +00:00
part - > physics - > DisableClip ( ) ;
}
part - > physics - > SaveState ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move the whole team
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
2012-11-26 18:58:24 +00:00
// run physics
moved = part - > physics - > Evaluate ( GetPhysicsTimeStep ( ) , endTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if the object is blocked
blockingEntity = part - > physics - > GetBlockingEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( blockingEntity )
{
2012-11-26 18:58:24 +00:00
blockedPart = part ;
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if moved or forced to update the visual position and orientation from the physics
2012-11-28 15:47:07 +00:00
if ( moved | | part - > fl . forcePhysicsUpdate )
{
2012-11-26 18:58:24 +00:00
part - > UpdateFromPhysics ( false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update any animation controllers here so an entity bound
// to a joint of this entity gets the correct position
2012-11-28 15:47:07 +00:00
if ( part - > UpdateAnimationControllers ( ) )
{
2012-11-26 18:58:24 +00:00
part - > BecomeActive ( TH_ANIMATE ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// enable the whole team for collision detection
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
if ( ! part - > fl . solidForTeam )
{
2012-11-26 18:58:24 +00:00
part - > physics - > EnableClip ( ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if one of the team entities is a pusher and blocked
2012-11-28 15:47:07 +00:00
if ( blockedPart )
{
2012-11-26 18:58:24 +00:00
// move the parts back to the previous position
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = blockedPart ; part = part - > teamChain )
{
if ( part - > physics )
{
2012-11-26 18:58:24 +00:00
// restore the physics state
part - > physics - > RestoreState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move back the visual position and orientation
part - > UpdateFromPhysics ( true ) ;
}
}
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
2012-11-26 18:58:24 +00:00
// update the physics time without moving
part - > physics - > UpdateTime ( endTime ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// restore the positions of any pushed entities
gameLocal . push . RestorePushedEntityPositions ( ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the master pusher has a "blocked" function, call it
Signal ( SIG_BLOCKED ) ;
ProcessEvent ( & EV_TeamBlocked , blockedPart , blockingEntity ) ;
// call the blocked function on the blocked part
blockedPart - > ProcessEvent ( & EV_PartBlocked , blockingEntity ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// This is to hack around an issue when reloading a game saved on certain movers would
// eject the player randomly through the world due to the first couple of frames imparting
// large pushVelocities.
const bool useAbnormalVelocityHack = ( idStr : : Cmp ( name , " houndola " ) = = 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Disable motion blur if this object pushes the local player
renderEntity . skipMotionBlur = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set pushed
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < gameLocal . push . GetNumPushedEntities ( ) ; i + + )
{
idEntity * ent = gameLocal . push . GetPushedEntity ( i ) ;
if ( ent - > physics - > IsType ( idPhysics_Player : : Type ) )
{
if ( gameLocal . GetLocalClientNum ( ) = = ent - > entityNumber )
{
2012-11-26 18:58:24 +00:00
renderEntity . skipMotionBlur = true ;
}
2012-11-28 15:47:07 +00:00
if ( useAbnormalVelocityHack )
{
idPhysics_Player * physics = static_cast < idPhysics_Player * > ( ent - > physics ) ;
2012-11-26 18:58:24 +00:00
physics - > SetPushedWithAbnormalVelocityHack ( GetPhysicsTimeStep ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
ent - > physics - > SetPushed ( endTime - startTime ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
ent - > physics - > SetPushed ( endTime - startTime ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Propogate skipMotionBlur to all team members
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
2012-11-26 18:58:24 +00:00
part - > renderEntity . skipMotionBlur = renderEntity . skipMotionBlur ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// post reached event if the current time is at or past the end point of the motion
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
2012-11-26 18:58:24 +00:00
reachedTime = part - > physics - > GetLinearEndTime ( ) ;
2012-11-28 15:47:07 +00:00
if ( startTime < reachedTime & & endTime > = reachedTime )
{
2012-11-26 18:58:24 +00:00
part - > ProcessEvent ( & EV_ReachedPos ) ;
}
reachedTime = part - > physics - > GetAngularEndTime ( ) ;
2012-11-28 15:47:07 +00:00
if ( startTime < reachedTime & & endTime > = reachedTime )
{
2012-11-26 18:58:24 +00:00
part - > ProcessEvent ( & EV_ReachedAng ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : InterpolatePhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : InterpolatePhysics ( const float fraction )
{
2012-11-26 18:58:24 +00:00
int i , startTime , endTime ;
2012-11-28 15:47:07 +00:00
idEntity * part = NULL , * blockedPart = NULL , * blockingEntity = NULL ;
2012-11-26 18:58:24 +00:00
trace_t results ;
bool moved ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't run physics if not enabled
2012-11-28 15:47:07 +00:00
if ( ! ( thinkFlags & TH_PHYSICS ) )
{
2012-11-26 18:58:24 +00:00
// however do update any animation controllers
2012-11-28 15:47:07 +00:00
if ( UpdateAnimationControllers ( ) )
{
2012-11-26 18:58:24 +00:00
BecomeActive ( TH_ANIMATE ) ;
}
return ;
}
// if this entity is a team slave, we still need to interpolate it's current position from the snapshot.
// The team master probably depends on the current physics state, and may be unaware of prev/next or interpolation.
2012-11-28 15:47:07 +00:00
if ( teamMaster & & teamMaster ! = this )
{
if ( physics ! = NULL & & useClientInterpolation )
{
if ( physics - > Interpolate ( fraction ) )
{
2012-11-26 18:58:24 +00:00
UpdateFromPhysics ( false ) ;
}
}
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
startTime = gameLocal . previousTime ;
endTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . push . InitSavingPushedEntityPositions ( ) ;
blockedPart = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save the physics state of the whole team and disable the team for collision detection
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
if ( ! part - > fl . solidForTeam )
{
2012-11-26 18:58:24 +00:00
part - > physics - > DisableClip ( ) ;
}
part - > physics - > SaveState ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move the whole team
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
2012-11-26 18:58:24 +00:00
// run physics
moved = part - > physics - > Evaluate ( GetPhysicsTimeStep ( ) , endTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if the object is blocked
blockingEntity = part - > physics - > GetBlockingEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( blockingEntity )
{
2012-11-26 18:58:24 +00:00
blockedPart = part ;
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if moved or forced to update the visual position and orientation from the physics
2012-11-28 15:47:07 +00:00
if ( moved | | part - > fl . forcePhysicsUpdate )
{
2012-11-26 18:58:24 +00:00
part - > UpdateFromPhysics ( false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update any animation controllers here so an entity bound
// to a joint of this entity gets the correct position
2012-11-28 15:47:07 +00:00
if ( part - > UpdateAnimationControllers ( ) )
{
2012-11-26 18:58:24 +00:00
part - > BecomeActive ( TH_ANIMATE ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// enable the whole team for collision detection
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
if ( ! part - > fl . solidForTeam )
{
2012-11-26 18:58:24 +00:00
part - > physics - > EnableClip ( ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if one of the team entities is a pusher and blocked
2012-11-28 15:47:07 +00:00
if ( blockedPart )
{
2012-11-26 18:58:24 +00:00
// move the parts back to the previous position
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = blockedPart ; part = part - > teamChain )
{
if ( part - > physics )
{
2012-11-26 18:58:24 +00:00
// restore the physics state
part - > physics - > RestoreState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move back the visual position and orientation
part - > UpdateFromPhysics ( true ) ;
}
}
2012-11-28 15:47:07 +00:00
for ( part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics )
{
2012-11-26 18:58:24 +00:00
// update the physics time without moving
part - > physics - > UpdateTime ( endTime ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// restore the positions of any pushed entities
gameLocal . push . RestorePushedEntityPositions ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set pushed
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < gameLocal . push . GetNumPushedEntities ( ) ; i + + )
{
idEntity * ent = gameLocal . push . GetPushedEntity ( i ) ;
2012-11-26 18:58:24 +00:00
ent - > physics - > SetPushed ( GetPhysicsTimeStep ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( physics & & useClientInterpolation )
{
if ( physics - > Interpolate ( fraction ) )
{
2012-11-26 18:58:24 +00:00
UpdateFromPhysics ( false ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : InterpolatePhysicsOnly
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : InterpolatePhysicsOnly ( const float fraction , bool updateTeam )
{
if ( physics & & useClientInterpolation )
{
if ( physics - > Interpolate ( fraction ) )
{
2012-11-26 18:58:24 +00:00
UpdateFromPhysics ( false ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( updateTeam )
{
2012-11-26 18:58:24 +00:00
int endTime = gameLocal . time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move the whole team
2012-11-28 15:47:07 +00:00
for ( idEntity * part = this ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > physics & & part ! = this )
{
2012-11-26 18:58:24 +00:00
// run physics
bool moved = part - > physics - > Evaluate ( GetPhysicsTimeStep ( ) , endTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if moved or forced to update the visual position and orientation from the physics
2012-11-28 15:47:07 +00:00
if ( moved | | part - > fl . forcePhysicsUpdate )
{
2012-11-26 18:58:24 +00:00
part - > UpdateFromPhysics ( false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update any animation controllers here so an entity bound
// to a joint of this entity gets the correct position
2012-11-28 15:47:07 +00:00
if ( part - > UpdateAnimationControllers ( ) )
{
2012-11-26 18:58:24 +00:00
part - > BecomeActive ( TH_ANIMATE ) ;
}
}
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateFromPhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : UpdateFromPhysics ( bool moveBack )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( IsType ( idActor : : Type ) )
{
idActor * actor = static_cast < idActor * > ( this ) ;
2012-11-26 18:58:24 +00:00
// set master delta angles for actors
2012-11-28 15:47:07 +00:00
if ( GetBindMaster ( ) )
{
2012-11-26 18:58:24 +00:00
idAngles delta = actor - > GetDeltaViewAngles ( ) ;
2012-11-28 15:47:07 +00:00
if ( moveBack )
{
delta . yaw - = static_cast < idPhysics_Actor * > ( physics ) - > GetMasterDeltaYaw ( ) ;
}
else
{
delta . yaw + = static_cast < idPhysics_Actor * > ( physics ) - > GetMasterDeltaYaw ( ) ;
2012-11-26 18:58:24 +00:00
}
actor - > SetDeltaViewAngles ( delta ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPhysicsTimeStep
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idEntity : : GetPhysicsTimeStep ( ) const
{
2012-11-26 18:58:24 +00:00
return gameLocal . time - gameLocal . previousTime ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetOrigin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetOrigin ( const idVec3 & org )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetOrigin ( org ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetAxis
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetAxis ( const idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( GetPhysics ( ) - > IsType ( idPhysics_Actor : : Type ) )
{
static_cast < idActor * > ( this ) - > viewAxis = axis ;
}
else
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetAxis ( axis ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetAngles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetAngles ( const idAngles & ang )
{
2012-11-26 18:58:24 +00:00
SetAxis ( ang . ToMat3 ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetFloorPos
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : GetFloorPos ( float max_dist , idVec3 & floorpos ) const
{
2012-11-26 18:58:24 +00:00
trace_t result ;
2012-11-28 15:47:07 +00:00
if ( ! GetPhysics ( ) - > HasGroundContacts ( ) )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > ClipTranslation ( result , GetPhysics ( ) - > GetGravityNormal ( ) * max_dist , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( result . fraction < 1.0f )
{
2012-11-26 18:58:24 +00:00
floorpos = result . endpos ;
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
floorpos = GetPhysics ( ) - > GetOrigin ( ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
floorpos = GetPhysics ( ) - > GetOrigin ( ) ;
return true ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPhysicsToVisualTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : GetPhysicsToVisualTransform ( idVec3 & origin , idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPhysicsToSoundTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : GetPhysicsToSoundTransform ( idVec3 & origin , idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
// by default play the sound at the center of the bounding box of the first clip model
2012-11-28 15:47:07 +00:00
if ( GetPhysics ( ) - > GetNumClipModels ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
origin = GetPhysics ( ) - > GetBounds ( ) . GetCenter ( ) ;
axis . Identity ( ) ;
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Collide
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : Collide ( const trace_t & collision , const idVec3 & velocity )
{
2012-11-26 18:58:24 +00:00
// this entity collides with collision.c.entityNum
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetImpactInfo
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : GetImpactInfo ( idEntity * ent , int id , const idVec3 & point , impactInfo_t * info )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > GetImpactInfo ( id , point , info ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ApplyImpulse
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ApplyImpulse ( idEntity * ent , int id , const idVec3 & point , const idVec3 & impulse )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > ApplyImpulse ( id , point , impulse ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : AddForce
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : AddForce ( idEntity * ent , int id , const idVec3 & point , const idVec3 & force )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > AddForce ( id , point , force ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ActivatePhysics
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ActivatePhysics ( idEntity * ent )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > Activate ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsAtRest
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : IsAtRest ( ) const
{
2012-11-26 18:58:24 +00:00
return GetPhysics ( ) - > IsAtRest ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetRestStartTime
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idEntity : : GetRestStartTime ( ) const
{
2012-11-26 18:58:24 +00:00
return GetPhysics ( ) - > GetRestStartTime ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : AddContactEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : AddContactEntity ( idEntity * ent )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > AddContactEntity ( ent ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RemoveContactEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : RemoveContactEntity ( idEntity * ent )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > RemoveContactEntity ( ent ) ;
}
/***********************************************************************
Damage
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = =
idEntity : : CanDamage
Returns true if the inflictor can directly damage the target . Used for
explosions and melee attacks .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : CanDamage ( const idVec3 & origin , idVec3 & damagePoint ) const
{
2012-11-26 18:58:24 +00:00
idVec3 dest ;
trace_t tr ;
idVec3 midpoint ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// use the midpoint of the bounds instead of the origin, because
// bmodels may have their origin at 0,0,0
midpoint = ( GetPhysics ( ) - > GetAbsBounds ( ) [ 0 ] + GetPhysics ( ) - > GetAbsBounds ( ) [ 1 ] ) * 0.5 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dest = midpoint ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) )
{
2012-11-26 18:58:24 +00:00
damagePoint = tr . endpos ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// this should probably check in the plane of projection, rather than in world coordinate
dest = midpoint ;
dest [ 0 ] + = 15.0 ;
dest [ 1 ] + = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) )
{
2012-11-26 18:58:24 +00:00
damagePoint = tr . endpos ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dest = midpoint ;
dest [ 0 ] + = 15.0 ;
dest [ 1 ] - = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) )
{
2012-11-26 18:58:24 +00:00
damagePoint = tr . endpos ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dest = midpoint ;
dest [ 0 ] - = 15.0 ;
dest [ 1 ] + = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) )
{
2012-11-26 18:58:24 +00:00
damagePoint = tr . endpos ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dest = midpoint ;
dest [ 0 ] - = 15.0 ;
dest [ 1 ] - = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) )
{
2012-11-26 18:58:24 +00:00
damagePoint = tr . endpos ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dest = midpoint ;
dest [ 2 ] + = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) )
{
2012-11-26 18:58:24 +00:00
damagePoint = tr . endpos ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dest = midpoint ;
dest [ 2 ] - = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) )
{
2012-11-26 18:58:24 +00:00
damagePoint = tr . endpos ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DamageFeedback
callback function for when another entity received damage from this entity . damage can be adjusted and returned to the caller .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : DamageFeedback ( idEntity * victim , idEntity * inflictor , int & damage )
{
2012-11-26 18:58:24 +00:00
// implemented in subclasses
}
/*
= = = = = = = = = = = =
Damage
this entity that is being damaged
inflictor entity that is causing the damage
attacker entity that caused the inflictor to damage targ
example : this = monster , inflictor = rocket , attacker = player
dir direction of the attack for knockback in global space
point point at which the damage is being inflicted , used for headshots
damage amount of damage being inflicted
inflictor , attacker , dir , and point can be NULL for environmental effects
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Damage ( idEntity * inflictor , idEntity * attacker , const idVec3 & dir ,
const char * damageDefName , const float damageScale , const int location )
{
if ( ! fl . takedamage )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetTimeState ts ( timeGroup ) ;
2012-11-28 15:47:07 +00:00
if ( ! inflictor )
{
2012-11-26 18:58:24 +00:00
inflictor = gameLocal . world ;
}
2012-11-28 15:47:07 +00:00
if ( ! attacker )
{
2012-11-26 18:58:24 +00:00
attacker = gameLocal . world ;
}
2012-11-28 15:47:07 +00:00
const idDict * damageDef = gameLocal . FindEntityDefDict ( damageDefName ) ;
if ( damageDef = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Unknown damageDef '%s' \n " , damageDefName ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int damage = damageDef - > GetInt ( " damage " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// inform the attacker that they hit someone
attacker - > DamageFeedback ( this , inflictor , damage ) ;
2012-11-28 15:47:07 +00:00
if ( damage )
{
2012-11-26 18:58:24 +00:00
// do the damage
health - = damage ;
2012-11-28 15:47:07 +00:00
if ( health < = 0 )
{
if ( health < - 999 )
{
2012-11-26 18:58:24 +00:00
health = - 999 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Killed ( inflictor , attacker , damage , dir , location ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Pain ( inflictor , attacker , damage , dir , location ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : AddDamageEffect
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : AddDamageEffect ( const trace_t & collision , const idVec3 & velocity , const char * damageDefName )
{
const char * sound , * decal , * key ;
const idDeclEntityDef * def = gameLocal . FindEntityDef ( damageDefName , false ) ;
if ( def = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const char * materialType = gameLocal . sufaceTypeNames [ collision . c . material - > GetSurfaceType ( ) ] ;
2012-11-26 18:58:24 +00:00
// start impact sound based on material type
key = va ( " snd_%s " , materialType ) ;
sound = spawnArgs . GetString ( key ) ;
2012-11-28 15:47:07 +00:00
if ( * sound = = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
sound = def - > dict . GetString ( key ) ;
}
2012-11-28 15:47:07 +00:00
if ( * sound ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_decals . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
// place a wound overlay on the model
key = va ( " mtr_wound_%s " , materialType ) ;
decal = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
2012-11-28 15:47:07 +00:00
if ( * decal = = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
decal = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
2012-11-28 15:47:07 +00:00
if ( * decal ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
idVec3 dir = velocity ;
dir . Normalize ( ) ;
ProjectOverlay ( collision . c . point , dir , 20.0f , decal ) ;
}
}
}
/*
= = = = = = = = = = = =
idEntity : : Pain
Called whenever an entity recieves damage . Returns whether the entity responds to the pain .
This is a virtual function that subclasses are expected to implement .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : Pain ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location )
{
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = =
idEntity : : Killed
Called whenever an entity ' s health is reduced to 0 or less .
This is a virtual function that subclasses are expected to implement .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location )
{
2012-11-26 18:58:24 +00:00
}
/***********************************************************************
Script functions
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : ShouldConstructScriptObjectAtSpawn
Called during idEntity : : Spawn to see if it should construct the script object or not .
Overridden by subclasses that need to spawn the script object themselves .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : ShouldConstructScriptObjectAtSpawn ( ) const
{
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ConstructScriptObject
Called during idEntity : : Spawn . Calls the constructor on the script object .
Can be overridden by subclasses when a thread doesn ' t need to be allocated .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idThread * idEntity : : ConstructScriptObject ( )
{
idThread * thread ;
const function_t * constructor ;
2012-11-26 18:58:24 +00:00
// init the script object's data
scriptObject . ClearObject ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// call script object's constructor
constructor = scriptObject . GetConstructor ( ) ;
2012-11-28 15:47:07 +00:00
if ( constructor )
{
2012-11-26 18:58:24 +00:00
// start a thread that will initialize after Spawn is done being called
thread = new idThread ( ) ;
thread - > SetThreadName ( name . c_str ( ) ) ;
thread - > CallFunction ( this , constructor , true ) ;
thread - > DelayedStart ( 0 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
thread = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear out the object's memory
scriptObject . ClearObject ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return thread ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DeconstructScriptObject
Called during idEntity : : ~ idEntity . Calls the destructor on the script object .
Can be overridden by subclasses when a thread doesn ' t need to be allocated .
Not called during idGameLocal : : MapShutdown .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : DeconstructScriptObject ( )
{
idThread * thread ;
const function_t * destructor ;
2012-11-26 18:58:24 +00:00
// don't bother calling the script object's destructor on map shutdown
2012-11-28 15:47:07 +00:00
if ( gameLocal . GameState ( ) = = GAMESTATE_SHUTDOWN )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// call script object's destructor
destructor = scriptObject . GetDestructor ( ) ;
2012-11-28 15:47:07 +00:00
if ( destructor )
{
2012-11-26 18:58:24 +00:00
// start a thread that will run immediately and be destroyed
thread = new idThread ( ) ;
thread - > SetThreadName ( name . c_str ( ) ) ;
thread - > CallFunction ( this , destructor , true ) ;
thread - > Execute ( ) ;
delete thread ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : HasSignal
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : HasSignal ( signalNum_t signalnum ) const
{
if ( ! signals )
{
2012-11-26 18:58:24 +00:00
return false ;
}
assert ( ( signalnum > = 0 ) & & ( signalnum < NUM_SIGNALS ) ) ;
return ( signals - > signal [ signalnum ] . Num ( ) > 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetSignal
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetSignal ( signalNum_t signalnum , idThread * thread , const function_t * function )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
signal_t sig ;
int threadnum ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ( signalnum > = 0 ) & & ( signalnum < NUM_SIGNALS ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! signals )
{
signals = new ( TAG_ENTITY ) signalList_t ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( thread ) ;
threadnum = thread - > GetThreadNum ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
num = signals - > signal [ signalnum ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
if ( signals - > signal [ signalnum ] [ i ] . threadnum = = threadnum )
{
2012-11-26 18:58:24 +00:00
signals - > signal [ signalnum ] [ i ] . function = function ;
return ;
}
}
2012-11-28 15:47:07 +00:00
if ( num > = MAX_SIGNAL_THREADS )
{
2012-11-26 18:58:24 +00:00
thread - > Error ( " Exceeded maximum number of signals per object " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
sig . threadnum = threadnum ;
sig . function = function ;
signals - > signal [ signalnum ] . Append ( sig ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClearSignal
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ClearSignal ( idThread * thread , signalNum_t signalnum )
{
2012-11-26 18:58:24 +00:00
assert ( thread ) ;
2012-11-28 15:47:07 +00:00
if ( ( signalnum < 0 ) | | ( signalnum > = NUM_SIGNALS ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Signal out of range " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( signals = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
signals - > signal [ signalnum ] . Clear ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClearSignalThread
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ClearSignalThread ( signalNum_t signalnum , idThread * thread )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
int threadnum ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( thread ) ;
2012-11-28 15:47:07 +00:00
if ( ( signalnum < 0 ) | | ( signalnum > = NUM_SIGNALS ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Signal out of range " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( signals = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
threadnum = thread - > GetThreadNum ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
num = signals - > signal [ signalnum ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
if ( signals - > signal [ signalnum ] [ i ] . threadnum = = threadnum )
{
2012-11-26 18:58:24 +00:00
signals - > signal [ signalnum ] . RemoveIndex ( i ) ;
return ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Signal
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Signal ( signalNum_t signalnum )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
signal_t sigs [ MAX_SIGNAL_THREADS ] ;
2012-11-28 15:47:07 +00:00
idThread * thread ;
2012-11-26 18:58:24 +00:00
assert ( ( signalnum > = 0 ) & & ( signalnum < NUM_SIGNALS ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! signals )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we copy the signal list since each thread has the potential
// to end any of the threads in the list. By copying the list
// we don't have to worry about the list changing as we're
// processing it.
num = signals - > signal [ signalnum ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
sigs [ i ] = signals - > signal [ signalnum ] [ i ] ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear out the signal list so that we don't get into an infinite loop
signals - > signal [ signalnum ] . Clear ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
thread = idThread : : GetThread ( sigs [ i ] . threadnum ) ;
2012-11-28 15:47:07 +00:00
if ( thread )
{
2012-11-26 18:58:24 +00:00
thread - > CallFunction ( this , sigs [ i ] . function , true ) ;
thread - > Execute ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SignalEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SignalEvent ( idThread * thread , signalNum_t signalnum )
{
if ( ( signalnum < 0 ) | | ( signalnum > = NUM_SIGNALS ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Signal out of range " ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! signals )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Signal ( signalnum ) ;
}
/***********************************************************************
Guis .
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : TriggerGuis
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : TriggerGuis ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + )
{
if ( renderEntity . gui [ i ] )
{
2012-11-26 18:58:24 +00:00
renderEntity . gui [ i ] - > Trigger ( gameLocal . time ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : HandleGuiCommands
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : HandleGuiCommands ( idEntity * entityGui , const char * cmds )
{
idEntity * targetEnt ;
2012-11-26 18:58:24 +00:00
bool ret = false ;
2012-11-28 15:47:07 +00:00
if ( entityGui & & cmds & & * cmds )
{
2012-11-26 18:58:24 +00:00
idLexer src ;
idToken token , token2 , token3 , token4 ;
src . LoadMemory ( cmds , strlen ( cmds ) , " guiCommands " ) ;
2012-11-28 15:47:07 +00:00
while ( 1 )
{
if ( ! src . ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
return ret ;
}
2012-11-28 15:47:07 +00:00
if ( token = = " ; " )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " activate " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
bool targets = true ;
2012-11-28 15:47:07 +00:00
if ( src . ReadToken ( & token2 ) )
{
if ( token2 = = " ; " )
{
2012-11-26 18:58:24 +00:00
src . UnreadToken ( & token2 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
targets = false ;
}
}
2012-11-28 15:47:07 +00:00
if ( targets )
{
2012-11-26 18:58:24 +00:00
entityGui - > ActivateTargets ( this ) ;
2012-11-28 15:47:07 +00:00
}
else
{
idEntity * ent = gameLocal . FindEntity ( token2 ) ;
if ( ent )
{
2012-11-26 18:58:24 +00:00
ent - > Signal ( SIG_TRIGGER ) ;
ent - > PostEventMS ( & EV_Activate , 0 , this ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
entityGui - > renderEntity . shaderParms [ SHADERPARM_MODE ] = 1.0f ;
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " runScript " ) = = 0 )
{
if ( src . ReadToken ( & token2 ) )
{
while ( src . CheckTokenString ( " :: " ) )
{
2012-11-26 18:58:24 +00:00
idToken token3 ;
2012-11-28 15:47:07 +00:00
if ( ! src . ReadToken ( & token3 ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Expecting function name following '::' in gui for entity '%s' " , entityGui - > name . c_str ( ) ) ;
}
token2 + = " :: " + token3 ;
}
2012-11-28 15:47:07 +00:00
const function_t * func = gameLocal . program . FindFunction ( token2 ) ;
if ( ! func )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Can't find function '%s' for gui in entity '%s' " , token2 . c_str ( ) , entityGui - > name . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
idThread * thread = new idThread ( func ) ;
2012-11-26 18:58:24 +00:00
thread - > DelayedStart ( 0 ) ;
}
}
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " play " ) = = 0 )
{
if ( src . ReadToken ( & token2 ) )
{
const idSoundShader * shader = declManager - > FindSound ( token2 ) ;
2012-11-26 18:58:24 +00:00
entityGui - > StartSoundShader ( shader , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " setkeyval " ) = = 0 )
{
if ( src . ReadToken ( & token2 ) & & src . ReadToken ( & token3 ) & & src . ReadToken ( & token4 ) )
{
idEntity * ent = gameLocal . FindEntity ( token2 ) ;
if ( ent )
{
2012-11-26 18:58:24 +00:00
ent - > spawnArgs . Set ( token3 , token4 ) ;
ent - > UpdateChangeableSpawnArgs ( NULL ) ;
ent - > UpdateVisuals ( ) ;
}
}
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " setshaderparm " ) = = 0 )
{
if ( src . ReadToken ( & token2 ) & & src . ReadToken ( & token3 ) )
{
2012-11-26 18:58:24 +00:00
entityGui - > SetShaderParm ( atoi ( token2 ) , atof ( token3 ) ) ;
entityGui - > UpdateVisuals ( ) ;
}
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " close " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
ret = true ;
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! token . Icmp ( " turkeyscore " ) )
{
if ( src . ReadToken ( & token2 ) & & entityGui - > renderEntity . gui [ 0 ] )
{
2012-11-26 18:58:24 +00:00
int score = entityGui - > renderEntity . gui [ 0 ] - > State ( ) . GetInt ( " score " ) ;
score + = atoi ( token2 ) ;
entityGui - > renderEntity . gui [ 0 ] - > SetStateInt ( " score " , score ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . GetLocalPlayer ( ) & & score > = 25000 )
{
2012-11-26 18:58:24 +00:00
gameLocal . GetLocalPlayer ( ) - > GetAchievementManager ( ) . EventCompletesAchievement ( ACHIEVEMENT_SCORE_25000_TURKEY_PUNCHER ) ;
2012-11-28 15:47:07 +00:00
gameLocal . GetLocalPlayer ( ) - > GiveEmail ( static_cast < const idDeclEmail * > ( declManager - > FindType ( DECL_EMAIL , " highScore " , false ) ) ) ;
2012-11-26 18:58:24 +00:00
}
}
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! token . Icmp ( " martianbuddycomplete " ) )
{
gameLocal . GetLocalPlayer ( ) - > GiveEmail ( static_cast < const idDeclEmail * > ( declManager - > FindType ( DECL_EMAIL , " MartianBuddyGameComplete " , false ) ) ) ;
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// handy for debugging GUI stuff
2012-11-28 15:47:07 +00:00
if ( ! token . Icmp ( " print " ) )
{
2012-11-26 18:58:24 +00:00
idStr msg ;
2012-11-28 15:47:07 +00:00
while ( src . ReadToken ( & token2 ) )
{
if ( token2 = = " ; " )
{
2012-11-26 18:58:24 +00:00
src . UnreadToken ( & token2 ) ;
break ;
}
msg + = token2 . c_str ( ) ;
}
common - > Printf ( " ent gui 0x%x '%s': %s \n " , entityNumber , name . c_str ( ) , msg . c_str ( ) ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we get to this point we don't know how to handle it
2012-11-28 15:47:07 +00:00
src . UnreadToken ( & token ) ;
if ( ! HandleSingleGuiCommand ( entityGui , & src ) )
{
2012-11-26 18:58:24 +00:00
// not handled there see if entity or any of its targets can handle it
// this will only work for one target atm
2012-11-28 15:47:07 +00:00
if ( entityGui - > HandleSingleGuiCommand ( entityGui , & src ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int c = entityGui - > targets . Num ( ) ;
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < c ; i + + )
{
2012-11-26 18:58:24 +00:00
targetEnt = entityGui - > targets [ i ] . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( targetEnt & & targetEnt - > HandleSingleGuiCommand ( entityGui , & src ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( i = = c )
{
2012-11-26 18:58:24 +00:00
// not handled
common - > DPrintf ( " idEntity::HandleGuiCommands: '%s' not handled \n " , token . c_str ( ) ) ;
src . ReadToken ( & token ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
}
return ret ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : HandleSingleGuiCommand
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : HandleSingleGuiCommand ( idEntity * entityGui , idLexer * src )
{
2012-11-26 18:58:24 +00:00
return false ;
}
/***********************************************************************
Targets
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = =
idEntity : : FindTargets
We have to wait until all entities are spawned
Used to build lists of targets after the entity is spawned . Since not all entities
have been spawned when the entity is created at map load time , we have to wait
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : FindTargets ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// targets can be a list of multiple names
gameLocal . GetTargets ( spawnArgs , targets , " target " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ensure that we don't target ourselves since that could cause an infinite loop when activating entities
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < targets . Num ( ) ; i + + )
{
if ( targets [ i ] . GetEntity ( ) = = this )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Entity '%s' is targeting itself " , name . c_str ( ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RemoveNullTargets
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : RemoveNullTargets ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = targets . Num ( ) - 1 ; i > = 0 ; i - - )
{
if ( ! targets [ i ] . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
targets . RemoveIndex ( i ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idEntity : : ActivateTargets
" activator " should be set to the entity that initiated the firing .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ActivateTargets ( idEntity * activator ) const
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
int i , j ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < targets . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
ent = targets [ i ] . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! ent )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent - > RespondsTo ( EV_Activate ) | | ent - > HasSignal ( SIG_TRIGGER ) )
{
2012-11-26 18:58:24 +00:00
ent - > Signal ( SIG_TRIGGER ) ;
ent - > ProcessEvent ( & EV_Activate , activator ) ;
2012-11-28 15:47:07 +00:00
}
for ( j = 0 ; j < MAX_RENDERENTITY_GUI ; j + + )
{
if ( ent - > renderEntity . gui [ j ] )
{
2012-11-26 18:58:24 +00:00
ent - > renderEntity . gui [ j ] - > Trigger ( gameLocal . time ) ;
}
}
}
}
/***********************************************************************
Misc .
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : Teleport
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Teleport ( const idVec3 & origin , const idAngles & angles , idEntity * destination )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetOrigin ( origin ) ;
GetPhysics ( ) - > SetAxis ( angles . ToMat3 ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = =
idEntity : : TouchTriggers
Activate all trigger entities touched at the current position .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : TouchTriggers ( ) const
{
2012-11-26 18:58:24 +00:00
int i , numClipModels , numEntities ;
2012-11-28 15:47:07 +00:00
idClipModel * cm ;
idClipModel * clipModels [ MAX_GENTITIES ] ;
idEntity * ent ;
2012-11-26 18:58:24 +00:00
trace_t trace ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( & trace , 0 , sizeof ( trace ) ) ;
trace . endpos = GetPhysics ( ) - > GetOrigin ( ) ;
trace . endAxis = GetPhysics ( ) - > GetAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numClipModels = gameLocal . clip . ClipModelsTouchingBounds ( GetPhysics ( ) - > GetAbsBounds ( ) , CONTENTS_TRIGGER , clipModels , MAX_GENTITIES ) ;
numEntities = 0 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numClipModels ; i + + )
{
2012-11-26 18:58:24 +00:00
cm = clipModels [ i ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't touch it if we're the owner
2012-11-28 15:47:07 +00:00
if ( cm - > GetOwner ( ) = = this )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ent = cm - > GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! ent - > RespondsTo ( EV_Touch ) & & ! ent - > HasSignal ( SIG_TOUCH ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! GetPhysics ( ) - > ClipContents ( cm ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetTimeState ts ( ent - > timeGroup ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numEntities + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
trace . c . contents = cm - > GetContents ( ) ;
trace . c . entityNum = cm - > GetEntity ( ) - > entityNumber ;
trace . c . id = cm - > GetId ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ent - > Signal ( SIG_TOUCH ) ;
ent - > ProcessEvent ( & EV_Touch , this , & trace ) ;
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . entities [ entityNumber ] )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " entity was removed while touching triggers \n " ) ;
return true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return ( numEntities ! = 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetSpline
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idCurve_Spline < idVec3 > * idEntity : : GetSpline ( ) const
{
2012-11-26 18:58:24 +00:00
int i , numPoints , t ;
2012-11-28 15:47:07 +00:00
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
idLexer lex ;
idVec3 v ;
2012-11-28 15:47:07 +00:00
idCurve_Spline < idVec3 > * spline ;
const char * curveTag = " curve_ " ;
2012-11-26 18:58:24 +00:00
kv = spawnArgs . MatchPrefix ( curveTag ) ;
2012-11-28 15:47:07 +00:00
if ( ! kv )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStr str = kv - > GetKey ( ) . Right ( kv - > GetKey ( ) . Length ( ) - strlen ( curveTag ) ) ;
2012-11-28 15:47:07 +00:00
if ( str . Icmp ( " CatmullRomSpline " ) = = 0 )
{
spline = new ( TAG_ENTITY ) idCurve_CatmullRomSpline < idVec3 > ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
else if ( str . Icmp ( " nubs " ) = = 0 )
{
spline = new ( TAG_ENTITY ) idCurve_NonUniformBSpline < idVec3 > ( ) ;
}
else if ( str . Icmp ( " nurbs " ) = = 0 )
{
spline = new ( TAG_ENTITY ) idCurve_NURBS < idVec3 > ( ) ;
}
else
{
spline = new ( TAG_ENTITY ) idCurve_BSpline < idVec3 > ( ) ;
}
2012-11-26 18:58:24 +00:00
spline - > SetBoundaryType ( idCurve_Spline < idVec3 > : : BT_CLAMPED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lex . LoadMemory ( kv - > GetValue ( ) , kv - > GetValue ( ) . Length ( ) , curveTag ) ;
numPoints = lex . ParseInt ( ) ;
lex . ExpectTokenString ( " ( " ) ;
2012-11-28 15:47:07 +00:00
for ( t = i = 0 ; i < numPoints ; i + + , t + = 100 )
{
2012-11-26 18:58:24 +00:00
v . x = lex . ParseFloat ( ) ;
v . y = lex . ParseFloat ( ) ;
v . z = lex . ParseFloat ( ) ;
spline - > AddValue ( t , v ) ;
}
lex . ExpectTokenString ( " ) " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return spline ;
}
/*
= = = = = = = = = = = = = = =
idEntity : : ShowEditingDialog
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ShowEditingDialog ( )
{
2012-11-26 18:58:24 +00:00
}
/***********************************************************************
Events
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetName
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetName ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnString ( name . c_str ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetName
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetName ( const char * newname )
{
2012-11-26 18:58:24 +00:00
SetName ( newname ) ;
}
/*
= = = = = = = = = = = = = = =
idEntity : : Event_FindTargets
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_FindTargets ( )
{
2012-11-26 18:58:24 +00:00
FindTargets ( ) ;
}
/*
= = = = = = = = = = = =
idEntity : : Event_ActivateTargets
Activates any entities targeted by this entity . Mainly used as an
event to delay activating targets .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_ActivateTargets ( idEntity * activator )
{
2012-11-26 18:58:24 +00:00
ActivateTargets ( activator ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_NumTargets
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_NumTargets ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnFloat ( targets . Num ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetTarget
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetTarget ( float index )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
i = ( int ) index ;
2012-11-28 15:47:07 +00:00
if ( ( i < 0 ) | | i > = targets . Num ( ) )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnEntity ( NULL ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnEntity ( targets [ i ] . GetEntity ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_RandomTarget
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_RandomTarget ( const char * ignore )
{
2012-11-26 18:58:24 +00:00
int num ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
2012-11-26 18:58:24 +00:00
int i ;
int ignoreNum ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RemoveNullTargets ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! targets . Num ( ) )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnEntity ( NULL ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ignoreNum = - 1 ;
2012-11-28 15:47:07 +00:00
if ( ignore & & ( ignore [ 0 ] ! = 0 ) & & ( targets . Num ( ) > 1 ) )
{
for ( i = 0 ; i < targets . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
ent = targets [ i ] . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ent & & ( ent - > name = = ignore ) )
{
2012-11-26 18:58:24 +00:00
ignoreNum = i ;
break ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( ignoreNum > = 0 )
{
2012-11-26 18:58:24 +00:00
num = gameLocal . random . RandomInt ( targets . Num ( ) - 1 ) ;
2012-11-28 15:47:07 +00:00
if ( num > = ignoreNum )
{
2012-11-26 18:58:24 +00:00
num + + ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
num = gameLocal . random . RandomInt ( targets . Num ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ent = targets [ num ] . GetEntity ( ) ;
idThread : : ReturnEntity ( ent ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_BindToJoint
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_BindToJoint ( idEntity * master , const char * jointname , float orientated )
{
2012-11-26 18:58:24 +00:00
BindToJoint ( master , jointname , ( orientated ! = 0.0f ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_RemoveBinds
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_RemoveBinds ( )
{
2012-11-26 18:58:24 +00:00
RemoveBinds ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Bind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_Bind ( idEntity * master )
{
2012-11-26 18:58:24 +00:00
Bind ( master , true ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_BindPosition
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_BindPosition ( idEntity * master )
{
2012-11-26 18:58:24 +00:00
Bind ( master , false ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Unbind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_Unbind ( )
{
2012-11-26 18:58:24 +00:00
Unbind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SpawnBind
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SpawnBind ( )
{
idEntity * parent ;
const char * bind , * joint , * bindanim ;
2012-11-26 18:58:24 +00:00
jointHandle_t bindJoint ;
bool bindOrientated ;
int id ;
2012-11-28 15:47:07 +00:00
const idAnim * anim ;
2012-11-26 18:58:24 +00:00
int animNum ;
2012-11-28 15:47:07 +00:00
idAnimator * parentAnimator ;
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " bind " , " " , & bind ) )
{
if ( idStr : : Icmp ( bind , " worldspawn " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
//FIXME: Completely unneccessary since the worldspawn is called "world"
parent = gameLocal . world ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
parent = gameLocal . FindEntity ( bind ) ;
}
bindOrientated = spawnArgs . GetBool ( " bindOrientated " , " 1 " ) ;
2012-11-28 15:47:07 +00:00
if ( parent )
{
2012-11-26 18:58:24 +00:00
// bind to a joint of the skeletal model of the parent
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " bindToJoint " , " " , & joint ) & & * joint )
{
2012-11-26 18:58:24 +00:00
parentAnimator = parent - > GetAnimator ( ) ;
2012-11-28 15:47:07 +00:00
if ( parentAnimator = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Cannot bind to joint '%s' on '%s'. Entity does not support skeletal models. " , joint , name . c_str ( ) ) ;
return ;
}
bindJoint = parentAnimator - > GetJointHandle ( joint ) ;
2012-11-28 15:47:07 +00:00
if ( bindJoint = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Joint '%s' not found for bind on '%s' " , joint , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bind it relative to a specific anim
2012-11-28 15:47:07 +00:00
if ( ( parent - > spawnArgs . GetString ( " bindanim " , " " , & bindanim ) | | parent - > spawnArgs . GetString ( " anim " , " " , & bindanim ) ) & & * bindanim )
{
2012-11-26 18:58:24 +00:00
animNum = parentAnimator - > GetAnim ( bindanim ) ;
2012-11-28 15:47:07 +00:00
if ( ! animNum )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Anim '%s' not found for bind on '%s' " , bindanim , name . c_str ( ) ) ;
}
anim = parentAnimator - > GetAnim ( animNum ) ;
2012-11-28 15:47:07 +00:00
if ( ! anim )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Anim '%s' not found for bind on '%s' " , bindanim , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure parent's render origin has been set
parent - > UpdateModelTransform ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//FIXME: need a BindToJoint that accepts a joint position
parentAnimator - > CreateFrame ( gameLocal . time , true ) ;
2012-11-28 15:47:07 +00:00
idJointMat * frame = parent - > renderEntity . joints ;
2012-11-26 18:58:24 +00:00
gameEdit - > ANIM_CreateAnimFrame ( parentAnimator - > ModelHandle ( ) , anim - > MD5Anim ( 0 ) , parent - > renderEntity . numJoints , frame , 0 , parentAnimator - > ModelDef ( ) - > GetVisualOffset ( ) , parentAnimator - > RemoveOrigin ( ) ) ;
BindToJoint ( parent , joint , bindOrientated ) ;
parentAnimator - > ForceUpdate ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
BindToJoint ( parent , joint , bindOrientated ) ;
}
}
// bind to a body of the physics object of the parent
2012-11-28 15:47:07 +00:00
else if ( spawnArgs . GetInt ( " bindToBody " , " 0 " , id ) )
{
2012-11-26 18:58:24 +00:00
BindToBody ( parent , id , bindOrientated ) ;
}
// bind to the parent
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
Bind ( parent , bindOrientated ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetOwner
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetOwner ( idEntity * owner )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < GetPhysics ( ) - > GetNumClipModels ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > GetClipModel ( i ) - > SetOwner ( owner ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetModel ( const char * modelname )
{
2012-11-26 18:58:24 +00:00
SetModel ( modelname ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetSkin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetSkin ( const char * skinname )
{
2012-11-26 18:58:24 +00:00
renderEntity . customSkin = declManager - > FindSkin ( skinname ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetShaderParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetShaderParm ( int parmnum )
{
if ( ( parmnum < 0 ) | | ( parmnum > = MAX_ENTITY_SHADER_PARMS ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " shader parm index (%d) out of range " , parmnum ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idThread : : ReturnFloat ( renderEntity . shaderParms [ parmnum ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetShaderParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetShaderParm ( int parmnum , float value )
{
2012-11-26 18:58:24 +00:00
SetShaderParm ( parmnum , value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetShaderParms
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetShaderParms ( float parm0 , float parm1 , float parm2 , float parm3 )
{
2012-11-26 18:58:24 +00:00
renderEntity . shaderParms [ SHADERPARM_RED ] = parm0 ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = parm1 ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = parm2 ;
renderEntity . shaderParms [ SHADERPARM_ALPHA ] = parm3 ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetColor ( float red , float green , float blue )
{
2012-11-26 18:58:24 +00:00
SetColor ( red , green , blue ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetColor ( )
{
2012-11-26 18:58:24 +00:00
idVec3 out ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetColor ( out ) ;
idThread : : ReturnVector ( out ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_IsHidden
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_IsHidden ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( fl . hidden ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Hide
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_Hide ( )
{
2012-11-26 18:58:24 +00:00
Hide ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Show
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_Show ( )
{
2012-11-26 18:58:24 +00:00
Show ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_CacheSoundShader
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_CacheSoundShader ( const char * soundName )
{
2012-11-26 18:58:24 +00:00
declManager - > FindSound ( soundName ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_StartSoundShader
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_StartSoundShader ( const char * soundName , int channel )
{
2012-11-26 18:58:24 +00:00
int length = 0 ;
2012-11-28 15:47:07 +00:00
if ( soundName = = NULL | | soundName [ 0 ] = = 0 )
{
2012-11-26 18:58:24 +00:00
StopSound ( channel , false ) ;
2012-11-28 15:47:07 +00:00
}
else
{
StartSoundShader ( declManager - > FindSound ( soundName ) , ( s_channelType ) channel , 0 , false , & length ) ;
2012-11-26 18:58:24 +00:00
}
idThread : : ReturnFloat ( MS2SEC ( length ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_StopSound
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_StopSound ( int channel , int netSync )
{
2012-11-26 18:58:24 +00:00
StopSound ( channel , ( netSync ! = 0 ) ) ;
}
/*
= = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idEntity : : Event_StartSound
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_StartSound ( const char * soundName , int channel , int netSync )
{
2012-11-26 18:58:24 +00:00
int time ;
StartSound ( soundName , ( s_channelType ) channel , 0 , ( netSync ! = 0 ) , & time ) ;
idThread : : ReturnFloat ( MS2SEC ( time ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_FadeSound
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_FadeSound ( int channel , float to , float over )
{
if ( refSound . referenceSound )
{
2012-11-26 18:58:24 +00:00
refSound . referenceSound - > FadeSound ( channel , to , over ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetWorldOrigin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetWorldOrigin ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( GetPhysics ( ) - > GetOrigin ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetWorldOrigin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetWorldOrigin ( idVec3 const & org )
{
2012-11-26 18:58:24 +00:00
idVec3 neworg = GetLocalCoordinates ( org ) ;
SetOrigin ( neworg ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetOrigin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetOrigin ( idVec3 const & org )
{
2012-11-26 18:58:24 +00:00
SetOrigin ( org ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetOrigin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetOrigin ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( GetLocalCoordinates ( GetPhysics ( ) - > GetOrigin ( ) ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetAngles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetAngles ( idAngles const & ang )
{
2012-11-26 18:58:24 +00:00
SetAngles ( ang ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetAngles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetAngles ( )
{
2012-11-26 18:58:24 +00:00
idAngles ang = GetPhysics ( ) - > GetAxis ( ) . ToAngles ( ) ;
idThread : : ReturnVector ( idVec3 ( ang [ 0 ] , ang [ 1 ] , ang [ 2 ] ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetLinearVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetLinearVelocity ( const idVec3 & velocity )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetLinearVelocity ( velocity ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetLinearVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetLinearVelocity ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( GetPhysics ( ) - > GetLinearVelocity ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetAngularVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetAngularVelocity ( const idVec3 & velocity )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetAngularVelocity ( velocity ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetAngularVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetAngularVelocity ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( GetPhysics ( ) - > GetAngularVelocity ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetSize
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetSize ( idVec3 const & mins , idVec3 const & maxs )
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetClipBox ( idBounds ( mins , maxs ) , 1.0f ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetSize
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetSize ( )
{
2012-11-26 18:58:24 +00:00
idBounds bounds ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bounds = GetPhysics ( ) - > GetBounds ( ) ;
idThread : : ReturnVector ( bounds [ 1 ] - bounds [ 0 ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetMins
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetMins ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( GetPhysics ( ) - > GetBounds ( ) [ 0 ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetMaxs
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetMaxs ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( GetPhysics ( ) - > GetBounds ( ) [ 1 ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Touches
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_Touches ( idEntity * ent )
{
if ( ! ent )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( false ) ;
return ;
}
2012-11-28 15:47:07 +00:00
const idBounds & myBounds = GetPhysics ( ) - > GetAbsBounds ( ) ;
const idBounds & entBounds = ent - > GetPhysics ( ) - > GetAbsBounds ( ) ;
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( myBounds . IntersectsBounds ( entBounds ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetGuiParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetGuiParm ( const char * key , const char * val )
{
for ( int i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + )
{
if ( renderEntity . gui [ i ] )
{
if ( idStr : : Icmpn ( key , " gui_ " , 4 ) = = 0 )
{
2012-11-26 18:58:24 +00:00
spawnArgs . Set ( key , val ) ;
}
renderEntity . gui [ i ] - > SetStateString ( key , val ) ;
renderEntity . gui [ i ] - > StateChanged ( gameLocal . time ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetGuiParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetGuiFloat ( const char * key , float f )
{
for ( int i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + )
{
if ( renderEntity . gui [ i ] )
{
2012-11-26 18:58:24 +00:00
renderEntity . gui [ i ] - > SetStateString ( key , va ( " %f " , f ) ) ;
renderEntity . gui [ i ] - > StateChanged ( gameLocal . time ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetNextKey
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetNextKey ( const char * prefix , const char * lastMatch )
{
const idKeyValue * kv ;
const idKeyValue * previous ;
if ( * lastMatch )
{
2012-11-26 18:58:24 +00:00
previous = spawnArgs . FindKey ( lastMatch ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
previous = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = spawnArgs . MatchPrefix ( prefix , previous ) ;
2012-11-28 15:47:07 +00:00
if ( ! kv )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnString ( " " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnString ( kv - > GetKey ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetKey
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetKey ( const char * key , const char * value )
{
2012-11-26 18:58:24 +00:00
spawnArgs . Set ( key , value ) ;
UpdateChangeableSpawnArgs ( NULL ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetKey
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetKey ( const char * key )
{
const char * value ;
2012-11-26 18:58:24 +00:00
spawnArgs . GetString ( key , " " , & value ) ;
idThread : : ReturnString ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetIntKey
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetIntKey ( const char * key )
{
2012-11-26 18:58:24 +00:00
int value ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . GetInt ( key , " 0 " , value ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// scripts only support floats
idThread : : ReturnFloat ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetFloatKey
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetFloatKey ( const char * key )
{
2012-11-26 18:58:24 +00:00
float value ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . GetFloat ( key , " 0 " , value ) ;
idThread : : ReturnFloat ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetVectorKey
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetVectorKey ( const char * key )
{
2012-11-26 18:58:24 +00:00
idVec3 value ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . GetVector ( key , " 0 0 0 " , value ) ;
idThread : : ReturnVector ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetEntityKey
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetEntityKey ( const char * key )
{
idEntity * ent ;
const char * entname ;
if ( ! spawnArgs . GetString ( key , NULL , & entname ) )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnEntity ( NULL ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ent = gameLocal . FindEntity ( entname ) ;
2012-11-28 15:47:07 +00:00
if ( ! ent )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Couldn't find entity '%s' specified in '%s' key in entity '%s' " , entname , key , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idThread : : ReturnEntity ( ent ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_RestorePosition
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_RestorePosition ( )
{
2012-11-26 18:58:24 +00:00
idVec3 org ;
idAngles angles ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
idEntity * part ;
2012-11-26 18:58:24 +00:00
spawnArgs . GetVector ( " origin " , " 0 0 0 " , org ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the rotation matrix in either full form, or single angle form
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetMatrix ( " rotation " , " 1 0 0 0 1 0 0 0 1 " , axis ) )
{
2012-11-26 18:58:24 +00:00
angles = axis . ToAngles ( ) ;
}
2012-11-28 15:47:07 +00:00
else
{
angles [ 0 ] = 0 ;
angles [ 1 ] = spawnArgs . GetFloat ( " angle " ) ;
angles [ 2 ] = 0 ;
}
2012-11-26 18:58:24 +00:00
Teleport ( org , angles , NULL ) ;
2012-11-28 15:47:07 +00:00
for ( part = teamChain ; part ! = NULL ; part = part - > teamChain )
{
if ( part - > bindMaster ! = this )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( part - > GetPhysics ( ) - > IsType ( idPhysics_Parametric : : Type ) )
{
if ( static_cast < idPhysics_Parametric * > ( part - > GetPhysics ( ) ) - > IsPusher ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " teleported '%s' which has the pushing mover '%s' bound to it \n " , GetName ( ) , part - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( part - > GetPhysics ( ) - > IsType ( idPhysics_AF : : Type ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " teleported '%s' which has the articulated figure '%s' bound to it \n " , GetName ( ) , part - > GetName ( ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_UpdateCameraTarget
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_UpdateCameraTarget ( )
{
const char * target ;
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
idVec3 dir ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
target = spawnArgs . GetString ( " cameraTarget " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
cameraTarget = gameLocal . FindEntity ( target ) ;
2012-11-28 15:47:07 +00:00
if ( cameraTarget ! = NULL )
{
2012-11-26 18:58:24 +00:00
kv = cameraTarget - > spawnArgs . MatchPrefix ( " target " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
idEntity * ent = gameLocal . FindEntity ( kv - > GetValue ( ) ) ;
if ( ent ! = NULL & & idStr : : Icmp ( ent - > GetEntityDefName ( ) , " target_null " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
dir = ent - > GetPhysics ( ) - > GetOrigin ( ) - cameraTarget - > GetPhysics ( ) - > GetOrigin ( ) ;
dir . Normalize ( ) ;
cameraTarget - > SetAxis ( dir . ToMat3 ( ) ) ;
2012-11-28 15:47:07 +00:00
SetAxis ( dir . ToMat3 ( ) ) ;
break ;
2012-11-26 18:58:24 +00:00
}
kv = cameraTarget - > spawnArgs . MatchPrefix ( " target " , kv ) ;
}
}
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_DistanceTo
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_DistanceTo ( idEntity * ent )
{
if ( ! ent )
{
2012-11-26 18:58:24 +00:00
// just say it's really far away
idThread : : ReturnFloat ( MAX_WORLD_SIZE ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
float dist = ( GetPhysics ( ) - > GetOrigin ( ) - ent - > GetPhysics ( ) - > GetOrigin ( ) ) . LengthFast ( ) ;
idThread : : ReturnFloat ( dist ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_DistanceToPoint
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_DistanceToPoint ( const idVec3 & point )
{
2012-11-26 18:58:24 +00:00
float dist = ( GetPhysics ( ) - > GetOrigin ( ) - point ) . LengthFast ( ) ;
idThread : : ReturnFloat ( dist ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_StartFx
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_StartFx ( const char * fx )
{
2012-11-26 18:58:24 +00:00
idEntityFx : : StartFx ( fx , NULL , NULL , this , true ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_WaitFrame
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_WaitFrame ( )
{
idThread * thread ;
2012-11-26 18:58:24 +00:00
thread = idThread : : CurrentThread ( ) ;
2012-11-28 15:47:07 +00:00
if ( thread )
{
2012-11-26 18:58:24 +00:00
thread - > WaitFrame ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_Wait
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_Wait ( float time )
{
idThread * thread = idThread : : CurrentThread ( ) ;
if ( thread = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Event 'wait' called from outside thread " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
thread - > WaitSec ( time ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_HasFunction
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_HasFunction ( const char * name )
{
const function_t * func ;
2012-11-26 18:58:24 +00:00
func = scriptObject . GetFunction ( name ) ;
2012-11-28 15:47:07 +00:00
if ( func )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( true ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( false ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_CallFunction
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_CallFunction ( const char * funcname )
{
const function_t * func ;
idThread * thread ;
2012-11-26 18:58:24 +00:00
thread = idThread : : CurrentThread ( ) ;
2012-11-28 15:47:07 +00:00
if ( thread = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Event 'callFunction' called from outside thread " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
func = scriptObject . GetFunction ( funcname ) ;
2012-11-28 15:47:07 +00:00
if ( func = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Unknown function '%s' in '%s' " , funcname , scriptObject . GetTypeName ( ) ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( func - > type - > NumParameters ( ) ! = 1 )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Function '%s' has the wrong number of parameters for 'callFunction' " , funcname ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! scriptObject . GetTypeDef ( ) - > Inherits ( func - > type - > GetParmType ( 0 ) ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Function '%s' is the wrong type for 'callFunction' " , funcname ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// function args will be invalid after this call
thread - > CallFunction ( this , func , false ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetNeverDormant
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetNeverDormant ( int enable )
{
2012-11-26 18:58:24 +00:00
fl . neverDormant = ( enable ! = 0 ) ;
dormantStart = 0 ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetGui
= = = = = = = = = = = = = = = =
* BSM Nerve : Allows guis to be changed at runtime . Guis that are
* loaded after the level loads should be precahced using PrecacheGui .
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_SetGui ( int guiNum , const char * guiName )
{
2012-11-26 18:58:24 +00:00
idUserInterface * * gui = NULL ;
2012-11-28 15:47:07 +00:00
if ( guiNum > = 1 & & guiNum < = MAX_RENDERENTITY_GUI )
{
gui = & renderEntity . gui [ guiNum - 1 ] ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( gui )
{
2012-11-26 18:58:24 +00:00
* gui = uiManager - > FindGui ( guiName , true , false ) ;
UpdateGuiParms ( * gui , & spawnArgs ) ;
UpdateChangeableSpawnArgs ( NULL ) ;
2012-11-28 15:47:07 +00:00
gameRenderWorld - > UpdateEntityDef ( modelDefHandle , & renderEntity ) ;
}
else
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Entity '%s' doesn't have a GUI %d " , name . c_str ( ) , guiNum ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_PrecacheGui
= = = = = = = = = = = = = = = =
* BSM Nerve : Forces the engine to initialize a gui even if it is not specified as used in a level .
* This is useful for preventing load hitches when switching guis during the game using " setGui "
*/
2012-11-28 15:47:07 +00:00
void idEntity : : Event_PrecacheGui ( const char * guiName )
{
2012-11-26 18:58:24 +00:00
uiManager - > FindGui ( guiName , true , true ) ;
}
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetGuiParm ( int guiNum , const char * key )
{
if ( renderEntity . gui [ guiNum - 1 ] )
{
idThread : : ReturnString ( renderEntity . gui [ guiNum - 1 ] - > GetStateString ( key ) ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idThread : : ReturnString ( " " ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GetGuiParmFloat ( int guiNum , const char * key )
{
if ( renderEntity . gui [ guiNum - 1 ] )
{
idThread : : ReturnFloat ( renderEntity . gui [ guiNum - 1 ] - > GetStateFloat ( key ) ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idThread : : ReturnFloat ( 0.0f ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
void idEntity : : Event_GuiNamedEvent ( int guiNum , const char * event )
{
if ( renderEntity . gui [ guiNum - 1 ] )
{
renderEntity . gui [ guiNum - 1 ] - > HandleNamedEvent ( event ) ;
2012-11-26 18:58:24 +00:00
}
}
/***********************************************************************
Network
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : ClientThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ClientThink ( const int curTime , const float fraction , const bool predict )
{
2012-11-26 18:58:24 +00:00
InterpolatePhysics ( fraction ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClientPredictionThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ClientPredictionThink ( )
{
2012-11-26 18:58:24 +00:00
RunPhysics ( ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteBindToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : WriteBindToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
int bindInfo ;
2012-11-28 15:47:07 +00:00
if ( bindMaster )
{
2012-11-26 18:58:24 +00:00
bindInfo = bindMaster - > entityNumber ;
bindInfo | = ( fl . bindOrientated & 1 ) < < GENTITYNUM_BITS ;
2012-11-28 15:47:07 +00:00
if ( bindJoint ! = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
bindInfo | = 1 < < ( GENTITYNUM_BITS + 1 ) ;
bindInfo | = bindJoint < < ( 3 + GENTITYNUM_BITS ) ;
2012-11-28 15:47:07 +00:00
}
else if ( bindBody ! = - 1 )
{
2012-11-26 18:58:24 +00:00
bindInfo | = 2 < < ( GENTITYNUM_BITS + 1 ) ;
bindInfo | = bindBody < < ( 3 + GENTITYNUM_BITS ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
bindInfo = ENTITYNUM_NONE ;
}
msg . WriteBits ( bindInfo , GENTITYNUM_BITS + 3 + 9 ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadBindFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ReadBindFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
int bindInfo , bindEntityNum , bindPos ;
bool bindOrientated ;
2012-11-28 15:47:07 +00:00
idEntity * master ;
2012-11-26 18:58:24 +00:00
bindInfo = msg . ReadBits ( GENTITYNUM_BITS + 3 + 9 ) ;
bindEntityNum = bindInfo & ( ( 1 < < GENTITYNUM_BITS ) - 1 ) ;
2012-11-28 15:47:07 +00:00
if ( ( bindEntityNum ! = ENTITYNUM_NONE ) & & ( bindEntityNum < MAX_GENTITIES ) )
{
2012-11-26 18:58:24 +00:00
master = gameLocal . entities [ bindEntityNum ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bindOrientated = ( bindInfo > > GENTITYNUM_BITS ) & 1 ;
bindPos = ( bindInfo > > ( GENTITYNUM_BITS + 3 ) ) ;
2012-11-28 15:47:07 +00:00
switch ( ( bindInfo > > ( GENTITYNUM_BITS + 1 ) ) & 3 )
{
case 1 :
{
BindToJoint ( master , ( jointHandle_t ) bindPos , bindOrientated ) ;
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
case 2 :
{
2012-11-26 18:58:24 +00:00
BindToBody ( master , bindPos , bindOrientated ) ;
break ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
Bind ( master , bindOrientated ) ;
break ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( bindMaster )
{
2012-11-26 18:58:24 +00:00
Unbind ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteColorToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : WriteColorToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
idVec4 color ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
color [ 0 ] = renderEntity . shaderParms [ SHADERPARM_RED ] ;
color [ 1 ] = renderEntity . shaderParms [ SHADERPARM_GREEN ] ;
color [ 2 ] = renderEntity . shaderParms [ SHADERPARM_BLUE ] ;
color [ 3 ] = renderEntity . shaderParms [ SHADERPARM_ALPHA ] ;
msg . WriteLong ( PackColor ( color ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadColorFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ReadColorFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
idVec4 color ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UnpackColor ( msg . ReadLong ( ) , color ) ;
renderEntity . shaderParms [ SHADERPARM_RED ] = color [ 0 ] ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = color [ 1 ] ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = color [ 2 ] ;
renderEntity . shaderParms [ SHADERPARM_ALPHA ] = color [ 3 ] ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteGUIToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : WriteGUIToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
// no need to loop over MAX_RENDERENTITY_GUI at this time
2012-11-28 15:47:07 +00:00
if ( renderEntity . gui [ 0 ] )
{
2012-11-26 18:58:24 +00:00
msg . WriteByte ( renderEntity . gui [ 0 ] - > State ( ) . GetInt ( " networkState " ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
msg . WriteByte ( 0 ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadGUIFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ReadGUIFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
int state ;
2012-11-28 15:47:07 +00:00
idUserInterface * gui ;
2012-11-26 18:58:24 +00:00
state = msg . ReadByte ( ) ;
gui = renderEntity . gui [ 0 ] ;
2012-11-28 15:47:07 +00:00
if ( gui & & state ! = mpGUIState )
{
2012-11-26 18:58:24 +00:00
mpGUIState = state ;
gui - > SetStateInt ( " networkState " , state ) ;
gui - > HandleNamedEvent ( " networkState " ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : WriteToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ReadFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadFromSnapshot_Ex
Increments the snapshot counter for the entity .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ReadFromSnapshot_Ex ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
snapshotsReceived + = 1 ;
ReadFromSnapshot ( msg ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FlagNewSnapshot
Updates the interpolationBehavior so that subclasses will know if it ' s safe to interpolate .
Only call this when a new snapshot has been received for this entity !
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : FlagNewSnapshot ( )
{
switch ( interpolationBehavior )
{
case USE_NO_INTERPOLATION :
{
interpolationBehavior = USE_LATEST_SNAP_ONLY ;
break ;
}
case USE_LATEST_SNAP_ONLY :
{
interpolationBehavior = USE_INTERPOLATION ;
break ;
}
default :
{
break ;
}
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ServerSendEvent
Saved events are also sent to any client that connects late so all clients
always receive the events nomatter what time they join the game .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ServerSendEvent ( int eventId , const idBitMsg * msg , bool saveEvent , lobbyUserID_t excluding ) const
{
2012-11-26 18:58:24 +00:00
idBitMsg outMsg ;
byte msgBuf [ MAX_GAME_MESSAGE_SIZE ] ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// prevent dupe events caused by frame re-runs
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . isNewFrame )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
outMsg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
outMsg . BeginWriting ( ) ;
outMsg . WriteBits ( gameLocal . GetSpawnId ( this ) , 32 ) ;
outMsg . WriteByte ( eventId ) ;
outMsg . WriteLong ( gameLocal . time ) ;
2012-11-28 15:47:07 +00:00
if ( msg )
{
2012-11-26 18:58:24 +00:00
outMsg . WriteBits ( msg - > GetSize ( ) , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
outMsg . WriteData ( msg - > GetReadData ( ) , msg - > GetSize ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
outMsg . WriteBits ( 0 , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
}
2012-11-28 15:47:07 +00:00
idLobbyBase & lobby = session - > GetActingGameStateLobbyBase ( ) ;
2012-11-26 18:58:24 +00:00
peerMask_t peerMask = MAX_UNSIGNED_TYPE ( peerMask_t ) ;
2012-11-28 15:47:07 +00:00
if ( excluding . IsValid ( ) )
{
peerMask = ~ ( peerMask_t ) lobby . PeerIndexFromLobbyUser ( excluding ) ;
2012-11-26 18:58:24 +00:00
}
lobby . SendReliable ( GAME_RELIABLE_MESSAGE_EVENT , outMsg , false , peerMask ) ;
2012-11-28 15:47:07 +00:00
if ( saveEvent )
{
2012-11-26 18:58:24 +00:00
gameLocal . SaveEntityNetworkEvent ( this , eventId , msg ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClientSendEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : ClientSendEvent ( int eventId , const idBitMsg * msg ) const
{
2012-11-26 18:58:24 +00:00
idBitMsg outMsg ;
byte msgBuf [ MAX_GAME_MESSAGE_SIZE ] ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// prevent dupe events caused by frame re-runs
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . isNewFrame )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
outMsg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
outMsg . BeginWriting ( ) ;
outMsg . WriteBits ( gameLocal . GetSpawnId ( this ) , 32 ) ;
outMsg . WriteByte ( eventId ) ;
outMsg . WriteLong ( gameLocal . serverTime ) ;
2012-11-28 15:47:07 +00:00
if ( msg )
{
2012-11-26 18:58:24 +00:00
outMsg . WriteBits ( msg - > GetSize ( ) , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
outMsg . WriteData ( msg - > GetReadData ( ) , msg - > GetSize ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
outMsg . WriteBits ( 0 , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
session - > GetActingGameStateLobbyBase ( ) . SendReliableToHost ( GAME_RELIABLE_MESSAGE_EVENT , outMsg ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ServerReceiveEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : ServerReceiveEvent ( int event , int time , const idBitMsg & msg )
{
switch ( event )
{
case 0 :
{
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
return false ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
int index ;
2012-11-28 15:47:07 +00:00
const idSoundShader * shader ;
2012-11-26 18:58:24 +00:00
s_channelType channel ;
2012-11-28 15:47:07 +00:00
switch ( event )
{
case EVENT_STARTSOUNDSHADER :
{
2012-11-26 18:58:24 +00:00
// the sound stuff would early out
assert ( gameLocal . isNewFrame ) ;
2012-11-28 15:47:07 +00:00
if ( time < gameLocal . realClientTime - 1000 )
{
2012-11-26 18:58:24 +00:00
// too old, skip it ( reliable messages don't need to be parsed in full )
common - > DPrintf ( " ent 0x%x: start sound shader too old (%d ms) \n " , entityNumber , gameLocal . realClientTime - time ) ;
return true ;
}
index = gameLocal . ClientRemapDecl ( DECL_SOUND , msg . ReadLong ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( index > = 0 & & index < declManager - > GetNumDecls ( DECL_SOUND ) )
{
2012-11-26 18:58:24 +00:00
shader = declManager - > SoundByIndex ( index , false ) ;
2012-11-28 15:47:07 +00:00
channel = ( s_channelType ) msg . ReadByte ( ) ;
2012-11-26 18:58:24 +00:00
StartSoundShader ( shader , channel , 0 , false , NULL ) ;
}
return true ;
}
2012-11-28 15:47:07 +00:00
case EVENT_STOPSOUNDSHADER :
{
2012-11-26 18:58:24 +00:00
// the sound stuff would early out
assert ( gameLocal . isNewFrame ) ;
2012-11-28 15:47:07 +00:00
channel = ( s_channelType ) msg . ReadByte ( ) ;
2012-11-26 18:58:24 +00:00
StopSound ( channel , false ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
return false ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DetermineTimeGroup
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : DetermineTimeGroup ( bool slowmo )
{
if ( slowmo | | common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
timeGroup = TIME_GROUP1 ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
timeGroup = TIME_GROUP2 ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetGrabbedState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : SetGrabbedState ( bool grabbed )
{
2012-11-26 18:58:24 +00:00
fl . grabbed = grabbed ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsGrabbed
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idEntity : : IsGrabbed ( )
{
2012-11-26 18:58:24 +00:00
return fl . grabbed ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idEntity : : DecayOriginAndAxisDelta
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : DecayOriginAndAxisDelta ( )
{
2012-11-26 18:58:24 +00:00
idVec3 delta = vec3_zero - originDelta ;
float length = delta . Length ( ) ;
2012-11-28 15:47:07 +00:00
if ( length > 0.01f )
{
2012-11-26 18:58:24 +00:00
length * = net_errorSmoothingDecay . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
if ( length > net_errorSmoothingMaxDecay . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
length = net_errorSmoothingMaxDecay . GetFloat ( ) ;
}
delta . Normalize ( ) ;
delta * = length ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
originDelta + = delta ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
originDelta = vec3_zero ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idQuat q ;
q . Slerp ( axisDelta . ToQuat ( ) , mat3_identity . ToQuat ( ) , net_errorSmoothingDecay . GetFloat ( ) ) ;
axisDelta = q . ToMat3 ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idEntity : : CreateDeltasFromOldOriginAndAxis
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idEntity : : CreateDeltasFromOldOriginAndAxis ( const idVec3 & oldOrigin , const idMat3 & oldAxis )
{
2012-11-26 18:58:24 +00:00
// Set smooth values so we transition from the old position/axis to what we are now (visual only)
2012-11-28 15:47:07 +00:00
if ( GetPhysics ( ) )
{
2012-11-26 18:58:24 +00:00
originDelta = oldOrigin - GetPhysics ( ) - > GetOrigin ( ) ;
axisDelta = oldAxis . Inverse ( ) * GetPhysics ( ) - > GetAxis ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idAnimatedEntity
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
const idEventDef EV_GetJointHandle ( " getJointHandle " , " s " , ' d ' ) ;
const idEventDef EV_ClearAllJoints ( " clearAllJoints " ) ;
const idEventDef EV_ClearJoint ( " clearJoint " , " d " ) ;
const idEventDef EV_SetJointPos ( " setJointPos " , " ddv " ) ;
const idEventDef EV_SetJointAngle ( " setJointAngle " , " ddv " ) ;
const idEventDef EV_GetJointPos ( " getJointPos " , " d " , ' v ' ) ;
const idEventDef EV_GetJointAngle ( " getJointAngle " , " d " , ' v ' ) ;
CLASS_DECLARATION ( idEntity , idAnimatedEntity )
2012-11-28 15:47:07 +00:00
EVENT ( EV_GetJointHandle , idAnimatedEntity : : Event_GetJointHandle )
EVENT ( EV_ClearAllJoints , idAnimatedEntity : : Event_ClearAllJoints )
EVENT ( EV_ClearJoint , idAnimatedEntity : : Event_ClearJoint )
EVENT ( EV_SetJointPos , idAnimatedEntity : : Event_SetJointPos )
EVENT ( EV_SetJointAngle , idAnimatedEntity : : Event_SetJointAngle )
EVENT ( EV_GetJointPos , idAnimatedEntity : : Event_GetJointPos )
EVENT ( EV_GetJointAngle , idAnimatedEntity : : Event_GetJointAngle )
2012-11-26 18:58:24 +00:00
END_CLASS
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : idAnimatedEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAnimatedEntity : : idAnimatedEntity ( )
{
2012-11-26 18:58:24 +00:00
animator . SetEntity ( this ) ;
damageEffects = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : ~ idAnimatedEntity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAnimatedEntity : : ~ idAnimatedEntity ( )
{
damageEffect_t * de ;
for ( de = damageEffects ; de ; de = damageEffects )
{
2012-11-26 18:58:24 +00:00
damageEffects = de - > next ;
delete de ;
}
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Save
archives object for save game file
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
animator . Save ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Wounds are very temporary, ignored at this time
//damageEffect_t *damageEffects;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Restore
unarchives object from save game file
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
animator . Restore ( savefile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if the entity has an MD5 model
2012-11-28 15:47:07 +00:00
if ( animator . ModelHandle ( ) )
{
2012-11-26 18:58:24 +00:00
// set the callback to update the joints
renderEntity . callback = idEntity : : ModelCallback ;
animator . GetJoints ( & renderEntity . numJoints , & renderEntity . joints ) ;
animator . GetBounds ( gameLocal . time , renderEntity . bounds ) ;
2012-11-28 15:47:07 +00:00
if ( modelDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > UpdateEntityDef ( modelDefHandle , & renderEntity ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : ClientPredictionThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : ClientPredictionThink ( )
{
2012-11-26 18:58:24 +00:00
RunPhysics ( ) ;
UpdateAnimation ( ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : ClientThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : ClientThink ( const int curTime , const float fraction , const bool predict )
{
2012-11-26 18:58:24 +00:00
InterpolatePhysics ( fraction ) ;
UpdateAnimation ( ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Think
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Think ( )
{
2012-11-26 18:58:24 +00:00
RunPhysics ( ) ;
UpdateAnimation ( ) ;
Present ( ) ;
UpdateDamageEffects ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : UpdateAnimation
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : UpdateAnimation ( )
{
2012-11-26 18:58:24 +00:00
// don't do animations if they're not enabled
2012-11-28 15:47:07 +00:00
if ( ! ( thinkFlags & TH_ANIMATE ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// is the model an MD5?
2012-11-28 15:47:07 +00:00
if ( ! animator . ModelHandle ( ) )
{
2012-11-26 18:58:24 +00:00
// no, so nothing to do
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// call any frame commands that have happened in the past frame
2012-11-28 15:47:07 +00:00
if ( ! fl . hidden )
{
2012-11-26 18:58:24 +00:00
animator . ServiceAnims ( gameLocal . previousTime , gameLocal . time ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the model is animating then we have to update it
2012-11-28 15:47:07 +00:00
if ( ! animator . FrameHasChanged ( gameLocal . time ) )
{
2012-11-26 18:58:24 +00:00
// still fine the way it was
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the latest frame bounds
animator . GetBounds ( gameLocal . time , renderEntity . bounds ) ;
2012-11-28 15:47:07 +00:00
if ( renderEntity . bounds . IsCleared ( ) & & ! fl . hidden )
{
2012-11-26 18:58:24 +00:00
gameLocal . DPrintf ( " %d: inside out bounds \n " , gameLocal . time ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update the renderEntity
UpdateVisuals ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the animation is updated
animator . ClearForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : GetAnimator
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAnimator * idAnimatedEntity : : GetAnimator ( )
{
2012-11-26 18:58:24 +00:00
return & animator ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : SetModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : SetModel ( const char * modelname )
{
2012-11-26 18:58:24 +00:00
FreeModelDef ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity . hModel = animator . SetModel ( modelname ) ;
2012-11-28 15:47:07 +00:00
if ( ! renderEntity . hModel )
{
2012-11-26 18:58:24 +00:00
idEntity : : SetModel ( modelname ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! renderEntity . customSkin )
{
2012-11-26 18:58:24 +00:00
renderEntity . customSkin = animator . ModelDef ( ) - > GetDefaultSkin ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the callback to update the joints
renderEntity . callback = idEntity : : ModelCallback ;
animator . GetJoints ( & renderEntity . numJoints , & renderEntity . joints ) ;
animator . GetBounds ( gameLocal . time , renderEntity . bounds ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimatedEntity : : GetJointWorldTransform
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAnimatedEntity : : GetJointWorldTransform ( jointHandle_t jointHandle , int currentTime , idVec3 & offset , idMat3 & axis )
{
if ( ! animator . GetJointTransform ( jointHandle , currentTime , offset , axis ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ConvertLocalToWorldTransform ( offset , axis ) ;
return true ;
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : GetJointTransformForAnim
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAnimatedEntity : : GetJointTransformForAnim ( jointHandle_t jointHandle , int animNum , int frameTime , idVec3 & offset , idMat3 & axis ) const
{
const idAnim * anim ;
2012-11-26 18:58:24 +00:00
int numJoints ;
2012-11-28 15:47:07 +00:00
idJointMat * frame ;
2012-11-26 18:58:24 +00:00
anim = animator . GetAnim ( animNum ) ;
2012-11-28 15:47:07 +00:00
if ( ! anim )
{
2012-11-26 18:58:24 +00:00
assert ( 0 ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numJoints = animator . NumJoints ( ) ;
2012-11-28 15:47:07 +00:00
if ( ( jointHandle < 0 ) | | ( jointHandle > = numJoints ) )
{
2012-11-26 18:58:24 +00:00
assert ( 0 ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
frame = ( idJointMat * ) _alloca16 ( numJoints * sizeof ( idJointMat ) ) ;
2012-11-26 18:58:24 +00:00
gameEdit - > ANIM_CreateAnimFrame ( animator . ModelHandle ( ) , anim - > MD5Anim ( 0 ) , renderEntity . numJoints , frame , frameTime , animator . ModelDef ( ) - > GetVisualOffset ( ) , animator . RemoveOrigin ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
offset = frame [ jointHandle ] . ToVec3 ( ) ;
axis = frame [ jointHandle ] . ToMat3 ( ) ;
return true ;
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : AddDamageEffect
Dammage effects track the animating impact position , spitting out particles .
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : AddDamageEffect ( const trace_t & collision , const idVec3 & velocity , const char * damageDefName )
{
2012-11-26 18:58:24 +00:00
jointHandle_t jointNum ;
idVec3 origin , dir , localDir , localOrigin , localNormal ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
if ( ! g_bloodEffects . GetBool ( ) | | renderEntity . joints = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * def = gameLocal . FindEntityDef ( damageDefName , false ) ;
if ( def = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
jointNum = CLIPMODEL_ID_TO_JOINT_HANDLE ( collision . c . id ) ;
2012-11-28 15:47:07 +00:00
if ( jointNum = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dir = velocity ;
dir . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis = renderEntity . joints [ jointNum ] . ToMat3 ( ) * renderEntity . axis ;
origin = renderEntity . origin + renderEntity . joints [ jointNum ] . ToVec3 ( ) * renderEntity . axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
localOrigin = ( collision . c . point - origin ) * axis . Transpose ( ) ;
localNormal = collision . c . normal * axis . Transpose ( ) ;
localDir = dir * axis . Transpose ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AddLocalDamageEffect ( jointNum , localOrigin , localNormal , localDir , def , collision . c . material ) ;
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : GetDefaultSurfaceType
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idAnimatedEntity : : GetDefaultSurfaceType ( ) const
{
2012-11-26 18:58:24 +00:00
return SURFTYPE_METAL ;
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : AddLocalDamageEffect
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : AddLocalDamageEffect ( jointHandle_t jointNum , const idVec3 & localOrigin , const idVec3 & localNormal , const idVec3 & localDir , const idDeclEntityDef * def , const idMaterial * collisionMaterial )
{
const char * sound , * splat , * decal , * bleed , * key ;
damageEffect_t * de ;
2012-11-26 18:58:24 +00:00
idVec3 origin , dir ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetTimeState ts ( timeGroup ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis = renderEntity . joints [ jointNum ] . ToMat3 ( ) * renderEntity . axis ;
origin = renderEntity . origin + renderEntity . joints [ jointNum ] . ToVec3 ( ) * renderEntity . axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
origin = origin + localOrigin * axis ;
dir = localDir * axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int type = collisionMaterial - > GetSurfaceType ( ) ;
2012-11-28 15:47:07 +00:00
if ( type = = SURFTYPE_NONE )
{
2012-11-26 18:58:24 +00:00
type = GetDefaultSurfaceType ( ) ;
}
2012-11-28 15:47:07 +00:00
const char * materialType = gameLocal . sufaceTypeNames [ type ] ;
2012-11-26 18:58:24 +00:00
// start impact sound based on material type
key = va ( " snd_%s " , materialType ) ;
sound = spawnArgs . GetString ( key ) ;
2012-11-28 15:47:07 +00:00
if ( * sound = = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
sound = def - > dict . GetString ( key ) ;
}
2012-11-28 15:47:07 +00:00
if ( * sound ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// blood splats are thrown onto nearby surfaces
key = va ( " mtr_splat_%s " , materialType ) ;
splat = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
2012-11-28 15:47:07 +00:00
if ( * splat = = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
splat = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
2012-11-28 15:47:07 +00:00
if ( * splat ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
gameLocal . BloodSplat ( origin , dir , 64.0f , splat ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// can't see wounds on the player model in single player mode
2012-11-28 15:47:07 +00:00
if ( ! ( IsType ( idPlayer : : Type ) & & ! common - > IsMultiplayer ( ) ) )
{
2012-11-26 18:58:24 +00:00
// place a wound overlay on the model
key = va ( " mtr_wound_%s " , materialType ) ;
decal = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
2012-11-28 15:47:07 +00:00
if ( * decal = = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
decal = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
2012-11-28 15:47:07 +00:00
if ( * decal ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
ProjectOverlay ( origin , dir , 20.0f , decal ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// a blood spurting wound is added
key = va ( " smoke_wound_%s " , materialType ) ;
bleed = spawnArgs . GetString ( key ) ;
2012-11-28 15:47:07 +00:00
if ( * bleed = = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
bleed = def - > dict . GetString ( key ) ;
}
2012-11-28 15:47:07 +00:00
if ( * bleed ! = ' \0 ' )
{
de = new ( TAG_ENTITY ) damageEffect_t ;
2012-11-26 18:58:24 +00:00
de - > next = this - > damageEffects ;
this - > damageEffects = de ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
de - > jointNum = jointNum ;
de - > localOrigin = localOrigin ;
de - > localNormal = localNormal ;
2012-11-28 15:47:07 +00:00
de - > type = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , bleed ) ) ;
2012-11-26 18:58:24 +00:00
de - > time = gameLocal . time ;
}
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : UpdateDamageEffects
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : UpdateDamageEffects ( )
{
damageEffect_t * de , * * prev ;
2012-11-26 18:58:24 +00:00
// free any that have timed out
prev = & this - > damageEffects ;
2012-11-28 15:47:07 +00:00
while ( * prev )
{
2012-11-26 18:58:24 +00:00
de = * prev ;
2012-11-28 15:47:07 +00:00
if ( de - > time = = 0 ) // FIXME:SMOKE
{
2012-11-26 18:58:24 +00:00
* prev = de - > next ;
delete de ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
prev = & de - > next ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! g_bloodEffects . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// emit a particle for each bleeding wound
2012-11-28 15:47:07 +00:00
for ( de = this - > damageEffects ; de ; de = de - > next )
{
2012-11-26 18:58:24 +00:00
idVec3 origin , start ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animator . GetJointTransform ( de - > jointNum , gameLocal . time , origin , axis ) ;
axis * = renderEntity . axis ;
origin = renderEntity . origin + origin * renderEntity . axis ;
start = origin + de - > localOrigin * axis ;
2012-11-28 15:47:07 +00:00
if ( ! gameLocal . smokeParticles - > EmitSmoke ( de - > type , de - > time , gameLocal . random . CRandomFloat ( ) , start , axis , timeGroup /*_D3XP*/ ) )
{
2012-11-26 18:58:24 +00:00
de - > time = 0 ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAnimatedEntity : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
int damageDefIndex ;
int materialIndex ;
jointHandle_t jointNum ;
idVec3 localOrigin , localNormal , localDir ;
2012-11-28 15:47:07 +00:00
switch ( event )
{
case EVENT_ADD_DAMAGE_EFFECT :
{
jointNum = ( jointHandle_t ) msg . ReadShort ( ) ;
2012-11-26 18:58:24 +00:00
localOrigin [ 0 ] = msg . ReadFloat ( ) ;
localOrigin [ 1 ] = msg . ReadFloat ( ) ;
localOrigin [ 2 ] = msg . ReadFloat ( ) ;
localNormal = msg . ReadDir ( 24 ) ;
localDir = msg . ReadDir ( 24 ) ;
damageDefIndex = gameLocal . ClientRemapDecl ( DECL_ENTITYDEF , msg . ReadLong ( ) ) ;
materialIndex = gameLocal . ClientRemapDecl ( DECL_MATERIAL , msg . ReadLong ( ) ) ;
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * damageDef = static_cast < const idDeclEntityDef * > ( declManager - > DeclByIndex ( DECL_ENTITYDEF , damageDefIndex ) ) ;
const idMaterial * collisionMaterial = static_cast < const idMaterial * > ( declManager - > DeclByIndex ( DECL_MATERIAL , materialIndex ) ) ;
2012-11-26 18:58:24 +00:00
AddLocalDamageEffect ( jointNum , localOrigin , localNormal , localDir , damageDef , collisionMaterial ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
return idEntity : : ClientReceiveEvent ( event , time , msg ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_GetJointHandle
looks up the number of the specified joint . returns INVALID_JOINT if the joint is not found .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Event_GetJointHandle ( const char * jointname )
{
2012-11-26 18:58:24 +00:00
jointHandle_t joint ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
joint = animator . GetJointHandle ( jointname ) ;
idThread : : ReturnInt ( joint ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_ClearAllJoints
removes any custom transforms on all joints
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Event_ClearAllJoints ( )
{
2012-11-26 18:58:24 +00:00
animator . ClearAllJoints ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_ClearJoint
removes any custom transforms on the specified joint
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Event_ClearJoint ( jointHandle_t jointnum )
{
2012-11-26 18:58:24 +00:00
animator . ClearJoint ( jointnum ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_SetJointPos
modifies the position of the joint based on the transform type
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Event_SetJointPos ( jointHandle_t jointnum , jointModTransform_t transform_type , const idVec3 & pos )
{
2012-11-26 18:58:24 +00:00
animator . SetJointPos ( jointnum , transform_type , pos ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_SetJointAngle
modifies the orientation of the joint based on the transform type
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Event_SetJointAngle ( jointHandle_t jointnum , jointModTransform_t transform_type , const idAngles & angles )
{
2012-11-26 18:58:24 +00:00
idMat3 mat ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mat = angles . ToMat3 ( ) ;
animator . SetJointAxis ( jointnum , transform_type , mat ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_GetJointPos
returns the position of the joint in worldspace
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Event_GetJointPos ( jointHandle_t jointnum )
{
2012-11-26 18:58:24 +00:00
idVec3 offset ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
if ( ! GetJointWorldTransform ( jointnum , gameLocal . time , offset , axis ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Joint # %d out of range on entity '%s' " , jointnum , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idThread : : ReturnVector ( offset ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_GetJointAngle
returns the orientation of the joint in worldspace
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAnimatedEntity : : Event_GetJointAngle ( jointHandle_t jointnum )
{
2012-11-26 18:58:24 +00:00
idVec3 offset ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
if ( ! GetJointWorldTransform ( jointnum , gameLocal . time , offset , axis ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " Joint # %d out of range on entity '%s' " , jointnum , name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idAngles ang = axis . ToAngles ( ) ;
idVec3 vec ( ang [ 0 ] , ang [ 1 ] , ang [ 2 ] ) ;
idThread : : ReturnVector ( vec ) ;
}