2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
2011-12-06 18:20:15 +00:00
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
2011-11-22 21:28:15 +00:00
2011-12-06 16:14:59 +00:00
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
2011-11-22 21:28:15 +00:00
Doom 3 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 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 Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 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 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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2011-12-16 22:28:29 +00:00
# include "sys/platform.h"
# include "idlib/geometry/JointTransform.h"
# include "idlib/LangDict.h"
# include "framework/async/NetworkSystem.h"
# include "framework/DeclEntityDef.h"
# include "renderer/ModelManager.h"
2011-11-22 21:28:15 +00:00
2011-12-16 22:28:29 +00:00
# include "gamesys/SysCvar.h"
# include "physics/Physics_Parametric.h"
# include "physics/Physics_Actor.h"
# include "script/Script_Thread.h"
# include "Fx.h"
# include "AFEntity.h"
# include "Player.h"
# include "Mover.h"
# include "WorldSpawn.h"
# include "SmokeParticles.h"
# include "Entity.h"
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idEntity
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// 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 " ) ;
2018-08-27 13:13:17 +00:00
//Ivan start
const idEventDef EV_GetGuiParm ( " getGuiParm " , " ds " , ' s ' ) ;
const idEventDef EV_GetGuiParmFloat ( " getGuiParmFloat " , " ds " , ' f ' ) ;
const idEventDef EV_GuiNamedEvent ( " guiNamedEvent " , " ds " ) ;
const idEventDef EV_GetEntityHealth ( " getEntityHealth " , NULL , ' f ' ) ;
const idEventDef EV_SetEntityHealth ( " setEntityHealth " , " f " ) ;
const idEventDef EV_Interact ( " interact " , " ed " ) ;
//Ivan end
//ivan start
const idEventDef EV_GetClosestTargetTypePrefix ( " getClosestTargetTypePrefix " , " ss " , ' e ' ) ;
const idEventDef EV_GetRandomTargetTypePrefix ( " getRandomTargetTypePrefix " , " ss " , ' e ' ) ;
const idEventDef EV_FireProjectile ( " fireProjectile " , " svv " , ' e ' ) ;
const idEventDef EV_FireProjAtTarget ( " fireProjAtTarget " , " svE " , ' e ' ) ; //E = NULL ok too
//ivan end
2011-11-22 21:28:15 +00:00
ABSTRACT_DECLARATION ( idClass , idEntity )
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 )
2011-12-06 18:20:15 +00:00
EVENT ( EV_SetGuiParm , idEntity : : Event_SetGuiParm )
EVENT ( EV_SetGuiFloat , idEntity : : Event_SetGuiFloat )
2011-11-22 21:28:15 +00:00
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 )
2018-08-27 13:13:17 +00:00
//ivan start
EVENT ( EV_GetGuiParm , idEntity : : Event_GetGuiParm )
EVENT ( EV_GetGuiParmFloat , idEntity : : Event_GetGuiParmFloat )
EVENT ( EV_GuiNamedEvent , idEntity : : Event_GuiNamedEvent )
EVENT ( EV_GetEntityHealth , idEntity : : Event_GetEntityHealth )
EVENT ( EV_SetEntityHealth , idEntity : : Event_SetEntityHealth )
EVENT ( EV_GetClosestTargetTypePrefix , idEntity : : Event_GetClosestTargetTypePrefix )
EVENT ( EV_GetRandomTargetTypePrefix , idEntity : : Event_GetRandomTargetTypePrefix )
EVENT ( EV_FireProjectile , idEntity : : Event_FireProjectile ) //ff 1.1
EVENT ( EV_FireProjAtTarget , idEntity : : Event_FireProjAtTarget ) //ff 1.1
//ivan end
2011-11-22 21:28:15 +00:00
END_CLASS
/*
= = = = = = = = = = = = = = = =
UpdateGuiParms
= = = = = = = = = = = = = = = =
*/
void UpdateGuiParms ( idUserInterface * gui , const idDict * args ) {
if ( gui = = NULL | | args = = NULL ) {
return ;
}
const idKeyValue * kv = args - > MatchPrefix ( " gui_parm " , NULL ) ;
while ( kv ) {
gui - > SetStateString ( kv - > GetKey ( ) , kv - > GetValue ( ) ) ;
kv = args - > MatchPrefix ( " gui_parm " , kv ) ;
}
gui - > SetStateBool ( " noninteractive " , args - > GetBool ( " gui_noninteractive " ) ) ;
gui - > StateChanged ( gameLocal . time ) ;
}
/*
= = = = = = = = = = = = = = = =
AddRenderGui
= = = = = = = = = = = = = = = =
*/
void AddRenderGui ( const char * name , idUserInterface * * gui , const idDict * args ) {
const idKeyValue * kv = args - > MatchPrefix ( " gui_parm " , NULL ) ;
* 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
= = = = = = = = = = = = = = = =
*/
void idGameEdit : : ParseSpawnArgsToRenderEntity ( const idDict * args , renderEntity_t * renderEntity ) {
int i ;
const char * temp ;
idVec3 color ;
float angle ;
const idDeclModelDef * modelDef ;
memset ( renderEntity , 0 , sizeof ( * renderEntity ) ) ;
temp = args - > GetString ( " model " ) ;
modelDef = NULL ;
if ( temp [ 0 ] ! = ' \0 ' ) {
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , temp , false ) ) ;
if ( modelDef ) {
renderEntity - > hModel = modelDef - > ModelHandle ( ) ;
}
if ( ! renderEntity - > hModel ) {
renderEntity - > hModel = renderModelManager - > FindModel ( temp ) ;
}
}
if ( renderEntity - > hModel ) {
renderEntity - > bounds = renderEntity - > hModel - > Bounds ( renderEntity ) ;
} else {
renderEntity - > bounds . Zero ( ) ;
}
temp = args - > GetString ( " skin " ) ;
if ( temp [ 0 ] ! = ' \0 ' ) {
renderEntity - > customSkin = declManager - > FindSkin ( temp ) ;
} else if ( modelDef ) {
renderEntity - > customSkin = modelDef - > GetDefaultSkin ( ) ;
}
temp = args - > GetString ( " shader " ) ;
if ( temp [ 0 ] ! = ' \0 ' ) {
renderEntity - > customShader = declManager - > FindMaterial ( temp ) ;
}
args - > GetVector ( " origin " , " 0 0 0 " , renderEntity - > origin ) ;
// get the rotation matrix in either full form, or single angle form
if ( ! args - > GetMatrix ( " rotation " , " 1 0 0 0 1 0 0 0 1 " , renderEntity - > axis ) ) {
angle = args - > GetFloat ( " angle " ) ;
if ( angle ! = 0.0f ) {
renderEntity - > axis = idAngles ( 0.0f , angle , 0.0f ) . ToMat3 ( ) ;
} else {
renderEntity - > axis . Identity ( ) ;
}
}
renderEntity - > referenceSound = NULL ;
// 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 " ) ;
// check noDynamicInteractions flag
renderEntity - > noDynamicInteractions = args - > GetBool ( " noDynamicInteractions " ) ;
// check noshadows flag
renderEntity - > noShadow = args - > GetBool ( " noshadows " ) ;
// check noselfshadows flag
renderEntity - > noSelfShadow = args - > GetBool ( " noselfshadows " ) ;
// init any guis, including entity-specific states
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + ) {
temp = args - > GetString ( i = = 0 ? " gui " : va ( " gui%d " , i + 1 ) ) ;
if ( temp [ 0 ] ! = ' \0 ' ) {
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
= = = = = = = = = = = = = = = =
*/
void idGameEdit : : ParseSpawnArgsToRefSound ( const idDict * args , refSound_t * refSound ) {
const char * temp ;
memset ( refSound , 0 , sizeof ( * refSound ) ) ;
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 " ) ;
args - > GetVector ( " origin " , " 0 0 0 " , refSound - > origin ) ;
refSound - > referenceSound = NULL ;
// 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 " ) ;
if ( args - > GetBool ( " s_omni " ) ) {
refSound - > parms . soundShaderFlags | = SSF_OMNIDIRECTIONAL ;
}
if ( args - > GetBool ( " s_looping " ) ) {
refSound - > parms . soundShaderFlags | = SSF_LOOPING ;
}
if ( args - > GetBool ( " s_occlusion " ) ) {
refSound - > parms . soundShaderFlags | = SSF_NO_OCCLUSION ;
}
if ( args - > GetBool ( " s_global " ) ) {
refSound - > parms . soundShaderFlags | = SSF_GLOBAL ;
}
if ( args - > GetBool ( " s_unclamped " ) ) {
refSound - > parms . soundShaderFlags | = SSF_UNCLAMPED ;
}
refSound - > parms . soundClass = args - > GetInt ( " s_soundClass " ) ;
temp = args - > GetString ( " s_shader " ) ;
if ( temp [ 0 ] ! = ' \0 ' ) {
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
= = = = = = = = = = = = = = =
*/
void idEntity : : UpdateChangeableSpawnArgs ( const idDict * source ) {
int i ;
const char * target ;
if ( ! source ) {
source = & spawnArgs ;
}
cameraTarget = NULL ;
target = source - > GetString ( " cameraTarget " ) ;
if ( target & & target [ 0 ] ) {
// update the camera taget
PostEventMS ( & EV_UpdateCameraTarget , 0 ) ;
}
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + ) {
UpdateGuiParms ( renderEntity . gui [ i ] , source ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : idEntity
= = = = = = = = = = = = = = = =
*/
idEntity : : idEntity ( ) {
entityNumber = ENTITYNUM_NONE ;
entityDefNumber = - 1 ;
spawnNode . SetOwner ( this ) ;
activeNode . SetOwner ( this ) ;
snapshotNode . SetOwner ( this ) ;
snapshotSequence = - 1 ;
snapshotBits = 0 ;
thinkFlags = 0 ;
dormantStart = 0 ;
cinematic = false ;
renderView = NULL ;
cameraTarget = NULL ;
health = 0 ;
physics = NULL ;
bindMaster = NULL ;
bindJoint = INVALID_JOINT ;
bindBody = - 1 ;
teamMaster = NULL ;
teamChain = NULL ;
signals = NULL ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
entDamageEffects = NULL ;
# endif
2011-11-22 21:28:15 +00:00
memset ( PVSAreas , 0 , sizeof ( PVSAreas ) ) ;
numPVSAreas = - 1 ;
memset ( & fl , 0 , sizeof ( fl ) ) ;
fl . neverDormant = true ; // most entities never go dormant
memset ( & renderEntity , 0 , sizeof ( renderEntity ) ) ;
modelDefHandle = - 1 ;
memset ( & refSound , 0 , sizeof ( refSound ) ) ;
mpGUIState = - 1 ;
2018-08-27 13:13:17 +00:00
//rev grab
noGrab = false ;
//rev grab
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FixupLocalizedStrings
= = = = = = = = = = = = = = = =
*/
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 ) {
spawnArgs . Set ( kv - > GetKey ( ) , common - > GetLanguageDict ( ) - > GetString ( kv - > GetValue ( ) ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Spawn
= = = = = = = = = = = = = = = =
*/
void idEntity : : Spawn ( void ) {
int i ;
const char * temp ;
idVec3 origin ;
idMat3 axis ;
const idKeyValue * networkSync ;
const char * classname ;
const char * scriptObjectName ;
gameLocal . RegisterEntity ( this ) ;
spawnArgs . GetString ( " classname " , NULL , & classname ) ;
const idDeclEntityDef * def = gameLocal . FindEntityDef ( classname , false ) ;
if ( def ) {
entityDefNumber = def - > Index ( ) ;
}
FixupLocalizedStrings ( ) ;
// parse static models the same way the editor display does
gameEdit - > ParseSpawnArgsToRenderEntity ( & spawnArgs , & renderEntity ) ;
renderEntity . entityNum = entityNumber ;
2011-12-06 18:20:15 +00:00
2018-08-27 13:13:17 +00:00
//rev grab
noGrab = spawnArgs . GetBool ( " noGrab " , " 0 " ) ;
//rev grab
2011-11-22 21:28:15 +00:00
// go dormant within 5 frames so that when the map starts most monsters are dormant
dormantStart = gameLocal . time - DELAY_DORMANT_TIME + gameLocal . msec * 5 ;
origin = renderEntity . origin ;
axis = renderEntity . axis ;
// do the audio parsing the same way dmap and the editor do
gameEdit - > ParseSpawnArgsToRefSound ( & spawnArgs , & refSound ) ;
// only play SCHANNEL_PRIVATE when sndworld->PlaceListener() is called with this listenerId
// don't spatialize sounds from the same entity
refSound . listenerId = entityNumber + 1 ;
cameraTarget = NULL ;
temp = spawnArgs . GetString ( " cameraTarget " ) ;
if ( temp & & temp [ 0 ] ) {
// update the camera taget
PostEventMS ( & EV_UpdateCameraTarget , 0 ) ;
}
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + ) {
UpdateGuiParms ( renderEntity . gui [ i ] , & spawnArgs ) ;
}
fl . solidForTeam = spawnArgs . GetBool ( " solidForTeam " , " 0 " ) ;
fl . neverDormant = spawnArgs . GetBool ( " neverDormant " , " 0 " ) ;
fl . hidden = spawnArgs . GetBool ( " hide " , " 0 " ) ;
if ( fl . hidden ) {
// make sure we're hidden, since a spawn function might not set it up right
PostEventMS ( & EV_Hide , 0 ) ;
}
cinematic = spawnArgs . GetBool ( " cinematic " , " 0 " ) ;
networkSync = spawnArgs . FindKey ( " networkSync " ) ;
if ( networkSync ) {
fl . networkSync = ( atoi ( networkSync - > GetValue ( ) ) ! = 0 ) ;
}
#if 0
if ( ! gameLocal . isClient ) {
// common->DPrintf( "NET: DBG %s - %s is synced: %s\n", spawnArgs.GetString( "classname", "" ), GetType()->classname, fl.networkSync ? "true" : "false" );
if ( spawnArgs . GetString ( " classname " , " " ) [ 0 ] = = ' \0 ' & & ! fl . networkSync ) {
common - > DPrintf ( " NET: WRN %s entity, no classname, and no networkSync? \n " , GetType ( ) - > classname ) ;
}
}
# endif
// every object will have a unique name
temp = spawnArgs . GetString ( " name " , va ( " %s_%s_%d " , GetClassname ( ) , spawnArgs . GetString ( " classname " ) , entityNumber ) ) ;
SetName ( temp ) ;
// if we have targets, wait until all entities are spawned to get them
if ( spawnArgs . MatchPrefix ( " target " ) | | spawnArgs . MatchPrefix ( " guiTarget " ) ) {
if ( gameLocal . GameState ( ) = = GAMESTATE_STARTUP ) {
PostEventMS ( & EV_FindTargets , 0 ) ;
} else {
// not during spawn, so it's ok to get the targets
FindTargets ( ) ;
}
}
health = spawnArgs . GetInt ( " health " ) ;
InitDefaultPhysics ( origin , axis ) ;
SetOrigin ( origin ) ;
SetAxis ( axis ) ;
temp = spawnArgs . GetString ( " model " ) ;
if ( temp & & * temp ) {
SetModel ( temp ) ;
}
if ( spawnArgs . GetString ( " bind " , " " , & temp ) ) {
PostEventMS ( & EV_SpawnBind , 0 ) ;
}
// auto-start a sound on the entity
if ( refSound . shader & & ! refSound . waitfortrigger ) {
StartSoundShader ( refSound . shader , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
// setup script object
if ( ShouldConstructScriptObjectAtSpawn ( ) & & spawnArgs . GetString ( " scriptobject " , NULL , & scriptObjectName ) ) {
if ( ! scriptObject . SetType ( scriptObjectName ) ) {
gameLocal . Error ( " Script object '%s' not found on entity '%s'. " , scriptObjectName , name . c_str ( ) ) ;
}
ConstructScriptObject ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ~ idEntity
= = = = = = = = = = = = = = = =
*/
idEntity : : ~ idEntity ( void ) {
if ( gameLocal . GameState ( ) ! = GAMESTATE_SHUTDOWN & & ! gameLocal . isClient & & fl . networkSync & & entityNumber > = MAX_CLIENTS ) {
idBitMsg msg ;
byte msgBuf [ MAX_GAME_MESSAGE_SIZE ] ;
msg . Init ( msgBuf , sizeof ( msgBuf ) ) ;
msg . WriteByte ( GAME_RELIABLE_MESSAGE_DELETE_ENT ) ;
msg . WriteBits ( gameLocal . GetSpawnId ( this ) , 32 ) ;
networkSystem - > ServerSendReliableMessage ( - 1 , msg ) ;
}
DeconstructScriptObject ( ) ;
scriptObject . Free ( ) ;
if ( thinkFlags ) {
BecomeInactive ( thinkFlags ) ;
}
activeNode . Remove ( ) ;
Signal ( SIG_REMOVED ) ;
// 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 ) ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
for ( entDamageEffect_t * de = entDamageEffects ; de ; de = entDamageEffects ) {
entDamageEffects = de - > next ; // Clear damage effects if any
delete de ;
}
# endif
2011-11-22 21:28:15 +00:00
// remove any entities that are bound to me
RemoveBinds ( ) ;
// unbind from master
Unbind ( ) ;
QuitTeam ( ) ;
gameLocal . RemoveEntityFromHash ( name . c_str ( ) , this ) ;
delete renderView ;
renderView = NULL ;
delete signals ;
signals = NULL ;
FreeModelDef ( ) ;
FreeSoundEmitter ( false ) ;
gameLocal . UnregisterEntity ( this ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Save
= = = = = = = = = = = = = = = =
*/
void idEntity : : Save ( idSaveGame * savefile ) const {
int i , j ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
// Wounds are very temporary, ignored at this time
# endif
2011-11-22 21:28:15 +00:00
savefile - > WriteInt ( entityNumber ) ;
savefile - > WriteInt ( entityDefNumber ) ;
// spawnNode and activeNode are restored by gameLocal
savefile - > WriteInt ( snapshotSequence ) ;
savefile - > WriteInt ( snapshotBits ) ;
savefile - > WriteDict ( & spawnArgs ) ;
savefile - > WriteString ( name ) ;
scriptObject . Save ( savefile ) ;
savefile - > WriteInt ( thinkFlags ) ;
savefile - > WriteInt ( dormantStart ) ;
savefile - > WriteBool ( cinematic ) ;
savefile - > WriteObject ( cameraTarget ) ;
savefile - > WriteInt ( health ) ;
savefile - > WriteInt ( targets . Num ( ) ) ;
for ( i = 0 ; i < targets . Num ( ) ; i + + ) {
targets [ i ] . Save ( savefile ) ;
}
entityFlags_s flags = fl ;
LittleBitField ( & flags , sizeof ( flags ) ) ;
savefile - > Write ( & flags , sizeof ( flags ) ) ;
2018-08-27 13:13:17 +00:00
//rev grab
savefile - > WriteBool ( noGrab ) ;
//rev grab
2011-11-22 21:28:15 +00:00
savefile - > WriteRenderEntity ( renderEntity ) ;
savefile - > WriteInt ( modelDefHandle ) ;
savefile - > WriteRefSound ( refSound ) ;
savefile - > WriteObject ( bindMaster ) ;
savefile - > WriteJoint ( bindJoint ) ;
savefile - > WriteInt ( bindBody ) ;
savefile - > WriteObject ( teamMaster ) ;
savefile - > WriteObject ( teamChain ) ;
savefile - > WriteStaticObject ( defaultPhysicsObj ) ;
savefile - > WriteInt ( numPVSAreas ) ;
for ( i = 0 ; i < MAX_PVS_AREAS ; i + + ) {
savefile - > WriteInt ( PVSAreas [ i ] ) ;
}
if ( ! signals ) {
savefile - > WriteBool ( false ) ;
} else {
savefile - > WriteBool ( true ) ;
for ( i = 0 ; i < NUM_SIGNALS ; i + + ) {
savefile - > WriteInt ( signals - > signal [ i ] . Num ( ) ) ;
for ( j = 0 ; j < signals - > signal [ i ] . Num ( ) ; j + + ) {
savefile - > WriteInt ( signals - > signal [ i ] [ j ] . threadnum ) ;
savefile - > WriteString ( signals - > signal [ i ] [ j ] . function - > Name ( ) ) ;
}
}
}
savefile - > WriteInt ( mpGUIState ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Restore
= = = = = = = = = = = = = = = =
*/
void idEntity : : Restore ( idRestoreGame * savefile ) {
int i , j ;
int num ;
idStr funcname ;
savefile - > ReadInt ( entityNumber ) ;
savefile - > ReadInt ( entityDefNumber ) ;
// spawnNode and activeNode are restored by gameLocal
savefile - > ReadInt ( snapshotSequence ) ;
savefile - > ReadInt ( snapshotBits ) ;
savefile - > ReadDict ( & spawnArgs ) ;
savefile - > ReadString ( name ) ;
SetName ( name ) ;
scriptObject . Restore ( savefile ) ;
savefile - > ReadInt ( thinkFlags ) ;
savefile - > ReadInt ( dormantStart ) ;
savefile - > ReadBool ( cinematic ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( cameraTarget ) ) ;
savefile - > ReadInt ( health ) ;
targets . Clear ( ) ;
savefile - > ReadInt ( num ) ;
targets . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
targets [ i ] . Restore ( savefile ) ;
}
savefile - > Read ( & fl , sizeof ( fl ) ) ;
LittleBitField ( & fl , sizeof ( fl ) ) ;
2018-08-27 13:13:17 +00:00
//rev grab
savefile - > ReadBool ( noGrab ) ;
//rev grab
2011-11-22 21:28:15 +00:00
savefile - > ReadRenderEntity ( renderEntity ) ;
savefile - > ReadInt ( modelDefHandle ) ;
savefile - > ReadRefSound ( refSound ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( bindMaster ) ) ;
savefile - > ReadJoint ( bindJoint ) ;
savefile - > ReadInt ( bindBody ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( teamMaster ) ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( teamChain ) ) ;
savefile - > ReadStaticObject ( defaultPhysicsObj ) ;
RestorePhysics ( & defaultPhysicsObj ) ;
savefile - > ReadInt ( numPVSAreas ) ;
for ( i = 0 ; i < MAX_PVS_AREAS ; i + + ) {
savefile - > ReadInt ( PVSAreas [ i ] ) ;
}
bool readsignals ;
savefile - > ReadBool ( readsignals ) ;
if ( readsignals ) {
signals = new signalList_t ;
for ( i = 0 ; i < NUM_SIGNALS ; i + + ) {
savefile - > ReadInt ( num ) ;
signals - > signal [ i ] . SetNum ( num ) ;
for ( j = 0 ; j < num ; j + + ) {
savefile - > ReadInt ( signals - > signal [ i ] [ j ] . threadnum ) ;
savefile - > ReadString ( funcname ) ;
signals - > signal [ i ] [ j ] . function = gameLocal . program . FindFunction ( funcname ) ;
if ( ! signals - > signal [ i ] [ j ] . function ) {
savefile - > Error ( " Function '%s' not found " , funcname . c_str ( ) ) ;
}
}
}
}
savefile - > ReadInt ( mpGUIState ) ;
// restore must retrieve modelDefHandle from the renderer
if ( modelDefHandle ! = - 1 ) {
modelDefHandle = gameRenderWorld - > AddEntityDef ( & renderEntity ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetEntityDefName
= = = = = = = = = = = = = = = =
*/
const char * idEntity : : GetEntityDefName ( void ) const {
if ( entityDefNumber < 0 ) {
return " *unknown* " ;
}
return declManager - > DeclByIndex ( DECL_ENTITYDEF , entityDefNumber , false ) - > GetName ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetName
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetName ( const char * newname ) {
if ( name . Length ( ) ) {
gameLocal . RemoveEntityFromHash ( name . c_str ( ) , this ) ;
gameLocal . program . SetEntity ( name , NULL ) ;
}
name = newname ;
if ( name . Length ( ) ) {
if ( ( name = = " NULL " ) | | ( name = = " null_entity " ) ) {
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
= = = = = = = = = = = = = = = =
*/
const char * idEntity : : GetName ( void ) const {
return name . c_str ( ) ;
}
/***********************************************************************
Thinking
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : Think
= = = = = = = = = = = = = = = =
*/
void idEntity : : Think ( void ) {
RunPhysics ( ) ;
Present ( ) ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
if ( thinkFlags & TH_UPDATEWOUNDPARTICLES )
UpdateParticles ( ) ;
# endif
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DoDormantTests
Monsters and other expensive entities that are completely closed
off from the player can skip all of their work
= = = = = = = = = = = = = = = =
*/
bool idEntity : : DoDormantTests ( void ) {
if ( fl . neverDormant ) {
return false ;
}
// if the monster area is not topologically connected to a player
if ( ! gameLocal . InPlayerConnectedArea ( this ) ) {
if ( dormantStart = = 0 ) {
dormantStart = gameLocal . time ;
}
if ( gameLocal . time - dormantStart < DELAY_DORMANT_TIME ) {
// just got closed off, don't go dormant yet
return false ;
}
return true ;
2012-01-15 12:39:23 +00:00
}
2011-11-22 21:28:15 +00:00
2012-01-15 12:39:23 +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
if ( ! fl . hasAwakened ) {
if ( ! gameLocal . InPlayerPVS ( this ) ) {
return true ; // stay dormant
}
2011-11-22 21:28:15 +00:00
}
2012-01-15 12:39:23 +00:00
// wake up
dormantStart = 0 ;
fl . hasAwakened = true ; // only go dormant when area closed off now, not just out of PVS
2011-11-22 21:28:15 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : CheckDormant
Monsters and other expensive entities that are completely closed
off from the player can skip all of their work
= = = = = = = = = = = = = = = =
*/
bool idEntity : : CheckDormant ( void ) {
bool dormant ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
dormant = DoDormantTests ( ) ;
if ( dormant & & ! fl . isDormant ) {
fl . isDormant = true ;
DormantBegin ( ) ;
} else if ( ! dormant & & fl . isDormant ) {
fl . isDormant = false ;
DormantEnd ( ) ;
}
return dormant ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DormantBegin
called when entity becomes dormant
= = = = = = = = = = = = = = = =
*/
void idEntity : : DormantBegin ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DormantEnd
called when entity wakes from being dormant
= = = = = = = = = = = = = = = =
*/
void idEntity : : DormantEnd ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsActive
= = = = = = = = = = = = = = = =
*/
bool idEntity : : IsActive ( void ) const {
return activeNode . InList ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BecomeActive
= = = = = = = = = = = = = = = =
*/
void idEntity : : BecomeActive ( int flags ) {
if ( ( flags & TH_PHYSICS ) ) {
// enable the team master if this entity is part of a physics team
if ( teamMaster & & teamMaster ! = this ) {
teamMaster - > BecomeActive ( TH_PHYSICS ) ;
} else if ( ! ( thinkFlags & TH_PHYSICS ) ) {
// if this is a pusher
if ( physics - > IsType ( idPhysics_Parametric : : Type ) | | physics - > IsType ( idPhysics_Actor : : Type ) ) {
gameLocal . sortPushers = true ;
}
}
}
int oldFlags = thinkFlags ;
thinkFlags | = flags ;
if ( thinkFlags ) {
if ( ! IsActive ( ) ) {
activeNode . AddToEnd ( gameLocal . activeEntities ) ;
} else if ( ! oldFlags ) {
// we became inactive this frame, so we have to decrease the count of entities to deactivate
gameLocal . numEntitiesToDeactivate - - ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BecomeInactive
= = = = = = = = = = = = = = = =
*/
void idEntity : : BecomeInactive ( int flags ) {
if ( ( flags & TH_PHYSICS ) ) {
// may only disable physics on a team master if no team members are running physics or bound to a joints
if ( teamMaster = = this ) {
for ( idEntity * ent = teamMaster - > teamChain ; ent ; ent = ent - > teamChain ) {
if ( ( ent - > thinkFlags & TH_PHYSICS ) | | ( ( ent - > bindMaster = = this ) & & ( ent - > bindJoint ! = INVALID_JOINT ) ) ) {
flags & = ~ TH_PHYSICS ;
break ;
}
}
}
}
if ( thinkFlags ) {
thinkFlags & = ~ flags ;
if ( ! thinkFlags & & IsActive ( ) ) {
gameLocal . numEntitiesToDeactivate + + ;
}
}
if ( ( flags & TH_PHYSICS ) ) {
// if this entity has a team master
if ( teamMaster & & teamMaster ! = this ) {
// if the team master is at rest
if ( teamMaster - > IsAtRest ( ) ) {
teamMaster - > BecomeInactive ( TH_PHYSICS ) ;
}
}
}
}
/***********************************************************************
Visuals
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : SetShaderParm
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetShaderParm ( int parmnum , float value ) {
if ( ( parmnum < 0 ) | | ( parmnum > = MAX_ENTITY_SHADER_PARMS ) ) {
gameLocal . Warning ( " shader parm index (%d) out of range " , parmnum ) ;
return ;
}
renderEntity . shaderParms [ parmnum ] = value ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetColor
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetColor ( float red , float green , float blue ) {
renderEntity . shaderParms [ SHADERPARM_RED ] = red ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = green ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = blue ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetColor
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetColor ( const idVec3 & color ) {
SetColor ( color [ 0 ] , color [ 1 ] , color [ 2 ] ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetColor
= = = = = = = = = = = = = = = =
*/
void idEntity : : GetColor ( idVec3 & out ) const {
out [ 0 ] = renderEntity . shaderParms [ SHADERPARM_RED ] ;
out [ 1 ] = renderEntity . shaderParms [ SHADERPARM_GREEN ] ;
out [ 2 ] = renderEntity . shaderParms [ SHADERPARM_BLUE ] ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetColor
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetColor ( const idVec4 & 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 ] ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetColor
= = = = = = = = = = = = = = = =
*/
void idEntity : : GetColor ( idVec4 & out ) const {
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
= = = = = = = = = = = = = = = =
*/
bool idEntity : : UpdateAnimationControllers ( void ) {
// any ragdoll and IK animation controllers should be updated here
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetModel
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetModel ( const char * modelname ) {
assert ( modelname ) ;
FreeModelDef ( ) ;
renderEntity . hModel = renderModelManager - > FindModel ( modelname ) ;
if ( renderEntity . hModel ) {
renderEntity . hModel - > Reset ( ) ;
}
renderEntity . callback = NULL ;
renderEntity . numJoints = 0 ;
renderEntity . joints = NULL ;
if ( renderEntity . hModel ) {
renderEntity . bounds = renderEntity . hModel - > Bounds ( & renderEntity ) ;
} else {
renderEntity . bounds . Zero ( ) ;
}
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetSkin
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetSkin ( const idDeclSkin * skin ) {
renderEntity . customSkin = skin ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetSkin
= = = = = = = = = = = = = = = =
*/
const idDeclSkin * idEntity : : GetSkin ( void ) const {
return renderEntity . customSkin ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FreeModelDef
= = = = = = = = = = = = = = = =
*/
void idEntity : : FreeModelDef ( void ) {
if ( modelDefHandle ! = - 1 ) {
gameRenderWorld - > FreeEntityDef ( modelDefHandle ) ;
modelDefHandle = - 1 ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FreeLightDef
= = = = = = = = = = = = = = = =
*/
void idEntity : : FreeLightDef ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsHidden
= = = = = = = = = = = = = = = =
*/
bool idEntity : : IsHidden ( void ) const {
return fl . hidden ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Hide
= = = = = = = = = = = = = = = =
*/
void idEntity : : Hide ( void ) {
if ( ! IsHidden ( ) ) {
fl . hidden = true ;
FreeModelDef ( ) ;
UpdateVisuals ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Show
= = = = = = = = = = = = = = = =
*/
void idEntity : : Show ( void ) {
if ( IsHidden ( ) ) {
fl . hidden = false ;
UpdateVisuals ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateModelTransform
= = = = = = = = = = = = = = = =
*/
void idEntity : : UpdateModelTransform ( void ) {
idVec3 origin ;
idMat3 axis ;
if ( GetPhysicsToVisualTransform ( origin , axis ) ) {
renderEntity . axis = axis * GetPhysics ( ) - > GetAxis ( ) ;
renderEntity . origin = GetPhysics ( ) - > GetOrigin ( ) + origin * renderEntity . axis ;
} else {
renderEntity . axis = GetPhysics ( ) - > GetAxis ( ) ;
renderEntity . origin = GetPhysics ( ) - > GetOrigin ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateModel
= = = = = = = = = = = = = = = =
*/
void idEntity : : UpdateModel ( void ) {
UpdateModelTransform ( ) ;
// check if the entity has an MD5 model
idAnimator * animator = GetAnimator ( ) ;
if ( animator & & animator - > ModelHandle ( ) ) {
// set the callback to update the joints
renderEntity . callback = idEntity : : ModelCallback ;
}
// set to invalid number to force an update the next time the PVS areas are retrieved
ClearPVSAreas ( ) ;
// ensure that we call Present this frame
BecomeActive ( TH_UPDATEVISUALS ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateVisuals
= = = = = = = = = = = = = = = =
*/
void idEntity : : UpdateVisuals ( void ) {
UpdateModel ( ) ;
UpdateSound ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdatePVSAreas
= = = = = = = = = = = = = = = =
*/
void idEntity : : UpdatePVSAreas ( void ) {
int localNumPVSAreas , localPVSAreas [ 32 ] ;
idBounds modelAbsBounds ;
int i ;
modelAbsBounds . FromTransformedBounds ( renderEntity . bounds , renderEntity . origin , renderEntity . axis ) ;
localNumPVSAreas = gameLocal . pvs . GetPVSAreas ( modelAbsBounds , localPVSAreas , sizeof ( localPVSAreas ) / sizeof ( localPVSAreas [ 0 ] ) ) ;
// 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
if ( localNumPVSAreas > MAX_PVS_AREAS ) {
localNumPVSAreas = gameLocal . pvs . GetPVSAreas ( idBounds ( modelAbsBounds . GetCenter ( ) ) . Expand ( 64.0f ) , localPVSAreas , sizeof ( localPVSAreas ) / sizeof ( localPVSAreas [ 0 ] ) ) ;
}
for ( numPVSAreas = 0 ; numPVSAreas < MAX_PVS_AREAS & & numPVSAreas < localNumPVSAreas ; numPVSAreas + + ) {
PVSAreas [ numPVSAreas ] = localPVSAreas [ numPVSAreas ] ;
}
for ( i = numPVSAreas ; i < MAX_PVS_AREAS ; i + + ) {
PVSAreas [ i ] = 0 ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdatePVSAreas
= = = = = = = = = = = = = = = =
*/
void idEntity : : UpdatePVSAreas ( const idVec3 & pos ) {
int i ;
numPVSAreas = gameLocal . pvs . GetPVSAreas ( idBounds ( pos ) , PVSAreas , MAX_PVS_AREAS ) ;
i = numPVSAreas ;
while ( i < MAX_PVS_AREAS ) {
PVSAreas [ i + + ] = 0 ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetNumPVSAreas
= = = = = = = = = = = = = = = =
*/
int idEntity : : GetNumPVSAreas ( void ) {
if ( numPVSAreas < 0 ) {
UpdatePVSAreas ( ) ;
}
return numPVSAreas ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPVSAreas
= = = = = = = = = = = = = = = =
*/
const int * idEntity : : GetPVSAreas ( void ) {
if ( numPVSAreas < 0 ) {
UpdatePVSAreas ( ) ;
}
return PVSAreas ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClearPVSAreas
= = = = = = = = = = = = = = = =
*/
void idEntity : : ClearPVSAreas ( void ) {
numPVSAreas = - 1 ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PhysicsTeamInPVS
FIXME : for networking also return true if any of the entity shadows is in the PVS
= = = = = = = = = = = = = = = =
*/
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 ( ) ) ) {
return true ;
}
}
} else {
return gameLocal . pvs . InCurrentPVS ( pvsHandle , GetPVSAreas ( ) , GetNumPVSAreas ( ) ) ;
}
return false ;
}
/*
= = = = = = = = = = = = = =
idEntity : : ProjectOverlay
= = = = = = = = = = = = = =
*/
void idEntity : : ProjectOverlay ( const idVec3 & origin , const idVec3 & dir , float size , const char * material ) {
float s , c ;
idMat3 axis , axistemp ;
idVec3 localOrigin , localAxis [ 2 ] ;
idPlane localPlane [ 2 ] ;
// make sure the entity has a valid model handle
if ( modelDefHandle < 0 ) {
return ;
}
// only do this on dynamic md5 models
if ( renderEntity . hModel - > IsDynamicModel ( ) ! = DM_CACHED ) {
return ;
}
idMath : : SinCos16 ( gameLocal . random . RandomFloat ( ) * idMath : : TWO_PI , s , c ) ;
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 ;
renderEntity . axis . ProjectVector ( origin - renderEntity . origin , localOrigin ) ;
renderEntity . axis . ProjectVector ( axis [ 0 ] , localAxis [ 0 ] ) ;
renderEntity . axis . ProjectVector ( axis [ 1 ] , localAxis [ 1 ] ) ;
size = 1.0f / size ;
localAxis [ 0 ] * = size ;
localAxis [ 1 ] * = size ;
localPlane [ 0 ] = localAxis [ 0 ] ;
localPlane [ 0 ] [ 3 ] = - ( localOrigin * localAxis [ 0 ] ) + 0.5f ;
localPlane [ 1 ] = localAxis [ 1 ] ;
localPlane [ 1 ] [ 3 ] = - ( localOrigin * localAxis [ 1 ] ) + 0.5f ;
const idMaterial * mtr = declManager - > FindMaterial ( material ) ;
// project an overlay onto the model
gameRenderWorld - > ProjectOverlay ( modelDefHandle , localPlane , mtr ) ;
// 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 .
= = = = = = = = = = = = = = = =
*/
void idEntity : : Present ( void ) {
if ( ! gameLocal . isNewFrame ) {
return ;
}
// don't present to the renderer if the entity hasn't changed
if ( ! ( thinkFlags & TH_UPDATEVISUALS ) ) {
return ;
}
BecomeInactive ( TH_UPDATEVISUALS ) ;
// camera target for remote render views
if ( cameraTarget & & gameLocal . InPlayerPVS ( this ) ) {
renderEntity . remoteRenderView = cameraTarget - > GetRenderView ( ) ;
}
// if set to invisible, skip
if ( ! renderEntity . hModel | | IsHidden ( ) ) {
return ;
}
// add to refresh list
if ( modelDefHandle = = - 1 ) {
modelDefHandle = gameRenderWorld - > AddEntityDef ( & renderEntity ) ;
} else {
gameRenderWorld - > UpdateEntityDef ( modelDefHandle , & renderEntity ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetRenderEntity
= = = = = = = = = = = = = = = =
*/
renderEntity_t * idEntity : : GetRenderEntity ( void ) {
return & renderEntity ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetModelDefHandle
= = = = = = = = = = = = = = = =
*/
int idEntity : : GetModelDefHandle ( void ) {
return modelDefHandle ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateRenderEntity
= = = = = = = = = = = = = = = =
*/
bool idEntity : : UpdateRenderEntity ( renderEntity_s * renderEntity , const renderView_t * renderView ) {
if ( gameLocal . inCinematic & & gameLocal . skipCinematic ) {
return false ;
}
idAnimator * animator = GetAnimator ( ) ;
if ( animator ) {
return animator - > CreateFrame ( gameLocal . time , false ) ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ModelCallback
NOTE : may not change the game state whatsoever !
= = = = = = = = = = = = = = = =
*/
bool idEntity : : ModelCallback ( renderEntity_s * renderEntity , const renderView_t * renderView ) {
idEntity * ent ;
ent = gameLocal . entities [ renderEntity - > entityNum ] ;
if ( ! ent ) {
gameLocal . Error ( " idEntity::ModelCallback: callback with NULL game entity " ) ;
}
return ent - > UpdateRenderEntity ( renderEntity , renderView ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetAnimator
Subclasses will be responsible for allocating animator .
= = = = = = = = = = = = = = = =
*/
idAnimator * idEntity : : GetAnimator ( void ) {
return NULL ;
}
/*
= = = = = = = = = = = = =
idEntity : : GetRenderView
This is used by remote camera views to look from an entity
= = = = = = = = = = = = =
*/
renderView_t * idEntity : : GetRenderView ( void ) {
if ( ! renderView ) {
renderView = new renderView_t ;
}
memset ( renderView , 0 , sizeof ( * renderView ) ) ;
renderView - > vieworg = GetPhysics ( ) - > GetOrigin ( ) ;
renderView - > fov_x = 120 ;
renderView - > fov_y = 120 ;
renderView - > viewaxis = GetPhysics ( ) - > GetAxis ( ) ;
// copy global shader parms
for ( int i = 0 ; i < MAX_GLOBAL_SHADER_PARMS ; i + + ) {
renderView - > shaderParms [ i ] = gameLocal . globalShaderParms [ i ] ;
}
renderView - > globalMaterial = gameLocal . GetGlobalMaterial ( ) ;
renderView - > time = gameLocal . time ;
return renderView ;
}
/***********************************************************************
Sound
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : CanPlayChatterSounds
Used for playing chatter sounds on monsters .
= = = = = = = = = = = = = = = =
*/
bool idEntity : : CanPlayChatterSounds ( void ) const {
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : StartSound
= = = = = = = = = = = = = = = =
*/
bool idEntity : : StartSound ( const char * soundName , const s_channelType channel , int soundShaderFlags , bool broadcast , int * length ) {
const idSoundShader * shader ;
const char * sound ;
if ( length ) {
* length = 0 ;
}
// 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 ) ;
if ( ! spawnArgs . GetString ( soundName , " " , & sound ) ) {
return false ;
}
if ( sound [ 0 ] = = ' \0 ' ) {
return false ;
}
if ( ! gameLocal . isNewFrame ) {
// don't play the sound, but don't report an error
return true ;
}
shader = declManager - > FindSound ( sound ) ;
return StartSoundShader ( shader , channel , soundShaderFlags , broadcast , length ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : StartSoundShader
= = = = = = = = = = = = = = = =
*/
bool idEntity : : StartSoundShader ( const idSoundShader * shader , const s_channelType channel , int soundShaderFlags , bool broadcast , int * length ) {
float diversity ;
int len ;
if ( length ) {
* length = 0 ;
}
if ( ! shader ) {
return false ;
}
if ( ! gameLocal . isNewFrame ) {
return true ;
}
if ( gameLocal . isServer & & broadcast ) {
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
msg . Init ( msgBuf , sizeof ( msgBuf ) ) ;
msg . BeginWriting ( ) ;
2012-06-28 11:15:40 +00:00
msg . WriteInt ( gameLocal . ServerRemapDecl ( - 1 , DECL_SOUND , shader - > Index ( ) ) ) ;
2011-11-22 21:28:15 +00:00
msg . WriteByte ( channel ) ;
ServerSendEvent ( EVENT_STARTSOUNDSHADER , & msg , false , - 1 ) ;
}
// set a random value for diversity unless one was parsed from the entity
if ( refSound . diversity < 0.0f ) {
diversity = gameLocal . random . RandomFloat ( ) ;
} else {
diversity = refSound . diversity ;
}
// if we don't have a soundEmitter allocated yet, get one now
if ( ! refSound . referenceSound ) {
refSound . referenceSound = gameSoundWorld - > AllocSoundEmitter ( ) ;
}
UpdateSound ( ) ;
len = refSound . referenceSound - > StartSound ( shader , channel , diversity , soundShaderFlags ) ;
if ( length ) {
* length = len ;
}
// set reference to the sound for shader synced effects
renderEntity . referenceSound = refSound . referenceSound ;
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : StopSound
= = = = = = = = = = = = = = = =
*/
void idEntity : : StopSound ( const s_channelType channel , bool broadcast ) {
if ( ! gameLocal . isNewFrame ) {
return ;
}
if ( gameLocal . isServer & & broadcast ) {
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
msg . Init ( msgBuf , sizeof ( msgBuf ) ) ;
msg . BeginWriting ( ) ;
msg . WriteByte ( channel ) ;
ServerSendEvent ( EVENT_STOPSOUNDSHADER , & msg , false , - 1 ) ;
}
if ( refSound . referenceSound ) {
refSound . referenceSound - > StopSound ( channel ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetSoundVolume
Must be called before starting a new sound .
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetSoundVolume ( float volume ) {
refSound . parms . volume = volume ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateSound
= = = = = = = = = = = = = = = =
*/
void idEntity : : UpdateSound ( void ) {
if ( refSound . referenceSound ) {
idVec3 origin ;
idMat3 axis ;
if ( GetPhysicsToSoundTransform ( origin , axis ) ) {
refSound . origin = GetPhysics ( ) - > GetOrigin ( ) + origin * axis ;
} else {
refSound . origin = GetPhysics ( ) - > GetOrigin ( ) ;
}
refSound . referenceSound - > UpdateEmitter ( refSound . origin , refSound . listenerId , & refSound . parms ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetListenerId
= = = = = = = = = = = = = = = =
*/
int idEntity : : GetListenerId ( void ) const {
return refSound . listenerId ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetSoundEmitter
= = = = = = = = = = = = = = = =
*/
idSoundEmitter * idEntity : : GetSoundEmitter ( void ) const {
return refSound . referenceSound ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FreeSoundEmitter
= = = = = = = = = = = = = = = =
*/
void idEntity : : FreeSoundEmitter ( bool immediate ) {
if ( refSound . referenceSound ) {
refSound . referenceSound - > Free ( immediate ) ;
refSound . referenceSound = NULL ;
}
}
/***********************************************************************
entity binding
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : PreBind
= = = = = = = = = = = = = = = =
*/
void idEntity : : PreBind ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PostBind
= = = = = = = = = = = = = = = =
*/
void idEntity : : PostBind ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PreUnbind
= = = = = = = = = = = = = = = =
*/
void idEntity : : PreUnbind ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : PostUnbind
= = = = = = = = = = = = = = = =
*/
void idEntity : : PostUnbind ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : InitBind
= = = = = = = = = = = = = = = =
*/
bool idEntity : : InitBind ( idEntity * master ) {
if ( master = = this ) {
gameLocal . Error ( " Tried to bind an object to itself. " ) ;
return false ;
}
if ( this = = gameLocal . world ) {
gameLocal . Error ( " Tried to bind world to another entity " ) ;
return false ;
}
// unbind myself from my master
Unbind ( ) ;
// add any bind constraints to an articulated figure
if ( master & & IsType ( idAFEntity_Base : : Type ) ) {
static_cast < idAFEntity_Base * > ( this ) - > AddBindConstraints ( ) ;
}
if ( ! master | | master = = gameLocal . world ) {
// this can happen in scripts, so safely exit out.
return false ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : FinishBind
= = = = = = = = = = = = = = = =
*/
void idEntity : : FinishBind ( void ) {
// set the master on the physics object
physics - > SetMaster ( bindMaster , fl . bindOrientated ) ;
// 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 ) ;
// if our bindMaster is enabled during a cinematic, we must be, too
cinematic = bindMaster - > cinematic ;
// 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
= = = = = = = = = = = = = = = =
*/
void idEntity : : Bind ( idEntity * master , bool orientated ) {
if ( ! InitBind ( master ) ) {
return ;
}
PreBind ( ) ;
bindJoint = INVALID_JOINT ;
bindBody = - 1 ;
bindMaster = master ;
fl . bindOrientated = orientated ;
FinishBind ( ) ;
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BindToJoint
bind relative to a joint of the md5 model used by the master
= = = = = = = = = = = = = = = =
*/
void idEntity : : BindToJoint ( idEntity * master , const char * jointname , bool orientated ) {
jointHandle_t jointnum ;
idAnimator * masterAnimator ;
if ( ! InitBind ( master ) ) {
return ;
}
masterAnimator = master - > GetAnimator ( ) ;
if ( ! masterAnimator ) {
gameLocal . Warning ( " idEntity::BindToJoint: entity '%s' cannot support skeletal models. " , master - > GetName ( ) ) ;
return ;
}
jointnum = masterAnimator - > GetJointHandle ( jointname ) ;
if ( jointnum = = INVALID_JOINT ) {
gameLocal . Warning ( " idEntity::BindToJoint: joint '%s' not found on entity '%s'. " , jointname , master - > GetName ( ) ) ;
}
PreBind ( ) ;
bindJoint = jointnum ;
bindBody = - 1 ;
bindMaster = master ;
fl . bindOrientated = orientated ;
FinishBind ( ) ;
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BindToJoint
bind relative to a joint of the md5 model used by the master
= = = = = = = = = = = = = = = =
*/
void idEntity : : BindToJoint ( idEntity * master , jointHandle_t jointnum , bool orientated ) {
if ( ! InitBind ( master ) ) {
return ;
}
PreBind ( ) ;
bindJoint = jointnum ;
bindBody = - 1 ;
bindMaster = master ;
fl . bindOrientated = orientated ;
FinishBind ( ) ;
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : BindToBody
bind relative to a collision model used by the physics of the master
= = = = = = = = = = = = = = = =
*/
void idEntity : : BindToBody ( idEntity * master , int bodyId , bool orientated ) {
if ( ! InitBind ( master ) ) {
return ;
}
if ( bodyId < 0 ) {
gameLocal . Warning ( " idEntity::BindToBody: body '%d' not found. " , bodyId ) ;
}
PreBind ( ) ;
bindJoint = INVALID_JOINT ;
bindBody = bodyId ;
bindMaster = master ;
fl . bindOrientated = orientated ;
FinishBind ( ) ;
PostBind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Unbind
= = = = = = = = = = = = = = = =
*/
void idEntity : : Unbind ( void ) {
idEntity * prev ;
idEntity * next ;
idEntity * last ;
idEntity * ent ;
// remove any bind constraints from an articulated figure
if ( IsType ( idAFEntity_Base : : Type ) ) {
static_cast < idAFEntity_Base * > ( this ) - > RemoveBindConstraints ( ) ;
}
if ( ! bindMaster ) {
return ;
}
if ( ! teamMaster ) {
// Teammaster already has been freed
bindMaster = NULL ;
return ;
}
PreUnbind ( ) ;
if ( physics ) {
physics - > SetMaster ( NULL , fl . bindOrientated ) ;
}
// 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 ;
for ( ent = teamMaster - > teamChain ; ent & & ( ent ! = this ) ; ent = ent - > teamChain ) {
prev = ent ;
}
assert ( ent = = this ) ; // If ent is not pointing to this, then something is very wrong.
// 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 ;
for ( next = teamChain ; next ! = NULL ; next = next - > teamChain ) {
if ( ! next - > IsBoundTo ( this ) ) {
break ;
}
// Tell them I'm now the teamMaster
next - > teamMaster = this ;
last = next ;
}
// disconnect the last member of our team from the old team
last - > teamChain = NULL ;
// connect up the previous member of the old team to the node that
// follow the last node bound to me (if one exists).
if ( teamMaster ! = this ) {
prev - > teamChain = next ;
if ( ! next & & ( teamMaster = = prev ) ) {
prev - > teamMaster = NULL ;
}
} else if ( next ) {
// 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.
for ( ent = next ; ent - > teamChain ! = NULL ; ent = ent - > teamChain ) {
ent - > teamMaster = next ;
}
next - > teamMaster = next ;
}
// If we don't have anyone on our team, then clear the team variables.
if ( teamChain ) {
// make myself my own team
teamMaster = this ;
} else {
// no longer a team
teamMaster = NULL ;
}
bindJoint = INVALID_JOINT ;
bindBody = - 1 ;
bindMaster = NULL ;
PostUnbind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RemoveBinds
= = = = = = = = = = = = = = = =
*/
void idEntity : : RemoveBinds ( void ) {
idEntity * ent ;
idEntity * next ;
for ( ent = teamChain ; ent ! = NULL ; ent = next ) {
next = ent - > teamChain ;
if ( ent - > bindMaster = = this ) {
ent - > Unbind ( ) ;
ent - > PostEventMS ( & EV_Remove , 0 ) ;
next = teamChain ;
}
}
}
2018-08-27 13:13:17 +00:00
//ivan start
/*
= = = = = = = = = = = = = = = =
idEntity : : UnbindBinds
= = = = = = = = = = = = = = = =
void idEntity : : UnbindBinds ( void ) {
idEntity * ent ;
idEntity * next ;
for ( ent = teamChain ; ent ! = NULL ; ent = next ) {
next = ent - > teamChain ;
if ( ent - > bindMaster = = this ) {
ent - > Unbind ( ) ;
next = teamChain ;
}
}
}
*/
//ivan end
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = =
idEntity : : IsBound
= = = = = = = = = = = = = = = =
*/
bool idEntity : : IsBound ( void ) const {
if ( bindMaster ) {
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsBoundTo
= = = = = = = = = = = = = = = =
*/
bool idEntity : : IsBoundTo ( idEntity * master ) const {
idEntity * ent ;
if ( ! bindMaster ) {
return false ;
}
for ( ent = bindMaster ; ent ! = NULL ; ent = ent - > bindMaster ) {
if ( ent = = master ) {
return true ;
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetBindMaster
= = = = = = = = = = = = = = = =
*/
idEntity * idEntity : : GetBindMaster ( void ) const {
return bindMaster ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetBindJoint
= = = = = = = = = = = = = = = =
*/
jointHandle_t idEntity : : GetBindJoint ( void ) const {
return bindJoint ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetBindBody
= = = = = = = = = = = = = = = =
*/
int idEntity : : GetBindBody ( void ) const {
return bindBody ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetTeamMaster
= = = = = = = = = = = = = = = =
*/
idEntity * idEntity : : GetTeamMaster ( void ) const {
return teamMaster ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetNextTeamEntity
= = = = = = = = = = = = = = = =
*/
idEntity * idEntity : : GetNextTeamEntity ( void ) const {
return teamChain ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : ConvertLocalToWorldTransform
= = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : ConvertLocalToWorldTransform ( idVec3 & offset , idMat3 & axis ) {
UpdateModelTransform ( ) ;
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 .
= = = = = = = = = = = = = = = =
*/
idVec3 idEntity : : GetLocalVector ( const idVec3 & vec ) const {
idVec3 pos ;
if ( ! bindMaster ) {
return vec ;
}
idVec3 masterOrigin ;
idMat3 masterAxis ;
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . ProjectVector ( vec , pos ) ;
return pos ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetLocalCoordinates
Takes a vector in world coordinates and transforms it into the parent
object ' s local coordinates .
= = = = = = = = = = = = = = = =
*/
idVec3 idEntity : : GetLocalCoordinates ( const idVec3 & vec ) const {
idVec3 pos ;
if ( ! bindMaster ) {
return vec ;
}
idVec3 masterOrigin ;
idMat3 masterAxis ;
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . ProjectVector ( vec - masterOrigin , pos ) ;
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 .
= = = = = = = = = = = = = = = =
*/
idVec3 idEntity : : GetWorldVector ( const idVec3 & vec ) const {
idVec3 pos ;
if ( ! bindMaster ) {
return vec ;
}
idVec3 masterOrigin ;
idMat3 masterAxis ;
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . UnprojectVector ( vec , pos ) ;
return pos ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetWorldCoordinates
Takes a vector in the parent object ' s local coordinates and transforms
it into world coordinates .
= = = = = = = = = = = = = = = =
*/
idVec3 idEntity : : GetWorldCoordinates ( const idVec3 & vec ) const {
idVec3 pos ;
if ( ! bindMaster ) {
return vec ;
}
idVec3 masterOrigin ;
idMat3 masterAxis ;
GetMasterPosition ( masterOrigin , masterAxis ) ;
masterAxis . UnprojectVector ( vec , pos ) ;
pos + = masterOrigin ;
return pos ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetMasterPosition
= = = = = = = = = = = = = = = =
*/
bool idEntity : : GetMasterPosition ( idVec3 & masterOrigin , idMat3 & masterAxis ) const {
idVec3 localOrigin ;
idMat3 localAxis ;
idAnimator * masterAnimator ;
if ( bindMaster ) {
// if bound to a joint of an animated model
if ( bindJoint ! = INVALID_JOINT ) {
masterAnimator = bindMaster - > GetAnimator ( ) ;
if ( ! masterAnimator ) {
masterOrigin = vec3_origin ;
masterAxis = mat3_identity ;
return false ;
} else {
masterAnimator - > GetJointTransform ( bindJoint , gameLocal . time , masterOrigin , masterAxis ) ;
masterAxis * = bindMaster - > renderEntity . axis ;
masterOrigin = bindMaster - > renderEntity . origin + masterOrigin * bindMaster - > renderEntity . axis ;
}
} else if ( bindBody > = 0 & & bindMaster - > GetPhysics ( ) ) {
masterOrigin = bindMaster - > GetPhysics ( ) - > GetOrigin ( bindBody ) ;
masterAxis = bindMaster - > GetPhysics ( ) - > GetAxis ( bindBody ) ;
} else {
masterOrigin = bindMaster - > renderEntity . origin ;
masterAxis = bindMaster - > renderEntity . axis ;
}
return true ;
} else {
masterOrigin = vec3_origin ;
masterAxis = mat3_identity ;
return false ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetWorldVelocities
= = = = = = = = = = = = = = = =
*/
void idEntity : : GetWorldVelocities ( idVec3 & linearVelocity , idVec3 & angularVelocity ) const {
linearVelocity = physics - > GetLinearVelocity ( ) ;
angularVelocity = physics - > GetAngularVelocity ( ) ;
if ( bindMaster ) {
idVec3 masterOrigin , masterLinearVelocity , masterAngularVelocity ;
idMat3 masterAxis ;
// get position of master
GetMasterPosition ( masterOrigin , masterAxis ) ;
// get master velocities
bindMaster - > GetWorldVelocities ( masterLinearVelocity , masterAngularVelocity ) ;
// linear velocity relative to master plus master linear and angular velocity
linearVelocity = linearVelocity * masterAxis + masterLinearVelocity +
masterAngularVelocity . Cross ( GetPhysics ( ) - > GetOrigin ( ) - masterOrigin ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : JoinTeam
= = = = = = = = = = = = = = = =
*/
void idEntity : : JoinTeam ( idEntity * teammember ) {
idEntity * ent ;
idEntity * master ;
idEntity * prev ;
idEntity * next ;
// if we're already on a team, quit it so we can join this one
if ( teamMaster & & ( teamMaster ! = this ) ) {
QuitTeam ( ) ;
}
assert ( teammember ) ;
if ( teammember = = this ) {
teamMaster = this ;
return ;
}
// check if our new team mate is already on a team
master = teammember - > teamMaster ;
if ( ! master ) {
// he's not on a team, so he's the new teamMaster
master = teammember ;
teammember - > teamMaster = teammember ;
teammember - > teamChain = this ;
// make anyone who's bound to me part of the new team
for ( ent = teamChain ; ent ! = NULL ; ent = ent - > teamChain ) {
ent - > teamMaster = master ;
}
} else {
// skip past the chain members bound to the entity we're teaming up with
prev = teammember ;
next = teammember - > teamChain ;
if ( bindMaster ) {
// if we have a bindMaster, join after any entities bound to the entity
// we're joining
while ( next & & next - > IsBoundTo ( teammember ) ) {
prev = next ;
next = next - > teamChain ;
}
} else {
// if we're not bound to someone, then put us at the end of the team
while ( next ) {
prev = next ;
next = next - > teamChain ;
}
}
// make anyone who's bound to me part of the new team and
// also find the last member of my team
for ( ent = this ; ent - > teamChain ! = NULL ; ent = ent - > teamChain ) {
ent - > teamChain - > teamMaster = master ;
}
2011-12-06 18:20:15 +00:00
prev - > teamChain = this ;
2011-11-22 21:28:15 +00:00
ent - > teamChain = next ;
}
teamMaster = master ;
2011-12-06 18:20:15 +00:00
// reorder the active entity list
2011-11-22 21:28:15 +00:00
gameLocal . sortTeamMasters = true ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : QuitTeam
= = = = = = = = = = = = = = = =
*/
void idEntity : : QuitTeam ( void ) {
idEntity * ent ;
if ( ! teamMaster ) {
return ;
}
// check if I'm the teamMaster
if ( teamMaster = = this ) {
// do we have more than one teammate?
if ( ! teamChain - > teamChain ) {
// no, break up the team
teamChain - > teamMaster = NULL ;
} else {
// yes, so make the first teammate the teamMaster
for ( ent = teamChain ; ent ; ent = ent - > teamChain ) {
ent - > teamMaster = teamChain ;
}
}
} else {
assert ( teamMaster ) ;
assert ( teamMaster - > teamChain ) ;
// find the previous member of the teamChain
ent = teamMaster ;
while ( ent - > teamChain ! = this ) {
assert ( ent - > teamChain ) ; // this should never happen
ent = ent - > teamChain ;
}
// remove this from the teamChain
ent - > teamChain = teamChain ;
// if no one is left on the team, break it up
if ( ! teamMaster - > teamChain ) {
teamMaster - > teamMaster = NULL ;
}
}
teamMaster = NULL ;
teamChain = NULL ;
}
/***********************************************************************
Physics .
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : InitDefaultPhysics
= = = = = = = = = = = = = = = =
*/
void idEntity : : InitDefaultPhysics ( const idVec3 & origin , const idMat3 & axis ) {
const char * temp ;
idClipModel * clipModel = NULL ;
// check if a clipmodel key/value pair is set
if ( spawnArgs . GetString ( " clipmodel " , " " , & temp ) ) {
if ( idClipModel : : CheckModel ( temp ) ) {
clipModel = new idClipModel ( temp ) ;
}
}
if ( ! spawnArgs . GetBool ( " noclipmodel " , " 0 " ) ) {
// check if mins/maxs or size key/value pairs are set
if ( ! clipModel ) {
idVec3 size ;
idBounds bounds ;
bool setClipModel = false ;
if ( spawnArgs . GetVector ( " mins " , NULL , bounds [ 0 ] ) & &
spawnArgs . GetVector ( " maxs " , NULL , bounds [ 1 ] ) ) {
setClipModel = true ;
if ( bounds [ 0 ] [ 0 ] > bounds [ 1 ] [ 0 ] | | bounds [ 0 ] [ 1 ] > bounds [ 1 ] [ 1 ] | | bounds [ 0 ] [ 2 ] > bounds [ 1 ] [ 2 ] ) {
gameLocal . Error ( " Invalid bounds '%s'-'%s' on entity '%s' " , bounds [ 0 ] . ToString ( ) , bounds [ 1 ] . ToString ( ) , name . c_str ( ) ) ;
}
} else if ( spawnArgs . GetVector ( " size " , NULL , size ) ) {
if ( ( size . x < 0.0f ) | | ( size . y < 0.0f ) | | ( size . z < 0.0f ) ) {
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 ;
}
if ( setClipModel ) {
int numSides ;
idTraceModel trm ;
if ( spawnArgs . GetInt ( " cylinder " , " 0 " , numSides ) & & numSides > 0 ) {
trm . SetupCylinder ( bounds , numSides < 3 ? 3 : numSides ) ;
} else if ( spawnArgs . GetInt ( " cone " , " 0 " , numSides ) & & numSides > 0 ) {
trm . SetupCone ( bounds , numSides < 3 ? 3 : numSides ) ;
} else {
trm . SetupBox ( bounds ) ;
}
clipModel = new idClipModel ( trm ) ;
}
}
// check if the visual model can be used as collision model
if ( ! clipModel ) {
temp = spawnArgs . GetString ( " model " ) ;
if ( ( temp ! = NULL ) & & ( * temp ! = 0 ) ) {
if ( idClipModel : : CheckModel ( temp ) ) {
clipModel = new idClipModel ( temp ) ;
}
}
}
}
defaultPhysicsObj . SetSelf ( this ) ;
defaultPhysicsObj . SetClipModel ( clipModel , 1.0f ) ;
defaultPhysicsObj . SetOrigin ( origin ) ;
defaultPhysicsObj . SetAxis ( axis ) ;
physics = & defaultPhysicsObj ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetPhysics
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetPhysics ( idPhysics * phys ) {
// clear any contacts the current physics object has
if ( physics ) {
physics - > ClearContacts ( ) ;
}
// set new physics object or set the default physics if NULL
if ( phys ! = NULL ) {
defaultPhysicsObj . SetClipModel ( NULL , 1.0f ) ;
physics = phys ;
physics - > Activate ( ) ;
} else {
physics = & defaultPhysicsObj ;
}
physics - > UpdateTime ( gameLocal . time ) ;
physics - > SetMaster ( bindMaster , fl . bindOrientated ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RestorePhysics
= = = = = = = = = = = = = = = =
*/
void idEntity : : RestorePhysics ( idPhysics * phys ) {
assert ( phys ! = NULL ) ;
// restore physics pointer
physics = phys ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPhysics
= = = = = = = = = = = = = = = =
*/
idPhysics * idEntity : : GetPhysics ( void ) const {
return physics ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RunPhysics
= = = = = = = = = = = = = = = =
*/
bool idEntity : : RunPhysics ( void ) {
int i , reachedTime , startTime , endTime ;
idEntity * part , * blockedPart , * blockingEntity ;
bool moved ;
// don't run physics if not enabled
if ( ! ( thinkFlags & TH_PHYSICS ) ) {
// however do update any animation controllers
if ( UpdateAnimationControllers ( ) ) {
BecomeActive ( TH_ANIMATE ) ;
}
return false ;
}
// if this entity is a team slave don't do anything because the team master will handle everything
if ( teamMaster & & teamMaster ! = this ) {
return false ;
}
startTime = gameLocal . previousTime ;
endTime = gameLocal . time ;
gameLocal . push . InitSavingPushedEntityPositions ( ) ;
blockedPart = NULL ;
// save the physics state of the whole team and disable the team for collision detection
for ( part = this ; part ! = NULL ; part = part - > teamChain ) {
if ( part - > physics ) {
if ( ! part - > fl . solidForTeam ) {
part - > physics - > DisableClip ( ) ;
}
part - > physics - > SaveState ( ) ;
}
}
// move the whole team
for ( part = this ; part ! = NULL ; part = part - > teamChain ) {
if ( part - > physics ) {
// run physics
moved = part - > physics - > Evaluate ( endTime - startTime , endTime ) ;
// check if the object is blocked
blockingEntity = part - > physics - > GetBlockingEntity ( ) ;
if ( blockingEntity ) {
blockedPart = part ;
break ;
}
// if moved or forced to update the visual position and orientation from the physics
if ( moved | | part - > fl . forcePhysicsUpdate ) {
part - > UpdateFromPhysics ( false ) ;
}
// update any animation controllers here so an entity bound
// to a joint of this entity gets the correct position
if ( part - > UpdateAnimationControllers ( ) ) {
part - > BecomeActive ( TH_ANIMATE ) ;
}
}
}
// enable the whole team for collision detection
for ( part = this ; part ! = NULL ; part = part - > teamChain ) {
if ( part - > physics ) {
if ( ! part - > fl . solidForTeam ) {
part - > physics - > EnableClip ( ) ;
}
}
}
// if one of the team entities is a pusher and blocked
if ( blockedPart ) {
// move the parts back to the previous position
for ( part = this ; part ! = blockedPart ; part = part - > teamChain ) {
if ( part - > physics ) {
// restore the physics state
part - > physics - > RestoreState ( ) ;
// move back the visual position and orientation
part - > UpdateFromPhysics ( true ) ;
}
}
for ( part = this ; part ! = NULL ; part = part - > teamChain ) {
if ( part - > physics ) {
// update the physics time without moving
part - > physics - > UpdateTime ( endTime ) ;
}
}
// restore the positions of any pushed entities
gameLocal . push . RestorePushedEntityPositions ( ) ;
if ( gameLocal . isClient ) {
return false ;
}
// 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 ;
}
// set pushed
for ( i = 0 ; i < gameLocal . push . GetNumPushedEntities ( ) ; i + + ) {
idEntity * ent = gameLocal . push . GetPushedEntity ( i ) ;
ent - > physics - > SetPushed ( endTime - startTime ) ;
}
if ( gameLocal . isClient ) {
return true ;
}
// post reached event if the current time is at or past the end point of the motion
for ( part = this ; part ! = NULL ; part = part - > teamChain ) {
if ( part - > physics ) {
reachedTime = part - > physics - > GetLinearEndTime ( ) ;
if ( startTime < reachedTime & & endTime > = reachedTime ) {
part - > ProcessEvent ( & EV_ReachedPos ) ;
}
reachedTime = part - > physics - > GetAngularEndTime ( ) ;
if ( startTime < reachedTime & & endTime > = reachedTime ) {
part - > ProcessEvent ( & EV_ReachedAng ) ;
}
}
}
return true ;
}
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
/*
= = = = = = = = = = = = = =
idEntity : : UpdateParticles
= = = = = = = = = = = = = =
*/
void idEntity : : UpdateParticles ( void ) {
entDamageEffect_t * de , * * prev ;
// free any that have timed out
prev = & this - > entDamageEffects ;
while ( * prev ) {
de = * prev ;
if ( de - > time = = 0 ) { // FIXME:SMOKE
* prev = de - > next ;
delete de ;
} else {
prev = & de - > next ;
}
}
if ( ! g_bloodEffects . GetBool ( ) ) {
return ;
}
if ( ! this - > entDamageEffects ) { // If no more particles left...
if ( thinkFlags & TH_UPDATEWOUNDPARTICLES )
BecomeInactive ( TH_UPDATEWOUNDPARTICLES ) ;
return ;
}
// emit a particle for each bleeding wound
for ( de = this - > entDamageEffects ; de ; de = de - > next ) {
idVec3 origin ;
idVec3 dir ;
dir = de - > dir * renderEntity . axis ;
origin = renderEntity . origin + de - > origin * renderEntity . axis ;
if ( de - > time = = - 1 ) { // This key fixes an issue where some particles are not at all emitted
de - > time = gameLocal . time ;
}
if ( ! gameLocal . smokeParticles - > EmitSmoke ( de - > type , de - > time , gameLocal . random . CRandomFloat ( ) , origin , dir . ToMat3 ( ) ) ) {
de - > time = 0 ;
}
}
}
# endif
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = =
idEntity : : UpdateFromPhysics
= = = = = = = = = = = = = = = =
*/
void idEntity : : UpdateFromPhysics ( bool moveBack ) {
if ( IsType ( idActor : : Type ) ) {
idActor * actor = static_cast < idActor * > ( this ) ;
// set master delta angles for actors
if ( GetBindMaster ( ) ) {
idAngles delta = actor - > GetDeltaViewAngles ( ) ;
if ( moveBack ) {
delta . yaw - = static_cast < idPhysics_Actor * > ( physics ) - > GetMasterDeltaYaw ( ) ;
} else {
delta . yaw + = static_cast < idPhysics_Actor * > ( physics ) - > GetMasterDeltaYaw ( ) ;
}
actor - > SetDeltaViewAngles ( delta ) ;
}
}
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetOrigin
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetOrigin ( const idVec3 & org ) {
GetPhysics ( ) - > SetOrigin ( org ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetAxis
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetAxis ( const idMat3 & axis ) {
if ( GetPhysics ( ) - > IsType ( idPhysics_Actor : : Type ) ) {
static_cast < idActor * > ( this ) - > viewAxis = axis ;
} else {
GetPhysics ( ) - > SetAxis ( axis ) ;
}
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetAngles
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetAngles ( const idAngles & ang ) {
SetAxis ( ang . ToMat3 ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetFloorPos
= = = = = = = = = = = = = = = =
*/
bool idEntity : : GetFloorPos ( float max_dist , idVec3 & floorpos ) const {
trace_t result ;
if ( ! GetPhysics ( ) - > HasGroundContacts ( ) ) {
GetPhysics ( ) - > ClipTranslation ( result , GetPhysics ( ) - > GetGravityNormal ( ) * max_dist , NULL ) ;
if ( result . fraction < 1.0f ) {
floorpos = result . endpos ;
return true ;
} else {
floorpos = GetPhysics ( ) - > GetOrigin ( ) ;
return false ;
}
} else {
floorpos = GetPhysics ( ) - > GetOrigin ( ) ;
return true ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPhysicsToVisualTransform
= = = = = = = = = = = = = = = =
*/
bool idEntity : : GetPhysicsToVisualTransform ( idVec3 & origin , idMat3 & axis ) {
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetPhysicsToSoundTransform
= = = = = = = = = = = = = = = =
*/
bool idEntity : : GetPhysicsToSoundTransform ( idVec3 & origin , idMat3 & axis ) {
// by default play the sound at the center of the bounding box of the first clip model
if ( GetPhysics ( ) - > GetNumClipModels ( ) > 0 ) {
origin = GetPhysics ( ) - > GetBounds ( ) . GetCenter ( ) ;
axis . Identity ( ) ;
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Collide
= = = = = = = = = = = = = = = =
*/
bool idEntity : : Collide ( const trace_t & collision , const idVec3 & velocity ) {
// this entity collides with collision.c.entityNum
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetImpactInfo
= = = = = = = = = = = = = = = =
*/
void idEntity : : GetImpactInfo ( idEntity * ent , int id , const idVec3 & point , impactInfo_t * info ) {
GetPhysics ( ) - > GetImpactInfo ( id , point , info ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ApplyImpulse
= = = = = = = = = = = = = = = =
*/
void idEntity : : ApplyImpulse ( idEntity * ent , int id , const idVec3 & point , const idVec3 & impulse ) {
GetPhysics ( ) - > ApplyImpulse ( id , point , impulse ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : AddForce
= = = = = = = = = = = = = = = =
*/
void idEntity : : AddForce ( idEntity * ent , int id , const idVec3 & point , const idVec3 & force ) {
GetPhysics ( ) - > AddForce ( id , point , force ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ActivatePhysics
= = = = = = = = = = = = = = = =
*/
void idEntity : : ActivatePhysics ( idEntity * ent ) {
GetPhysics ( ) - > Activate ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsAtRest
= = = = = = = = = = = = = = = =
*/
bool idEntity : : IsAtRest ( void ) const {
return GetPhysics ( ) - > IsAtRest ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : GetRestStartTime
= = = = = = = = = = = = = = = =
*/
int idEntity : : GetRestStartTime ( void ) const {
return GetPhysics ( ) - > GetRestStartTime ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : AddContactEntity
= = = = = = = = = = = = = = = =
*/
void idEntity : : AddContactEntity ( idEntity * ent ) {
GetPhysics ( ) - > AddContactEntity ( ent ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RemoveContactEntity
= = = = = = = = = = = = = = = =
*/
void idEntity : : RemoveContactEntity ( idEntity * ent ) {
GetPhysics ( ) - > RemoveContactEntity ( ent ) ;
}
/***********************************************************************
Damage
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = =
idEntity : : CanDamage
Returns true if the inflictor can directly damage the target . Used for
explosions and melee attacks .
= = = = = = = = = = = =
*/
bool idEntity : : CanDamage ( const idVec3 & origin , idVec3 & damagePoint ) const {
2011-12-06 18:20:15 +00:00
idVec3 dest ;
2011-11-22 21:28:15 +00:00
trace_t tr ;
2011-12-06 18:20:15 +00:00
idVec3 midpoint ;
2011-11-22 21:28:15 +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 ;
dest = midpoint ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) ) {
damagePoint = tr . endpos ;
return true ;
}
// 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 ) ;
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) ) {
damagePoint = tr . endpos ;
return true ;
}
dest = midpoint ;
dest [ 0 ] + = 15.0 ;
dest [ 1 ] - = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) ) {
damagePoint = tr . endpos ;
return true ;
}
dest = midpoint ;
dest [ 0 ] - = 15.0 ;
dest [ 1 ] + = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) ) {
damagePoint = tr . endpos ;
return true ;
}
dest = midpoint ;
dest [ 0 ] - = 15.0 ;
dest [ 1 ] - = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) ) {
damagePoint = tr . endpos ;
return true ;
}
dest = midpoint ;
dest [ 2 ] + = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) ) {
damagePoint = tr . endpos ;
return true ;
}
dest = midpoint ;
dest [ 2 ] - = 15.0 ;
gameLocal . clip . TracePoint ( tr , origin , dest , MASK_SOLID , NULL ) ;
if ( tr . fraction = = 1.0 | | ( gameLocal . GetTraceEntity ( tr ) = = this ) ) {
damagePoint = tr . endpos ;
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : DamageFeedback
callback function for when another entity received damage from this entity . damage can be adjusted and returned to the caller .
= = = = = = = = = = = = = = = =
*/
void idEntity : : DamageFeedback ( idEntity * victim , idEntity * inflictor , int & damage ) {
// 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
= = = = = = = = = = = =
*/
2018-08-27 13:13:17 +00:00
/*
Ivan note : idPlayer and idActor are the only classes that override this method without calling idEntity : : Damage
*/
2011-12-06 18:20:15 +00:00
void idEntity : : Damage ( idEntity * inflictor , idEntity * attacker , const idVec3 & dir ,
2011-11-22 21:28:15 +00:00
const char * damageDefName , const float damageScale , const int location ) {
if ( ! fl . takedamage ) {
return ;
}
if ( ! inflictor ) {
inflictor = gameLocal . world ;
}
if ( ! attacker ) {
attacker = gameLocal . world ;
}
const idDict * damageDef = gameLocal . FindEntityDefDict ( damageDefName ) ;
if ( ! damageDef ) {
gameLocal . Error ( " Unknown damageDef '%s' \n " , damageDefName ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start - damaging fx
//CheckDamageFx( damageDef );
//ivan end
2011-11-22 21:28:15 +00:00
int damage = damageDef - > GetInt ( " damage " ) ;
// inform the attacker that they hit someone
attacker - > DamageFeedback ( this , inflictor , damage ) ;
if ( damage ) {
// do the damage
health - = damage ;
if ( health < = 0 ) {
if ( health < - 999 ) {
health = - 999 ;
}
Killed ( inflictor , attacker , damage , dir , location ) ;
} else {
Pain ( inflictor , attacker , damage , dir , location ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : AddDamageEffect
= = = = = = = = = = = = = = = =
*/
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD
void idEntity : : AddDamageEffect ( const trace_t & collision , const idVec3 & velocity , const char * damageDefName , idEntity * soundEnt ) {
# else
2011-11-22 21:28:15 +00:00
void idEntity : : AddDamageEffect ( const trace_t & collision , const idVec3 & velocity , const char * damageDefName ) {
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
const char * sound , * decal , * key ;
const idDeclEntityDef * def = gameLocal . FindEntityDef ( damageDefName , false ) ;
if ( def = = NULL ) {
return ;
}
const char * materialType = gameLocal . sufaceTypeNames [ collision . c . material - > GetSurfaceType ( ) ] ;
// start impact sound based on material type
key = va ( " snd_%s " , materialType ) ;
sound = spawnArgs . GetString ( key ) ;
if ( * sound = = ' \0 ' ) {
sound = def - > dict . GetString ( key ) ;
}
2018-08-27 13:13:17 +00:00
if ( * sound = = ' \0 ' ) {
sound = def - > dict . GetString ( " snd_metal " ) ; // default sound 1
}
if ( * sound = = ' \0 ' ) {
sound = def - > dict . GetString ( " snd_impact " ) ; // default sound 2
}
2011-11-22 21:28:15 +00:00
if ( * sound ! = ' \0 ' ) {
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD
if ( soundEnt = = NULL ) {
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
else {
soundEnt - > StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
# else
2011-11-22 21:28:15 +00:00
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
}
if ( g_decals . GetBool ( ) ) {
// place a wound overlay on the model
2018-08-27 13:13:17 +00:00
if ( g_debugDamage . GetBool ( ) ) {
gameLocal . Printf ( " \n Collision Material Type- %s " , materialType ) ;
gameLocal . Printf ( " \n file :%s " , collision . c . material - > GetFileName ( ) ) ;
gameLocal . Printf ( " \n Collision material:%s " , collision . c . material - > ImageName ( ) ) ;
}
2011-11-22 21:28:15 +00:00
key = va ( " mtr_wound_%s " , materialType ) ;
decal = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
if ( * decal = = ' \0 ' ) {
decal = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
2018-08-27 13:13:17 +00:00
if ( * decal = = ' \0 ' ) {
decal = def - > dict . GetString ( " mtr_wound " ) ; // Default decal
}
2011-11-22 21:28:15 +00:00
if ( * decal ! = ' \0 ' ) {
2018-08-27 13:13:17 +00:00
float size ;
2011-11-22 21:28:15 +00:00
idVec3 dir = velocity ;
dir . Normalize ( ) ;
2018-08-27 13:13:17 +00:00
if ( ! def - > dict . GetFloat ( va ( " size_wound_%s " , materialType ) , " 6.0 " , size ) ) { // If Material Specific decal size not found, look for default size
size = def - > dict . GetFloat ( " size_wound " , " 6.0 " ) ;
}
2018-09-02 01:42:59 +00:00
if ( size > 0.0f ) {
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
2018-09-02 01:42:59 +00:00
gameLocal . ProjectDecal ( collision . c . point , - collision . c . normal , 8.0f , true , size , decal ) ;
2018-08-27 13:13:17 +00:00
# else
2018-09-02 01:42:59 +00:00
ProjectOverlay ( collision . c . point , dir , size , decal ) ; // added by Clone JCD
# endif // Modified for custom wound size
}
2018-08-27 13:13:17 +00:00
}
}
# ifdef _DENTONMOD_ENTITY_CPP
// a blood spurting wound is added -By Clone JC Denton
key = va ( " smoke_wound_%s " , materialType ) ;
const char * bleed = spawnArgs . GetString ( key ) ;
if ( * bleed = = ' \0 ' ) {
bleed = def - > dict . GetString ( key ) ;
if ( * bleed = = ' \0 ' )
bleed = def - > dict . GetString ( " smoke_wound_metal " ) ; // play default smoke
if ( * bleed = = ' \0 ' )
bleed = def - > dict . GetString ( " smoke_wound " ) ; // play default smoke
}
if ( * bleed ! = ' \0 ' ) {
entDamageEffect_t * de = new entDamageEffect_t ;
de - > next = this - > entDamageEffects ;
this - > entDamageEffects = de ;
de - > origin = ( collision . c . point - renderEntity . origin ) * renderEntity . axis . Transpose ( ) ;
de - > dir = collision . c . normal * renderEntity . axis . Transpose ( ) ;
de - > type = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , bleed ) ) ;
//de->isTimeInitialized = false;
de - > time = - 1 ; // -1 means this effect has just started, see idEntity::UpdateParticles()
if ( ! ( thinkFlags & TH_UPDATEWOUNDPARTICLES ) ) { // if flag was not set before set it now
BecomeActive ( TH_UPDATEWOUNDPARTICLES ) ;
2011-11-22 21:28:15 +00:00
}
}
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = =
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 .
= = = = = = = = = = = =
*/
bool idEntity : : Pain ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location ) {
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 .
= = = = = = = = = = = =
*/
void idEntity : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location ) {
}
/***********************************************************************
Script functions
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +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 .
= = = = = = = = = = = = = = = =
*/
bool idEntity : : ShouldConstructScriptObjectAtSpawn ( void ) const {
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 .
= = = = = = = = = = = = = = = =
*/
idThread * idEntity : : ConstructScriptObject ( void ) {
idThread * thread ;
const function_t * constructor ;
// init the script object's data
scriptObject . ClearObject ( ) ;
// call script object's constructor
constructor = scriptObject . GetConstructor ( ) ;
if ( constructor ) {
// 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 ) ;
} else {
thread = NULL ;
}
// clear out the object's memory
scriptObject . ClearObject ( ) ;
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 .
= = = = = = = = = = = = = = = =
*/
void idEntity : : DeconstructScriptObject ( void ) {
idThread * thread ;
const function_t * destructor ;
// don't bother calling the script object's destructor on map shutdown
if ( gameLocal . GameState ( ) = = GAMESTATE_SHUTDOWN ) {
return ;
}
// call script object's destructor
destructor = scriptObject . GetDestructor ( ) ;
if ( destructor ) {
// 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
= = = = = = = = = = = = = = = =
*/
bool idEntity : : HasSignal ( signalNum_t signalnum ) const {
if ( ! signals ) {
return false ;
}
assert ( ( signalnum > = 0 ) & & ( signalnum < NUM_SIGNALS ) ) ;
return ( signals - > signal [ signalnum ] . Num ( ) > 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SetSignal
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetSignal ( signalNum_t signalnum , idThread * thread , const function_t * function ) {
int i ;
int num ;
signal_t sig ;
int threadnum ;
assert ( ( signalnum > = 0 ) & & ( signalnum < NUM_SIGNALS ) ) ;
if ( ! signals ) {
signals = new signalList_t ;
}
assert ( thread ) ;
threadnum = thread - > GetThreadNum ( ) ;
num = signals - > signal [ signalnum ] . Num ( ) ;
for ( i = 0 ; i < num ; i + + ) {
if ( signals - > signal [ signalnum ] [ i ] . threadnum = = threadnum ) {
signals - > signal [ signalnum ] [ i ] . function = function ;
return ;
}
}
if ( num > = MAX_SIGNAL_THREADS ) {
thread - > Error ( " Exceeded maximum number of signals per object " ) ;
}
sig . threadnum = threadnum ;
sig . function = function ;
signals - > signal [ signalnum ] . Append ( sig ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClearSignal
= = = = = = = = = = = = = = = =
*/
void idEntity : : ClearSignal ( idThread * thread , signalNum_t signalnum ) {
assert ( thread ) ;
if ( ( signalnum < 0 ) | | ( signalnum > = NUM_SIGNALS ) ) {
gameLocal . Error ( " Signal out of range " ) ;
}
if ( ! signals ) {
return ;
}
signals - > signal [ signalnum ] . Clear ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClearSignalThread
= = = = = = = = = = = = = = = =
*/
void idEntity : : ClearSignalThread ( signalNum_t signalnum , idThread * thread ) {
int i ;
int num ;
int threadnum ;
assert ( thread ) ;
if ( ( signalnum < 0 ) | | ( signalnum > = NUM_SIGNALS ) ) {
gameLocal . Error ( " Signal out of range " ) ;
}
if ( ! signals ) {
return ;
}
threadnum = thread - > GetThreadNum ( ) ;
num = signals - > signal [ signalnum ] . Num ( ) ;
for ( i = 0 ; i < num ; i + + ) {
if ( signals - > signal [ signalnum ] [ i ] . threadnum = = threadnum ) {
signals - > signal [ signalnum ] . RemoveIndex ( i ) ;
return ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Signal
= = = = = = = = = = = = = = = =
*/
void idEntity : : Signal ( signalNum_t signalnum ) {
int i ;
int num ;
signal_t sigs [ MAX_SIGNAL_THREADS ] ;
idThread * thread ;
assert ( ( signalnum > = 0 ) & & ( signalnum < NUM_SIGNALS ) ) ;
if ( ! signals ) {
return ;
}
// 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 ( ) ;
for ( i = 0 ; i < num ; i + + ) {
sigs [ i ] = signals - > signal [ signalnum ] [ i ] ;
}
// clear out the signal list so that we don't get into an infinite loop
signals - > signal [ signalnum ] . Clear ( ) ;
for ( i = 0 ; i < num ; i + + ) {
thread = idThread : : GetThread ( sigs [ i ] . threadnum ) ;
if ( thread ) {
thread - > CallFunction ( this , sigs [ i ] . function , true ) ;
thread - > Execute ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : SignalEvent
= = = = = = = = = = = = = = = =
*/
void idEntity : : SignalEvent ( idThread * thread , signalNum_t signalnum ) {
if ( ( signalnum < 0 ) | | ( signalnum > = NUM_SIGNALS ) ) {
gameLocal . Error ( " Signal out of range " ) ;
}
if ( ! signals ) {
return ;
}
Signal ( signalnum ) ;
}
/***********************************************************************
Guis .
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : TriggerGuis
= = = = = = = = = = = = = = = =
*/
void idEntity : : TriggerGuis ( void ) {
int i ;
for ( i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + ) {
if ( renderEntity . gui [ i ] ) {
renderEntity . gui [ i ] - > Trigger ( gameLocal . time ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : HandleGuiCommands
= = = = = = = = = = = = = = = =
*/
bool idEntity : : HandleGuiCommands ( idEntity * entityGui , const char * cmds ) {
idEntity * targetEnt ;
bool ret = false ;
if ( entityGui & & cmds & & * cmds ) {
idLexer src ;
idToken token , token2 , token3 , token4 ;
src . LoadMemory ( cmds , strlen ( cmds ) , " guiCommands " ) ;
while ( 1 ) {
if ( ! src . ReadToken ( & token ) ) {
return ret ;
}
if ( token = = " ; " ) {
continue ;
}
if ( token . Icmp ( " activate " ) = = 0 ) {
bool targets = true ;
if ( src . ReadToken ( & token2 ) ) {
if ( token2 = = " ; " ) {
src . UnreadToken ( & token2 ) ;
} else {
targets = false ;
}
}
if ( targets ) {
entityGui - > ActivateTargets ( this ) ;
} else {
idEntity * ent = gameLocal . FindEntity ( token2 ) ;
if ( ent ) {
ent - > Signal ( SIG_TRIGGER ) ;
ent - > PostEventMS ( & EV_Activate , 0 , this ) ;
}
}
entityGui - > renderEntity . shaderParms [ SHADERPARM_MODE ] = 1.0f ;
continue ;
}
if ( token . Icmp ( " runScript " ) = = 0 ) {
if ( src . ReadToken ( & token2 ) ) {
while ( src . CheckTokenString ( " :: " ) ) {
idToken token3 ;
if ( ! src . ReadToken ( & token3 ) ) {
gameLocal . Error ( " Expecting function name following '::' in gui for entity '%s' " , entityGui - > name . c_str ( ) ) ;
}
token2 + = " :: " + token3 ;
}
const function_t * func = gameLocal . program . FindFunction ( token2 ) ;
if ( ! func ) {
gameLocal . Error ( " Can't find function '%s' for gui in entity '%s' " , token2 . c_str ( ) , entityGui - > name . c_str ( ) ) ;
} else {
idThread * thread = new idThread ( func ) ;
thread - > DelayedStart ( 0 ) ;
}
}
continue ;
}
if ( token . Icmp ( " play " ) = = 0 ) {
if ( src . ReadToken ( & token2 ) ) {
const idSoundShader * shader = declManager - > FindSound ( token2 ) ;
entityGui - > StartSoundShader ( shader , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
continue ;
}
if ( token . Icmp ( " setkeyval " ) = = 0 ) {
if ( src . ReadToken ( & token2 ) & & src . ReadToken ( & token3 ) & & src . ReadToken ( & token4 ) ) {
idEntity * ent = gameLocal . FindEntity ( token2 ) ;
if ( ent ) {
ent - > spawnArgs . Set ( token3 , token4 ) ;
ent - > UpdateChangeableSpawnArgs ( NULL ) ;
ent - > UpdateVisuals ( ) ;
}
}
continue ;
}
if ( token . Icmp ( " setshaderparm " ) = = 0 ) {
if ( src . ReadToken ( & token2 ) & & src . ReadToken ( & token3 ) ) {
entityGui - > SetShaderParm ( atoi ( token2 ) , atof ( token3 ) ) ;
entityGui - > UpdateVisuals ( ) ;
}
continue ;
}
if ( token . Icmp ( " close " ) = = 0 ) {
ret = true ;
continue ;
}
if ( ! token . Icmp ( " turkeyscore " ) ) {
if ( src . ReadToken ( & token2 ) & & entityGui - > renderEntity . gui [ 0 ] ) {
int score = entityGui - > renderEntity . gui [ 0 ] - > State ( ) . GetInt ( " score " ) ;
score + = atoi ( token2 ) ;
entityGui - > renderEntity . gui [ 0 ] - > SetStateInt ( " score " , score ) ;
if ( gameLocal . GetLocalPlayer ( ) & & score > = 25000 & & ! gameLocal . GetLocalPlayer ( ) - > inventory . turkeyScore ) {
gameLocal . GetLocalPlayer ( ) - > GiveEmail ( " highScore " ) ;
gameLocal . GetLocalPlayer ( ) - > inventory . turkeyScore = true ;
}
}
continue ;
}
// handy for debugging GUI stuff
if ( ! token . Icmp ( " print " ) ) {
idStr msg ;
while ( src . ReadToken ( & token2 ) ) {
if ( token2 = = " ; " ) {
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 ;
}
// if we get to this point we don't know how to handle it
src . UnreadToken ( & token ) ;
if ( ! HandleSingleGuiCommand ( entityGui , & src ) ) {
// not handled there see if entity or any of its targets can handle it
// this will only work for one target atm
if ( entityGui - > HandleSingleGuiCommand ( entityGui , & src ) ) {
continue ;
}
int c = entityGui - > targets . Num ( ) ;
int i ;
for ( i = 0 ; i < c ; i + + ) {
targetEnt = entityGui - > targets [ i ] . GetEntity ( ) ;
if ( targetEnt & & targetEnt - > HandleSingleGuiCommand ( entityGui , & src ) ) {
break ;
}
}
if ( i = = c ) {
// not handled
common - > DPrintf ( " idEntity::HandleGuiCommands: '%s' not handled \n " , token . c_str ( ) ) ;
src . ReadToken ( & token ) ;
}
}
}
}
return ret ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : HandleSingleGuiCommand
= = = = = = = = = = = = = = = =
*/
bool idEntity : : HandleSingleGuiCommand ( idEntity * entityGui , idLexer * src ) {
return false ;
}
/***********************************************************************
Targets
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +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
= = = = = = = = = = = = = = =
*/
void idEntity : : FindTargets ( void ) {
int i ;
// targets can be a list of multiple names
gameLocal . GetTargets ( spawnArgs , targets , " target " ) ;
// ensure that we don't target ourselves since that could cause an infinite loop when activating entities
for ( i = 0 ; i < targets . Num ( ) ; i + + ) {
if ( targets [ i ] . GetEntity ( ) = = this ) {
gameLocal . Error ( " Entity '%s' is targeting itself " , name . c_str ( ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : RemoveNullTargets
= = = = = = = = = = = = = = = =
*/
void idEntity : : RemoveNullTargets ( void ) {
int i ;
for ( i = targets . Num ( ) - 1 ; i > = 0 ; i - - ) {
if ( ! targets [ i ] . GetEntity ( ) ) {
targets . RemoveIndex ( i ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idEntity : : ActivateTargets
" activator " should be set to the entity that initiated the firing .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : ActivateTargets ( idEntity * activator ) const {
idEntity * ent ;
int i , j ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
for ( i = 0 ; i < targets . Num ( ) ; i + + ) {
ent = targets [ i ] . GetEntity ( ) ;
if ( ! ent ) {
continue ;
}
if ( ent - > RespondsTo ( EV_Activate ) | | ent - > HasSignal ( SIG_TRIGGER ) ) {
ent - > Signal ( SIG_TRIGGER ) ;
ent - > ProcessEvent ( & EV_Activate , activator ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
for ( j = 0 ; j < MAX_RENDERENTITY_GUI ; j + + ) {
if ( ent - > renderEntity . gui [ j ] ) {
ent - > renderEntity . gui [ j ] - > Trigger ( gameLocal . time ) ;
}
}
}
}
/***********************************************************************
Misc .
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : Teleport
= = = = = = = = = = = = = = = =
*/
void idEntity : : Teleport ( const idVec3 & origin , const idAngles & angles , idEntity * destination ) {
GetPhysics ( ) - > SetOrigin ( origin ) ;
GetPhysics ( ) - > SetAxis ( angles . ToMat3 ( ) ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = =
idEntity : : TouchTriggers
Activate all trigger entities touched at the current position .
= = = = = = = = = = = =
*/
bool idEntity : : TouchTriggers ( void ) const {
int i , numClipModels , numEntities ;
idClipModel * cm ;
idClipModel * clipModels [ MAX_GENTITIES ] ;
idEntity * ent ;
trace_t trace ;
memset ( & trace , 0 , sizeof ( trace ) ) ;
trace . endpos = GetPhysics ( ) - > GetOrigin ( ) ;
trace . endAxis = GetPhysics ( ) - > GetAxis ( ) ;
numClipModels = gameLocal . clip . ClipModelsTouchingBounds ( GetPhysics ( ) - > GetAbsBounds ( ) , CONTENTS_TRIGGER , clipModels , MAX_GENTITIES ) ;
numEntities = 0 ;
for ( i = 0 ; i < numClipModels ; i + + ) {
cm = clipModels [ i ] ;
// don't touch it if we're the owner
if ( cm - > GetOwner ( ) = = this ) {
continue ;
}
ent = cm - > GetEntity ( ) ;
if ( ! ent - > RespondsTo ( EV_Touch ) & & ! ent - > HasSignal ( SIG_TOUCH ) ) {
continue ;
}
if ( ! GetPhysics ( ) - > ClipContents ( cm ) ) {
continue ;
}
numEntities + + ;
trace . c . contents = cm - > GetContents ( ) ;
trace . c . entityNum = cm - > GetEntity ( ) - > entityNumber ;
trace . c . id = cm - > GetId ( ) ;
ent - > Signal ( SIG_TOUCH ) ;
ent - > ProcessEvent ( & EV_Touch , this , & trace ) ;
if ( ! gameLocal . entities [ entityNumber ] ) {
gameLocal . Printf ( " entity was removed while touching triggers \n " ) ;
return true ;
}
}
return ( numEntities ! = 0 ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start
/*
= = = = = = = = = = = =
idEntity : : CanInteract
If it returns false , prevents EV_Interact to be raised .
Overridden by subclasses .
= = = = = = = = = = = =
*/
bool idEntity : : CanInteract ( int flags ) const {
return false ; //by default
}
/*
= = = = = = = = = = = =
idEntity : : InteractTouchingTriggers
Interact with all trigger entities touched at the current position .
= = = = = = = = = = = =
*/
bool idEntity : : InteractTouchingTriggers ( int flags ) const {
int i , numClipModels , numEntities ;
idClipModel * cm ;
idClipModel * clipModels [ MAX_GENTITIES ] ;
idEntity * ent ;
trace_t trace ;
memset ( & trace , 0 , sizeof ( trace ) ) ;
trace . endpos = GetPhysics ( ) - > GetOrigin ( ) ;
trace . endAxis = GetPhysics ( ) - > GetAxis ( ) ;
numClipModels = gameLocal . clip . ClipModelsTouchingBounds ( GetPhysics ( ) - > GetAbsBounds ( ) , CONTENTS_TRIGGER , clipModels , MAX_GENTITIES ) ;
numEntities = 0 ;
for ( i = 0 ; i < numClipModels ; i + + ) {
cm = clipModels [ i ] ;
// don't touch it if we're the owner
if ( cm - > GetOwner ( ) = = this ) {
continue ;
}
ent = cm - > GetEntity ( ) ;
if ( ! ent - > RespondsTo ( EV_Interact ) ) { //if ( !ent->RespondsTo( EV_Touch ) && !ent->HasSignal( SIG_TOUCH ) ) {
continue ;
}
if ( ! GetPhysics ( ) - > ClipContents ( cm ) ) {
continue ;
}
if ( ! ent - > CanInteract ( flags ) ) { //we need to know if it can interact, otherwise we'll return true even if nothing is done.
continue ;
}
numEntities + + ;
/*
trace . c . contents = cm - > GetContents ( ) ;
trace . c . entityNum = cm - > GetEntity ( ) - > entityNumber ;
trace . c . id = cm - > GetId ( ) ;
*/
ent - > ProcessEvent ( & EV_Interact , this , flags ) ; //sono arrivato qui - ora chiamo sta funz in player ::think se <20> il caso e vedo se posso semplificare il mio trigger...
/* was
ent - > Signal ( SIG_TOUCH ) ;
ent - > ProcessEvent ( & EV_Touch , this , & trace ) ;
*/
if ( ! gameLocal . entities [ entityNumber ] ) {
gameLocal . Printf ( " entity was removed while interacting with triggers \n " ) ;
return true ;
}
}
return ( numEntities ! = 0 ) ;
}
/*
= = = = = = = = = = = = = = =
idEntity : : GetFirstValidTarget
= = = = = = = = = = = = = = =
*/
idEntity * idEntity : : GetFirstValidTarget ( void ) const {
idEntity * ent = NULL ;
for ( int i = 0 ; i < targets . Num ( ) ; i + + ) {
ent = targets [ i ] . GetEntity ( ) ;
if ( ent ) break ;
}
return ent ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : CheckDamageFx
= = = = = = = = = = = = = = = = = = = = =
void idEntity : : CheckDamageFx ( const idDict * damageDef ) { //TODO: move to actors?
if ( ! damageDef ) { return ; }
if ( ! spawnArgs . GetBool ( " allowDmgfxs " , " 0 " ) ) {
return ;
}
int dmgFxType = damageDef - > GetInt ( " dmgFxType " , " 0 " ) ; //default is "0" -> no fx
if ( dmgFxType > DMGFX_NONE & & dmgFxType < NUM_DMGFX_TYPES ) {
StartDamageFx ( dmgFxType ) ;
}
}
*/
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : StartDamageFx
= = = = = = = = = = = = = = = = = = = = =
void idEntity : : StartDamageFx ( int type ) { //TODO: move to actors?
int i ;
idDamagingFx * tempFx ;
if ( type < = DMGFX_NONE | | type > = NUM_DMGFX_TYPES ) {
gameLocal . Warning ( " StartDamageFx: invalid dmgFxType " ) ;
return ;
}
//remove invalid ones
for ( i = dmgFxEntities . Num ( ) - 1 ; i > = 0 ; i - - ) {
if ( ! dmgFxEntities [ i ] . GetEntity ( ) ) {
dmgFxEntities . RemoveIndex ( i ) ;
}
}
//check if the effect is already active --> restart it
for ( i = dmgFxEntities . Num ( ) - 1 ; i > = 0 ; i - - ) {
tempFx = dmgFxEntities [ i ] . GetEntity ( ) ;
if ( tempFx - > GetDmgFxType ( ) = = type ) {
tempFx - > Restart ( ) ;
return ;
}
}
//start a new one
tempFx = idDamagingFx : : StartDamagingFx ( type , this ) ;
if ( tempFx ) {
idEntityPtr < idDamagingFx > & newFxPtr = dmgFxEntities . Alloc ( ) ;
newFxPtr = tempFx ;
}
}
*/
//ivan end
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = =
idEntity : : GetSpline
= = = = = = = = = = = = = = = =
*/
idCurve_Spline < idVec3 > * idEntity : : GetSpline ( void ) const {
int i , numPoints , t ;
const idKeyValue * kv ;
idLexer lex ;
idVec3 v ;
idCurve_Spline < idVec3 > * spline ;
const char * curveTag = " curve_ " ;
kv = spawnArgs . MatchPrefix ( curveTag ) ;
if ( ! kv ) {
return NULL ;
}
idStr str = kv - > GetKey ( ) . Right ( kv - > GetKey ( ) . Length ( ) - strlen ( curveTag ) ) ;
if ( str . Icmp ( " CatmullRomSpline " ) = = 0 ) {
spline = new idCurve_CatmullRomSpline < idVec3 > ( ) ;
} else if ( str . Icmp ( " nubs " ) = = 0 ) {
spline = new idCurve_NonUniformBSpline < idVec3 > ( ) ;
} else if ( str . Icmp ( " nurbs " ) = = 0 ) {
spline = new idCurve_NURBS < idVec3 > ( ) ;
} else {
spline = new idCurve_BSpline < idVec3 > ( ) ;
}
spline - > SetBoundaryType ( idCurve_Spline < idVec3 > : : BT_CLAMPED ) ;
lex . LoadMemory ( kv - > GetValue ( ) , kv - > GetValue ( ) . Length ( ) , curveTag ) ;
numPoints = lex . ParseInt ( ) ;
lex . ExpectTokenString ( " ( " ) ;
for ( t = i = 0 ; i < numPoints ; i + + , t + = 100 ) {
v . x = lex . ParseFloat ( ) ;
v . y = lex . ParseFloat ( ) ;
v . z = lex . ParseFloat ( ) ;
spline - > AddValue ( t , v ) ;
}
lex . ExpectTokenString ( " ) " ) ;
return spline ;
}
/*
= = = = = = = = = = = = = = =
idEntity : : ShowEditingDialog
= = = = = = = = = = = = = = =
*/
void idEntity : : ShowEditingDialog ( void ) {
}
/***********************************************************************
Events
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetName
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetName ( void ) {
idThread : : ReturnString ( name . c_str ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetName
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetName ( const char * newname ) {
SetName ( newname ) ;
}
/*
= = = = = = = = = = = = = = =
idEntity : : Event_FindTargets
= = = = = = = = = = = = = = =
*/
void idEntity : : Event_FindTargets ( void ) {
FindTargets ( ) ;
}
/*
= = = = = = = = = = = =
idEntity : : Event_ActivateTargets
Activates any entities targeted by this entity . Mainly used as an
event to delay activating targets .
= = = = = = = = = = = =
*/
void idEntity : : Event_ActivateTargets ( idEntity * activator ) {
ActivateTargets ( activator ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_NumTargets
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_NumTargets ( void ) {
idThread : : ReturnFloat ( targets . Num ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetTarget
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetTarget ( float index ) {
int i ;
i = ( int ) index ;
if ( ( i < 0 ) | | i > = targets . Num ( ) ) {
idThread : : ReturnEntity ( NULL ) ;
} else {
idThread : : ReturnEntity ( targets [ i ] . GetEntity ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_RandomTarget
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_RandomTarget ( const char * ignore ) {
int num ;
idEntity * ent ;
int i ;
int ignoreNum ;
RemoveNullTargets ( ) ;
if ( ! targets . Num ( ) ) {
idThread : : ReturnEntity ( NULL ) ;
return ;
}
ignoreNum = - 1 ;
if ( ignore & & ( ignore [ 0 ] ! = 0 ) & & ( targets . Num ( ) > 1 ) ) {
for ( i = 0 ; i < targets . Num ( ) ; i + + ) {
ent = targets [ i ] . GetEntity ( ) ;
if ( ent & & ( ent - > name = = ignore ) ) {
ignoreNum = i ;
break ;
}
}
}
if ( ignoreNum > = 0 ) {
num = gameLocal . random . RandomInt ( targets . Num ( ) - 1 ) ;
if ( num > = ignoreNum ) {
num + + ;
}
} else {
num = gameLocal . random . RandomInt ( targets . Num ( ) ) ;
}
ent = targets [ num ] . GetEntity ( ) ;
idThread : : ReturnEntity ( ent ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_BindToJoint
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_BindToJoint ( idEntity * master , const char * jointname , float orientated ) {
BindToJoint ( master , jointname , ( orientated ! = 0.0f ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_RemoveBinds
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_RemoveBinds ( void ) {
RemoveBinds ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Bind
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_Bind ( idEntity * master ) {
Bind ( master , true ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_BindPosition
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_BindPosition ( idEntity * master ) {
Bind ( master , false ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Unbind
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_Unbind ( void ) {
Unbind ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SpawnBind
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SpawnBind ( void ) {
idEntity * parent ;
const char * bind , * joint , * bindanim ;
jointHandle_t bindJoint ;
bool bindOrientated ;
int id ;
const idAnim * anim ;
int animNum ;
idAnimator * parentAnimator ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( spawnArgs . GetString ( " bind " , " " , & bind ) ) {
if ( idStr : : Icmp ( bind , " worldspawn " ) = = 0 ) {
//FIXME: Completely unneccessary since the worldspawn is called "world"
parent = gameLocal . world ;
} else {
parent = gameLocal . FindEntity ( bind ) ;
}
bindOrientated = spawnArgs . GetBool ( " bindOrientated " , " 1 " ) ;
if ( parent ) {
// bind to a joint of the skeletal model of the parent
if ( spawnArgs . GetString ( " bindToJoint " , " " , & joint ) & & * joint ) {
parentAnimator = parent - > GetAnimator ( ) ;
if ( ! parentAnimator ) {
gameLocal . Error ( " Cannot bind to joint '%s' on '%s'. Entity does not support skeletal models. " , joint , name . c_str ( ) ) ;
}
bindJoint = parentAnimator - > GetJointHandle ( joint ) ;
if ( bindJoint = = INVALID_JOINT ) {
gameLocal . Error ( " Joint '%s' not found for bind on '%s' " , joint , name . c_str ( ) ) ;
}
// bind it relative to a specific anim
if ( ( parent - > spawnArgs . GetString ( " bindanim " , " " , & bindanim ) | | parent - > spawnArgs . GetString ( " anim " , " " , & bindanim ) ) & & * bindanim ) {
animNum = parentAnimator - > GetAnim ( bindanim ) ;
if ( ! animNum ) {
gameLocal . Error ( " Anim '%s' not found for bind on '%s' " , bindanim , name . c_str ( ) ) ;
}
anim = parentAnimator - > GetAnim ( animNum ) ;
if ( ! anim ) {
gameLocal . Error ( " Anim '%s' not found for bind on '%s' " , bindanim , name . c_str ( ) ) ;
}
// make sure parent's render origin has been set
parent - > UpdateModelTransform ( ) ;
//FIXME: need a BindToJoint that accepts a joint position
parentAnimator - > CreateFrame ( gameLocal . time , true ) ;
idJointMat * frame = parent - > renderEntity . joints ;
gameEdit - > ANIM_CreateAnimFrame ( parentAnimator - > ModelHandle ( ) , anim - > MD5Anim ( 0 ) , parent - > renderEntity . numJoints , frame , 0 , parentAnimator - > ModelDef ( ) - > GetVisualOffset ( ) , parentAnimator - > RemoveOrigin ( ) ) ;
BindToJoint ( parent , joint , bindOrientated ) ;
parentAnimator - > ForceUpdate ( ) ;
} else {
BindToJoint ( parent , joint , bindOrientated ) ;
}
}
// bind to a body of the physics object of the parent
else if ( spawnArgs . GetInt ( " bindToBody " , " 0 " , id ) ) {
BindToBody ( parent , id , bindOrientated ) ;
}
// bind to the parent
else {
Bind ( parent , bindOrientated ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetOwner
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetOwner ( idEntity * owner ) {
int i ;
for ( i = 0 ; i < GetPhysics ( ) - > GetNumClipModels ( ) ; i + + ) {
GetPhysics ( ) - > GetClipModel ( i ) - > SetOwner ( owner ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetModel
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetModel ( const char * modelname ) {
SetModel ( modelname ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetSkin
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetSkin ( const char * skinname ) {
renderEntity . customSkin = declManager - > FindSkin ( skinname ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetShaderParm
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetShaderParm ( int parmnum ) {
if ( ( parmnum < 0 ) | | ( parmnum > = MAX_ENTITY_SHADER_PARMS ) ) {
gameLocal . Error ( " shader parm index (%d) out of range " , parmnum ) ;
}
idThread : : ReturnFloat ( renderEntity . shaderParms [ parmnum ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetShaderParm
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetShaderParm ( int parmnum , float value ) {
SetShaderParm ( parmnum , value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetShaderParms
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetShaderParms ( float parm0 , float parm1 , float parm2 , float parm3 ) {
renderEntity . shaderParms [ SHADERPARM_RED ] = parm0 ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = parm1 ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = parm2 ;
renderEntity . shaderParms [ SHADERPARM_ALPHA ] = parm3 ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetColor
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetColor ( float red , float green , float blue ) {
SetColor ( red , green , blue ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetColor
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetColor ( void ) {
idVec3 out ;
GetColor ( out ) ;
idThread : : ReturnVector ( out ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_IsHidden
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_IsHidden ( void ) {
idThread : : ReturnInt ( fl . hidden ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Hide
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_Hide ( void ) {
Hide ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Show
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_Show ( void ) {
Show ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_CacheSoundShader
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_CacheSoundShader ( const char * soundName ) {
declManager - > FindSound ( soundName ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_StartSoundShader
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_StartSoundShader ( const char * soundName , int channel ) {
int length ;
StartSoundShader ( declManager - > FindSound ( soundName ) , ( s_channelType ) channel , 0 , false , & length ) ;
idThread : : ReturnFloat ( MS2SEC ( length ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_StopSound
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_StopSound ( int channel , int netSync ) {
StopSound ( channel , ( netSync ! = 0 ) ) ;
}
/*
= = = = = = = = = = = = = = = =
2011-12-06 18:20:15 +00:00
idEntity : : Event_StartSound
2011-11-22 21:28:15 +00:00
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_StartSound ( const char * soundName , int channel , int netSync ) {
int time ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
StartSound ( soundName , ( s_channelType ) channel , 0 , ( netSync ! = 0 ) , & time ) ;
idThread : : ReturnFloat ( MS2SEC ( time ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_FadeSound
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_FadeSound ( int channel , float to , float over ) {
if ( refSound . referenceSound ) {
refSound . referenceSound - > FadeSound ( channel , to , over ) ;
}
}
2018-08-27 13:13:17 +00:00
//ivan start
/*
= = = = = = = = = = = = = = = =
idEntity : : FadeSound
= = = = = = = = = = = = = = = =
*/
void idEntity : : FadeSound ( int channel , float to , float over ) {
if ( refSound . referenceSound ) {
refSound . referenceSound - > FadeSound ( channel , to , over ) ;
}
}
//ivan end
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetWorldOrigin
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetWorldOrigin ( void ) {
idThread : : ReturnVector ( GetPhysics ( ) - > GetOrigin ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetWorldOrigin
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetWorldOrigin ( idVec3 const & org ) {
idVec3 neworg = GetLocalCoordinates ( org ) ;
SetOrigin ( neworg ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetOrigin
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetOrigin ( idVec3 const & org ) {
SetOrigin ( org ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetOrigin
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetOrigin ( void ) {
idThread : : ReturnVector ( GetLocalCoordinates ( GetPhysics ( ) - > GetOrigin ( ) ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetAngles
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetAngles ( idAngles const & ang ) {
SetAngles ( ang ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetAngles
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetAngles ( void ) {
idAngles ang = GetPhysics ( ) - > GetAxis ( ) . ToAngles ( ) ;
idThread : : ReturnVector ( idVec3 ( ang [ 0 ] , ang [ 1 ] , ang [ 2 ] ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetLinearVelocity
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetLinearVelocity ( const idVec3 & velocity ) {
GetPhysics ( ) - > SetLinearVelocity ( velocity ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetLinearVelocity
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetLinearVelocity ( void ) {
idThread : : ReturnVector ( GetPhysics ( ) - > GetLinearVelocity ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetAngularVelocity
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetAngularVelocity ( const idVec3 & velocity ) {
GetPhysics ( ) - > SetAngularVelocity ( velocity ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetAngularVelocity
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetAngularVelocity ( void ) {
idThread : : ReturnVector ( GetPhysics ( ) - > GetAngularVelocity ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetSize
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetSize ( idVec3 const & mins , idVec3 const & maxs ) {
GetPhysics ( ) - > SetClipBox ( idBounds ( mins , maxs ) , 1.0f ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetSize
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetSize ( void ) {
idBounds bounds ;
bounds = GetPhysics ( ) - > GetBounds ( ) ;
idThread : : ReturnVector ( bounds [ 1 ] - bounds [ 0 ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetMins
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetMins ( void ) {
idThread : : ReturnVector ( GetPhysics ( ) - > GetBounds ( ) [ 0 ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetMaxs
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetMaxs ( void ) {
idThread : : ReturnVector ( GetPhysics ( ) - > GetBounds ( ) [ 1 ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_Touches
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_Touches ( idEntity * ent ) {
if ( ! ent ) {
idThread : : ReturnInt ( false ) ;
return ;
}
const idBounds & myBounds = GetPhysics ( ) - > GetAbsBounds ( ) ;
const idBounds & entBounds = ent - > GetPhysics ( ) - > GetAbsBounds ( ) ;
idThread : : ReturnInt ( myBounds . IntersectsBounds ( entBounds ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetGuiParm
= = = = = = = = = = = = = = = =
*/
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 ) {
spawnArgs . Set ( key , val ) ;
}
renderEntity . gui [ i ] - > SetStateString ( key , val ) ;
renderEntity . gui [ i ] - > StateChanged ( gameLocal . time ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetGuiParm
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetGuiFloat ( const char * key , float f ) {
for ( int i = 0 ; i < MAX_RENDERENTITY_GUI ; i + + ) {
if ( renderEntity . gui [ i ] ) {
renderEntity . gui [ i ] - > SetStateString ( key , va ( " %f " , f ) ) ;
renderEntity . gui [ i ] - > StateChanged ( gameLocal . time ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetNextKey
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetNextKey ( const char * prefix , const char * lastMatch ) {
const idKeyValue * kv ;
const idKeyValue * previous ;
if ( * lastMatch ) {
previous = spawnArgs . FindKey ( lastMatch ) ;
} else {
previous = NULL ;
}
kv = spawnArgs . MatchPrefix ( prefix , previous ) ;
if ( ! kv ) {
idThread : : ReturnString ( " " ) ;
} else {
idThread : : ReturnString ( kv - > GetKey ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetKey
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetKey ( const char * key , const char * value ) {
spawnArgs . Set ( key , value ) ;
2018-08-27 13:13:17 +00:00
//rev grab
UpdateChangeableSpawnArgs ( NULL ) ;
//rev grab
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetKey
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetKey ( const char * key ) {
const char * value ;
spawnArgs . GetString ( key , " " , & value ) ;
idThread : : ReturnString ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetIntKey
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetIntKey ( const char * key ) {
int value ;
spawnArgs . GetInt ( key , " 0 " , value ) ;
// scripts only support floats
idThread : : ReturnFloat ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetFloatKey
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetFloatKey ( const char * key ) {
float value ;
spawnArgs . GetFloat ( key , " 0 " , value ) ;
idThread : : ReturnFloat ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetVectorKey
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetVectorKey ( const char * key ) {
idVec3 value ;
spawnArgs . GetVector ( key , " 0 0 0 " , value ) ;
idThread : : ReturnVector ( value ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_GetEntityKey
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetEntityKey ( const char * key ) {
idEntity * ent ;
const char * entname ;
if ( ! spawnArgs . GetString ( key , NULL , & entname ) ) {
idThread : : ReturnEntity ( NULL ) ;
return ;
}
ent = gameLocal . FindEntity ( entname ) ;
if ( ! ent ) {
gameLocal . Warning ( " Couldn't find entity '%s' specified in '%s' key in entity '%s' " , entname , key , name . c_str ( ) ) ;
}
idThread : : ReturnEntity ( ent ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_RestorePosition
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_RestorePosition ( void ) {
idVec3 org ;
idAngles angles ;
idMat3 axis ;
idEntity * part ;
spawnArgs . GetVector ( " origin " , " 0 0 0 " , org ) ;
// get the rotation matrix in either full form, or single angle form
if ( spawnArgs . GetMatrix ( " rotation " , " 1 0 0 0 1 0 0 0 1 " , axis ) ) {
angles = axis . ToAngles ( ) ;
} else {
2011-12-06 18:20:15 +00:00
angles [ 0 ] = 0 ;
angles [ 1 ] = spawnArgs . GetFloat ( " angle " ) ;
angles [ 2 ] = 0 ;
2011-11-22 21:28:15 +00:00
}
Teleport ( org , angles , NULL ) ;
for ( part = teamChain ; part ! = NULL ; part = part - > teamChain ) {
if ( part - > bindMaster ! = this ) {
continue ;
}
if ( part - > GetPhysics ( ) - > IsType ( idPhysics_Parametric : : Type ) ) {
if ( static_cast < idPhysics_Parametric * > ( part - > GetPhysics ( ) ) - > IsPusher ( ) ) {
gameLocal . Warning ( " teleported '%s' which has the pushing mover '%s' bound to it \n " , GetName ( ) , part - > GetName ( ) ) ;
}
} else if ( part - > GetPhysics ( ) - > IsType ( idPhysics_AF : : Type ) ) {
gameLocal . Warning ( " teleported '%s' which has the articulated figure '%s' bound to it \n " , GetName ( ) , part - > GetName ( ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_UpdateCameraTarget
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_UpdateCameraTarget ( void ) {
const char * target ;
const idKeyValue * kv ;
idVec3 dir ;
target = spawnArgs . GetString ( " cameraTarget " ) ;
cameraTarget = gameLocal . FindEntity ( target ) ;
if ( cameraTarget ) {
kv = cameraTarget - > spawnArgs . MatchPrefix ( " target " , NULL ) ;
while ( kv ) {
idEntity * ent = gameLocal . FindEntity ( kv - > GetValue ( ) ) ;
if ( ent & & idStr : : Icmp ( ent - > GetEntityDefName ( ) , " target_null " ) = = 0 ) {
dir = ent - > GetPhysics ( ) - > GetOrigin ( ) - cameraTarget - > GetPhysics ( ) - > GetOrigin ( ) ;
dir . Normalize ( ) ;
cameraTarget - > SetAxis ( dir . ToMat3 ( ) ) ;
SetAxis ( dir . ToMat3 ( ) ) ;
2011-12-06 18:20:15 +00:00
break ;
2011-11-22 21:28:15 +00:00
}
kv = cameraTarget - > spawnArgs . MatchPrefix ( " target " , kv ) ;
}
}
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_DistanceTo
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_DistanceTo ( idEntity * ent ) {
if ( ! ent ) {
// just say it's really far away
idThread : : ReturnFloat ( MAX_WORLD_SIZE ) ;
} else {
float dist = ( GetPhysics ( ) - > GetOrigin ( ) - ent - > GetPhysics ( ) - > GetOrigin ( ) ) . LengthFast ( ) ;
idThread : : ReturnFloat ( dist ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_DistanceToPoint
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_DistanceToPoint ( const idVec3 & point ) {
float dist = ( GetPhysics ( ) - > GetOrigin ( ) - point ) . LengthFast ( ) ;
idThread : : ReturnFloat ( dist ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_StartFx
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_StartFx ( const char * fx ) {
idEntityFx : : StartFx ( fx , NULL , NULL , this , true ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_WaitFrame
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_WaitFrame ( void ) {
idThread * thread ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
thread = idThread : : CurrentThread ( ) ;
if ( thread ) {
thread - > WaitFrame ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_Wait
= = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : Event_Wait ( float time ) {
idThread * thread = idThread : : CurrentThread ( ) ;
if ( ! thread ) {
gameLocal . Error ( " Event 'wait' called from outside thread " ) ;
}
thread - > WaitSec ( time ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_HasFunction
= = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : Event_HasFunction ( const char * name ) {
const function_t * func ;
func = scriptObject . GetFunction ( name ) ;
if ( func ) {
idThread : : ReturnInt ( true ) ;
} else {
idThread : : ReturnInt ( false ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_CallFunction
= = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : Event_CallFunction ( const char * funcname ) {
const function_t * func ;
idThread * thread ;
thread = idThread : : CurrentThread ( ) ;
if ( ! thread ) {
gameLocal . Error ( " Event 'callFunction' called from outside thread " ) ;
}
func = scriptObject . GetFunction ( funcname ) ;
if ( ! func ) {
gameLocal . Error ( " Unknown function '%s' in '%s' " , funcname , scriptObject . GetTypeName ( ) ) ;
}
if ( func - > type - > NumParameters ( ) ! = 1 ) {
gameLocal . Error ( " Function '%s' has the wrong number of parameters for 'callFunction' " , funcname ) ;
}
if ( ! scriptObject . GetTypeDef ( ) - > Inherits ( func - > type - > GetParmType ( 0 ) ) ) {
gameLocal . Error ( " Function '%s' is the wrong type for 'callFunction' " , funcname ) ;
}
// function args will be invalid after this call
thread - > CallFunction ( this , func , false ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_SetNeverDormant
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_SetNeverDormant ( int enable ) {
fl . neverDormant = ( enable ! = 0 ) ;
dormantStart = 0 ;
}
2018-08-27 13:13:17 +00:00
//Ivan start
void idEntity : : Event_GetGuiParm ( int guiNum , const char * key ) {
if ( renderEntity . gui [ guiNum - 1 ] ) {
idThread : : ReturnString ( renderEntity . gui [ guiNum - 1 ] - > GetStateString ( key ) ) ;
return ;
}
idThread : : ReturnString ( " " ) ;
}
void idEntity : : Event_GetGuiParmFloat ( int guiNum , const char * key ) {
if ( renderEntity . gui [ guiNum - 1 ] ) {
idThread : : ReturnFloat ( renderEntity . gui [ guiNum - 1 ] - > GetStateFloat ( key ) ) ;
return ;
}
idThread : : ReturnFloat ( 0.0f ) ;
}
void idEntity : : Event_GuiNamedEvent ( int guiNum , const char * event ) {
if ( renderEntity . gui [ guiNum - 1 ] ) {
renderEntity . gui [ guiNum - 1 ] - > HandleNamedEvent ( event ) ;
}
}
void idEntity : : Event_SetEntityHealth ( float newHealth ) {
health = newHealth ;
}
void idEntity : : Event_GetEntityHealth ( void ) {
idThread : : ReturnFloat ( health ) ;
}
//Ivan end
2011-11-22 21:28:15 +00:00
/***********************************************************************
Network
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idEntity : : ClientPredictionThink
= = = = = = = = = = = = = = = =
*/
void idEntity : : ClientPredictionThink ( void ) {
RunPhysics ( ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteBindToSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : WriteBindToSnapshot ( idBitMsgDelta & msg ) const {
int bindInfo ;
if ( bindMaster ) {
bindInfo = bindMaster - > entityNumber ;
bindInfo | = ( fl . bindOrientated & 1 ) < < GENTITYNUM_BITS ;
if ( bindJoint ! = INVALID_JOINT ) {
bindInfo | = 1 < < ( GENTITYNUM_BITS + 1 ) ;
bindInfo | = bindJoint < < ( 3 + GENTITYNUM_BITS ) ;
} else if ( bindBody ! = - 1 ) {
bindInfo | = 2 < < ( GENTITYNUM_BITS + 1 ) ;
bindInfo | = bindBody < < ( 3 + GENTITYNUM_BITS ) ;
}
} else {
bindInfo = ENTITYNUM_NONE ;
}
msg . WriteBits ( bindInfo , GENTITYNUM_BITS + 3 + 9 ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadBindFromSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : ReadBindFromSnapshot ( const idBitMsgDelta & msg ) {
int bindInfo , bindEntityNum , bindPos ;
bool bindOrientated ;
idEntity * master ;
bindInfo = msg . ReadBits ( GENTITYNUM_BITS + 3 + 9 ) ;
bindEntityNum = bindInfo & ( ( 1 < < GENTITYNUM_BITS ) - 1 ) ;
if ( bindEntityNum ! = ENTITYNUM_NONE ) {
master = gameLocal . entities [ bindEntityNum ] ;
bindOrientated = ( bindInfo > > GENTITYNUM_BITS ) & 1 ;
bindPos = ( bindInfo > > ( GENTITYNUM_BITS + 3 ) ) ;
switch ( ( bindInfo > > ( GENTITYNUM_BITS + 1 ) ) & 3 ) {
case 1 : {
BindToJoint ( master , ( jointHandle_t ) bindPos , bindOrientated ) ;
break ;
}
case 2 : {
BindToBody ( master , bindPos , bindOrientated ) ;
break ;
}
default : {
Bind ( master , bindOrientated ) ;
break ;
}
}
} else if ( bindMaster ) {
Unbind ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteColorToSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : WriteColorToSnapshot ( idBitMsgDelta & msg ) const {
idVec4 color ;
color [ 0 ] = renderEntity . shaderParms [ SHADERPARM_RED ] ;
color [ 1 ] = renderEntity . shaderParms [ SHADERPARM_GREEN ] ;
color [ 2 ] = renderEntity . shaderParms [ SHADERPARM_BLUE ] ;
color [ 3 ] = renderEntity . shaderParms [ SHADERPARM_ALPHA ] ;
2012-06-28 11:15:40 +00:00
msg . WriteInt ( PackColor ( color ) ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadColorFromSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : ReadColorFromSnapshot ( const idBitMsgDelta & msg ) {
idVec4 color ;
2012-06-28 11:19:14 +00:00
UnpackColor ( msg . ReadInt ( ) , color ) ;
2011-11-22 21:28:15 +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 ] ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteGUIToSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : WriteGUIToSnapshot ( idBitMsgDelta & msg ) const {
// no need to loop over MAX_RENDERENTITY_GUI at this time
if ( renderEntity . gui [ 0 ] ) {
msg . WriteByte ( renderEntity . gui [ 0 ] - > State ( ) . GetInt ( " networkState " ) ) ;
} else {
msg . WriteByte ( 0 ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadGUIFromSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : ReadGUIFromSnapshot ( const idBitMsgDelta & msg ) {
int state ;
idUserInterface * gui ;
state = msg . ReadByte ( ) ;
gui = renderEntity . gui [ 0 ] ;
if ( gui & & state ! = mpGUIState ) {
mpGUIState = state ;
gui - > SetStateInt ( " networkState " , state ) ;
gui - > HandleNamedEvent ( " networkState " ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : WriteToSnapshot ( idBitMsgDelta & msg ) const {
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
void idEntity : : ReadFromSnapshot ( const idBitMsgDelta & msg ) {
}
/*
= = = = = = = = = = = = = = = =
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 .
= = = = = = = = = = = = = = = =
*/
void idEntity : : ServerSendEvent ( int eventId , const idBitMsg * msg , bool saveEvent , int excludeClient ) const {
idBitMsg outMsg ;
byte msgBuf [ MAX_GAME_MESSAGE_SIZE ] ;
if ( ! gameLocal . isServer ) {
return ;
}
// prevent dupe events caused by frame re-runs
if ( ! gameLocal . isNewFrame ) {
return ;
}
outMsg . Init ( msgBuf , sizeof ( msgBuf ) ) ;
outMsg . BeginWriting ( ) ;
2011-12-06 18:20:15 +00:00
outMsg . WriteByte ( GAME_RELIABLE_MESSAGE_EVENT ) ;
2011-11-22 21:28:15 +00:00
outMsg . WriteBits ( gameLocal . GetSpawnId ( this ) , 32 ) ;
outMsg . WriteByte ( eventId ) ;
2012-06-28 11:15:40 +00:00
outMsg . WriteInt ( gameLocal . time ) ;
2011-11-22 21:28:15 +00:00
if ( msg ) {
outMsg . WriteBits ( msg - > GetSize ( ) , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
outMsg . WriteData ( msg - > GetData ( ) , msg - > GetSize ( ) ) ;
} else {
outMsg . WriteBits ( 0 , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
}
if ( excludeClient ! = - 1 ) {
networkSystem - > ServerSendReliableMessageExcluding ( excludeClient , outMsg ) ;
} else {
networkSystem - > ServerSendReliableMessage ( - 1 , outMsg ) ;
}
if ( saveEvent ) {
gameLocal . SaveEntityNetworkEvent ( this , eventId , msg ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClientSendEvent
= = = = = = = = = = = = = = = =
*/
void idEntity : : ClientSendEvent ( int eventId , const idBitMsg * msg ) const {
idBitMsg outMsg ;
byte msgBuf [ MAX_GAME_MESSAGE_SIZE ] ;
if ( ! gameLocal . isClient ) {
return ;
}
// prevent dupe events caused by frame re-runs
if ( ! gameLocal . isNewFrame ) {
return ;
}
outMsg . Init ( msgBuf , sizeof ( msgBuf ) ) ;
outMsg . BeginWriting ( ) ;
outMsg . WriteByte ( GAME_RELIABLE_MESSAGE_EVENT ) ;
outMsg . WriteBits ( gameLocal . GetSpawnId ( this ) , 32 ) ;
outMsg . WriteByte ( eventId ) ;
2012-06-28 11:15:40 +00:00
outMsg . WriteInt ( gameLocal . time ) ;
2011-11-22 21:28:15 +00:00
if ( msg ) {
outMsg . WriteBits ( msg - > GetSize ( ) , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
outMsg . WriteData ( msg - > GetData ( ) , msg - > GetSize ( ) ) ;
} else {
outMsg . WriteBits ( 0 , idMath : : BitsForInteger ( MAX_EVENT_PARAM_SIZE ) ) ;
}
networkSystem - > ClientSendReliableMessage ( outMsg ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ServerReceiveEvent
= = = = = = = = = = = = = = = =
*/
bool idEntity : : ServerReceiveEvent ( int event , int time , const idBitMsg & msg ) {
switch ( event ) {
case 0 : {
}
default : {
return false ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
bool idEntity : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg ) {
int index ;
const idSoundShader * shader ;
s_channelType channel ;
switch ( event ) {
case EVENT_STARTSOUNDSHADER : {
// the sound stuff would early out
assert ( gameLocal . isNewFrame ) ;
if ( time < gameLocal . realClientTime - 1000 ) {
// 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 ;
}
2012-06-28 11:19:14 +00:00
index = gameLocal . ClientRemapDecl ( DECL_SOUND , msg . ReadInt ( ) ) ;
2011-11-22 21:28:15 +00:00
if ( index > = 0 & & index < declManager - > GetNumDecls ( DECL_SOUND ) ) {
shader = declManager - > SoundByIndex ( index , false ) ;
channel = ( s_channelType ) msg . ReadByte ( ) ;
StartSoundShader ( shader , channel , 0 , false , NULL ) ;
}
return true ;
}
case EVENT_STOPSOUNDSHADER : {
// the sound stuff would early out
assert ( gameLocal . isNewFrame ) ;
channel = ( s_channelType ) msg . ReadByte ( ) ;
StopSound ( channel , false ) ;
return true ;
}
2012-01-15 12:39:23 +00:00
default :
break ;
2011-11-22 21:28:15 +00:00
}
2012-01-15 12:39:23 +00:00
2011-11-22 21:28:15 +00:00
return false ;
}
2018-08-27 13:13:17 +00:00
//rev grab
/*
= = = = = = = = = = = = = = = =
idEntity : : SetGrabbedState
= = = = = = = = = = = = = = = =
*/
void idEntity : : SetGrabbedState ( bool grabbed ) {
fl . grabbed = grabbed ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : IsGrabbed
= = = = = = = = = = = = = = = =
*/
bool idEntity : : IsGrabbed ( ) {
return fl . grabbed ;
}
//rev grab
//ivan start - just copied from ff1.1
/*
= = = = = = = = = = = = = = = =
idEntity : : CommonFireProjectile
= = = = = = = = = = = = = = = =
*/
idProjectile * idEntity : : CommonFireProjectile ( const char * projDefName , const idVec3 & firePos , const idVec3 & dir ) {
idProjectile * proj ;
idEntity * ent ;
idDict projectileDict ;
if ( gameLocal . isClient ) { return NULL ; }
const idDeclEntityDef * projectileDef = gameLocal . FindEntityDef ( projDefName , false ) ;
if ( ! projectileDef ) {
gameLocal . Warning ( " No def '%s' found " , projDefName ) ;
return NULL ;
}
projectileDict = projectileDef - > dict ;
if ( ! projectileDict . GetNumKeyVals ( ) ) {
gameLocal . Warning ( " No projectile defined '%s' " , projDefName ) ;
return NULL ;
}
if ( IsType ( idPlayer : : Type ) ) {
static_cast < idPlayer * > ( this ) - > AddProjectilesFired ( 1 ) ;
gameLocal . AlertAI ( this ) ;
}
gameLocal . SpawnEntityDef ( projectileDict , & ent , false ) ;
if ( ! ent | | ! ent - > IsType ( idProjectile : : Type ) ) {
gameLocal . Error ( " '%s' is not an idProjectile " , projDefName ) ;
}
if ( projectileDict . GetBool ( " net_instanthit " ) ) {
ent - > fl . networkSync = false ;
}
proj = static_cast < idProjectile * > ( ent ) ;
proj - > Create ( this , firePos , dir ) ;
proj - > Launch ( firePos , dir , vec3_origin ) ;
return proj ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : CommonGetAimDir
= = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : CommonGetAimDir ( const idVec3 & firePos , idEntity * aimAtEnt , idVec3 & aimDir ) {
idVec3 mainTargetPos ;
idVec3 secTargetPos ; //not used, but necessary
if ( aimAtEnt ) { //target entity ok!
if ( aimAtEnt - > IsType ( idPlayer : : Type ) ) { //player - head
static_cast < idPlayer * > ( aimAtEnt ) - > GetAIAimTargets ( aimAtEnt - > GetPhysics ( ) - > GetOrigin ( ) , mainTargetPos , secTargetPos ) ;
} else if ( aimAtEnt - > IsType ( idActor : : Type ) ) { //AI - chest
static_cast < idActor * > ( aimAtEnt ) - > GetAIAimTargets ( aimAtEnt - > GetPhysics ( ) - > GetOrigin ( ) , secTargetPos , mainTargetPos ) ;
} else { //center
mainTargetPos = aimAtEnt - > GetPhysics ( ) - > GetAbsBounds ( ) . GetCenter ( ) ;
}
aimDir = mainTargetPos - firePos ;
aimDir . Normalize ( ) ;
} else { //no valid aimAtEnt entity!
if ( IsType ( idPlayer : : Type ) ) { //player - view
static_cast < idPlayer * > ( this ) - > viewAngles . ToVectors ( & aimDir , NULL , NULL ) ;
} else if ( IsType ( idActor : : Type ) ) { //AI - axis
aimDir = static_cast < idActor * > ( this ) - > viewAxis [ 0 ] ;
} else {
aimDir = GetPhysics ( ) - > GetAxis ( ) [ 0 ] ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_FireProjectile
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_FireProjectile ( const char * projDefName , const idVec3 & firePos , const idAngles & fireAng ) {
idProjectile * proj ;
idVec3 dir ;
dir = fireAng . ToForward ( ) ;
proj = CommonFireProjectile ( projDefName , firePos , dir ) ;
idThread : : ReturnEntity ( proj ) ;
}
/*
= = = = = = = = = = = = = = = =
idEntity : : Event_FireProjAtTarget
= = = = = = = = = = = = = = = =
*/
void idEntity : : Event_FireProjAtTarget ( const char * projDefName , const idVec3 & firePos , idEntity * aimAtEnt ) {
idProjectile * proj ;
idVec3 dir ;
CommonGetAimDir ( firePos , aimAtEnt , dir ) ;
proj = CommonFireProjectile ( projDefName , firePos , dir ) ;
idThread : : ReturnEntity ( proj ) ;
}
//ivan end
//ivan start
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_GetClosestTargetTypePrefix
= = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetClosestTargetTypePrefix ( const char * typePrefix , const char * ignoreType ) {
int i ;
float dist ;
float bestDist ;
int prefixLenght ;
int ignoreLenght ;
idEntity * ent ;
idEntity * bestEnt ;
prefixLenght = idStr : : Length ( typePrefix ) ;
ignoreLenght = idStr : : Length ( ignoreType ) ;
bestDist = idMath : : INFINITY ;
bestEnt = NULL ;
for ( i = 0 ; i < targets . Num ( ) ; i + + ) {
ent = targets [ i ] . GetEntity ( ) ;
if ( ent ) {
if ( ( ignoreLenght > 0 ) & & ( idStr : : Cmp ( ent - > GetEntityDefName ( ) , ignoreType ) = = 0 ) ) {
continue ;
}
if ( idStr : : Cmpn ( ent - > GetEntityDefName ( ) , typePrefix , prefixLenght ) = = 0 ) {
dist = ( GetPhysics ( ) - > GetOrigin ( ) - ent - > GetPhysics ( ) - > GetOrigin ( ) ) . LengthFast ( ) ;
if ( dist < bestDist ) {
bestDist = dist ;
bestEnt = ent ;
}
}
}
}
idThread : : ReturnEntity ( bestEnt ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idEntity : : Event_GetRandomTargetTypePrefix
= = = = = = = = = = = = = = = = = = = = =
*/
void idEntity : : Event_GetRandomTargetTypePrefix ( const char * typePrefix , const char * ignoreType ) {
int i ;
int num ;
int which ;
int prefixLenght ;
int ignoreLenght ;
idEntity * ent ;
idEntity * ents [ MAX_GENTITIES ] ;
prefixLenght = idStr : : Length ( typePrefix ) ;
ignoreLenght = idStr : : Length ( ignoreType ) ;
num = 0 ;
for ( i = 0 ; i < targets . Num ( ) ; i + + ) {
ent = targets [ i ] . GetEntity ( ) ;
if ( ent ) {
if ( ( ignoreLenght > 0 ) & & ( idStr : : Cmp ( ent - > GetEntityDefName ( ) , ignoreType ) = = 0 ) ) {
continue ;
}
if ( idStr : : Cmpn ( ent - > GetEntityDefName ( ) , typePrefix , prefixLenght ) = = 0 ) {
ents [ num + + ] = ent ;
if ( num > = MAX_GENTITIES ) {
break ;
}
}
}
}
if ( ! num ) {
idThread : : ReturnEntity ( NULL ) ;
return ;
}
which = gameLocal . random . RandomInt ( num ) ;
idThread : : ReturnEntity ( ents [ which ] ) ;
}
//ivan end
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
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 ' ) ;
2018-08-27 13:13:17 +00:00
//ivan start
const idEventDef EV_FireProjectileFromJoint ( " fireProjectileFromJoint " , " sdv " , ' e ' ) ;
const idEventDef EV_FireProjAtTargetFromJoint ( " fireProjAtTargetFromJoint " , " sdE " , ' e ' ) ; //E = NULL ok too
//ivan end
2011-11-22 21:28:15 +00:00
CLASS_DECLARATION ( idEntity , idAnimatedEntity )
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 )
2018-08-27 13:13:17 +00:00
//ivan start
EVENT ( EV_FireProjectileFromJoint , idAnimatedEntity : : Event_FireProjectileFromJoint )
EVENT ( EV_FireProjAtTargetFromJoint , idAnimatedEntity : : Event_FireProjAtTargetFromJoint )
//ivan end
2011-11-22 21:28:15 +00:00
END_CLASS
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : idAnimatedEntity
= = = = = = = = = = = = = = = =
*/
idAnimatedEntity : : idAnimatedEntity ( ) {
animator . SetEntity ( this ) ;
damageEffects = NULL ;
2018-08-27 13:13:17 +00:00
nextBloodPoolTime = 0 ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : ~ idAnimatedEntity
= = = = = = = = = = = = = = = =
*/
idAnimatedEntity : : ~ idAnimatedEntity ( ) {
damageEffect_t * de ;
for ( de = damageEffects ; de ; de = damageEffects ) {
damageEffects = de - > next ;
delete de ;
}
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Save
archives object for save game file
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Save ( idSaveGame * savefile ) const {
animator . Save ( savefile ) ;
// Wounds are very temporary, ignored at this time
//damageEffect_t *damageEffects;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Restore
unarchives object from save game file
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Restore ( idRestoreGame * savefile ) {
animator . Restore ( savefile ) ;
// check if the entity has an MD5 model
if ( animator . ModelHandle ( ) ) {
// set the callback to update the joints
renderEntity . callback = idEntity : : ModelCallback ;
animator . GetJoints ( & renderEntity . numJoints , & renderEntity . joints ) ;
animator . GetBounds ( gameLocal . time , renderEntity . bounds ) ;
if ( modelDefHandle ! = - 1 ) {
gameRenderWorld - > UpdateEntityDef ( modelDefHandle , & renderEntity ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : ClientPredictionThink
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : ClientPredictionThink ( void ) {
RunPhysics ( ) ;
UpdateAnimation ( ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Think
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Think ( void ) {
RunPhysics ( ) ;
UpdateAnimation ( ) ;
Present ( ) ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
if ( thinkFlags & TH_UPDATEWOUNDPARTICLES )
# endif
UpdateDamageEffects ( ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : UpdateAnimation
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : UpdateAnimation ( void ) {
// don't do animations if they're not enabled
if ( ! ( thinkFlags & TH_ANIMATE ) ) {
return ;
}
// is the model an MD5?
if ( ! animator . ModelHandle ( ) ) {
// no, so nothing to do
return ;
}
// call any frame commands that have happened in the past frame
if ( ! fl . hidden ) {
animator . ServiceAnims ( gameLocal . previousTime , gameLocal . time ) ;
}
// if the model is animating then we have to update it
if ( ! animator . FrameHasChanged ( gameLocal . time ) ) {
// still fine the way it was
return ;
}
// get the latest frame bounds
animator . GetBounds ( gameLocal . time , renderEntity . bounds ) ;
if ( renderEntity . bounds . IsCleared ( ) & & ! fl . hidden ) {
gameLocal . DPrintf ( " %d: inside out bounds \n " , gameLocal . time ) ;
}
// update the renderEntity
UpdateVisuals ( ) ;
// the animation is updated
animator . ClearForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : GetAnimator
= = = = = = = = = = = = = = = =
*/
idAnimator * idAnimatedEntity : : GetAnimator ( void ) {
return & animator ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : SetModel
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : SetModel ( const char * modelname ) {
FreeModelDef ( ) ;
renderEntity . hModel = animator . SetModel ( modelname ) ;
if ( ! renderEntity . hModel ) {
idEntity : : SetModel ( modelname ) ;
return ;
}
if ( ! renderEntity . customSkin ) {
renderEntity . customSkin = animator . ModelDef ( ) - > GetDefaultSkin ( ) ;
}
// set the callback to update the joints
renderEntity . callback = idEntity : : ModelCallback ;
animator . GetJoints ( & renderEntity . numJoints , & renderEntity . joints ) ;
animator . GetBounds ( gameLocal . time , renderEntity . bounds ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimatedEntity : : GetJointWorldTransform
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimatedEntity : : GetJointWorldTransform ( jointHandle_t jointHandle , int currentTime , idVec3 & offset , idMat3 & axis ) {
if ( ! animator . GetJointTransform ( jointHandle , currentTime , offset , axis ) ) {
return false ;
}
ConvertLocalToWorldTransform ( offset , axis ) ;
return true ;
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : GetJointTransformForAnim
= = = = = = = = = = = = = =
*/
bool idAnimatedEntity : : GetJointTransformForAnim ( jointHandle_t jointHandle , int animNum , int frameTime , idVec3 & offset , idMat3 & axis ) const {
const idAnim * anim ;
int numJoints ;
idJointMat * frame ;
anim = animator . GetAnim ( animNum ) ;
if ( ! anim ) {
assert ( 0 ) ;
return false ;
}
numJoints = animator . NumJoints ( ) ;
if ( ( jointHandle < 0 ) | | ( jointHandle > = numJoints ) ) {
assert ( 0 ) ;
return false ;
}
frame = ( idJointMat * ) _alloca16 ( numJoints * sizeof ( idJointMat ) ) ;
gameEdit - > ANIM_CreateAnimFrame ( animator . ModelHandle ( ) , anim - > MD5Anim ( 0 ) , renderEntity . numJoints , frame , frameTime , animator . ModelDef ( ) - > GetVisualOffset ( ) , animator . RemoveOrigin ( ) ) ;
offset = frame [ jointHandle ] . ToVec3 ( ) ;
axis = frame [ jointHandle ] . ToMat3 ( ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return true ;
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : AddDamageEffect
Dammage effects track the animating impact position , spitting out particles .
= = = = = = = = = = = = = =
*/
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD
void idAnimatedEntity : : AddDamageEffect ( const trace_t & collision , const idVec3 & velocity , const char * damageDefName , idEntity * soundEnt = NULL ) {
# else
2011-11-22 21:28:15 +00:00
void idAnimatedEntity : : AddDamageEffect ( const trace_t & collision , const idVec3 & velocity , const char * damageDefName ) {
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
jointHandle_t jointNum ;
2018-08-27 13:13:17 +00:00
idVec3 dir ;
2011-11-22 21:28:15 +00:00
if ( ! g_bloodEffects . GetBool ( ) | | renderEntity . joints = = NULL ) {
return ;
}
const idDeclEntityDef * def = gameLocal . FindEntityDef ( damageDefName , false ) ;
if ( def = = NULL ) {
return ;
}
jointNum = CLIPMODEL_ID_TO_JOINT_HANDLE ( collision . c . id ) ;
if ( jointNum = = INVALID_JOINT ) {
return ;
}
dir = velocity ;
dir . Normalize ( ) ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
AddLocalDamageEffect ( jointNum , collision . c . point , collision . c . normal , dir , def , collision . c . material , soundEnt ) ;
# else
idVec3 origin , localDir , localOrigin , localNormal ;
idMat3 axis ;
2011-11-22 21:28:15 +00:00
axis = renderEntity . joints [ jointNum ] . ToMat3 ( ) * renderEntity . axis ;
origin = renderEntity . origin + renderEntity . joints [ jointNum ] . ToVec3 ( ) * renderEntity . axis ;
localOrigin = ( collision . c . point - origin ) * axis . Transpose ( ) ;
localNormal = collision . c . normal * axis . Transpose ( ) ;
localDir = dir * axis . Transpose ( ) ;
AddLocalDamageEffect ( jointNum , localOrigin , localNormal , localDir , def , collision . c . material ) ;
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
if ( gameLocal . isServer ) {
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
msg . Init ( msgBuf , sizeof ( msgBuf ) ) ;
msg . BeginWriting ( ) ;
msg . WriteShort ( ( int ) jointNum ) ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
msg . WriteFloat ( collision . c . point [ 0 ] ) ;
msg . WriteFloat ( collision . c . point [ 1 ] ) ;
msg . WriteFloat ( collision . c . point [ 2 ] ) ;
msg . WriteDir ( collision . c . normal , 24 ) ;
msg . WriteDir ( dir , 24 ) ;
# else
2011-11-22 21:28:15 +00:00
msg . WriteFloat ( localOrigin [ 0 ] ) ;
msg . WriteFloat ( localOrigin [ 1 ] ) ;
msg . WriteFloat ( localOrigin [ 2 ] ) ;
msg . WriteDir ( localNormal , 24 ) ;
msg . WriteDir ( localDir , 24 ) ;
2018-08-27 13:13:17 +00:00
# endif
2012-06-28 11:15:40 +00:00
msg . WriteInt ( gameLocal . ServerRemapDecl ( - 1 , DECL_ENTITYDEF , def - > Index ( ) ) ) ;
msg . WriteInt ( gameLocal . ServerRemapDecl ( - 1 , DECL_MATERIAL , collision . c . material - > Index ( ) ) ) ;
2011-11-22 21:28:15 +00:00
ServerSendEvent ( EVENT_ADD_DAMAGE_EFFECT , & msg , false , - 1 ) ;
}
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : GetDefaultSurfaceType
= = = = = = = = = = = = = =
*/
int idAnimatedEntity : : GetDefaultSurfaceType ( void ) const {
return SURFTYPE_METAL ;
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : AddLocalDamageEffect
= = = = = = = = = = = = = =
*/
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
void idAnimatedEntity : : AddLocalDamageEffect ( jointHandle_t jointNum , const idVec3 & origin , const idVec3 & normal , const idVec3 & dir , const idDeclEntityDef * def , const idMaterial * collisionMaterial , idEntity * soundEnt ) {
# else
2011-11-22 21:28:15 +00:00
void idAnimatedEntity : : AddLocalDamageEffect ( jointHandle_t jointNum , const idVec3 & localOrigin , const idVec3 & localNormal , const idVec3 & localDir , const idDeclEntityDef * def , const idMaterial * collisionMaterial ) {
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
const char * sound , * splat , * decal , * bleed , * key ;
damageEffect_t * de ;
2018-08-27 13:13:17 +00:00
idVec3 gravDir ;
idPhysics * phys ;
2011-11-22 21:28:15 +00:00
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
# else
idMat3 axis ;
idVec3 origin , dir ;
2011-11-22 21:28:15 +00:00
axis = renderEntity . joints [ jointNum ] . ToMat3 ( ) * renderEntity . axis ;
origin = renderEntity . origin + renderEntity . joints [ jointNum ] . ToVec3 ( ) * renderEntity . axis ;
origin = origin + localOrigin * axis ;
dir = localDir * axis ;
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
int type = collisionMaterial - > GetSurfaceType ( ) ;
if ( type = = SURFTYPE_NONE ) {
type = GetDefaultSurfaceType ( ) ;
}
const char * materialType = gameLocal . sufaceTypeNames [ type ] ;
// start impact sound based on material type
key = va ( " snd_%s " , materialType ) ;
sound = spawnArgs . GetString ( key ) ;
if ( * sound = = ' \0 ' ) {
sound = def - > dict . GetString ( key ) ;
}
2018-08-27 13:13:17 +00:00
if ( * sound = = ' \0 ' ) {
sound = def - > dict . GetString ( " snd_metal " ) ; // default sound 1
}
if ( * sound = = ' \0 ' ) {
sound = def - > dict . GetString ( " snd_impact " ) ; // default sound 2
}
2011-11-22 21:28:15 +00:00
if ( * sound ! = ' \0 ' ) {
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD
if ( soundEnt = = NULL ) {
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
else {
soundEnt - > StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
# else
2011-11-22 21:28:15 +00:00
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
}
// blood splats are thrown onto nearby surfaces
key = va ( " mtr_splat_%s " , materialType ) ;
splat = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
if ( * splat = = ' \0 ' ) {
splat = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
if ( * splat ! = ' \0 ' ) {
gameLocal . BloodSplat ( origin , dir , 64.0f , splat ) ;
}
2018-08-27 13:13:17 +00:00
// Create blood pools at feet, Only when alive - By Clone JCD
if ( health > 0 ) {
int bloodpoolTime ;
if ( gameLocal . time > nextBloodPoolTime ) { // You can use this condition instead :- if (gameLocal.isNewFrame)
key = va ( " mtr_bloodPool_%s " , materialType ) ;
splat = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
if ( * splat = = ' \0 ' ) {
splat = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
if ( * splat ! = ' \0 ' ) {
phys = GetPhysics ( ) ;
gravDir = phys - > GetGravity ( ) ;
gravDir . Normalize ( ) ;
if ( spawnArgs . GetBool ( " bloodPool_below_origin " ) ) {
gameLocal . BloodSplat ( phys - > GetOrigin ( ) , gravDir , def - > dict . GetFloat ( va ( " size_bloodPool_%s " , materialType ) , " 64.0f " ) , splat ) ;
}
else {
gameLocal . BloodSplat ( origin , gravDir , def - > dict . GetFloat ( va ( " size_bloodPool_%s " , materialType ) , " 64.0f " ) , splat ) ;
}
}
// This condition makes sure that we dont spawn overlapping bloodpools in a single frame.
if ( ! spawnArgs . GetInt ( " next_bloodpool_time " , " 050 " , bloodpoolTime ) ) {
bloodpoolTime = def - > dict . GetInt ( " next_bloodpool_time " , " 050 " ) ;
}
nextBloodPoolTime = gameLocal . time + bloodpoolTime ; // This avoids excessive bloodpool overlapping
}
}
2011-11-22 21:28:15 +00:00
// can't see wounds on the player model in single player mode
if ( ! ( IsType ( idPlayer : : Type ) & & ! gameLocal . isMultiplayer ) ) {
2018-08-27 13:13:17 +00:00
// blood splats can be thrown on the body itself two - By Clone JC Denton
key = va ( " mtr_splatSelf_%s " , materialType ) ;
splat = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
if ( * splat = = ' \0 ' ) {
splat = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
if ( * splat ! = ' \0 ' ) {
ProjectOverlay ( origin , dir , def - > dict . GetFloat ( va ( " size_splatSelf_%s " , materialType ) , " 15.0f " ) , splat ) ;
}
2011-11-22 21:28:15 +00:00
// place a wound overlay on the model
2018-08-27 13:13:17 +00:00
if ( g_debugDamage . GetBool ( ) ) {
gameLocal . Printf ( " \n Collision Material Type: %s " , materialType ) ;
gameLocal . Printf ( " \n File: %s " , collisionMaterial - > GetFileName ( ) ) ;
gameLocal . Printf ( " \n material: %s " , collisionMaterial - > ImageName ( ) ) ;
}
2011-11-22 21:28:15 +00:00
key = va ( " mtr_wound_%s " , materialType ) ;
decal = spawnArgs . RandomPrefix ( key , gameLocal . random ) ;
if ( * decal = = ' \0 ' ) {
decal = def - > dict . RandomPrefix ( key , gameLocal . random ) ;
}
2018-08-27 13:13:17 +00:00
if ( * decal = = ' \0 ' ) {
decal = def - > dict . GetString ( " mtr_wound " ) ; // Default decal
}
2011-11-22 21:28:15 +00:00
if ( * decal ! = ' \0 ' ) {
2018-08-27 13:13:17 +00:00
float size ;
if ( ! def - > dict . GetFloat ( va ( " size_wound_%s " , materialType ) , " 6.0 " , size ) ) { // If Material Specific decal size not found, look for default size
size = def - > dict . GetFloat ( " size_wound " , " 6.0 " ) ;
}
ProjectOverlay ( origin , dir , size , decal ) ;
2011-11-22 21:28:15 +00:00
}
}
// a blood spurting wound is added
key = va ( " smoke_wound_%s " , materialType ) ;
bleed = spawnArgs . GetString ( key ) ;
if ( * bleed = = ' \0 ' ) {
bleed = def - > dict . GetString ( key ) ;
2018-08-27 13:13:17 +00:00
if ( * bleed = = ' \0 ' )
bleed = def - > dict . GetString ( " smoke_wound " ) ; // play default smoke
2011-11-22 21:28:15 +00:00
}
2018-08-27 13:13:17 +00:00
2011-11-22 21:28:15 +00:00
if ( * bleed ! = ' \0 ' ) {
2018-08-27 13:13:17 +00:00
2011-11-22 21:28:15 +00:00
de = new damageEffect_t ;
de - > next = this - > damageEffects ;
this - > damageEffects = de ;
de - > jointNum = jointNum ;
de - > type = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , bleed ) ) ;
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
idVec3 boneOrigin ;
idMat3 boneAxis ;
boneAxis = renderEntity . joints [ jointNum ] . ToMat3 ( ) * renderEntity . axis ;
boneOrigin = renderEntity . origin + renderEntity . joints [ jointNum ] . ToVec3 ( ) * renderEntity . axis ;
de - > localOrigin = ( origin - boneOrigin ) * boneAxis . Transpose ( ) ;
de - > localNormal = normal * boneAxis . Transpose ( ) ;
de - > time = - 1 ; // used as flag, notifies UpdateDamageEffects that this effect is just started
if ( ! ( thinkFlags & TH_UPDATEWOUNDPARTICLES ) ) // if flag was not set before set it now
BecomeActive ( TH_UPDATEWOUNDPARTICLES ) ;
# else
de - > localOrigin = localOrigin ;
de - > localNormal = localNormal ;
de - > time = gameLocal . time ;
# endif
2011-11-22 21:28:15 +00:00
}
}
/*
= = = = = = = = = = = = = =
idAnimatedEntity : : UpdateDamageEffects
= = = = = = = = = = = = = =
*/
void idAnimatedEntity : : UpdateDamageEffects ( void ) {
damageEffect_t * de , * * prev ;
2018-08-27 13:13:17 +00:00
2011-11-22 21:28:15 +00:00
// free any that have timed out
prev = & this - > damageEffects ;
while ( * prev ) {
de = * prev ;
if ( de - > time = = 0 ) { // FIXME:SMOKE
* prev = de - > next ;
delete de ;
} else {
prev = & de - > next ;
}
}
if ( ! g_bloodEffects . GetBool ( ) ) {
return ;
}
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
if ( ! this - > damageEffects ) { // If no more particles left...
if ( thinkFlags & TH_UPDATEWOUNDPARTICLES )
BecomeInactive ( TH_UPDATEWOUNDPARTICLES ) ;
return ;
}
# endif
2011-11-22 21:28:15 +00:00
// emit a particle for each bleeding wound
for ( de = this - > damageEffects ; de ; de = de - > next ) {
2018-08-27 13:13:17 +00:00
# ifdef _DENTONMOD_ENTITY_CPP
idVec3 origin , dir ;
idMat3 axis ;
// Sometimes it happens that the original animated model is replace by a particle effect, e.g. on flying lost soul's death.
// In that case we wont be able to find any joints. So a proper check should be made.
if ( renderEntity . numJoints < = 0 ) {
axis = renderEntity . axis ;
origin = renderEntity . origin ;
}
else {
axis = renderEntity . joints [ de - > jointNum ] . ToMat3 ( ) * renderEntity . axis ;
origin = renderEntity . origin + renderEntity . joints [ de - > jointNum ] . ToVec3 ( ) * renderEntity . axis ;
}
origin = origin + de - > localOrigin * axis ;
dir = de - > localNormal * axis ;
if ( de - > time = = - 1 ) { // initialize start time just before passing it to emitSmoke
de - > time = gameLocal . time ;
}
if ( ! gameLocal . smokeParticles - > EmitSmoke ( de - > type , de - > time , gameLocal . random . CRandomFloat ( ) , origin , dir . ToMat3 ( ) ) ) {
# else
2011-11-22 21:28:15 +00:00
idVec3 origin , start ;
idMat3 axis ;
animator . GetJointTransform ( de - > jointNum , gameLocal . time , origin , axis ) ;
axis * = renderEntity . axis ;
origin = renderEntity . origin + origin * renderEntity . axis ;
start = origin + de - > localOrigin * axis ;
2018-08-27 13:13:17 +00:00
2011-11-22 21:28:15 +00:00
if ( ! gameLocal . smokeParticles - > EmitSmoke ( de - > type , de - > time , gameLocal . random . CRandomFloat ( ) , start , axis ) ) {
2018-08-27 13:13:17 +00:00
# endif
2011-11-22 21:28:15 +00:00
de - > time = 0 ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
bool idAnimatedEntity : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg ) {
int damageDefIndex ;
int materialIndex ;
jointHandle_t jointNum ;
idVec3 localOrigin , localNormal , localDir ;
switch ( event ) {
case EVENT_ADD_DAMAGE_EFFECT : {
jointNum = ( jointHandle_t ) msg . ReadShort ( ) ;
localOrigin [ 0 ] = msg . ReadFloat ( ) ;
localOrigin [ 1 ] = msg . ReadFloat ( ) ;
localOrigin [ 2 ] = msg . ReadFloat ( ) ;
localNormal = msg . ReadDir ( 24 ) ;
localDir = msg . ReadDir ( 24 ) ;
2012-06-28 11:19:14 +00:00
damageDefIndex = gameLocal . ClientRemapDecl ( DECL_ENTITYDEF , msg . ReadInt ( ) ) ;
materialIndex = gameLocal . ClientRemapDecl ( DECL_MATERIAL , msg . ReadInt ( ) ) ;
2011-11-22 21:28:15 +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 ) ) ;
AddLocalDamageEffect ( jointNum , localOrigin , localNormal , localDir , damageDef , collisionMaterial ) ;
return true ;
}
2012-01-15 12:39:23 +00:00
default :
break ;
2011-11-22 21:28:15 +00:00
}
2012-01-15 12:39:23 +00:00
return idEntity : : ClientReceiveEvent ( event , time , msg ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_GetJointHandle
looks up the number of the specified joint . returns INVALID_JOINT if the joint is not found .
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_GetJointHandle ( const char * jointname ) {
jointHandle_t joint ;
joint = animator . GetJointHandle ( jointname ) ;
idThread : : ReturnInt ( joint ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_ClearAllJoints
removes any custom transforms on all joints
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_ClearAllJoints ( void ) {
animator . ClearAllJoints ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_ClearJoint
removes any custom transforms on the specified joint
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_ClearJoint ( jointHandle_t jointnum ) {
animator . ClearJoint ( jointnum ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_SetJointPos
modifies the position of the joint based on the transform type
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_SetJointPos ( jointHandle_t jointnum , jointModTransform_t transform_type , const idVec3 & pos ) {
animator . SetJointPos ( jointnum , transform_type , pos ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_SetJointAngle
modifies the orientation of the joint based on the transform type
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_SetJointAngle ( jointHandle_t jointnum , jointModTransform_t transform_type , const idAngles & angles ) {
idMat3 mat ;
mat = angles . ToMat3 ( ) ;
animator . SetJointAxis ( jointnum , transform_type , mat ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_GetJointPos
returns the position of the joint in worldspace
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_GetJointPos ( jointHandle_t jointnum ) {
idVec3 offset ;
idMat3 axis ;
if ( ! GetJointWorldTransform ( jointnum , gameLocal . time , offset , axis ) ) {
gameLocal . Warning ( " Joint # %d out of range on entity '%s' " , jointnum , name . c_str ( ) ) ;
}
idThread : : ReturnVector ( offset ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_GetJointAngle
returns the orientation of the joint in worldspace
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_GetJointAngle ( jointHandle_t jointnum ) {
idVec3 offset ;
idMat3 axis ;
if ( ! GetJointWorldTransform ( jointnum , gameLocal . time , offset , axis ) ) {
gameLocal . Warning ( " Joint # %d out of range on entity '%s' " , jointnum , name . c_str ( ) ) ;
}
idAngles ang = axis . ToAngles ( ) ;
idVec3 vec ( ang [ 0 ] , ang [ 1 ] , ang [ 2 ] ) ;
idThread : : ReturnVector ( vec ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_FireProjectileFromJoint
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_FireProjectileFromJoint ( const char * projDefName , jointHandle_t jointnum , const idAngles & fireAng ) {
idProjectile * proj ;
idVec3 dir ;
idVec3 firePos ;
idMat3 axis ; //useless but needed
if ( ! GetJointWorldTransform ( jointnum , gameLocal . time , firePos , axis ) ) {
gameLocal . Warning ( " Joint # %d out of range on entity '%s' " , jointnum , name . c_str ( ) ) ;
}
dir = fireAng . ToForward ( ) ;
proj = CommonFireProjectile ( projDefName , firePos , dir ) ;
idThread : : ReturnEntity ( proj ) ;
}
/*
= = = = = = = = = = = = = = = =
idAnimatedEntity : : Event_FireProjAtTargetFromJoint
= = = = = = = = = = = = = = = =
*/
void idAnimatedEntity : : Event_FireProjAtTargetFromJoint ( const char * projDefName , jointHandle_t jointnum , idEntity * aimAtEnt ) {
idProjectile * proj ;
idVec3 dir ;
idVec3 firePos ;
idMat3 axis ; //useless but needed
if ( ! GetJointWorldTransform ( jointnum , gameLocal . time , firePos , axis ) ) {
gameLocal . Warning ( " Joint # %d out of range on entity '%s' " , jointnum , name . c_str ( ) ) ;
}
CommonGetAimDir ( firePos , aimAtEnt , dir ) ;
proj = CommonFireProjectile ( projDefName , firePos , dir ) ;
idThread : : ReturnEntity ( proj ) ;
}
//ivan end
//test:
/*
= = = = = = = = = = = = = = = =
idWeapon : : ModelCallback
= = = = = = = = = = = = = = = =
bool idAnimatedEntity : : ModelCallback ( renderEntity_s * renderEntity , const renderView_t * renderView ) {
const idWeapon * ent ;
//gameLocal.Printf("idWeapon::ModelCallback\n");
ent = static_cast < idWeapon * > ( gameLocal . entities [ renderEntity - > entityNum ] ) ;
if ( ! ent ) {
gameLocal . Error ( " idBrittleFracture::ModelCallback: callback with NULL game entity " ) ;
}
return ent - > UpdateRenderEntity ( renderEntity , renderView ) ;
}
bool idAnimatedEntity : : UpdateRenderEntity ( renderEntity_s * renderEntity , const renderView_t * renderView ) const {
int i , j , k , n , msec , numTris ;
float fade ;
dword packedColor ;
srfTriangles_t * tris , * decalTris ;
modelSurface_t surface ;
idDrawVert * v ;
idPlane plane ;
idMat3 tangents ;
//ivan
const idMaterial * material = declManager - > FindMaterial ( " textures/decals/irblend " ) ;
// this may be triggered by a model trace or other non-view related source,
// to which we should look like an empty model
if ( ! renderView ) {
return false ;
}
gameLocal . Printf ( " idAnimatedEntity::UpdateRenderEntity... \n %s \n %s \n %s \n %s \n " ,
spawnArgs . GetString ( " pointL_old " , " 0 0 0 " ) ,
spawnArgs . GetString ( " pointH_old " , " 0 0 0 " ) ,
spawnArgs . GetString ( " pointL_new " , " 0 0 0 " ) ,
spawnArgs . GetString ( " pointH_new " , " 0 0 0 " )
) ;
numTris = 2 ; //1 quadrato = 2 tris
// FIXME: re-use model surfaces
//renderEntity->hModel->InitEmpty( brittleFracture_SnapshotName );
// allocate triangle surfaces for the fractures and decals
tris = renderEntity - > hModel - > AllocSurfaceTriangles ( numTris * 3 , material - > ShouldCreateBackSides ( ) ? numTris * 6 : numTris * 3 ) ;
for ( i = 0 ; i < 1 ; i + + ) { //shards.Num()
//const idVec3 &origin = GetOrigin();
//const idMat3 &axis = GetAxis();
fade = 1.0f ;
if ( shards [ i ] - > droppedTime > = 0 ) {
msec = gameLocal . time - shards [ i ] - > droppedTime - SHARD_FADE_START ;
if ( msec > 0 ) {
fade = 1.0f - ( float ) msec / ( SHARD_ALIVE_TIME - SHARD_FADE_START ) ;
}
}
packedColor = PackColor ( idVec4 ( renderEntity - > shaderParms [ SHADERPARM_RED ] * fade ,
renderEntity - > shaderParms [ SHADERPARM_GREEN ] * fade ,
renderEntity - > shaderParms [ SHADERPARM_BLUE ] * fade ,
fade ) ) ;
packedColor = PackColor ( idVec4 ( 1 , 1 , 1 , 1 ) ) ; //ivan
//was: const idWinding &winding = shards[i]->winding;
//ivan
idFixedWinding winding ;
winding . Clear ( ) ;
winding . AddPoint ( spawnArgs . GetVector ( " pointL_old " , " 0 0 0 " ) ) ;
winding . AddPoint ( spawnArgs . GetVector ( " pointH_old " , " 0 0 0 " ) ) ;
winding . AddPoint ( spawnArgs . GetVector ( " pointL_new " , " 0 0 0 " ) ) ;
winding . AddPoint ( spawnArgs . GetVector ( " pointH_new " , " 0 0 0 " ) ) ;
//ivan end
winding . GetPlane ( plane ) ;
tangents = ( plane . Normal ( ) ) . ToMat3 ( ) ; //was: ( plane.Normal() * axis ).ToMat3();
for ( j = 2 ; j < winding . GetNumPoints ( ) ; j + + ) {
v = & tris - > verts [ tris - > numVerts + + ] ;
v - > Clear ( ) ;
v - > xyz = winding [ 0 ] . ToVec3 ( ) ; //was: origin + winding[0].ToVec3() * axis;
v - > st [ 0 ] = winding [ 0 ] . s ;
v - > st [ 1 ] = winding [ 0 ] . t ;
v - > normal = tangents [ 0 ] ;
v - > tangents [ 0 ] = tangents [ 1 ] ;
v - > tangents [ 1 ] = tangents [ 2 ] ;
v - > SetColor ( packedColor ) ;
v = & tris - > verts [ tris - > numVerts + + ] ;
v - > Clear ( ) ;
v - > xyz = winding [ j - 1 ] . ToVec3 ( ) ; //was: origin + winding[j-1].ToVec3() * axis;
v - > st [ 0 ] = winding [ j - 1 ] . s ;
v - > st [ 1 ] = winding [ j - 1 ] . t ;
v - > normal = tangents [ 0 ] ;
v - > tangents [ 0 ] = tangents [ 1 ] ;
v - > tangents [ 1 ] = tangents [ 2 ] ;
v - > SetColor ( packedColor ) ;
v = & tris - > verts [ tris - > numVerts + + ] ;
v - > Clear ( ) ;
v - > xyz = winding [ j ] . ToVec3 ( ) ; //was: origin + winding[j].ToVec3() * axis;
v - > st [ 0 ] = winding [ j ] . s ;
v - > st [ 1 ] = winding [ j ] . t ;
v - > normal = tangents [ 0 ] ;
v - > tangents [ 0 ] = tangents [ 1 ] ;
v - > tangents [ 1 ] = tangents [ 2 ] ;
v - > SetColor ( packedColor ) ;
tris - > indexes [ tris - > numIndexes + + ] = tris - > numVerts - 3 ;
tris - > indexes [ tris - > numIndexes + + ] = tris - > numVerts - 2 ;
tris - > indexes [ tris - > numIndexes + + ] = tris - > numVerts - 1 ;
if ( material - > ShouldCreateBackSides ( ) ) {
tris - > indexes [ tris - > numIndexes + + ] = tris - > numVerts - 2 ;
tris - > indexes [ tris - > numIndexes + + ] = tris - > numVerts - 3 ;
tris - > indexes [ tris - > numIndexes + + ] = tris - > numVerts - 1 ;
}
}
}
tris - > tangentsCalculated = true ;
SIMDProcessor - > MinMax ( tris - > bounds [ 0 ] , tris - > bounds [ 1 ] , tris - > verts , tris - > numVerts ) ;
memset ( & surface , 0 , sizeof ( surface ) ) ;
surface . shader = material ;
surface . id = 0 ;
surface . geometry = tris ;
renderEntity - > hModel - > AddSurface ( surface ) ;
return true ;
}
*/
//test: