/* =========================================================================== IceTech GPL Source Code Copyright (C) 2026 Justin Marshall This file is part of the IceTech GPL Source Code (?IceTech Source Code?). IceTech 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. IceTech 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 IceTech Source Code. If not, see . In addition, the IceTech 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 IceTech 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 Justin Marshall, justinmarshall20@gmail.com =========================================================================== */ #ifndef __GAME_ACTOR_H__ #define __GAME_ACTOR_H__ /* =============================================================================== idActor =============================================================================== */ class idDeclParticle; class idAnimState { public: bool idleAnim; int animBlendFrames; int lastAnimBlendFrames; // allows override anims to blend based on the last transition time public: idAnimState(); ~idAnimState(); void Save(idSaveGame* savefile) const; void Restore(idRestoreGame* savefile); void Init(idEntity* owner, idAnimator* _animator, int animchannel); void Shutdown(void); void SetState(const char* name, int blendFrames, int flags = 0); void PostState(const char* name, int blendFrames = 0, int delay = 0, int flags = 0); void StopAnim(int frames); void PlayAnim(int anim); void CycleAnim(int anim); void BecomeIdle(void); bool UpdateState(void); bool Disabled(void) const; void Enable(int blendFrames); void Disable(void); bool AnimDone(int blendFrames) const; bool IsIdle(void) const; animFlags_t GetAnimFlags(void) const; rvStateThread& GetStateThread(void); idAnimator* GetAnimator(void) const { return animator; }; private: // RAVEN BEGIN // bdube: converted self to entity ptr so any entity can use it idEntity* self; // RAVEN END idAnimator* animator; int channel; bool disabled; rvStateThread stateThread; }; class idAttachInfo { public: idEntityPtr ent; int channel; }; typedef struct { jointModTransform_t mod; jointHandle_t from; jointHandle_t to; } copyJoints_t; class idActor : public idAFEntity_Gibbable { public: friend class rvmAIObject; CLASS_PROTOTYPE( idActor ); int team; int rank; // monsters don't fight back if the attacker's rank is higher idMat3 viewAxis; // view axis of the actor idLinkList enemyNode; // node linked into an entity's enemy list for quick lookups of who is attacking him idLinkList enemyList; // list of characters that have targeted the player as their enemy public: idActor( void ); virtual ~idActor( void ); void Spawn( void ); virtual void Restart( void ); void Save( idSaveGame *savefile ) const; void Restore( idRestoreGame *savefile ); virtual void Hide( void ); virtual void Show( void ); virtual int GetDefaultSurfaceType( void ) const; virtual void ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material ); virtual bool LoadAF( void ); void SetupBody( void ); void CheckBlink( void ); void SetAnimState(int channel, const char* statename, int blendFrames, int flags); void PostAnimState(int channel, const char* statename, int blendFrames, int delay = 0, int flags = 0); void StopAnimState(int channel); virtual bool GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ); virtual bool GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ); // script state management void ShutdownThreads( void ); virtual bool ShouldConstructScriptObjectAtSpawn( void ) const; virtual idThread * ConstructScriptObject( void ); void UpdateScript( void ); const function_t *GetScriptFunction( const char *funcname ); void SetState( const function_t *newState ); void SetState( const char *statename ); // vision testing void SetEyeHeight( float height ); float EyeHeight( void ) const; idVec3 EyeOffset( void ) const; idVec3 GetEyePosition( void ) const; virtual void GetViewPos( idVec3 &origin, idMat3 &axis ) const; void SetFOV( float fov ); bool CheckFOV( const idVec3 &pos ) const; bool CanSee( idEntity *ent, bool useFOV ) const; bool PointVisible( const idVec3 &point ) const; virtual void GetAIAimTargets( const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos ); // damage void SetupDamageGroups( void ); virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location ); int GetDamageForLocation( int damage, int location ); const char * GetDamageGroup( int location ); void ClearPain( void ); virtual bool Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ); // model/combat model/ragdoll void SetCombatModel( void ); idClipModel * GetCombatModel( void ) const; virtual void LinkCombat( void ); virtual void UnlinkCombat( void ); bool StartRagdoll( void ); void StopRagdoll( void ); virtual bool UpdateAnimationControllers( void ); // delta view angles to allow movers to rotate the view of the actor const idAngles & GetDeltaViewAngles( void ) const; void SetDeltaViewAngles( const idAngles &delta ); bool HasEnemies( void ) const; idActor * ClosestEnemyToPoint( const idVec3 &pos ); idActor * EnemyWithMostHealth(); virtual bool OnLadder( void ) const; virtual void GetNAVLocation( idNAV *aas, idVec3 &pos, int &areaNum ) const; void Attach( idEntity *ent ); virtual void Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination ); virtual renderView_t * GetRenderView(); // animation state control int GetAnim( int channel, const char *name ); void UpdateAnimState( void ); void SetAnimState( int channel, const char *name, int blendFrames ); idAnimState& GetAnimState(int channel); bool InAnimState( int channel, const char *name ) const; const char * WaitState( void ) const; void SetWaitState( const char *_waitstate ); bool AnimDone( int channel, int blendFrames ) const; virtual void SpawnGibs( const idVec3 &dir, const char *damageDefName ); protected: friend class idAnimState; float fovDot; // cos( fovDegrees ) idVec3 eyeOffset; // offset of eye relative to physics origin idVec3 modelOffset; // offset of visual model relative to the physics origin idAngles deltaViewAngles; // delta angles relative to view input angles int pain_debounce_time; // next time the actor can show pain int pain_delay; // time between playing pain sound int pain_threshold; // how much damage monster can take at any one time before playing pain animation idStrList damageGroups; // body damage groups idList damageScale; // damage scale per damage gruop bool use_combat_bbox; // whether to use the bounding box for combat collision idEntityPtr head; idList copyJoints; // copied from the body animation to the head model // state variables const function_t *state; const function_t *idealState; // joint handles jointHandle_t leftEyeJoint; jointHandle_t rightEyeJoint; jointHandle_t soundJoint; idIK_Walk walkIK; idStr animPrefix; idStr painAnim; // blinking int blink_anim; int blink_time; int blink_min; int blink_max; // script variables idThread * scriptThread; idStr waitState; idAnimState headAnim; idAnimState torsoAnim; idAnimState legsAnim; rvStateThread stateThread; bool allowPain; bool allowEyeFocus; bool finalBoss; int painTime; idList attachments; virtual void Gib( const idVec3 &dir, const char *damageDefName ); // removes attachments with "remove" set for when character dies void RemoveAttachments( void ); // copies animation from body to head joints void CopyJointsFromBodyToHead( void ); void Event_PlayAnim(int channel, const char* animname, int blendFrames); void Event_PlayCycle(int channel, const char* animname, int blendFrames); bool HasAnim(int channel, const char* animname, bool forcePrefix); protected: void SyncAnimChannels( int channel, int syncToChannel, int blendFrames ); void FinishSetup( void ); void SetupHead( void ); void PlayFootStepSound( void ); ID_SCRIPT_EVENT( "enableEyeFocus", 0 ) void Event_EnableEyeFocus( void ); ID_SCRIPT_EVENT( "disableEyeFocus", 0 ) void Event_DisableEyeFocus( void ); ID_SCRIPT_EVENT( "footstep", 0 ) ID_SCRIPT_EVENT( "leftFoot", 0 ) ID_SCRIPT_EVENT( "rightFoot", 0 ) void Event_Footstep( void ); ID_SCRIPT_EVENT( "EnableWalkIK", 0 ) void Event_EnableWalkIK( void ); ID_SCRIPT_EVENT( "DisableWalkIK", 0 ) void Event_DisableWalkIK( void ); ID_SCRIPT_EVENT( "EnableLegIK", 0 ) void Event_EnableLegIK( int num ); ID_SCRIPT_EVENT( "DisableLegIK", 0 ) void Event_DisableLegIK( int num ); ID_SCRIPT_EVENT( "setAnimPrefix", 0 ) void Event_SetAnimPrefix( const char *name ); void Event_LookAtEntity( idEntity *ent, float duration ); ID_SCRIPT_EVENT( "preventPain", 0 ) void Event_PreventPain( float duration ); ID_SCRIPT_EVENT( "disablePain", 0 ) void Event_DisablePain( void ); ID_SCRIPT_EVENT( "enablePain", 0 ) void Event_EnablePain( void ); ID_SCRIPT_EVENT( "getPainAnim", 's' ) void Event_GetPainAnim( void ); ID_SCRIPT_EVENT( "stopAnim", 0 ) void Event_StopAnim( int channel, int frames ); ID_SCRIPT_EVENT( "playAnim", 'd' ) void Event_PlayAnimScript( int channel, const char *name ); ID_SCRIPT_EVENT( "playCycle", 'd' ) void Event_PlayCycleScript( int channel, const char *name ); ID_SCRIPT_EVENT( "idleAnim", 'd' ) void Event_IdleAnim( int channel, const char *name ); ID_SCRIPT_EVENT( "setSyncedAnimWeight", 0 ) void Event_SetSyncedAnimWeight( int channel, int anim, float weight ); ID_SCRIPT_EVENT( "overrideAnim", 0 ) void Event_OverrideAnim( int channel ); ID_SCRIPT_EVENT( "enableAnim", 0 ) void Event_EnableAnim( int channel, int blendFrames ); ID_SCRIPT_EVENT( "setBlendFrames", 0 ) void Event_SetBlendFrames( int channel, int blendFrames ); ID_SCRIPT_EVENT( "getBlendFrames", 'd' ) void Event_GetBlendFrames( int channel ); ID_SCRIPT_EVENT( "animState", 0 ) void Event_AnimState( int channel, const char *name, int blendFrames ); ID_SCRIPT_EVENT( "getAnimState", 's' ) void Event_GetAnimState( int channel ); ID_SCRIPT_EVENT( "inAnimState", 'd' ) void Event_InAnimState( int channel, const char *name ); ID_SCRIPT_EVENT( "finishAction", 0 ) void Event_FinishAction( const char *name ); ID_SCRIPT_EVENT( "animDone", 'd' ) void Event_AnimDone( int channel, int blendFrames ); ID_SCRIPT_EVENT( "hasAnim", 'f' ) void Event_HasAnim( int channel, const char *name ); ID_SCRIPT_EVENT( "checkAnim", 0 ) void Event_CheckAnim( int channel, const char *animname ); ID_SCRIPT_EVENT( "chooseAnim", 's' ) void Event_ChooseAnim( int channel, const char *animname ); ID_SCRIPT_EVENT( "animLength", 'f' ) void Event_AnimLength( int channel, const char *animname ); ID_SCRIPT_EVENT( "animDistance", 'f' ) void Event_AnimDistance( int channel, const char *animname ); ID_SCRIPT_EVENT( "hasEnemies", 'd' ) void Event_HasEnemies( void ); ID_SCRIPT_EVENT( "nextEnemy", 'e' ) void Event_NextEnemy( idEntity *ent ); ID_SCRIPT_EVENT( "closestEnemyToPoint", 'e' ) void Event_ClosestEnemyToPoint( const idVec3 &pos ); ID_SCRIPT_EVENT( "stopSound", 0 ) void Event_StopSound( int channel, int netsync ); ID_SCRIPT_EVENT( "setNextState", 0 ) void Event_SetNextState( const char *name ); ID_SCRIPT_EVENT( "setState", 0 ) void Event_SetState( const char *name ); ID_SCRIPT_EVENT( "getState", 's' ) void Event_GetState( void ); ID_SCRIPT_EVENT( "getHead", 'e' ) void Event_GetHead( void ); idAnimState& GetAnimStateVar(int channel); const idAnimState& GetAnimStateVar(int channel) const; }; ID_INLINE rvStateThread& idAnimState::GetStateThread(void) { return stateThread; } #endif /* !__GAME_ACTOR_H__ */