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 "gamesys/SysCvar.h"
# include "script/Script_Thread.h"
# include "Item.h"
# include "Light.h"
# include "Projectile.h"
# include "WorldSpawn.h"
2018-08-27 13:13:36 +00:00
# include "Player.h"
# include "Fx.h"
2011-12-16 22:28:29 +00:00
# include "Actor.h"
2011-11-22 21:28:15 +00:00
/***********************************************************************
idAnimState
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : idAnimState
= = = = = = = = = = = = = = = = = = = = =
*/
idAnimState : : idAnimState ( ) {
self = NULL ;
animator = NULL ;
thread = NULL ;
idleAnim = true ;
disabled = true ;
channel = ANIMCHANNEL_ALL ;
animBlendFrames = 0 ;
lastAnimBlendFrames = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : ~ idAnimState
= = = = = = = = = = = = = = = = = = = = =
*/
idAnimState : : ~ idAnimState ( ) {
delete thread ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : Save
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : Save ( idSaveGame * savefile ) const {
savefile - > WriteObject ( self ) ;
// Save the entity owner of the animator
2018-11-18 05:07:22 +00:00
if ( animator ! = NULL ) // DG: don't crash if it's NULL
savefile - > WriteObject ( animator - > GetEntity ( ) ) ;
else
savefile - > WriteInt ( 0 ) ;
2011-11-22 21:28:15 +00:00
savefile - > WriteObject ( thread ) ;
savefile - > WriteString ( state ) ;
savefile - > WriteInt ( animBlendFrames ) ;
savefile - > WriteInt ( lastAnimBlendFrames ) ;
savefile - > WriteInt ( channel ) ;
savefile - > WriteBool ( idleAnim ) ;
savefile - > WriteBool ( disabled ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : Restore
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : Restore ( idRestoreGame * savefile ) {
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( self ) ) ;
idEntity * animowner ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( animowner ) ) ;
if ( animowner ) {
animator = animowner - > GetAnimator ( ) ;
}
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( thread ) ) ;
savefile - > ReadString ( state ) ;
savefile - > ReadInt ( animBlendFrames ) ;
savefile - > ReadInt ( lastAnimBlendFrames ) ;
savefile - > ReadInt ( channel ) ;
savefile - > ReadBool ( idleAnim ) ;
savefile - > ReadBool ( disabled ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : Init
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : Init ( idActor * owner , idAnimator * _animator , int animchannel ) {
assert ( owner ) ;
assert ( _animator ) ;
self = owner ;
animator = _animator ;
channel = animchannel ;
if ( ! thread ) {
thread = new idThread ( ) ;
thread - > ManualDelete ( ) ;
}
thread - > EndThread ( ) ;
thread - > ManualControl ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : Shutdown
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : Shutdown ( void ) {
delete thread ;
thread = NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : SetState
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : SetState ( const char * statename , int blendFrames ) {
const function_t * func ;
func = self - > scriptObject . GetFunction ( statename ) ;
if ( ! func ) {
assert ( 0 ) ;
gameLocal . Error ( " Can't find function '%s' in object '%s' " , statename , self - > scriptObject . GetTypeName ( ) ) ;
}
state = statename ;
disabled = false ;
animBlendFrames = blendFrames ;
lastAnimBlendFrames = blendFrames ;
thread - > CallFunction ( self , func , true ) ;
animBlendFrames = blendFrames ;
lastAnimBlendFrames = blendFrames ;
disabled = false ;
idleAnim = false ;
if ( ai_debugScript . GetInteger ( ) = = self - > entityNumber ) {
gameLocal . Printf ( " %d: %s: Animstate: %s \n " , gameLocal . time , self - > name . c_str ( ) , state . c_str ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : StopAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : StopAnim ( int frames ) {
animBlendFrames = 0 ;
animator - > Clear ( channel , gameLocal . time , FRAME2MS ( frames ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : PlayAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : PlayAnim ( int anim ) {
if ( anim ) {
animator - > PlayAnim ( channel , anim , gameLocal . time , FRAME2MS ( animBlendFrames ) ) ;
}
animBlendFrames = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : CycleAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : CycleAnim ( int anim ) {
if ( anim ) {
animator - > CycleAnim ( channel , anim , gameLocal . time , FRAME2MS ( animBlendFrames ) ) ;
}
animBlendFrames = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : BecomeIdle
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : BecomeIdle ( void ) {
idleAnim = true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : Disabled
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimState : : Disabled ( void ) const {
return disabled ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : AnimDone
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimState : : AnimDone ( int blendFrames ) const {
int animDoneTime ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
animDoneTime = animator - > CurrentAnim ( channel ) - > GetEndTime ( ) ;
if ( animDoneTime < 0 ) {
// playing a cycle
return false ;
} else if ( animDoneTime - FRAME2MS ( blendFrames ) < = gameLocal . time ) {
return true ;
} else {
return false ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : IsIdle
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimState : : IsIdle ( void ) const {
return disabled | | idleAnim ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : GetAnimFlags
= = = = = = = = = = = = = = = = = = = = =
*/
animFlags_t idAnimState : : GetAnimFlags ( void ) const {
animFlags_t flags ;
memset ( & flags , 0 , sizeof ( flags ) ) ;
if ( ! disabled & & ! AnimDone ( 0 ) ) {
flags = animator - > GetAnimFlags ( animator - > CurrentAnim ( channel ) - > AnimNum ( ) ) ;
}
return flags ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : Enable
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : Enable ( int blendFrames ) {
if ( disabled ) {
disabled = false ;
animBlendFrames = blendFrames ;
lastAnimBlendFrames = blendFrames ;
if ( state . Length ( ) ) {
SetState ( state . c_str ( ) , blendFrames ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : Disable
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimState : : Disable ( void ) {
disabled = true ;
idleAnim = false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimState : : UpdateState
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimState : : UpdateState ( void ) {
if ( disabled ) {
return false ;
}
if ( ai_debugScript . GetInteger ( ) = = self - > entityNumber ) {
thread - > EnableDebugInfo ( ) ;
} else {
thread - > DisableDebugInfo ( ) ;
}
thread - > Execute ( ) ;
return true ;
}
/***********************************************************************
idActor
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const idEventDef AI_EnableEyeFocus ( " enableEyeFocus " ) ;
const idEventDef AI_DisableEyeFocus ( " disableEyeFocus " ) ;
const idEventDef EV_Footstep ( " footstep " ) ;
const idEventDef EV_FootstepLeft ( " leftFoot " ) ;
const idEventDef EV_FootstepRight ( " rightFoot " ) ;
const idEventDef EV_EnableWalkIK ( " EnableWalkIK " ) ;
const idEventDef EV_DisableWalkIK ( " DisableWalkIK " ) ;
const idEventDef EV_EnableLegIK ( " EnableLegIK " , " d " ) ;
const idEventDef EV_DisableLegIK ( " DisableLegIK " , " d " ) ;
const idEventDef AI_StopAnim ( " stopAnim " , " dd " ) ;
const idEventDef AI_PlayAnim ( " playAnim " , " ds " , ' d ' ) ;
const idEventDef AI_PlayCycle ( " playCycle " , " ds " , ' d ' ) ;
const idEventDef AI_IdleAnim ( " idleAnim " , " ds " , ' d ' ) ;
const idEventDef AI_SetSyncedAnimWeight ( " setSyncedAnimWeight " , " ddf " ) ;
const idEventDef AI_SetBlendFrames ( " setBlendFrames " , " dd " ) ;
const idEventDef AI_GetBlendFrames ( " getBlendFrames " , " d " , ' d ' ) ;
const idEventDef AI_AnimState ( " animState " , " dsd " ) ;
const idEventDef AI_GetAnimState ( " getAnimState " , " d " , ' s ' ) ;
const idEventDef AI_InAnimState ( " inAnimState " , " ds " , ' d ' ) ;
const idEventDef AI_FinishAction ( " finishAction " , " s " ) ;
const idEventDef AI_AnimDone ( " animDone " , " dd " , ' d ' ) ;
const idEventDef AI_OverrideAnim ( " overrideAnim " , " d " ) ;
const idEventDef AI_EnableAnim ( " enableAnim " , " dd " ) ;
const idEventDef AI_PreventPain ( " preventPain " , " f " ) ;
const idEventDef AI_DisablePain ( " disablePain " ) ;
const idEventDef AI_EnablePain ( " enablePain " ) ;
const idEventDef AI_GetPainAnim ( " getPainAnim " , NULL , ' s ' ) ;
const idEventDef AI_SetAnimPrefix ( " setAnimPrefix " , " s " ) ;
const idEventDef AI_HasAnim ( " hasAnim " , " ds " , ' f ' ) ;
const idEventDef AI_CheckAnim ( " checkAnim " , " ds " ) ;
const idEventDef AI_ChooseAnim ( " chooseAnim " , " ds " , ' s ' ) ;
const idEventDef AI_AnimLength ( " animLength " , " ds " , ' f ' ) ;
const idEventDef AI_AnimDistance ( " animDistance " , " ds " , ' f ' ) ;
const idEventDef AI_HasEnemies ( " hasEnemies " , NULL , ' d ' ) ;
const idEventDef AI_NextEnemy ( " nextEnemy " , " E " , ' e ' ) ;
const idEventDef AI_ClosestEnemyToPoint ( " closestEnemyToPoint " , " v " , ' e ' ) ;
const idEventDef AI_SetNextState ( " setNextState " , " s " ) ;
const idEventDef AI_SetState ( " setState " , " s " ) ;
const idEventDef AI_GetState ( " getState " , NULL , ' s ' ) ;
const idEventDef AI_GetHead ( " getHead " , NULL , ' e ' ) ;
2018-08-27 13:13:17 +00:00
//ivan start - particles
const idEventDef AI_TriggerFX ( " triggerFX " , " ssdd " ) ; //ivan - dd added
const idEventDef AI_StartEmitter ( " startEmitter " , " sss " , ' e ' ) ;
const idEventDef AI_GetEmitter ( " getEmitter " , " s " , ' e ' ) ;
const idEventDef AI_StopEmitter ( " stopEmitter " , " s " ) ;
//ivan end
2011-11-22 21:28:15 +00:00
CLASS_DECLARATION ( idAFEntity_Gibbable , idActor )
EVENT ( AI_EnableEyeFocus , idActor : : Event_EnableEyeFocus )
EVENT ( AI_DisableEyeFocus , idActor : : Event_DisableEyeFocus )
EVENT ( EV_Footstep , idActor : : Event_Footstep )
EVENT ( EV_FootstepLeft , idActor : : Event_Footstep )
EVENT ( EV_FootstepRight , idActor : : Event_Footstep )
EVENT ( EV_EnableWalkIK , idActor : : Event_EnableWalkIK )
EVENT ( EV_DisableWalkIK , idActor : : Event_DisableWalkIK )
EVENT ( EV_EnableLegIK , idActor : : Event_EnableLegIK )
EVENT ( EV_DisableLegIK , idActor : : Event_DisableLegIK )
EVENT ( AI_PreventPain , idActor : : Event_PreventPain )
EVENT ( AI_DisablePain , idActor : : Event_DisablePain )
EVENT ( AI_EnablePain , idActor : : Event_EnablePain )
EVENT ( AI_GetPainAnim , idActor : : Event_GetPainAnim )
EVENT ( AI_SetAnimPrefix , idActor : : Event_SetAnimPrefix )
EVENT ( AI_StopAnim , idActor : : Event_StopAnim )
EVENT ( AI_PlayAnim , idActor : : Event_PlayAnim )
EVENT ( AI_PlayCycle , idActor : : Event_PlayCycle )
EVENT ( AI_IdleAnim , idActor : : Event_IdleAnim )
EVENT ( AI_SetSyncedAnimWeight , idActor : : Event_SetSyncedAnimWeight )
EVENT ( AI_SetBlendFrames , idActor : : Event_SetBlendFrames )
EVENT ( AI_GetBlendFrames , idActor : : Event_GetBlendFrames )
EVENT ( AI_AnimState , idActor : : Event_AnimState )
EVENT ( AI_GetAnimState , idActor : : Event_GetAnimState )
EVENT ( AI_InAnimState , idActor : : Event_InAnimState )
EVENT ( AI_FinishAction , idActor : : Event_FinishAction )
EVENT ( AI_AnimDone , idActor : : Event_AnimDone )
EVENT ( AI_OverrideAnim , idActor : : Event_OverrideAnim )
EVENT ( AI_EnableAnim , idActor : : Event_EnableAnim )
EVENT ( AI_HasAnim , idActor : : Event_HasAnim )
EVENT ( AI_CheckAnim , idActor : : Event_CheckAnim )
EVENT ( AI_ChooseAnim , idActor : : Event_ChooseAnim )
EVENT ( AI_AnimLength , idActor : : Event_AnimLength )
EVENT ( AI_AnimDistance , idActor : : Event_AnimDistance )
EVENT ( AI_HasEnemies , idActor : : Event_HasEnemies )
EVENT ( AI_NextEnemy , idActor : : Event_NextEnemy )
EVENT ( AI_ClosestEnemyToPoint , idActor : : Event_ClosestEnemyToPoint )
EVENT ( EV_StopSound , idActor : : Event_StopSound )
EVENT ( AI_SetNextState , idActor : : Event_SetNextState )
EVENT ( AI_SetState , idActor : : Event_SetState )
EVENT ( AI_GetState , idActor : : Event_GetState )
EVENT ( AI_GetHead , idActor : : Event_GetHead )
2018-08-27 13:13:17 +00:00
//ivan start - particles
EVENT ( AI_TriggerFX , idActor : : Event_TriggerFX )
EVENT ( AI_StartEmitter , idActor : : Event_StartEmitter )
EVENT ( AI_GetEmitter , idActor : : Event_GetEmitter )
EVENT ( AI_StopEmitter , idActor : : Event_StopEmitter )
//ivan end
2011-11-22 21:28:15 +00:00
END_CLASS
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : idActor
= = = = = = = = = = = = = = = = = = = = =
*/
idActor : : idActor ( void ) {
viewAxis . Identity ( ) ;
2018-08-27 13:13:17 +00:00
//ivan start
nextImpulse = 0 ;
force_torso_override = false ;
//ivan end
2011-11-22 21:28:15 +00:00
scriptThread = NULL ; // initialized by ConstructScriptObject, which is called by idEntity::Spawn
use_combat_bbox = false ;
head = NULL ;
team = 0 ;
rank = 0 ;
fovDot = 0.0f ;
eyeOffset . Zero ( ) ;
pain_debounce_time = 0 ;
pain_delay = 0 ;
pain_threshold = 0 ;
state = NULL ;
idealState = NULL ;
leftEyeJoint = INVALID_JOINT ;
rightEyeJoint = INVALID_JOINT ;
soundJoint = INVALID_JOINT ;
modelOffset . Zero ( ) ;
deltaViewAngles . Zero ( ) ;
painTime = 0 ;
allowPain = false ;
allowEyeFocus = false ;
waitState = " " ;
2011-12-06 18:20:15 +00:00
2011-11-30 21:57:48 +00:00
blink_anim = 0 ;
2011-11-22 21:28:15 +00:00
blink_time = 0 ;
blink_min = 0 ;
blink_max = 0 ;
finalBoss = false ;
attachments . SetGranularity ( 1 ) ;
enemyNode . SetOwner ( this ) ;
enemyList . SetOwner ( this ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : ~ idActor
= = = = = = = = = = = = = = = = = = = = =
*/
idActor : : ~ idActor ( void ) {
int i ;
idEntity * ent ;
DeconstructScriptObject ( ) ;
scriptObject . Free ( ) ;
StopSound ( SND_CHANNEL_ANY , false ) ;
delete combatModel ;
combatModel = NULL ;
if ( head . GetEntity ( ) ) {
head . GetEntity ( ) - > ClearBody ( ) ;
head . GetEntity ( ) - > PostEventMS ( & EV_Remove , 0 ) ;
}
// remove any attached entities
for ( i = 0 ; i < attachments . Num ( ) ; i + + ) {
ent = attachments [ i ] . ent . GetEntity ( ) ;
if ( ent ) {
ent - > PostEventMS ( & EV_Remove , 0 ) ;
}
}
ShutdownThreads ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Spawn
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Spawn ( void ) {
idEntity * ent ;
idStr jointName ;
float fovDegrees ;
copyJoints_t copyJoint ;
animPrefix = " " ;
state = NULL ;
idealState = NULL ;
spawnArgs . GetInt ( " rank " , " 0 " , rank ) ;
spawnArgs . GetInt ( " team " , " 0 " , team ) ;
spawnArgs . GetVector ( " offsetModel " , " 0 0 0 " , modelOffset ) ;
2011-12-06 18:20:15 +00:00
spawnArgs . GetBool ( " use_combat_bbox " , " 0 " , use_combat_bbox ) ;
2011-11-22 21:28:15 +00:00
viewAxis = GetPhysics ( ) - > GetAxis ( ) ;
spawnArgs . GetFloat ( " fov " , " 90 " , fovDegrees ) ;
SetFOV ( fovDegrees ) ;
pain_debounce_time = 0 ;
pain_delay = SEC2MS ( spawnArgs . GetFloat ( " pain_delay " ) ) ;
pain_threshold = spawnArgs . GetInt ( " pain_threshold " ) ;
LoadAF ( ) ;
walkIK . Init ( this , IK_ANIM , modelOffset ) ;
// the animation used to be set to the IK_ANIM at this point, but that was fixed, resulting in
// attachments not binding correctly, so we're stuck setting the IK_ANIM before attaching things.
animator . ClearAllAnims ( gameLocal . time , 0 ) ;
animator . SetFrame ( ANIMCHANNEL_ALL , animator . GetAnim ( IK_ANIM ) , 0 , 0 , 0 ) ;
// spawn any attachments we might have
const idKeyValue * kv = spawnArgs . MatchPrefix ( " def_attach " , NULL ) ;
while ( kv ) {
idDict args ;
args . Set ( " classname " , kv - > GetValue ( ) . c_str ( ) ) ;
// make items non-touchable so the player can't take them out of the character's hands
args . Set ( " no_touch " , " 1 " ) ;
// don't let them drop to the floor
args . Set ( " dropToFloor " , " 0 " ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
gameLocal . SpawnEntityDef ( args , & ent ) ;
if ( ! ent ) {
gameLocal . Error ( " Couldn't spawn '%s' to attach to entity '%s' " , kv - > GetValue ( ) . c_str ( ) , name . c_str ( ) ) ;
} else {
Attach ( ent ) ;
}
kv = spawnArgs . MatchPrefix ( " def_attach " , kv ) ;
}
SetupDamageGroups ( ) ;
SetupHead ( ) ;
// clear the bind anim
animator . ClearAllAnims ( gameLocal . time , 0 ) ;
idEntity * headEnt = head . GetEntity ( ) ;
idAnimator * headAnimator ;
if ( headEnt ) {
headAnimator = headEnt - > GetAnimator ( ) ;
} else {
headAnimator = & animator ;
}
if ( headEnt ) {
// set up the list of joints to copy to the head
for ( kv = spawnArgs . MatchPrefix ( " copy_joint " , NULL ) ; kv ! = NULL ; kv = spawnArgs . MatchPrefix ( " copy_joint " , kv ) ) {
if ( kv - > GetValue ( ) = = " " ) {
// probably clearing out inherited key, so skip it
continue ;
}
jointName = kv - > GetKey ( ) ;
if ( jointName . StripLeadingOnce ( " copy_joint_world " ) ) {
copyJoint . mod = JOINTMOD_WORLD_OVERRIDE ;
} else {
jointName . StripLeadingOnce ( " copy_joint " ) ;
copyJoint . mod = JOINTMOD_LOCAL_OVERRIDE ;
}
copyJoint . from = animator . GetJointHandle ( jointName ) ;
if ( copyJoint . from = = INVALID_JOINT ) {
gameLocal . Warning ( " Unknown copy_joint '%s' on entity %s " , jointName . c_str ( ) , name . c_str ( ) ) ;
continue ;
}
jointName = kv - > GetValue ( ) ;
copyJoint . to = headAnimator - > GetJointHandle ( jointName ) ;
if ( copyJoint . to = = INVALID_JOINT ) {
gameLocal . Warning ( " Unknown copy_joint '%s' on head of entity %s " , jointName . c_str ( ) , name . c_str ( ) ) ;
continue ;
}
copyJoints . Append ( copyJoint ) ;
}
}
// set up blinking
blink_anim = headAnimator - > GetAnim ( " blink " ) ;
blink_time = 0 ; // it's ok to blink right away
blink_min = SEC2MS ( spawnArgs . GetFloat ( " blink_min " , " 0.5 " ) ) ;
blink_max = SEC2MS ( spawnArgs . GetFloat ( " blink_max " , " 8 " ) ) ;
// set up the head anim if necessary
int headAnim = headAnimator - > GetAnim ( " def_head " ) ;
if ( headAnim ) {
if ( headEnt ) {
2011-12-06 18:20:15 +00:00
headAnimator - > CycleAnim ( ANIMCHANNEL_ALL , headAnim , gameLocal . time , 0 ) ;
2011-11-22 21:28:15 +00:00
} else {
headAnimator - > CycleAnim ( ANIMCHANNEL_HEAD , headAnim , gameLocal . time , 0 ) ;
}
}
if ( spawnArgs . GetString ( " sound_bone " , " " , jointName ) ) {
soundJoint = animator . GetJointHandle ( jointName ) ;
if ( soundJoint = = INVALID_JOINT ) {
gameLocal . Warning ( " idAnimated '%s' at (%s): cannot find joint '%s' for sound playback " , name . c_str ( ) , GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) , jointName . c_str ( ) ) ;
}
}
finalBoss = spawnArgs . GetBool ( " finalBoss " ) ;
FinishSetup ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : FinishSetup
= = = = = = = = = = = = = = = =
*/
void idActor : : FinishSetup ( void ) {
const char * scriptObjectName ;
// setup script object
if ( spawnArgs . GetString ( " scriptobject " , NULL , & scriptObjectName ) ) {
if ( ! scriptObject . SetType ( scriptObjectName ) ) {
gameLocal . Error ( " Script object '%s' not found on entity '%s'. " , scriptObjectName , name . c_str ( ) ) ;
}
ConstructScriptObject ( ) ;
}
SetupBody ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : SetupHead
= = = = = = = = = = = = = = = =
*/
void idActor : : SetupHead ( void ) {
idAFAttachment * headEnt ;
idStr jointName ;
const char * headModel ;
jointHandle_t joint ;
jointHandle_t damageJoint ;
int i ;
const idKeyValue * sndKV ;
if ( gameLocal . isClient ) {
return ;
}
headModel = spawnArgs . GetString ( " def_head " , " " ) ;
if ( headModel [ 0 ] ) {
jointName = spawnArgs . GetString ( " head_joint " ) ;
joint = animator . GetJointHandle ( jointName ) ;
if ( joint = = INVALID_JOINT ) {
gameLocal . Error ( " Joint '%s' not found for 'head_joint' on '%s' " , jointName . c_str ( ) , name . c_str ( ) ) ;
}
// set the damage joint to be part of the head damage group
damageJoint = joint ;
for ( i = 0 ; i < damageGroups . Num ( ) ; i + + ) {
if ( damageGroups [ i ] = = " head " ) {
damageJoint = static_cast < jointHandle_t > ( i ) ;
break ;
}
}
// copy any sounds in case we have frame commands on the head
idDict args ;
sndKV = spawnArgs . MatchPrefix ( " snd_ " , NULL ) ;
while ( sndKV ) {
args . Set ( sndKV - > GetKey ( ) , sndKV - > GetValue ( ) ) ;
sndKV = spawnArgs . MatchPrefix ( " snd_ " , sndKV ) ;
}
headEnt = static_cast < idAFAttachment * > ( gameLocal . SpawnEntityType ( idAFAttachment : : Type , & args ) ) ;
headEnt - > SetName ( va ( " %s_head " , name . c_str ( ) ) ) ;
headEnt - > SetBody ( this , headModel , damageJoint ) ;
head = headEnt ;
idVec3 origin ;
idMat3 axis ;
idAttachInfo & attach = attachments . Alloc ( ) ;
attach . channel = animator . GetChannelForJoint ( joint ) ;
animator . GetJointTransform ( joint , gameLocal . time , origin , axis ) ;
origin = renderEntity . origin + ( origin + modelOffset ) * renderEntity . axis ;
attach . ent = headEnt ;
headEnt - > SetOrigin ( origin ) ;
headEnt - > SetAxis ( renderEntity . axis ) ;
headEnt - > BindToJoint ( this , joint , true ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : CopyJointsFromBodyToHead
= = = = = = = = = = = = = = = =
*/
void idActor : : CopyJointsFromBodyToHead ( void ) {
idEntity * headEnt = head . GetEntity ( ) ;
idAnimator * headAnimator ;
int i ;
idMat3 mat ;
idMat3 axis ;
idVec3 pos ;
if ( ! headEnt ) {
return ;
}
headAnimator = headEnt - > GetAnimator ( ) ;
// copy the animation from the body to the head
for ( i = 0 ; i < copyJoints . Num ( ) ; i + + ) {
if ( copyJoints [ i ] . mod = = JOINTMOD_WORLD_OVERRIDE ) {
mat = headEnt - > GetPhysics ( ) - > GetAxis ( ) . Transpose ( ) ;
GetJointWorldTransform ( copyJoints [ i ] . from , gameLocal . time , pos , axis ) ;
pos - = headEnt - > GetPhysics ( ) - > GetOrigin ( ) ;
headAnimator - > SetJointPos ( copyJoints [ i ] . to , copyJoints [ i ] . mod , pos * mat ) ;
headAnimator - > SetJointAxis ( copyJoints [ i ] . to , copyJoints [ i ] . mod , axis * mat ) ;
} else {
animator . GetJointLocalTransform ( copyJoints [ i ] . from , gameLocal . time , pos , axis ) ;
headAnimator - > SetJointPos ( copyJoints [ i ] . to , copyJoints [ i ] . mod , pos ) ;
headAnimator - > SetJointAxis ( copyJoints [ i ] . to , copyJoints [ i ] . mod , axis ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : Restart
= = = = = = = = = = = = = = = =
*/
void idActor : : Restart ( void ) {
assert ( ! head . GetEntity ( ) ) ;
SetupHead ( ) ;
FinishSetup ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Save
archive object for savegame file
= = = = = = = = = = = = = = = =
*/
void idActor : : Save ( idSaveGame * savefile ) const {
idActor * ent ;
int i ;
savefile - > WriteInt ( team ) ;
savefile - > WriteInt ( rank ) ;
savefile - > WriteMat3 ( viewAxis ) ;
savefile - > WriteInt ( enemyList . Num ( ) ) ;
for ( ent = enemyList . Next ( ) ; ent ! = NULL ; ent = ent - > enemyNode . Next ( ) ) {
savefile - > WriteObject ( ent ) ;
}
savefile - > WriteFloat ( fovDot ) ;
savefile - > WriteVec3 ( eyeOffset ) ;
savefile - > WriteVec3 ( modelOffset ) ;
savefile - > WriteAngles ( deltaViewAngles ) ;
savefile - > WriteInt ( pain_debounce_time ) ;
savefile - > WriteInt ( pain_delay ) ;
savefile - > WriteInt ( pain_threshold ) ;
savefile - > WriteInt ( damageGroups . Num ( ) ) ;
for ( i = 0 ; i < damageGroups . Num ( ) ; i + + ) {
savefile - > WriteString ( damageGroups [ i ] ) ;
}
savefile - > WriteInt ( damageScale . Num ( ) ) ;
for ( i = 0 ; i < damageScale . Num ( ) ; i + + ) {
savefile - > WriteFloat ( damageScale [ i ] ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start
savefile - > WriteInt ( damageGroupsNames . Num ( ) ) ;
for ( i = 0 ; i < damageGroupsNames . Num ( ) ; i + + ) {
savefile - > WriteString ( damageGroupsNames [ i ] ) ;
}
savefile - > WriteInt ( highpainThreshold . Num ( ) ) ;
for ( i = 0 ; i < highpainThreshold . Num ( ) ; i + + ) {
savefile - > WriteFloat ( highpainThreshold [ i ] ) ;
}
savefile - > WriteInt ( highpainDecreaseRate . Num ( ) ) ;
for ( i = 0 ; i < highpainDecreaseRate . Num ( ) ; i + + ) {
savefile - > WriteFloat ( highpainDecreaseRate [ i ] ) ;
}
savefile - > WriteInt ( highpainCurrentDamage . Num ( ) ) ;
for ( i = 0 ; i < highpainCurrentDamage . Num ( ) ; i + + ) {
savefile - > WriteFloat ( highpainCurrentDamage [ i ] ) ;
}
savefile - > WriteInt ( nextImpulse ) ;
//ivan end
2011-11-22 21:28:15 +00:00
savefile - > WriteBool ( use_combat_bbox ) ;
head . Save ( savefile ) ;
savefile - > WriteInt ( copyJoints . Num ( ) ) ;
for ( i = 0 ; i < copyJoints . Num ( ) ; i + + ) {
savefile - > WriteInt ( copyJoints [ i ] . mod ) ;
savefile - > WriteJoint ( copyJoints [ i ] . from ) ;
savefile - > WriteJoint ( copyJoints [ i ] . to ) ;
}
savefile - > WriteJoint ( leftEyeJoint ) ;
savefile - > WriteJoint ( rightEyeJoint ) ;
savefile - > WriteJoint ( soundJoint ) ;
walkIK . Save ( savefile ) ;
savefile - > WriteString ( animPrefix ) ;
savefile - > WriteString ( painAnim ) ;
savefile - > WriteInt ( blink_anim ) ;
savefile - > WriteInt ( blink_time ) ;
savefile - > WriteInt ( blink_min ) ;
savefile - > WriteInt ( blink_max ) ;
// script variables
savefile - > WriteObject ( scriptThread ) ;
savefile - > WriteString ( waitState ) ;
headAnim . Save ( savefile ) ;
torsoAnim . Save ( savefile ) ;
legsAnim . Save ( savefile ) ;
savefile - > WriteBool ( allowPain ) ;
savefile - > WriteBool ( allowEyeFocus ) ;
savefile - > WriteInt ( painTime ) ;
savefile - > WriteInt ( attachments . Num ( ) ) ;
for ( i = 0 ; i < attachments . Num ( ) ; i + + ) {
attachments [ i ] . ent . Save ( savefile ) ;
savefile - > WriteInt ( attachments [ i ] . channel ) ;
}
savefile - > WriteBool ( finalBoss ) ;
idToken token ;
//FIXME: this is unneccesary
if ( state ) {
idLexer src ( state - > Name ( ) , idStr : : Length ( state - > Name ( ) ) , " idAI::Save " ) ;
src . ReadTokenOnLine ( & token ) ;
src . ExpectTokenString ( " :: " ) ;
src . ReadTokenOnLine ( & token ) ;
savefile - > WriteString ( token ) ;
} else {
savefile - > WriteString ( " " ) ;
}
if ( idealState ) {
idLexer src ( idealState - > Name ( ) , idStr : : Length ( idealState - > Name ( ) ) , " idAI::Save " ) ;
src . ReadTokenOnLine ( & token ) ;
src . ExpectTokenString ( " :: " ) ;
src . ReadTokenOnLine ( & token ) ;
savefile - > WriteString ( token ) ;
} else {
savefile - > WriteString ( " " ) ;
}
2018-08-27 13:13:17 +00:00
savefile - > WriteBool ( force_torso_override ) ; //ivan
//ivan start - particles
savefile - > WriteInt ( funcEmitters . Num ( ) ) ;
for ( int i = 0 ; i < funcEmitters . Num ( ) ; i + + ) {
funcEmitter_t * emitter = funcEmitters . GetIndex ( i ) ;
savefile - > WriteString ( emitter - > name ) ;
savefile - > WriteJoint ( emitter - > joint ) ;
savefile - > WriteObject ( emitter - > particle ) ;
}
//dmgfx start
savefile - > WriteInt ( dmgFxEntities . Num ( ) ) ;
for ( i = 0 ; i < dmgFxEntities . Num ( ) ; i + + ) {
dmgFxEntities [ i ] . Save ( savefile ) ;
}
//dmgfx end
//ivan end
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idActor : : Restore
unarchives object from save game file
= = = = = = = = = = = = = = = =
*/
void idActor : : Restore ( idRestoreGame * savefile ) {
int i , num ;
idActor * ent ;
savefile - > ReadInt ( team ) ;
savefile - > ReadInt ( rank ) ;
savefile - > ReadMat3 ( viewAxis ) ;
savefile - > ReadInt ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( ent ) ) ;
assert ( ent ) ;
if ( ent ) {
ent - > enemyNode . AddToEnd ( enemyList ) ;
}
}
savefile - > ReadFloat ( fovDot ) ;
savefile - > ReadVec3 ( eyeOffset ) ;
savefile - > ReadVec3 ( modelOffset ) ;
savefile - > ReadAngles ( deltaViewAngles ) ;
savefile - > ReadInt ( pain_debounce_time ) ;
savefile - > ReadInt ( pain_delay ) ;
savefile - > ReadInt ( pain_threshold ) ;
savefile - > ReadInt ( num ) ;
damageGroups . SetGranularity ( 1 ) ;
damageGroups . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
savefile - > ReadString ( damageGroups [ i ] ) ;
}
savefile - > ReadInt ( num ) ;
damageScale . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
savefile - > ReadFloat ( damageScale [ i ] ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start
savefile - > ReadInt ( num ) ;
damageGroupsNames . SetGranularity ( 1 ) ;
damageGroupsNames . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
savefile - > ReadString ( damageGroupsNames [ i ] ) ;
}
savefile - > ReadInt ( num ) ;
highpainThreshold . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
savefile - > ReadFloat ( highpainThreshold [ i ] ) ;
}
savefile - > ReadInt ( num ) ;
highpainDecreaseRate . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
savefile - > ReadFloat ( highpainDecreaseRate [ i ] ) ;
}
savefile - > ReadInt ( num ) ;
highpainCurrentDamage . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
savefile - > ReadFloat ( highpainCurrentDamage [ i ] ) ;
}
savefile - > ReadInt ( nextImpulse ) ;
//ivan end
2011-11-22 21:28:15 +00:00
savefile - > ReadBool ( use_combat_bbox ) ;
head . Restore ( savefile ) ;
savefile - > ReadInt ( num ) ;
copyJoints . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
int val ;
savefile - > ReadInt ( val ) ;
copyJoints [ i ] . mod = static_cast < jointModTransform_t > ( val ) ;
savefile - > ReadJoint ( copyJoints [ i ] . from ) ;
savefile - > ReadJoint ( copyJoints [ i ] . to ) ;
}
savefile - > ReadJoint ( leftEyeJoint ) ;
savefile - > ReadJoint ( rightEyeJoint ) ;
savefile - > ReadJoint ( soundJoint ) ;
walkIK . Restore ( savefile ) ;
savefile - > ReadString ( animPrefix ) ;
savefile - > ReadString ( painAnim ) ;
savefile - > ReadInt ( blink_anim ) ;
savefile - > ReadInt ( blink_time ) ;
savefile - > ReadInt ( blink_min ) ;
savefile - > ReadInt ( blink_max ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( scriptThread ) ) ;
savefile - > ReadString ( waitState ) ;
headAnim . Restore ( savefile ) ;
torsoAnim . Restore ( savefile ) ;
legsAnim . Restore ( savefile ) ;
savefile - > ReadBool ( allowPain ) ;
savefile - > ReadBool ( allowEyeFocus ) ;
savefile - > ReadInt ( painTime ) ;
savefile - > ReadInt ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
idAttachInfo & attach = attachments . Alloc ( ) ;
attach . ent . Restore ( savefile ) ;
savefile - > ReadInt ( attach . channel ) ;
}
savefile - > ReadBool ( finalBoss ) ;
idStr statename ;
savefile - > ReadString ( statename ) ;
if ( statename . Length ( ) > 0 ) {
state = GetScriptFunction ( statename ) ;
}
savefile - > ReadString ( statename ) ;
if ( statename . Length ( ) > 0 ) {
idealState = GetScriptFunction ( statename ) ;
}
2018-08-27 13:13:17 +00:00
savefile - > ReadBool ( force_torso_override ) ; //ivan
//ivan start - particles
//Clean up the emitters
for ( int i = 0 ; i < funcEmitters . Num ( ) ; i + + ) {
funcEmitter_t * emitter = funcEmitters . GetIndex ( i ) ;
if ( emitter - > particle ) {
//Destroy the emitters
emitter - > particle - > PostEventMS ( & EV_Remove , 0 ) ;
}
}
funcEmitters . Clear ( ) ;
int emitterCount ;
savefile - > ReadInt ( emitterCount ) ;
for ( int i = 0 ; i < emitterCount ; i + + ) {
funcEmitter_t newEmitter ;
memset ( & newEmitter , 0 , sizeof ( newEmitter ) ) ;
idStr name ;
savefile - > ReadString ( name ) ;
strcpy ( newEmitter . name , name . c_str ( ) ) ;
savefile - > ReadJoint ( newEmitter . joint ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( newEmitter . particle ) ) ;
funcEmitters . Set ( newEmitter . name , newEmitter ) ;
}
//dmgfx start
dmgFxEntities . Clear ( ) ;
savefile - > ReadInt ( num ) ;
dmgFxEntities . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
dmgFxEntities [ i ] . Restore ( savefile ) ;
}
//dmgfx end
//ivan end
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idActor : : Hide
= = = = = = = = = = = = = = = =
*/
void idActor : : Hide ( void ) {
idEntity * ent ;
idEntity * next ;
idAFEntity_Base : : Hide ( ) ;
if ( head . GetEntity ( ) ) {
head . GetEntity ( ) - > Hide ( ) ;
}
for ( ent = GetNextTeamEntity ( ) ; ent ! = NULL ; ent = next ) {
next = ent - > GetNextTeamEntity ( ) ;
if ( ent - > GetBindMaster ( ) = = this ) {
ent - > Hide ( ) ;
if ( ent - > IsType ( idLight : : Type ) ) {
static_cast < idLight * > ( ent ) - > Off ( ) ;
}
}
}
UnlinkCombat ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Show
= = = = = = = = = = = = = = = =
*/
void idActor : : Show ( void ) {
idEntity * ent ;
idEntity * next ;
idAFEntity_Base : : Show ( ) ;
if ( head . GetEntity ( ) ) {
head . GetEntity ( ) - > Show ( ) ;
}
for ( ent = GetNextTeamEntity ( ) ; ent ! = NULL ; ent = next ) {
next = ent - > GetNextTeamEntity ( ) ;
if ( ent - > GetBindMaster ( ) = = this ) {
ent - > Show ( ) ;
if ( ent - > IsType ( idLight : : Type ) ) {
static_cast < idLight * > ( ent ) - > On ( ) ;
}
}
}
LinkCombat ( ) ;
}
/*
= = = = = = = = = = = = = =
idActor : : GetDefaultSurfaceType
= = = = = = = = = = = = = =
*/
int idActor : : GetDefaultSurfaceType ( void ) const {
return SURFTYPE_FLESH ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : ProjectOverlay
= = = = = = = = = = = = = = = =
*/
void idActor : : ProjectOverlay ( const idVec3 & origin , const idVec3 & dir , float size , const char * material ) {
idEntity * ent ;
idEntity * next ;
idEntity : : ProjectOverlay ( origin , dir , size , material ) ;
for ( ent = GetNextTeamEntity ( ) ; ent ! = NULL ; ent = next ) {
next = ent - > GetNextTeamEntity ( ) ;
if ( ent - > GetBindMaster ( ) = = this ) {
if ( ent - > fl . takedamage & & ent - > spawnArgs . GetBool ( " bleed " ) ) {
ent - > ProjectOverlay ( origin , dir , size , material ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : LoadAF
= = = = = = = = = = = = = = = =
*/
bool idActor : : LoadAF ( void ) {
idStr fileName ;
if ( ! spawnArgs . GetString ( " ragdoll " , " *unknown* " , fileName ) | | ! fileName . Length ( ) ) {
return false ;
}
af . SetAnimator ( GetAnimator ( ) ) ;
return af . Load ( this , fileName ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SetupBody
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetupBody ( void ) {
const char * jointname ;
animator . ClearAllAnims ( gameLocal . time , 0 ) ;
animator . ClearAllJoints ( ) ;
idEntity * headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
jointname = spawnArgs . GetString ( " bone_leftEye " ) ;
leftEyeJoint = headEnt - > GetAnimator ( ) - > GetJointHandle ( jointname ) ;
jointname = spawnArgs . GetString ( " bone_rightEye " ) ;
rightEyeJoint = headEnt - > GetAnimator ( ) - > GetJointHandle ( jointname ) ;
// set up the eye height. check if it's specified in the def.
if ( ! spawnArgs . GetFloat ( " eye_height " , " 0 " , eyeOffset . z ) ) {
// if not in the def, then try to base it off the idle animation
int anim = headEnt - > GetAnimator ( ) - > GetAnim ( " idle " ) ;
if ( anim & & ( leftEyeJoint ! = INVALID_JOINT ) ) {
idVec3 pos ;
idMat3 axis ;
headEnt - > GetAnimator ( ) - > PlayAnim ( ANIMCHANNEL_ALL , anim , gameLocal . time , 0 ) ;
headEnt - > GetAnimator ( ) - > GetJointTransform ( leftEyeJoint , gameLocal . time , pos , axis ) ;
headEnt - > GetAnimator ( ) - > ClearAllAnims ( gameLocal . time , 0 ) ;
headEnt - > GetAnimator ( ) - > ForceUpdate ( ) ;
pos + = headEnt - > GetPhysics ( ) - > GetOrigin ( ) - GetPhysics ( ) - > GetOrigin ( ) ;
eyeOffset = pos + modelOffset ;
} else {
// just base it off the bounding box size
eyeOffset . z = GetPhysics ( ) - > GetBounds ( ) [ 1 ] . z - 6 ;
}
}
headAnim . Init ( this , headEnt - > GetAnimator ( ) , ANIMCHANNEL_ALL ) ;
} else {
jointname = spawnArgs . GetString ( " bone_leftEye " ) ;
leftEyeJoint = animator . GetJointHandle ( jointname ) ;
jointname = spawnArgs . GetString ( " bone_rightEye " ) ;
rightEyeJoint = animator . GetJointHandle ( jointname ) ;
// set up the eye height. check if it's specified in the def.
if ( ! spawnArgs . GetFloat ( " eye_height " , " 0 " , eyeOffset . z ) ) {
// if not in the def, then try to base it off the idle animation
int anim = animator . GetAnim ( " idle " ) ;
if ( anim & & ( leftEyeJoint ! = INVALID_JOINT ) ) {
idVec3 pos ;
idMat3 axis ;
animator . PlayAnim ( ANIMCHANNEL_ALL , anim , gameLocal . time , 0 ) ;
animator . GetJointTransform ( leftEyeJoint , gameLocal . time , pos , axis ) ;
animator . ClearAllAnims ( gameLocal . time , 0 ) ;
animator . ForceUpdate ( ) ;
eyeOffset = pos + modelOffset ;
} else {
// just base it off the bounding box size
eyeOffset . z = GetPhysics ( ) - > GetBounds ( ) [ 1 ] . z - 6 ;
}
}
headAnim . Init ( this , & animator , ANIMCHANNEL_HEAD ) ;
}
waitState = " " ;
torsoAnim . Init ( this , & animator , ANIMCHANNEL_TORSO ) ;
legsAnim . Init ( this , & animator , ANIMCHANNEL_LEGS ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : CheckBlink
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : CheckBlink ( void ) {
// check if it's time to blink
if ( ! blink_anim | | ( health < = 0 ) | | ! allowEyeFocus | | ( blink_time > gameLocal . time ) ) {
return ;
}
idEntity * headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headEnt - > GetAnimator ( ) - > PlayAnim ( ANIMCHANNEL_EYELIDS , blink_anim , gameLocal . time , 1 ) ;
} else {
animator . PlayAnim ( ANIMCHANNEL_EYELIDS , blink_anim , gameLocal . time , 1 ) ;
}
// set the next blink time
blink_time = gameLocal . time + blink_min + gameLocal . random . RandomFloat ( ) * ( blink_max - blink_min ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : GetPhysicsToVisualTransform
= = = = = = = = = = = = = = = =
*/
bool idActor : : GetPhysicsToVisualTransform ( idVec3 & origin , idMat3 & axis ) {
if ( af . IsActive ( ) ) {
af . GetPhysicsToVisualTransform ( origin , axis ) ;
return true ;
}
origin = modelOffset ;
axis = viewAxis ;
return true ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : GetPhysicsToSoundTransform
= = = = = = = = = = = = = = = =
*/
bool idActor : : GetPhysicsToSoundTransform ( idVec3 & origin , idMat3 & axis ) {
if ( soundJoint ! = INVALID_JOINT ) {
animator . GetJointTransform ( soundJoint , gameLocal . time , origin , axis ) ;
origin + = modelOffset ;
axis = viewAxis ;
} else {
origin = GetPhysics ( ) - > GetGravityNormal ( ) * - eyeOffset . z ;
axis . Identity ( ) ;
}
return true ;
}
/***********************************************************************
script state management
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idActor : : ShutdownThreads
= = = = = = = = = = = = = = = =
*/
void idActor : : ShutdownThreads ( void ) {
headAnim . Shutdown ( ) ;
torsoAnim . Shutdown ( ) ;
legsAnim . Shutdown ( ) ;
if ( scriptThread ) {
scriptThread - > EndThread ( ) ;
scriptThread - > PostEventMS ( & EV_Remove , 0 ) ;
delete scriptThread ;
scriptThread = NULL ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : 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 idActor : : ShouldConstructScriptObjectAtSpawn ( void ) const {
return false ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : 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 * idActor : : ConstructScriptObject ( void ) {
const function_t * constructor ;
// make sure we have a scriptObject
if ( ! scriptObject . HasObject ( ) ) {
gameLocal . Error ( " No scriptobject set on '%s'. Check the '%s' entityDef. " , name . c_str ( ) , GetEntityDefName ( ) ) ;
}
if ( ! scriptThread ) {
// create script thread
scriptThread = new idThread ( ) ;
scriptThread - > ManualDelete ( ) ;
scriptThread - > ManualControl ( ) ;
scriptThread - > SetThreadName ( name . c_str ( ) ) ;
} else {
scriptThread - > EndThread ( ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// call script object's constructor
constructor = scriptObject . GetConstructor ( ) ;
if ( ! constructor ) {
gameLocal . Error ( " Missing constructor on '%s' for entity '%s' " , scriptObject . GetTypeName ( ) , name . c_str ( ) ) ;
}
// init the script object's data
scriptObject . ClearObject ( ) ;
// just set the current function on the script. we'll execute in the subclasses.
scriptThread - > CallFunction ( this , constructor , true ) ;
return scriptThread ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetScriptFunction
= = = = = = = = = = = = = = = = = = = = =
*/
const function_t * idActor : : GetScriptFunction ( const char * funcname ) {
const function_t * func ;
func = scriptObject . GetFunction ( funcname ) ;
if ( ! func ) {
scriptThread - > Error ( " Unknown function '%s' in '%s' " , funcname , scriptObject . GetTypeName ( ) ) ;
}
return func ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SetState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetState ( const function_t * newState ) {
if ( ! newState ) {
gameLocal . Error ( " idActor::SetState: Null state " ) ;
}
if ( ai_debugScript . GetInteger ( ) = = entityNumber ) {
gameLocal . Printf ( " %d: %s: State: %s \n " , gameLocal . time , name . c_str ( ) , newState - > Name ( ) ) ;
}
state = newState ;
idealState = state ;
scriptThread - > CallFunction ( this , state , true ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SetState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetState ( const char * statename ) {
const function_t * newState ;
newState = GetScriptFunction ( statename ) ;
SetState ( newState ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : UpdateScript
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : UpdateScript ( void ) {
int i ;
if ( ai_debugScript . GetInteger ( ) = = entityNumber ) {
scriptThread - > EnableDebugInfo ( ) ;
} else {
scriptThread - > DisableDebugInfo ( ) ;
}
// a series of state changes can happen in a single frame.
// this loop limits them in case we've entered an infinite loop.
for ( i = 0 ; i < 20 ; i + + ) {
if ( idealState ! = state ) {
SetState ( idealState ) ;
}
// don't call script until it's done waiting
if ( scriptThread - > IsWaiting ( ) ) {
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
scriptThread - > Execute ( ) ;
if ( idealState = = state ) {
break ;
}
}
if ( i = = 20 ) {
scriptThread - > Warning ( " idActor::UpdateScript: exited loop to prevent lockup " ) ;
}
}
/***********************************************************************
vision
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : setFov
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetFOV ( float fov ) {
fovDot = ( float ) cos ( DEG2RAD ( fov * 0.5f ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SetEyeHeight
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetEyeHeight ( float height ) {
eyeOffset . z = height ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : EyeHeight
= = = = = = = = = = = = = = = = = = = = =
*/
float idActor : : EyeHeight ( void ) const {
return eyeOffset . z ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : EyeOffset
= = = = = = = = = = = = = = = = = = = = =
*/
idVec3 idActor : : EyeOffset ( void ) const {
return GetPhysics ( ) - > GetGravityNormal ( ) * - eyeOffset . z ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetEyePosition
= = = = = = = = = = = = = = = = = = = = =
*/
idVec3 idActor : : GetEyePosition ( void ) const {
return GetPhysics ( ) - > GetOrigin ( ) + ( GetPhysics ( ) - > GetGravityNormal ( ) * - eyeOffset . z ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetViewPos
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : GetViewPos ( idVec3 & origin , idMat3 & axis ) const {
origin = GetEyePosition ( ) ;
axis = viewAxis ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : CheckFOV
= = = = = = = = = = = = = = = = = = = = =
*/
bool idActor : : CheckFOV ( const idVec3 & pos ) const {
if ( fovDot = = 1.0f ) {
return true ;
}
float dot ;
idVec3 delta ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
delta = pos - GetEyePosition ( ) ;
// get our gravity normal
const idVec3 & gravityDir = GetPhysics ( ) - > GetGravityNormal ( ) ;
// infinite vertical vision, so project it onto our orientation plane
delta - = gravityDir * ( gravityDir * delta ) ;
delta . Normalize ( ) ;
dot = viewAxis [ 0 ] * delta ;
return ( dot > = fovDot ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : CanSee
= = = = = = = = = = = = = = = = = = = = =
*/
bool idActor : : CanSee ( idEntity * ent , bool useFov ) const {
trace_t tr ;
idVec3 eye ;
idVec3 toPos ;
if ( ent - > IsHidden ( ) ) {
return false ;
}
if ( ent - > IsType ( idActor : : Type ) ) {
toPos = ( ( idActor * ) ent ) - > GetEyePosition ( ) ;
} else {
toPos = ent - > GetPhysics ( ) - > GetOrigin ( ) ;
}
if ( useFov & & ! CheckFOV ( toPos ) ) {
return false ;
}
eye = GetEyePosition ( ) ;
gameLocal . clip . TracePoint ( tr , eye , toPos , MASK_OPAQUE , this ) ;
if ( tr . fraction > = 1.0f | | ( gameLocal . GetTraceEntity ( tr ) = = ent ) ) {
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : PointVisible
= = = = = = = = = = = = = = = = = = = = =
*/
bool idActor : : PointVisible ( const idVec3 & point ) const {
trace_t results ;
idVec3 start , end ;
start = GetEyePosition ( ) ;
end = point ;
end [ 2 ] + = 1.0f ;
gameLocal . clip . TracePoint ( results , start , end , MASK_OPAQUE , this ) ;
return ( results . fraction > = 1.0f ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetAIAimTargets
Returns positions for the AI to aim at .
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : GetAIAimTargets ( const idVec3 & lastSightPos , idVec3 & headPos , idVec3 & chestPos ) {
headPos = lastSightPos + EyeOffset ( ) ;
chestPos = ( headPos + lastSightPos + GetPhysics ( ) - > GetBounds ( ) . GetCenter ( ) ) * 0.5f ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetRenderView
= = = = = = = = = = = = = = = = = = = = =
*/
renderView_t * idActor : : GetRenderView ( ) {
renderView_t * rv = idEntity : : GetRenderView ( ) ;
rv - > viewaxis = viewAxis ;
rv - > vieworg = GetEyePosition ( ) ;
return rv ;
}
/***********************************************************************
Model / Ragdoll
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = =
idActor : : SetCombatModel
= = = = = = = = = = = = = = = =
*/
void idActor : : SetCombatModel ( void ) {
idAFAttachment * headEnt ;
if ( ! use_combat_bbox ) {
if ( combatModel ) {
combatModel - > Unlink ( ) ;
combatModel - > LoadModel ( modelDefHandle ) ;
} else {
combatModel = new idClipModel ( modelDefHandle ) ;
}
headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headEnt - > SetCombatModel ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : GetCombatModel
= = = = = = = = = = = = = = = =
*/
idClipModel * idActor : : GetCombatModel ( void ) const {
return combatModel ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : LinkCombat
= = = = = = = = = = = = = = = =
*/
void idActor : : LinkCombat ( void ) {
idAFAttachment * headEnt ;
if ( fl . hidden | | use_combat_bbox ) {
return ;
}
if ( combatModel ) {
combatModel - > Link ( gameLocal . clip , this , 0 , renderEntity . origin , renderEntity . axis , modelDefHandle ) ;
}
headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headEnt - > LinkCombat ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : UnlinkCombat
= = = = = = = = = = = = = = = =
*/
void idActor : : UnlinkCombat ( void ) {
idAFAttachment * headEnt ;
if ( combatModel ) {
combatModel - > Unlink ( ) ;
}
headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headEnt - > UnlinkCombat ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : StartRagdoll
= = = = = = = = = = = = = = = =
*/
bool idActor : : StartRagdoll ( void ) {
float slomoStart , slomoEnd ;
float jointFrictionDent , jointFrictionDentStart , jointFrictionDentEnd ;
float contactFrictionDent , contactFrictionDentStart , contactFrictionDentEnd ;
// if no AF loaded
if ( ! af . IsLoaded ( ) ) {
return false ;
}
// if the AF is already active
if ( af . IsActive ( ) ) {
return true ;
}
// disable the monster bounding box
GetPhysics ( ) - > DisableClip ( ) ;
// start using the AF
af . StartFromCurrentPose ( spawnArgs . GetInt ( " velocityTime " , " 0 " ) ) ;
slomoStart = MS2SEC ( gameLocal . time ) + spawnArgs . GetFloat ( " ragdoll_slomoStart " , " -1.6 " ) ;
slomoEnd = MS2SEC ( gameLocal . time ) + spawnArgs . GetFloat ( " ragdoll_slomoEnd " , " 0.8 " ) ;
// do the first part of the death in slow motion
af . GetPhysics ( ) - > SetTimeScaleRamp ( slomoStart , slomoEnd ) ;
jointFrictionDent = spawnArgs . GetFloat ( " ragdoll_jointFrictionDent " , " 0.1 " ) ;
jointFrictionDentStart = MS2SEC ( gameLocal . time ) + spawnArgs . GetFloat ( " ragdoll_jointFrictionStart " , " 0.2 " ) ;
jointFrictionDentEnd = MS2SEC ( gameLocal . time ) + spawnArgs . GetFloat ( " ragdoll_jointFrictionEnd " , " 1.2 " ) ;
// set joint friction dent
af . GetPhysics ( ) - > SetJointFrictionDent ( jointFrictionDent , jointFrictionDentStart , jointFrictionDentEnd ) ;
contactFrictionDent = spawnArgs . GetFloat ( " ragdoll_contactFrictionDent " , " 0.1 " ) ;
contactFrictionDentStart = MS2SEC ( gameLocal . time ) + spawnArgs . GetFloat ( " ragdoll_contactFrictionStart " , " 1.0 " ) ;
contactFrictionDentEnd = MS2SEC ( gameLocal . time ) + spawnArgs . GetFloat ( " ragdoll_contactFrictionEnd " , " 2.0 " ) ;
// set contact friction dent
af . GetPhysics ( ) - > SetContactFrictionDent ( contactFrictionDent , contactFrictionDentStart , contactFrictionDentEnd ) ;
// drop any items the actor is holding
idMoveableItem : : DropItems ( this , " death " , NULL ) ;
// drop any articulated figures the actor is holding
idAFEntity_Base : : DropAFs ( this , " death " , NULL ) ;
RemoveAttachments ( ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : StopRagdoll
= = = = = = = = = = = = = = = =
*/
void idActor : : StopRagdoll ( void ) {
if ( af . IsActive ( ) ) {
af . Stop ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : UpdateAnimationControllers
= = = = = = = = = = = = = = = =
*/
bool idActor : : UpdateAnimationControllers ( void ) {
if ( af . IsActive ( ) ) {
return idAFEntity_Base : : UpdateAnimationControllers ( ) ;
} else {
animator . ClearAFPose ( ) ;
}
if ( walkIK . IsInitialized ( ) ) {
walkIK . Evaluate ( ) ;
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : RemoveAttachments
= = = = = = = = = = = = = = = =
*/
void idActor : : RemoveAttachments ( void ) {
int i ;
idEntity * ent ;
// remove any attached entities
for ( i = 0 ; i < attachments . Num ( ) ; i + + ) {
ent = attachments [ i ] . ent . GetEntity ( ) ;
if ( ent & & ent - > spawnArgs . GetBool ( " remove " ) ) {
ent - > PostEventMS ( & EV_Remove , 0 ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : Attach
= = = = = = = = = = = = = = = =
*/
void idActor : : Attach ( idEntity * ent ) {
idVec3 origin ;
idMat3 axis ;
jointHandle_t joint ;
idStr jointName ;
idAttachInfo & attach = attachments . Alloc ( ) ;
idAngles angleOffset ;
idVec3 originOffset ;
jointName = ent - > spawnArgs . GetString ( " joint " ) ;
joint = animator . GetJointHandle ( jointName ) ;
if ( joint = = INVALID_JOINT ) {
gameLocal . Error ( " Joint '%s' not found for attaching '%s' on '%s' " , jointName . c_str ( ) , ent - > GetClassname ( ) , name . c_str ( ) ) ;
}
angleOffset = ent - > spawnArgs . GetAngles ( " angles " ) ;
originOffset = ent - > spawnArgs . GetVector ( " origin " ) ;
attach . channel = animator . GetChannelForJoint ( joint ) ;
GetJointWorldTransform ( joint , gameLocal . time , origin , axis ) ;
attach . ent = ent ;
ent - > SetOrigin ( origin + originOffset * renderEntity . axis ) ;
idMat3 rotate = angleOffset . ToMat3 ( ) ;
idMat3 newAxis = rotate * axis ;
ent - > SetAxis ( newAxis ) ;
ent - > BindToJoint ( this , joint , true ) ;
ent - > cinematic = cinematic ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Teleport
= = = = = = = = = = = = = = = =
*/
void idActor : : Teleport ( const idVec3 & origin , const idAngles & angles , idEntity * destination ) {
GetPhysics ( ) - > SetOrigin ( origin + idVec3 ( 0 , 0 , CM_CLIP_EPSILON ) ) ;
GetPhysics ( ) - > SetLinearVelocity ( vec3_origin ) ;
viewAxis = angles . ToMat3 ( ) ;
UpdateVisuals ( ) ;
if ( ! IsHidden ( ) ) {
// kill anything at the new position
gameLocal . KillBox ( this ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : GetDeltaViewAngles
= = = = = = = = = = = = = = = =
*/
const idAngles & idActor : : GetDeltaViewAngles ( void ) const {
return deltaViewAngles ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : SetDeltaViewAngles
= = = = = = = = = = = = = = = =
*/
void idActor : : SetDeltaViewAngles ( const idAngles & delta ) {
deltaViewAngles = delta ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : HasEnemies
= = = = = = = = = = = = = = = =
*/
bool idActor : : HasEnemies ( void ) const {
idActor * ent ;
for ( ent = enemyList . Next ( ) ; ent ! = NULL ; ent = ent - > enemyNode . Next ( ) ) {
if ( ! ent - > fl . hidden ) {
return true ;
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : ClosestEnemyToPoint
= = = = = = = = = = = = = = = =
*/
idActor * idActor : : ClosestEnemyToPoint ( const idVec3 & pos ) {
idActor * ent ;
idActor * bestEnt ;
float bestDistSquared ;
float distSquared ;
idVec3 delta ;
bestDistSquared = idMath : : INFINITY ;
bestEnt = NULL ;
for ( ent = enemyList . Next ( ) ; ent ! = NULL ; ent = ent - > enemyNode . Next ( ) ) {
if ( ent - > fl . hidden ) {
continue ;
}
delta = ent - > GetPhysics ( ) - > GetOrigin ( ) - pos ;
distSquared = delta . LengthSqr ( ) ;
if ( distSquared < bestDistSquared ) {
bestEnt = ent ;
bestDistSquared = distSquared ;
}
}
return bestEnt ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : EnemyWithMostHealth
= = = = = = = = = = = = = = = =
*/
idActor * idActor : : EnemyWithMostHealth ( ) {
idActor * ent ;
idActor * bestEnt ;
int most = - 9999 ;
bestEnt = NULL ;
for ( ent = enemyList . Next ( ) ; ent ! = NULL ; ent = ent - > enemyNode . Next ( ) ) {
if ( ! ent - > fl . hidden & & ( ent - > health > most ) ) {
bestEnt = ent ;
most = ent - > health ;
}
}
return bestEnt ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : OnLadder
= = = = = = = = = = = = = = = =
*/
bool idActor : : OnLadder ( void ) const {
return false ;
}
/*
= = = = = = = = = = = = = =
idActor : : GetAASLocation
= = = = = = = = = = = = = =
*/
void idActor : : GetAASLocation ( idAAS * aas , idVec3 & pos , int & areaNum ) const {
idVec3 size ;
idBounds bounds ;
GetFloorPos ( 64.0f , pos ) ;
if ( ! aas ) {
areaNum = 0 ;
return ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
size = aas - > GetSettings ( ) - > boundingBoxes [ 0 ] [ 1 ] ;
bounds [ 0 ] = - size ;
size . z = 32.0f ;
bounds [ 1 ] = size ;
areaNum = aas - > PointReachableAreaNum ( pos , bounds , AREA_REACHABLE_WALK ) ;
if ( areaNum ) {
aas - > PushPointIntoAreaNum ( areaNum , pos ) ;
}
}
/***********************************************************************
animation state
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SetAnimState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetAnimState ( int channel , const char * statename , int blendFrames ) {
const function_t * func ;
func = scriptObject . GetFunction ( statename ) ;
if ( ! func ) {
assert ( 0 ) ;
gameLocal . Error ( " Can't find function '%s' in object '%s' " , statename , scriptObject . GetTypeName ( ) ) ;
}
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . SetState ( statename , blendFrames ) ;
allowEyeFocus = true ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ANIMCHANNEL_TORSO :
torsoAnim . SetState ( statename , blendFrames ) ;
legsAnim . Enable ( blendFrames ) ;
allowPain = true ;
allowEyeFocus = true ;
break ;
case ANIMCHANNEL_LEGS :
legsAnim . SetState ( statename , blendFrames ) ;
torsoAnim . Enable ( blendFrames ) ;
allowPain = true ;
allowEyeFocus = true ;
break ;
default :
gameLocal . Error ( " idActor::SetAnimState: Unknown anim group " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetAnimState
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idActor : : GetAnimState ( int channel ) const {
switch ( channel ) {
case ANIMCHANNEL_HEAD :
return headAnim . state ;
break ;
case ANIMCHANNEL_TORSO :
return torsoAnim . state ;
break ;
case ANIMCHANNEL_LEGS :
return legsAnim . state ;
break ;
default :
gameLocal . Error ( " idActor::GetAnimState: Unknown anim group " ) ;
return NULL ;
break ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : InAnimState
= = = = = = = = = = = = = = = = = = = = =
*/
bool idActor : : InAnimState ( int channel , const char * statename ) const {
switch ( channel ) {
case ANIMCHANNEL_HEAD :
if ( headAnim . state = = statename ) {
return true ;
}
break ;
case ANIMCHANNEL_TORSO :
if ( torsoAnim . state = = statename ) {
return true ;
}
break ;
case ANIMCHANNEL_LEGS :
if ( legsAnim . state = = statename ) {
return true ;
}
break ;
default :
gameLocal . Error ( " idActor::InAnimState: Unknown anim group " ) ;
break ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : WaitState
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idActor : : WaitState ( void ) const {
if ( waitState . Length ( ) ) {
return waitState ;
} else {
return NULL ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SetWaitState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetWaitState ( const char * _waitstate ) {
waitState = _waitstate ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : UpdateAnimState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : UpdateAnimState ( void ) {
headAnim . UpdateState ( ) ;
torsoAnim . UpdateState ( ) ;
legsAnim . UpdateState ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetAnim
= = = = = = = = = = = = = = = = = = = = =
*/
int idActor : : GetAnim ( int channel , const char * animname ) {
int anim ;
const char * temp ;
idAnimator * animatorPtr ;
if ( channel = = ANIMCHANNEL_HEAD ) {
if ( ! head . GetEntity ( ) ) {
return 0 ;
}
animatorPtr = head . GetEntity ( ) - > GetAnimator ( ) ;
} else {
animatorPtr = & animator ;
}
if ( animPrefix . Length ( ) ) {
temp = va ( " %s_%s " , animPrefix . c_str ( ) , animname ) ;
anim = animatorPtr - > GetAnim ( temp ) ;
if ( anim ) {
return anim ;
}
}
anim = animatorPtr - > GetAnim ( animname ) ;
return anim ;
}
/*
= = = = = = = = = = = = = = =
idActor : : SyncAnimChannels
= = = = = = = = = = = = = = =
*/
void idActor : : SyncAnimChannels ( int channel , int syncToChannel , int blendFrames ) {
idAnimator * headAnimator ;
idAFAttachment * headEnt ;
int anim ;
idAnimBlend * syncAnim ;
int starttime ;
int blendTime ;
int cycle ;
blendTime = FRAME2MS ( blendFrames ) ;
if ( channel = = ANIMCHANNEL_HEAD ) {
headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headAnimator = headEnt - > GetAnimator ( ) ;
syncAnim = animator . CurrentAnim ( syncToChannel ) ;
if ( syncAnim ) {
anim = headAnimator - > GetAnim ( syncAnim - > AnimFullName ( ) ) ;
if ( ! anim ) {
anim = headAnimator - > GetAnim ( syncAnim - > AnimName ( ) ) ;
}
if ( anim ) {
cycle = animator . CurrentAnim ( syncToChannel ) - > GetCycleCount ( ) ;
starttime = animator . CurrentAnim ( syncToChannel ) - > GetStartTime ( ) ;
headAnimator - > PlayAnim ( ANIMCHANNEL_ALL , anim , gameLocal . time , blendTime ) ;
headAnimator - > CurrentAnim ( ANIMCHANNEL_ALL ) - > SetCycleCount ( cycle ) ;
headAnimator - > CurrentAnim ( ANIMCHANNEL_ALL ) - > SetStartTime ( starttime ) ;
} else {
headEnt - > PlayIdleAnim ( blendTime ) ;
}
}
}
} else if ( syncToChannel = = ANIMCHANNEL_HEAD ) {
headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headAnimator = headEnt - > GetAnimator ( ) ;
syncAnim = headAnimator - > CurrentAnim ( ANIMCHANNEL_ALL ) ;
if ( syncAnim ) {
anim = GetAnim ( channel , syncAnim - > AnimFullName ( ) ) ;
if ( ! anim ) {
anim = GetAnim ( channel , syncAnim - > AnimName ( ) ) ;
}
if ( anim ) {
cycle = headAnimator - > CurrentAnim ( ANIMCHANNEL_ALL ) - > GetCycleCount ( ) ;
starttime = headAnimator - > CurrentAnim ( ANIMCHANNEL_ALL ) - > GetStartTime ( ) ;
animator . PlayAnim ( channel , anim , gameLocal . time , blendTime ) ;
animator . CurrentAnim ( channel ) - > SetCycleCount ( cycle ) ;
animator . CurrentAnim ( channel ) - > SetStartTime ( starttime ) ;
}
}
}
} else {
animator . SyncAnimChannels ( channel , syncToChannel , gameLocal . time , blendTime ) ;
}
}
/***********************************************************************
Damage
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = =
idActor : : Gib
= = = = = = = = = = = =
*/
void idActor : : Gib ( const idVec3 & dir , const char * damageDefName ) {
// no gibbing in multiplayer - by self damage or by moving objects
if ( gameLocal . isMultiplayer ) {
return ;
}
// only gib once
if ( gibbed ) {
return ;
}
idAFEntity_Gibbable : : Gib ( dir , damageDefName ) ;
if ( head . GetEntity ( ) ) {
head . GetEntity ( ) - > Hide ( ) ;
}
StopSound ( SND_CHANNEL_VOICE , false ) ;
}
/*
= = = = = = = = = = = =
idActor : : 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
Bleeding wounds and surface overlays are applied in the collision code that
calls Damage ( )
= = = = = = = = = = = =
*/
2018-08-27 13:13:17 +00:00
//ivan note: Damage() is only used by idAI because idPlayer overrides it.
//ivan note: Pain() is used by idAI and idPlayer.
2011-12-06 18:20:15 +00:00
void idActor : : 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 ;
}
2018-08-27 13:13:17 +00:00
//gameLocal.Printf( "idActor::Damage - damageDefName: '%s' -location '%d' \n", damageDefName, location);
2011-11-22 21:28:15 +00:00
if ( ! inflictor ) {
inflictor = gameLocal . world ;
}
if ( ! attacker ) {
attacker = gameLocal . world ;
}
const idDict * damageDef = gameLocal . FindEntityDefDict ( damageDefName ) ;
if ( ! damageDef ) {
gameLocal . Error ( " Unknown damageDef '%s' " , damageDefName ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start
if ( damageDef - > GetBool ( " ignore_friends " ) ) {
if ( team = = attacker - > spawnArgs . GetInt ( " team " , " 0 " ) ) {
return ;
}
}
if ( ! gibbed ) {
CheckDamageFx ( damageDef ) ; //damaging fx
}
//ivan end
//REVILITY IDGUIDEDPROJECTILEX START
//Since there is no soul cube in Ruiner or need for one. We are replacing the soulcube special damage with a new projectile for special damage on spirits.
//if ( finalBoss && !inflictor->IsType( idSoulCubeMissile::Type ) ) {
//return;
//}
if ( finalBoss & & ! damageDef - > GetBool ( " damageSpirits " , " 0 " ) ) { //Ivan - was !inflictor->IsType( idGuidedProjectilex::Type )
return ;
}
//REVILITY IDGUIDEDPROJECTILEX END
2011-11-22 21:28:15 +00:00
int damage = damageDef - > GetInt ( " damage " ) * damageScale ;
2018-08-27 13:13:17 +00:00
//ivan start - damage anims code
int forceHighPain = damageDef - > GetInt ( " useHighPain " , " 0 " ) ; //was: 0; //-1 deny, 0 allow, 1 force
bool fromMelee = damageDef - > GetBool ( " melee " , " 0 " ) ;
bool useHighPain = false ;
//decide if we have to force highpain
//1 - from damagedef - not used.
//forceHighPain = damageDef->GetInt("forceHighPainAnim","0"); //-1 deny, 0 allow, 1 force
//2 - from player
if ( forceHighPain = = 0 ) { //if no preference is expressed
if ( attacker - > IsType ( idPlayer : : Type ) ) {
idPlayer * thePlayer = static_cast < idPlayer * > ( attacker ) ;
forceHighPain = thePlayer - > comboForceHighPain ;
}
}
//ivan end
// By Clone JCD For Improved damage behaviour
if ( health > 0 ) { // Make sure that an actor is alive when we go for Damage location
damage = GetDamageForLocation ( damage , location ) ; //damage multiplier
// gameLocal.Printf(" \n damage applied: %d", damage );
//ivan start - choose if we need to play highpain anims
addDamageToLocation ( damage , location ) ; //upd pain value
if ( forceHighPain = = 1 ) { //force
useHighPain = true ;
} else if ( forceHighPain = = 0 ) { //if no forced or denied...check
if ( checkDamageForLocation ( location ) ) { useHighPain = true ; }
} //else is denied -> false!
//ivan end
}
2011-11-22 21:28:15 +00:00
// inform the attacker that they hit someone
attacker - > DamageFeedback ( this , inflictor , damage ) ;
if ( damage > 0 ) {
health - = damage ;
if ( health < = 0 ) {
if ( health < - 999 ) {
health = - 999 ;
}
2018-08-27 13:13:17 +00:00
//Ivan start - headshot
if ( head . GetEntity ( ) ) {
if ( damageDef - > GetBool ( " check_headshot " ) ) { //damage requests checking headshots
if ( spawnArgs . GetInt ( " headshot_disabled " , " 0 " ) = = 0 ) { //headshots are not disabled on this actor
idStr damageGroup = GetDamageGroup ( location ) ;
if ( damageGroup . Length ( ) & & ( damageGroup = = " head " ) ) { //hit on head
//search the "headshot" script function
const function_t * func ;
func = scriptObject . GetFunction ( " headshot " ) ;
if ( func ) {
// create a thread and call the function
idThread * thread ;
thread = new idThread ( ) ;
thread - > CallFunction ( this , func , false ) ;
thread - > Start ( ) ;
//don't apply impulse
2018-09-22 21:52:23 +00:00
nextImpulse = gameLocal . time ; // was + 10 commented out 2018 revility. Was causing frozen ragdolls after head shots.
2018-08-27 13:13:17 +00:00
}
}
}
}
}
//Ivan end
2011-11-22 21:28:15 +00:00
Killed ( inflictor , attacker , damage , dir , location ) ;
2018-08-27 13:13:17 +00:00
//Improved Gibbing System by Clone JC Denton
int healthToGib = spawnArgs . GetInt ( " gibHealth " ) ; // GibHealth is suppossed to be declared in entityDef
if ( healthToGib = = 0 ) // If its not there, set it to default value
healthToGib = - 20 ;
if ( ( health < healthToGib ) & & spawnArgs . GetBool ( " gib " ) & & damageDef - > GetBool ( " gib " ) ) {
2011-11-22 21:28:15 +00:00
Gib ( dir , damageDefName ) ;
}
} else {
2018-08-27 13:13:17 +00:00
Pain ( inflictor , attacker , damage , dir , location , useHighPain , fromMelee ) ;
2011-11-22 21:28:15 +00:00
}
} else {
// don't accumulate knockback
if ( af . IsLoaded ( ) ) {
// clear impacts
af . Rest ( ) ;
// physics is turned off by calling af.Rest()
BecomeActive ( TH_PHYSICS ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : ClearPain
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : ClearPain ( void ) {
pain_debounce_time = 0 ;
}
2018-08-27 13:13:17 +00:00
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
2018-08-27 13:13:17 +00:00
idActor : : ChoosePainAnim
2011-11-22 21:28:15 +00:00
= = = = = = = = = = = = = = = = = = = = =
*/
2018-08-27 13:13:17 +00:00
void idActor : : ChoosePainAnim ( int location , bool useHighPain ) { //ivan - new function: code extracted from old idActor::Pain function
2011-11-22 21:28:15 +00:00
// set the pain anim
idStr damageGroup = GetDamageGroup ( location ) ;
2018-08-27 13:13:17 +00:00
//ivan start - set the anim prefix
idStr typePrefix ;
if ( useHighPain ) {
typePrefix = " highpain " ;
resetCurrentDamageForLocations ( ) ; //if we use an HighPain anim, reset the damage for all locations
} else {
typePrefix = " pain " ;
}
//ivan end
2011-11-22 21:28:15 +00:00
painAnim = " " ;
2018-08-27 13:13:17 +00:00
2011-11-22 21:28:15 +00:00
if ( animPrefix . Length ( ) ) {
2018-08-27 13:13:17 +00:00
if ( damageGroup . Length ( ) ) { //ivan - && ( damageGroup != "legs" )
sprintf ( painAnim , " %s_%s_%s " , animPrefix . c_str ( ) , typePrefix . c_str ( ) , damageGroup . c_str ( ) ) ; //ivan - typePrefix added insted of "pain"
2011-11-22 21:28:15 +00:00
if ( ! animator . HasAnim ( painAnim ) ) {
2018-08-27 13:13:17 +00:00
sprintf ( painAnim , " %s_%s " , typePrefix . c_str ( ) , damageGroup . c_str ( ) ) ; //ivan - typePrefix added insted of "pain"
2011-11-22 21:28:15 +00:00
if ( ! animator . HasAnim ( painAnim ) ) {
painAnim = " " ;
}
}
}
if ( ! painAnim . Length ( ) ) {
2018-08-27 13:13:17 +00:00
sprintf ( painAnim , " %s_%s " , animPrefix . c_str ( ) , typePrefix . c_str ( ) ) ; //ivan - typePrefix added insted of "pain"
2011-11-22 21:28:15 +00:00
if ( ! animator . HasAnim ( painAnim ) ) {
painAnim = " " ;
}
}
2018-08-27 13:13:17 +00:00
} else if ( damageGroup . Length ( ) ) { //ivan - && ( damageGroup != "legs" )
sprintf ( painAnim , " %s_%s " , typePrefix . c_str ( ) , damageGroup . c_str ( ) ) ; //ivan - typePrefix added insted of "pain"
//if ( !animator.HasAnim( painAnim ) ) { //ivan - why was the same thing checked twice ??
// sprintf( painAnim, "%s_%s", typePrefix.c_str(), damageGroup.c_str() ); //ivan - typePrefix added insted of "pain"
2011-11-22 21:28:15 +00:00
if ( ! animator . HasAnim ( painAnim ) ) {
painAnim = " " ;
}
2018-08-27 13:13:17 +00:00
//}
2011-11-22 21:28:15 +00:00
}
if ( ! painAnim . Length ( ) ) {
2018-08-27 13:13:17 +00:00
if ( useHighPain & & ! animator . HasAnim ( " highpain " ) ) { //ivan fix if "highpain" not found
painAnim = " pain " ;
} else {
painAnim = typePrefix ; //ivan - was "pain";
}
2011-11-22 21:28:15 +00:00
}
if ( g_debugDamage . GetBool ( ) ) {
2011-12-06 18:20:15 +00:00
gameLocal . Printf ( " Damage: joint: '%s', zone '%s', anim '%s' \n " , animator . GetJointName ( ( jointHandle_t ) location ) ,
2011-11-22 21:28:15 +00:00
damageGroup . c_str ( ) , painAnim . c_str ( ) ) ;
}
2018-08-27 13:13:17 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Pain
= = = = = = = = = = = = = = = = = = = = =
*/
//ivan note: Damage() is only used by idAI because idPlayer overrides it.
//ivan note: Pain() is used by idAI and idPlayer.
bool idActor : : Pain ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location , bool useHighPain , bool fromMelee ) { //ivan - useHighPain and fromMelee added
if ( af . IsLoaded ( ) ) {
// clear impacts
af . Rest ( ) ;
// physics is turned off by calling af.Rest()
BecomeActive ( TH_PHYSICS ) ;
}
if ( ! fromMelee ) { //ivan - ignore the "pain_delay" key if it's a melee damage
if ( gameLocal . time < pain_debounce_time ) {
return false ;
}
}
// don't play pain sounds more than necessary
pain_debounce_time = gameLocal . time + pain_delay ;
if ( health > 75 ) {
StartSound ( " snd_pain_small " , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
} else if ( health > 50 ) {
StartSound ( " snd_pain_medium " , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
} else if ( health > 25 ) {
StartSound ( " snd_pain_large " , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
} else {
StartSound ( " snd_pain_huge " , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
}
if ( ! allowPain | | ( gameLocal . time < painTime ) ) { //don't play it if it's disabled... even if fromMelee is true!
// don't play a pain anim
return false ;
}
2011-11-22 21:28:15 +00:00
2018-08-27 13:13:17 +00:00
if ( ! fromMelee ) { //ivan - ignore the "pain_threshold" key if it's a melee damage
if ( pain_threshold & & ( damage < pain_threshold ) ) {
return false ;
}
}
ChoosePainAnim ( location , useHighPain ) ;
2011-11-22 21:28:15 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SpawnGibs
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SpawnGibs ( const idVec3 & dir , const char * damageDefName ) {
idAFEntity_Gibbable : : SpawnGibs ( dir , damageDefName ) ;
RemoveAttachments ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : SetupDamageGroups
FIXME : only store group names once and store an index for each joint
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : SetupDamageGroups ( void ) {
int i ;
const idKeyValue * arg ;
idStr groupname ;
idList < jointHandle_t > jointList ;
int jointnum ;
float scale ;
// create damage zones
2018-08-27 13:13:17 +00:00
damageGroupsNames . SetNum ( 0 ) ;
2011-11-22 21:28:15 +00:00
damageGroups . SetNum ( animator . NumJoints ( ) ) ;
arg = spawnArgs . MatchPrefix ( " damage_zone " , NULL ) ;
while ( arg ) {
groupname = arg - > GetKey ( ) ;
groupname . Strip ( " damage_zone " ) ;
animator . GetJointList ( arg - > GetValue ( ) , jointList ) ;
for ( i = 0 ; i < jointList . Num ( ) ; i + + ) {
jointnum = jointList [ i ] ;
damageGroups [ jointnum ] = groupname ;
}
jointList . Clear ( ) ;
2018-08-27 13:13:17 +00:00
//ivan start
damageGroupsNames . Append ( groupname ) ;
//ivan start
2011-11-22 21:28:15 +00:00
arg = spawnArgs . MatchPrefix ( " damage_zone " , arg ) ;
}
// initilize the damage zones to normal damage
damageScale . SetNum ( animator . NumJoints ( ) ) ;
for ( i = 0 ; i < damageScale . Num ( ) ; i + + ) {
damageScale [ i ] = 1.0f ;
}
// set the percentage on damage zones
arg = spawnArgs . MatchPrefix ( " damage_scale " , NULL ) ;
while ( arg ) {
scale = atof ( arg - > GetValue ( ) ) ;
groupname = arg - > GetKey ( ) ;
groupname . Strip ( " damage_scale " ) ;
for ( i = 0 ; i < damageScale . Num ( ) ; i + + ) {
if ( damageGroups [ i ] = = groupname ) {
damageScale [ i ] = scale ;
}
}
arg = spawnArgs . MatchPrefix ( " damage_scale " , arg ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start - pain stuff
//init
highpainThreshold . SetNum ( damageGroupsNames . Num ( ) ) ;
highpainDecreaseRate . SetNum ( damageGroupsNames . Num ( ) ) ;
highpainCurrentDamage . SetNum ( damageGroupsNames . Num ( ) ) ;
for ( i = 0 ; i < highpainThreshold . Num ( ) ; i + + ) {
highpainThreshold [ i ] = 0.0f ; // initilize the max damage per zone to 0hp --> disabled on that zone
highpainDecreaseRate [ i ] = 0.0f ; // initilize the decrease rate per zone to 0hp per tick
highpainCurrentDamage [ i ] = 0.0f ; // initilize the current damage per zone to 0hp
}
// set the max damage for pain anims on damage zones
arg = spawnArgs . MatchPrefix ( " highpain_threshold " , NULL ) ;
while ( arg ) {
scale = atof ( arg - > GetValue ( ) ) ;
groupname = arg - > GetKey ( ) ;
groupname . Strip ( " highpain_threshold " ) ;
for ( i = 0 ; i < damageGroupsNames . Num ( ) ; i + + ) {
if ( damageGroupsNames [ i ] = = groupname ) {
highpainThreshold [ i ] = scale ;
}
}
arg = spawnArgs . MatchPrefix ( " highpain_threshold " , arg ) ;
}
// set the amount of damage that will be subtracted each tick on damage zones
arg = spawnArgs . MatchPrefix ( " highpain_resettime " , NULL ) ;
while ( arg ) {
scale = atof ( arg - > GetValue ( ) ) ;
groupname = arg - > GetKey ( ) ;
groupname . Strip ( " highpain_resettime " ) ;
for ( i = 0 ; i < damageGroupsNames . Num ( ) ; i + + ) {
if ( damageGroupsNames [ i ] = = groupname ) {
if ( scale > 0 ) {
highpainDecreaseRate [ i ] = highpainThreshold [ i ] / ( 60.0f * scale ) ; //this will be subtracted each tick (60 per second)
} else {
highpainDecreaseRate [ i ] = highpainThreshold [ i ] ; //if scale is 0, always remove all the damage
}
//gameLocal.Printf( "Setup damage: zone '%s', highpainDecreaseRate: %f \n", damageGroupsNames[i].c_str(), highpainDecreaseRate[ i ] );
}
}
arg = spawnArgs . MatchPrefix ( " highpain_resettime " , arg ) ;
}
//ivan end
}
//ivan start
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : addDamageToLocation
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : addDamageToLocation ( int damage , int location ) {
idStr damageGroup = GetDamageGroup ( location ) ; //from joint to group name
for ( int i = 0 ; i < damageGroupsNames . Num ( ) ; i + + ) {
if ( damageGroupsNames [ i ] = = damageGroup ) { //from group name to number
if ( highpainThreshold [ i ] > 0 ) { //update only if enabled on that zone
highpainCurrentDamage [ i ] + = damage ;
//gameLocal.Printf( "Added damage: zone '%s', added: %d ,painvalue: %f \n", damageGroupsNames[i].c_str(), damage ,highpainCurrentDamage[ i ] );
}
return ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : checkDamageForLocation
= = = = = = = = = = = = = = = = = = = = =
*/
bool idActor : : checkDamageForLocation ( int location ) { //returns true if the damage is greater than the max
idStr damageGroup = GetDamageGroup ( location ) ; //from joint to group name
for ( int i = 0 ; i < damageGroupsNames . Num ( ) ; i + + ) {
if ( damageGroupsNames [ i ] = = damageGroup ) { //from group name to number
if ( ( highpainThreshold [ i ] > 0 ) & & ( highpainCurrentDamage [ i ] > highpainThreshold [ i ] ) ) {
//gameLocal.Printf( "Exceeded damage in zone '%s'\n", damageGroupsNames[i].c_str() );
return true ;
}
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : resetCurrentDamageForLocations
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : resetCurrentDamageForLocations ( void ) { //returns true if the damage is greater than the max
for ( int i = 0 ; i < highpainCurrentDamage . Num ( ) ; i + + ) {
highpainCurrentDamage [ i ] = 0.0f ;
//gameLocal.Printf( "reset damage: zone '%s', painvalue: '%f'\n", damageGroupsNames[i].c_str(), highpainCurrentDamage[ i ] );
}
2011-11-22 21:28:15 +00:00
}
2018-08-27 13:13:17 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : updateCurrentDamageForLocations - this should be called in a " think " function of the class that uses this stuff . Since there ' s no " think " function for idActor it ' ll be only called in idAI . But it ' s ready to use for players too .
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : updateCurrentDamageForLocations ( void ) { //decrease pain values
for ( int location = 0 ; location < highpainCurrentDamage . Num ( ) ; location + + ) {
if ( highpainCurrentDamage [ location ] > 0 ) {
highpainCurrentDamage [ location ] - = highpainDecreaseRate [ location ] ;
//set it to 0 if we get a negative number
if ( highpainCurrentDamage [ location ] < 0 ) highpainCurrentDamage [ location ] = 0 ;
/*
if ( g_debugDamage . GetBool ( ) ) {
gameLocal . Printf ( " Upd damage: zone '%s', painvalue: '%f' \n " , damageGroupsNames [ location ] . c_str ( ) , highpainCurrentDamage [ location ] ) ;
} */
}
}
}
//ivan end
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetDamageForLocation
= = = = = = = = = = = = = = = = = = = = =
*/
int idActor : : GetDamageForLocation ( int damage , int location ) {
if ( ( location < 0 ) | | ( location > = damageScale . Num ( ) ) ) {
return damage ;
}
return ( int ) ceil ( damage * damageScale [ location ] ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetDamageGroup
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idActor : : GetDamageGroup ( int location ) {
if ( ( location < 0 ) | | ( location > = damageGroups . Num ( ) ) ) {
return " " ;
}
return damageGroups [ location ] ;
}
/***********************************************************************
Events
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_EnableEyeFocus
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : PlayFootStepSound ( void ) {
const char * sound = NULL ;
const idMaterial * material ;
if ( ! GetPhysics ( ) - > HasGroundContacts ( ) ) {
return ;
}
// start footstep sound based on material type
material = GetPhysics ( ) - > GetContact ( 0 ) . material ;
if ( material ! = NULL ) {
sound = spawnArgs . GetString ( va ( " snd_footstep_%s " , gameLocal . sufaceTypeNames [ material - > GetSurfaceType ( ) ] ) ) ;
}
if ( * sound = = ' \0 ' ) {
sound = spawnArgs . GetString ( " snd_footstep " ) ;
}
if ( * sound ! = ' \0 ' ) {
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_EnableEyeFocus
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_EnableEyeFocus ( void ) {
allowEyeFocus = true ;
blink_time = gameLocal . time + blink_min + gameLocal . random . RandomFloat ( ) * ( blink_max - blink_min ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_DisableEyeFocus
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_DisableEyeFocus ( void ) {
allowEyeFocus = false ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
idEntity * headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headEnt - > GetAnimator ( ) - > Clear ( ANIMCHANNEL_EYELIDS , gameLocal . time , FRAME2MS ( 2 ) ) ;
} else {
animator . Clear ( ANIMCHANNEL_EYELIDS , gameLocal . time , FRAME2MS ( 2 ) ) ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_Footstep
= = = = = = = = = = = = = = =
*/
void idActor : : Event_Footstep ( void ) {
PlayFootStepSound ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_EnableWalkIK
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_EnableWalkIK ( void ) {
walkIK . EnableAll ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_DisableWalkIK
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_DisableWalkIK ( void ) {
walkIK . DisableAll ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_EnableLegIK
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_EnableLegIK ( int num ) {
walkIK . EnableLeg ( num ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_DisableLegIK
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_DisableLegIK ( int num ) {
walkIK . DisableLeg ( num ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_PreventPain
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_PreventPain ( float duration ) {
painTime = gameLocal . time + SEC2MS ( duration ) ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_DisablePain
= = = = = = = = = = = = = = =
*/
void idActor : : Event_DisablePain ( void ) {
allowPain = false ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_EnablePain
= = = = = = = = = = = = = = =
*/
void idActor : : Event_EnablePain ( void ) {
allowPain = true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_GetPainAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_GetPainAnim ( void ) {
if ( ! painAnim . Length ( ) ) {
idThread : : ReturnString ( " pain " ) ;
} else {
idThread : : ReturnString ( painAnim ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_SetAnimPrefix
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_SetAnimPrefix ( const char * prefix ) {
animPrefix = prefix ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_StopAnim
= = = = = = = = = = = = = = =
*/
void idActor : : Event_StopAnim ( int channel , int frames ) {
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . StopAnim ( frames ) ;
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . StopAnim ( frames ) ;
break ;
case ANIMCHANNEL_LEGS :
legsAnim . StopAnim ( frames ) ;
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_PlayAnim
= = = = = = = = = = = = = = =
*/
void idActor : : Event_PlayAnim ( int channel , const char * animname ) {
animFlags_t flags ;
idEntity * headEnt ;
int anim ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
anim = GetAnim ( channel , animname ) ;
if ( ! anim ) {
if ( ( channel = = ANIMCHANNEL_HEAD ) & & head . GetEntity ( ) ) {
gameLocal . DPrintf ( " missing '%s' animation on '%s' (%s) \n " , animname , name . c_str ( ) , spawnArgs . GetString ( " def_head " , " " ) ) ;
} else {
gameLocal . DPrintf ( " missing '%s' animation on '%s' (%s) \n " , animname , name . c_str ( ) , GetEntityDefName ( ) ) ;
}
idThread : : ReturnInt ( 0 ) ;
return ;
}
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headAnim . idleAnim = false ;
headAnim . PlayAnim ( anim ) ;
flags = headAnim . GetAnimFlags ( ) ;
if ( ! flags . prevent_idle_override ) {
if ( torsoAnim . IsIdle ( ) ) {
torsoAnim . animBlendFrames = headAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_HEAD , headAnim . lastAnimBlendFrames ) ;
if ( legsAnim . IsIdle ( ) ) {
legsAnim . animBlendFrames = headAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_HEAD , headAnim . lastAnimBlendFrames ) ;
}
}
}
}
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . idleAnim = false ;
torsoAnim . PlayAnim ( anim ) ;
flags = torsoAnim . GetAnimFlags ( ) ;
2018-08-27 13:13:17 +00:00
//ivan test
if ( force_torso_override ) {
legsAnim . animBlendFrames = torsoAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
} else
//ivan end
2011-11-22 21:28:15 +00:00
if ( ! flags . prevent_idle_override ) {
if ( headAnim . IsIdle ( ) ) {
headAnim . animBlendFrames = torsoAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
}
if ( legsAnim . IsIdle ( ) ) {
legsAnim . animBlendFrames = torsoAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
}
}
break ;
case ANIMCHANNEL_LEGS :
legsAnim . idleAnim = false ;
legsAnim . PlayAnim ( anim ) ;
flags = legsAnim . GetAnimFlags ( ) ;
if ( ! flags . prevent_idle_override ) {
if ( torsoAnim . IsIdle ( ) ) {
torsoAnim . animBlendFrames = legsAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
if ( headAnim . IsIdle ( ) ) {
headAnim . animBlendFrames = legsAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
}
}
}
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
break ;
}
idThread : : ReturnInt ( 1 ) ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_PlayCycle
= = = = = = = = = = = = = = =
*/
void idActor : : Event_PlayCycle ( int channel , const char * animname ) {
animFlags_t flags ;
int anim ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
anim = GetAnim ( channel , animname ) ;
if ( ! anim ) {
if ( ( channel = = ANIMCHANNEL_HEAD ) & & head . GetEntity ( ) ) {
gameLocal . DPrintf ( " missing '%s' animation on '%s' (%s) \n " , animname , name . c_str ( ) , spawnArgs . GetString ( " def_head " , " " ) ) ;
} else {
gameLocal . DPrintf ( " missing '%s' animation on '%s' (%s) \n " , animname , name . c_str ( ) , GetEntityDefName ( ) ) ;
}
idThread : : ReturnInt ( false ) ;
return ;
}
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . idleAnim = false ;
headAnim . CycleAnim ( anim ) ;
flags = headAnim . GetAnimFlags ( ) ;
if ( ! flags . prevent_idle_override ) {
if ( torsoAnim . IsIdle ( ) & & legsAnim . IsIdle ( ) ) {
torsoAnim . animBlendFrames = headAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_HEAD , headAnim . lastAnimBlendFrames ) ;
legsAnim . animBlendFrames = headAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_HEAD , headAnim . lastAnimBlendFrames ) ;
}
}
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . idleAnim = false ;
torsoAnim . CycleAnim ( anim ) ;
flags = torsoAnim . GetAnimFlags ( ) ;
if ( ! flags . prevent_idle_override ) {
if ( headAnim . IsIdle ( ) ) {
headAnim . animBlendFrames = torsoAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
}
if ( legsAnim . IsIdle ( ) ) {
legsAnim . animBlendFrames = torsoAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
}
}
break ;
case ANIMCHANNEL_LEGS :
legsAnim . idleAnim = false ;
legsAnim . CycleAnim ( anim ) ;
flags = legsAnim . GetAnimFlags ( ) ;
if ( ! flags . prevent_idle_override ) {
if ( torsoAnim . IsIdle ( ) ) {
torsoAnim . animBlendFrames = legsAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
if ( headAnim . IsIdle ( ) ) {
headAnim . animBlendFrames = legsAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
}
}
}
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
}
idThread : : ReturnInt ( true ) ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_IdleAnim
= = = = = = = = = = = = = = =
*/
void idActor : : Event_IdleAnim ( int channel , const char * animname ) {
int anim ;
2011-12-06 18:20:15 +00:00
anim = GetAnim ( channel , animname ) ;
2011-11-22 21:28:15 +00:00
if ( ! anim ) {
if ( ( channel = = ANIMCHANNEL_HEAD ) & & head . GetEntity ( ) ) {
gameLocal . DPrintf ( " missing '%s' animation on '%s' (%s) \n " , animname , name . c_str ( ) , spawnArgs . GetString ( " def_head " , " " ) ) ;
} else {
gameLocal . DPrintf ( " missing '%s' animation on '%s' (%s) \n " , animname , name . c_str ( ) , GetEntityDefName ( ) ) ;
}
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . BecomeIdle ( ) ;
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . BecomeIdle ( ) ;
break ;
case ANIMCHANNEL_LEGS :
legsAnim . BecomeIdle ( ) ;
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
}
idThread : : ReturnInt ( false ) ;
return ;
}
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . BecomeIdle ( ) ;
if ( torsoAnim . GetAnimFlags ( ) . prevent_idle_override ) {
// don't sync to torso body if it doesn't override idle anims
headAnim . CycleAnim ( anim ) ;
} else if ( torsoAnim . IsIdle ( ) & & legsAnim . IsIdle ( ) ) {
// everything is idle, so play the anim on the head and copy it to the torso and legs
headAnim . CycleAnim ( anim ) ;
torsoAnim . animBlendFrames = headAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_HEAD , headAnim . lastAnimBlendFrames ) ;
legsAnim . animBlendFrames = headAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_HEAD , headAnim . lastAnimBlendFrames ) ;
} else if ( torsoAnim . IsIdle ( ) ) {
// sync the head and torso to the legs
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_LEGS , headAnim . animBlendFrames ) ;
torsoAnim . animBlendFrames = headAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_LEGS , torsoAnim . animBlendFrames ) ;
} else {
// sync the head to the torso
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_TORSO , headAnim . animBlendFrames ) ;
}
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . BecomeIdle ( ) ;
if ( legsAnim . GetAnimFlags ( ) . prevent_idle_override ) {
// don't sync to legs if legs anim doesn't override idle anims
torsoAnim . CycleAnim ( anim ) ;
} else if ( legsAnim . IsIdle ( ) ) {
// play the anim in both legs and torso
torsoAnim . CycleAnim ( anim ) ;
legsAnim . animBlendFrames = torsoAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
} else {
// sync the anim to the legs
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_LEGS , torsoAnim . animBlendFrames ) ;
}
if ( headAnim . IsIdle ( ) ) {
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
}
break ;
case ANIMCHANNEL_LEGS :
legsAnim . BecomeIdle ( ) ;
if ( torsoAnim . GetAnimFlags ( ) . prevent_idle_override ) {
// don't sync to torso if torso anim doesn't override idle anims
legsAnim . CycleAnim ( anim ) ;
} else if ( torsoAnim . IsIdle ( ) ) {
// play the anim in both legs and torso
legsAnim . CycleAnim ( anim ) ;
torsoAnim . animBlendFrames = legsAnim . lastAnimBlendFrames ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
if ( headAnim . IsIdle ( ) ) {
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
}
} else {
// sync the anim to the torso
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_TORSO , legsAnim . animBlendFrames ) ;
}
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
}
idThread : : ReturnInt ( true ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_SetSyncedAnimWeight
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_SetSyncedAnimWeight ( int channel , int anim , float weight ) {
idEntity * headEnt ;
headEnt = head . GetEntity ( ) ;
switch ( channel ) {
case ANIMCHANNEL_HEAD :
if ( headEnt ) {
animator . CurrentAnim ( ANIMCHANNEL_ALL ) - > SetSyncedAnimWeight ( anim , weight ) ;
} else {
animator . CurrentAnim ( ANIMCHANNEL_HEAD ) - > SetSyncedAnimWeight ( anim , weight ) ;
}
if ( torsoAnim . IsIdle ( ) ) {
animator . CurrentAnim ( ANIMCHANNEL_TORSO ) - > SetSyncedAnimWeight ( anim , weight ) ;
if ( legsAnim . IsIdle ( ) ) {
animator . CurrentAnim ( ANIMCHANNEL_LEGS ) - > SetSyncedAnimWeight ( anim , weight ) ;
}
}
break ;
case ANIMCHANNEL_TORSO :
animator . CurrentAnim ( ANIMCHANNEL_TORSO ) - > SetSyncedAnimWeight ( anim , weight ) ;
if ( legsAnim . IsIdle ( ) ) {
animator . CurrentAnim ( ANIMCHANNEL_LEGS ) - > SetSyncedAnimWeight ( anim , weight ) ;
}
if ( headEnt & & headAnim . IsIdle ( ) ) {
animator . CurrentAnim ( ANIMCHANNEL_ALL ) - > SetSyncedAnimWeight ( anim , weight ) ;
}
break ;
case ANIMCHANNEL_LEGS :
animator . CurrentAnim ( ANIMCHANNEL_LEGS ) - > SetSyncedAnimWeight ( anim , weight ) ;
if ( torsoAnim . IsIdle ( ) ) {
animator . CurrentAnim ( ANIMCHANNEL_TORSO ) - > SetSyncedAnimWeight ( anim , weight ) ;
if ( headEnt & & headAnim . IsIdle ( ) ) {
animator . CurrentAnim ( ANIMCHANNEL_ALL ) - > SetSyncedAnimWeight ( anim , weight ) ;
}
}
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_OverrideAnim
= = = = = = = = = = = = = = =
*/
void idActor : : Event_OverrideAnim ( int channel ) {
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . Disable ( ) ;
if ( ! torsoAnim . IsIdle ( ) ) {
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
} else {
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
}
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . Disable ( ) ;
SyncAnimChannels ( ANIMCHANNEL_TORSO , ANIMCHANNEL_LEGS , legsAnim . lastAnimBlendFrames ) ;
if ( headAnim . IsIdle ( ) ) {
SyncAnimChannels ( ANIMCHANNEL_HEAD , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
}
break ;
case ANIMCHANNEL_LEGS :
legsAnim . Disable ( ) ;
SyncAnimChannels ( ANIMCHANNEL_LEGS , ANIMCHANNEL_TORSO , torsoAnim . lastAnimBlendFrames ) ;
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_EnableAnim
= = = = = = = = = = = = = = =
*/
void idActor : : Event_EnableAnim ( int channel , int blendFrames ) {
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . Enable ( blendFrames ) ;
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . Enable ( blendFrames ) ;
break ;
case ANIMCHANNEL_LEGS :
legsAnim . Enable ( blendFrames ) ;
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_SetBlendFrames
= = = = = = = = = = = = = = =
*/
void idActor : : Event_SetBlendFrames ( int channel , int blendFrames ) {
switch ( channel ) {
case ANIMCHANNEL_HEAD :
headAnim . animBlendFrames = blendFrames ;
headAnim . lastAnimBlendFrames = blendFrames ;
break ;
case ANIMCHANNEL_TORSO :
torsoAnim . animBlendFrames = blendFrames ;
torsoAnim . lastAnimBlendFrames = blendFrames ;
break ;
case ANIMCHANNEL_LEGS :
legsAnim . animBlendFrames = blendFrames ;
legsAnim . lastAnimBlendFrames = blendFrames ;
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_GetBlendFrames
= = = = = = = = = = = = = = =
*/
void idActor : : Event_GetBlendFrames ( int channel ) {
switch ( channel ) {
case ANIMCHANNEL_HEAD :
idThread : : ReturnInt ( headAnim . animBlendFrames ) ;
break ;
case ANIMCHANNEL_TORSO :
idThread : : ReturnInt ( torsoAnim . animBlendFrames ) ;
break ;
case ANIMCHANNEL_LEGS :
idThread : : ReturnInt ( legsAnim . animBlendFrames ) ;
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_AnimState
= = = = = = = = = = = = = = =
*/
void idActor : : Event_AnimState ( int channel , const char * statename , int blendFrames ) {
SetAnimState ( channel , statename , blendFrames ) ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_GetAnimState
= = = = = = = = = = = = = = =
*/
void idActor : : Event_GetAnimState ( int channel ) {
const char * state ;
state = GetAnimState ( channel ) ;
idThread : : ReturnString ( state ) ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_InAnimState
= = = = = = = = = = = = = = =
*/
void idActor : : Event_InAnimState ( int channel , const char * statename ) {
bool instate ;
instate = InAnimState ( channel , statename ) ;
idThread : : ReturnInt ( instate ) ;
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_FinishAction
= = = = = = = = = = = = = = =
*/
void idActor : : Event_FinishAction ( const char * actionname ) {
if ( waitState = = actionname ) {
SetWaitState ( " " ) ;
}
}
/*
= = = = = = = = = = = = = = =
idActor : : Event_AnimDone
= = = = = = = = = = = = = = =
*/
void idActor : : Event_AnimDone ( int channel , int blendFrames ) {
bool result ;
switch ( channel ) {
case ANIMCHANNEL_HEAD :
result = headAnim . AnimDone ( blendFrames ) ;
idThread : : ReturnInt ( result ) ;
break ;
case ANIMCHANNEL_TORSO :
result = torsoAnim . AnimDone ( blendFrames ) ;
idThread : : ReturnInt ( result ) ;
break ;
case ANIMCHANNEL_LEGS :
result = legsAnim . AnimDone ( blendFrames ) ;
idThread : : ReturnInt ( result ) ;
break ;
default :
gameLocal . Error ( " Unknown anim group " ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_HasAnim
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_HasAnim ( int channel , const char * animname ) {
2011-11-30 22:14:44 +00:00
if ( GetAnim ( channel , animname ) ! = 0 ) {
2011-11-22 21:28:15 +00:00
idThread : : ReturnFloat ( 1.0f ) ;
} else {
idThread : : ReturnFloat ( 0.0f ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_CheckAnim
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_CheckAnim ( int channel , const char * animname ) {
if ( ! GetAnim ( channel , animname ) ) {
if ( animPrefix . Length ( ) ) {
gameLocal . Error ( " Can't find anim '%s_%s' for '%s' " , animPrefix . c_str ( ) , animname , name . c_str ( ) ) ;
} else {
gameLocal . Error ( " Can't find anim '%s' for '%s' " , animname , name . c_str ( ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_ChooseAnim
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_ChooseAnim ( int channel , const char * animname ) {
int anim ;
anim = GetAnim ( channel , animname ) ;
if ( anim ) {
if ( channel = = ANIMCHANNEL_HEAD ) {
if ( head . GetEntity ( ) ) {
idThread : : ReturnString ( head . GetEntity ( ) - > GetAnimator ( ) - > AnimFullName ( anim ) ) ;
return ;
}
} else {
idThread : : ReturnString ( animator . AnimFullName ( anim ) ) ;
return ;
}
}
idThread : : ReturnString ( " " ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_AnimLength
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_AnimLength ( int channel , const char * animname ) {
int anim ;
anim = GetAnim ( channel , animname ) ;
if ( anim ) {
if ( channel = = ANIMCHANNEL_HEAD ) {
if ( head . GetEntity ( ) ) {
idThread : : ReturnFloat ( MS2SEC ( head . GetEntity ( ) - > GetAnimator ( ) - > AnimLength ( anim ) ) ) ;
return ;
}
} else {
idThread : : ReturnFloat ( MS2SEC ( animator . AnimLength ( anim ) ) ) ;
return ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
idThread : : ReturnFloat ( 0.0f ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_AnimDistance
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_AnimDistance ( int channel , const char * animname ) {
int anim ;
anim = GetAnim ( channel , animname ) ;
if ( anim ) {
if ( channel = = ANIMCHANNEL_HEAD ) {
if ( head . GetEntity ( ) ) {
idThread : : ReturnFloat ( head . GetEntity ( ) - > GetAnimator ( ) - > TotalMovementDelta ( anim ) . Length ( ) ) ;
return ;
}
} else {
idThread : : ReturnFloat ( animator . TotalMovementDelta ( anim ) . Length ( ) ) ;
return ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
idThread : : ReturnFloat ( 0.0f ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_HasEnemies
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_HasEnemies ( void ) {
bool hasEnemy ;
hasEnemy = HasEnemies ( ) ;
idThread : : ReturnInt ( hasEnemy ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_NextEnemy
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_NextEnemy ( idEntity * ent ) {
idActor * actor ;
if ( ! ent | | ( ent = = this ) ) {
actor = enemyList . Next ( ) ;
} else {
if ( ! ent - > IsType ( idActor : : Type ) ) {
gameLocal . Error ( " '%s' cannot be an enemy " , ent - > name . c_str ( ) ) ;
}
actor = static_cast < idActor * > ( ent ) ;
if ( actor - > enemyNode . ListHead ( ) ! = & enemyList ) {
gameLocal . Error ( " '%s' is not in '%s' enemy list " , actor - > name . c_str ( ) , name . c_str ( ) ) ;
}
}
for ( ; actor ! = NULL ; actor = actor - > enemyNode . Next ( ) ) {
if ( ! actor - > fl . hidden ) {
idThread : : ReturnEntity ( actor ) ;
return ;
}
}
2011-12-06 18:20:15 +00:00
idThread : : ReturnEntity ( NULL ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_ClosestEnemyToPoint
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_ClosestEnemyToPoint ( const idVec3 & pos ) {
idActor * bestEnt = ClosestEnemyToPoint ( pos ) ;
idThread : : ReturnEntity ( bestEnt ) ;
}
/*
= = = = = = = = = = = = = = = =
idActor : : Event_StopSound
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_StopSound ( int channel , int netSync ) {
if ( channel = = SND_CHANNEL_VOICE ) {
idEntity * headEnt = head . GetEntity ( ) ;
if ( headEnt ) {
headEnt - > StopSound ( channel , ( netSync ! = 0 ) ) ;
}
}
StopSound ( channel , ( netSync ! = 0 ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_SetNextState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_SetNextState ( const char * name ) {
idealState = GetScriptFunction ( name ) ;
if ( idealState = = state ) {
state = NULL ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_SetState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_SetState ( const char * name ) {
idealState = GetScriptFunction ( name ) ;
if ( idealState = = state ) {
state = NULL ;
}
scriptThread - > DoneProcessing ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_GetState
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_GetState ( void ) {
if ( state ) {
idThread : : ReturnString ( state - > Name ( ) ) ;
} else {
idThread : : ReturnString ( " " ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : Event_GetHead
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : Event_GetHead ( void ) {
idThread : : ReturnEntity ( head . GetEntity ( ) ) ;
}
2018-08-27 13:13:17 +00:00
//ivan start - particles
void idActor : : TriggerFX ( const char * joint , const char * fx , bool bindToJoint , bool orientated ) { //ivan - bool bindToJoint, bool orientated added
if ( ! strcmp ( joint , " origin " ) ) {
idEntityFx : : StartFx ( fx , NULL , NULL , this , true ) ;
} else {
idVec3 joint_origin ;
idMat3 joint_axis ;
jointHandle_t jointNum ;
jointNum = animator . GetJointHandle ( joint ) ;
if ( jointNum = = INVALID_JOINT ) {
gameLocal . Warning ( " Unknown fx joint '%s' on entity %s " , joint , name . c_str ( ) ) ;
return ;
}
GetJointWorldTransform ( jointNum , gameLocal . time , joint_origin , joint_axis ) ;
//idEntityFx::StartFx( fx, &joint_origin, &joint_axis, this, true );
idEntityFx : : StartFx ( fx , & joint_origin , & joint_axis , this , true , orientated , ( bindToJoint ? jointNum : INVALID_JOINT ) ) ; //ivan - joint passed... I wonder how they thought to bind it to a joint... without knowing the joint O_o
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : StartEmitter
= = = = = = = = = = = = = = = = = = = = =
*/
idEntity * idActor : : StartEmitter ( const char * name , const char * joint , const char * particle ) {
idEntity * existing = GetEmitter ( name ) ;
if ( existing ) {
return existing ;
}
jointHandle_t jointNum ;
jointNum = animator . GetJointHandle ( joint ) ;
idVec3 offset ;
idMat3 axis ;
GetJointWorldTransform ( jointNum , gameLocal . time , offset , axis ) ;
/*animator.GetJointTransform( jointNum, gameLocal.time, offset, axis );
offset = GetPhysics ( ) - > GetOrigin ( ) + offset * GetPhysics ( ) - > GetAxis ( ) ;
axis = axis * GetPhysics ( ) - > GetAxis ( ) ; */
idDict args ;
const idDeclEntityDef * emitterDef = gameLocal . FindEntityDef ( " func_emitter " , false ) ;
args = emitterDef - > dict ;
args . Set ( " model " , particle ) ;
args . Set ( " origin " , offset . ToString ( ) ) ;
args . SetBool ( " start_off " , true ) ;
idEntity * ent ;
gameLocal . SpawnEntityDef ( args , & ent , false ) ;
ent - > GetPhysics ( ) - > SetOrigin ( offset ) ;
// case 1: joint axis
ent - > GetPhysics ( ) - > SetAxis ( axis ) ;
/*
// case 2: joint axis - z fixed
// align z-axis of model with the direction
idVec3 tmp ;
//axis = (viewAxis[ 0 ] * physicsObj.GetGravityAxis()).ToMat3();
axis = ( viewAxis [ 0 ] * GetPhysics ( ) - > GetAxis ( ) ) . ToMat3 ( ) ; //ivan fix - no physicsObj here...
tmp = axis [ 2 ] ;
axis [ 2 ] = axis [ 0 ] ;
axis [ 0 ] = - tmp ;
ent - > GetPhysics ( ) - > SetAxis ( axis ) ;
*/
/*
// case 3: entity axis
//axis = physicsObj.GetGravityAxis();
axis = GetPhysics ( ) - > GetAxis ( ) ; //ivan fix - no physicsObj here...
ent - > GetPhysics ( ) - > SetAxis ( axis ) ;
*/
ent - > GetPhysics ( ) - > GetClipModel ( ) - > SetOwner ( this ) ;
//Keep a reference to the emitter so we can track it
funcEmitter_t newEmitter ;
strcpy ( newEmitter . name , name ) ;
newEmitter . particle = ( idFuncEmitter * ) ent ;
newEmitter . joint = jointNum ;
funcEmitters . Set ( newEmitter . name , newEmitter ) ;
//Bind it to the joint and make it active
newEmitter . particle - > BindToJoint ( this , jointNum , true ) ;
newEmitter . particle - > BecomeActive ( TH_THINK ) ;
newEmitter . particle - > Show ( ) ;
newEmitter . particle - > PostEventMS ( & EV_Activate , 0 , this ) ;
return newEmitter . particle ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : GetEmitter
= = = = = = = = = = = = = = = = = = = = =
*/
idEntity * idActor : : GetEmitter ( const char * name ) {
funcEmitter_t * emitter ;
funcEmitters . Get ( name , & emitter ) ;
if ( emitter ) {
return emitter - > particle ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : StopEmitter
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : StopEmitter ( const char * name ) {
funcEmitter_t * emitter ;
funcEmitters . Get ( name , & emitter ) ;
if ( emitter ) {
emitter - > particle - > Unbind ( ) ;
emitter - > particle - > PostEventMS ( & EV_Remove , 0 ) ;
funcEmitters . Remove ( name ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idAI : : Event_TriggerFX
= = = = = = = = = = = = = = = =
*/
void idActor : : Event_TriggerFX ( const char * joint , const char * fx , int bindToJoint , int orientated ) { //ivan - int bindToJoint, int orientated added
TriggerFX ( joint , fx , ( bindToJoint ! = 0 ) , ( orientated ! = 0 ) ) ;
}
void idActor : : Event_StartEmitter ( const char * name , const char * joint , const char * particle ) {
idEntity * ent = StartEmitter ( name , joint , particle ) ;
idThread : : ReturnEntity ( ent ) ;
}
void idActor : : Event_GetEmitter ( const char * name ) {
idThread : : ReturnEntity ( GetEmitter ( name ) ) ;
}
void idActor : : Event_StopEmitter ( const char * name ) {
StopEmitter ( name ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : CheckDamageFx
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : CheckDamageFx ( const idDict * damageDef ) {
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 ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : StartDamageFx
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : StartDamageFx ( int type ) {
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 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idActor : : StopDamageFxs
= = = = = = = = = = = = = = = = = = = = =
*/
void idActor : : StopDamageFxs ( void ) {
int i ;
idDamagingFx * tempFx ;
//set the end time
for ( i = dmgFxEntities . Num ( ) - 1 ; i > = 0 ; i - - ) {
tempFx = dmgFxEntities [ i ] . GetEntity ( ) ;
if ( tempFx ) {
tempFx - > FadeOutFx ( ) ;
}
}
}
2018-08-27 13:13:36 +00:00
//ivan end