//----------------------------------------------------------------------------- // // $Logfile:: /Quake 2 Engine/Sin/code/game/actor.h $ // $Revision:: 90 $ // $Author:: Jimdose $ // $Date:: 1/29/99 7:02p $ // // Copyright (C) 1998 by Ritual Entertainment, Inc. // All rights reserved. // // This source may not be distributed and/or modified without // expressly written permission by Ritual Entertainment, Inc. // // $Log:: /Quake 2 Engine/Sin/code/game/actor.h $ // // 90 1/29/99 7:02p Jimdose // added 2015 changes // // 89 11/09/98 6:23p Markd // Added turnspeed event // // 88 11/08/98 7:07p Markd // added nochatter command // // 87 11/08/98 6:57p Jimdose // reordered some variables in archive and unarchive so that they match the // order they're defined in the class // // 86 11/07/98 3:34p Markd // Added nodeathfade command // // 85 11/06/98 8:25p Jimdose // made visiondistance adjustable from script // // 84 10/27/98 9:41p Jimdose // made gun orienting functions virtual // // 83 10/27/98 7:53p Jimdose // added IfEnemyWithinEvent // // 82 10/27/98 1:50a Markd // Made Chatter a virtual void function // // 81 10/26/98 2:19p Markd // Added last_jump_time // // 80 10/25/98 11:52p Jimdose // added EXPORT_TEMPLATE // // 79 10/25/98 4:43a Markd // Added animal events // // 78 10/24/98 3:10p Markd // Put in eyeoffset command // // 77 10/22/98 9:29p Aldie // Added support for deathgib animations // // 76 10/20/98 2:37a Markd // Added additional JumpTo methods // // 75 10/20/98 12:44a Markd // Added setSize and setHealth // // 74 10/17/98 11:02p Markd // Added ifcanshoot // // 73 10/17/98 4:59p Markd // Added Attackmode event // // 72 10/16/98 7:19p Markd // Added a bunch of new events // // 71 10/16/98 1:41a Jimdose // Added goto command for actors. This helps the all too common mistake of // typing "local.self goto label" // // 70 10/14/98 5:22p Markd // Added jumpto and jumpto function // // 69 10/14/98 2:17a Markd // Added in ifcanmeleeattack event // // 68 10/14/98 1:27a Markd // Added HasWeapon method // // 67 10/13/98 9:11p Markd // Externed Actor_AttackEntity Actor_AttackPlayer // // 66 10/11/98 5:01p Markd // Added variables to keep track of drowning and lack of oxygen // // 65 10/11/98 12:32a Markd // Added AirMove // // 64 10/10/98 7:59p Markd // Added painthreshold and snd_pain_taunt // // 63 10/10/98 6:08p Markd // Added FleeAndRemove, FindFlee, fixed max_ainode bug // // 62 10/10/98 1:25a Jimdose // Did some bulletproofing against possible NULL actorthread // Prethink kills actors with NULL threads // added SetVariable for setting thread variables safely // stateStack is now properly archived without destroying its contents // // 61 10/06/98 5:26p Markd // Made MakeEnemy and DoAction take the force parameter // // 60 10/06/98 12:14p Markd // Added ForceAction // // 59 10/05/98 10:33p Markd // Added nostrafe and canstrafe // // 58 10/05/98 2:25a Jimdose // Made archive functions properly handle NULL behaviors // // 57 10/04/98 10:26p Markd // Added AttackFinishedEvent // // 56 10/03/98 7:27p Markd // working on swimming character and redid some weapon aiming stuff // // 55 10/01/98 8:01p Markd // Added melee variables // // 54 9/30/98 1:18p Markd // Added actor melee variables // // 53 9/29/98 5:58p Markd // put in archive and unarchive // // 52 9/24/98 7:10p Jimdose // Added MyGunAngles // // 51 9/22/98 5:11p Jimdose // made the anim variables public // // 50 9/22/98 5:31a Jimdose // Added attackmode // // 49 9/22/98 1:58a Jimdose // Added lastmove and forwardspeed // Regrouped functions by functionality // // 48 9/19/98 6:16p Jimdose // Added AttackPlayer // // 47 9/18/98 10:55p Jimdose // Added inanimate actor type // started work on swimming monsters // added showinfo // // 46 9/14/98 5:26p Jimdose // ProcessScript now allows events to be passed in // // 45 8/26/98 11:13p Jimdose // Began strafe support // // 44 8/24/98 6:56p Jimdose // Added crouching pain and death animations // Added path // Moved hueristics for path finding to actor // // 43 8/19/98 3:59p Jimdose // Added IfNearEvent and CopyStateEvent // // 42 8/19/98 2:30p Jimdose // Can no longer alias "alert" to "idle" so I've added a hasalert variable // // 41 8/14/98 11:34p Jimdose // added seenenemy // // 40 8/14/98 6:24p Jimdose // Got rid of decelleration for steering // // 39 8/07/98 7:57p Markd // Added ForwardToBehavior event // // 38 8/07/98 6:02p Jimdose // Added NotifyBehavior // // 37 8/06/98 6:59p Jimdose // Added IfEnemyVisible // // 36 8/05/98 7:19p Jimdose // Added definestate, ignoresounds, respondtosounds, respondtoall // Added StateInfo // // 35 7/29/98 6:32p Jimdose // Added MonsterStart // // 34 7/26/98 11:43a Jimdose // Added EnemyCanSeeMeFrom // // 33 7/26/98 3:49a Jimdose // Modified aim based on skill // // 32 7/25/98 2:12a Jimdose // Made trig a TouchFieldPtr // // 31 7/24/98 3:10p Jimdose // Removed ignore enemies stuff // // 30 7/22/98 7:03p Aldie // Remove useless bodies // // 29 7/14/98 11:49p Jimdose // Made PopState return whether a new state was popped off the stack // // 28 7/08/98 12:58p Jimdose // added min and max for crouch and stand sizes // // 27 7/08/98 12:56p Jimdose // added crouchsize and standsize // // 26 7/07/98 11:37p Jimdose // Replaced priority-based system with full script-based state system // // 25 7/06/98 1:06p Jimdose // working on ai // // 24 7/06/98 1:06p Jimdose // working on ai // // 23 6/30/98 6:49p Aldie // Added Gib event // // 22 6/30/98 6:00p Jimdose // Added more states and state detection code. // Added range detection // added health level detection // // 21 6/25/98 8:11p Jimdose // Added global actor scripts // // 20 6/19/98 9:29p Jimdose // Added GetGunOrientation // // 19 6/19/98 5:53p Jimdose // Added InFOV // // 18 6/18/98 8:45p Jimdose // Removed string based SetBehavior and PushState functions // // 17 6/17/98 1:16a Jimdose // Moved setOwner to Item. // Added EV_Item_Pickup // // 16 6/13/98 8:22p Jimdose // Added some enemy visibility functions for FindCover // // 15 6/11/98 12:44a Jimdose // behaviors now get info from the script at startup // // 14 6/10/98 10:25p Jimdose // Added priority based state system // // 13 6/09/98 4:24p Jimdose // worked on ai // // 12 6/04/98 10:48p Jimdose // Fixed a bunch of things that got broken just in time for E3. Paths and // scripting actually work now. // // 11 6/03/98 5:44p Jimdose // Fixed spelling of behavior. :) // // 10 5/27/98 5:11a Jimdose // working on ai // // 9 5/25/98 6:47p Jimdose // Made animateframe, prethink and posthink into functions built into the base // entity class // // 8 5/25/98 5:31p Jimdose // Pathnodes are no longer a subclass of Entity. This was done to save on // edicts // // 7 5/25/98 1:06a Jimdose // Added chatter // // 6 5/24/98 1:02a Jimdose // Added monster hearing // // 5 5/23/98 6:29p Jimdose // changed waitfordoor to a float // // 4 5/22/98 9:39p Jimdose // Worked on ai // // 3 5/20/98 6:38p Jimdose // working on ai // // 2 5/18/98 8:15p Jimdose // Created file // // DESCRIPTION: // Base class for character AI. // #ifndef __ACTOR_H__ #define __ACTOR_H__ #include "g_local.h" #include "weapon.h" #include "sentient.h" #include "container.h" #include "stack.h" #include "navigate.h" #include "behavior.h" #include "scriptmaster.h" #include "prioritystack.h" extern Event EV_Actor_Start; extern Event EV_Actor_Dead; extern Event EV_Actor_PopAnim; extern Event EV_Actor_LookAt; extern Event EV_Actor_TurnTo; extern Event EV_Actor_FinishedBehavior; extern Event EV_Actor_NotifyBehavior; extern Event EV_Actor_FinishedMove; extern Event EV_Actor_FinishedAnim; extern Event EV_Actor_WalkTo; extern Event EV_Actor_RunTo; extern Event EV_Actor_Anim; extern Event EV_Actor_Attack; extern Event EV_Actor_InPain; extern Event EV_Actor_Gib; extern Event EV_Actor_ForwardToBehavior; extern Event EV_Actor_Aim; extern Event EV_Actor_MeleeRange; extern Event EV_Actor_MeleeDamage; extern Event EV_Actor_AttackFinished; extern Event EV_Actor_Attack; extern Event EV_Actor_AttackPlayer; typedef enum { RANGE_MELEE, RANGE_NEAR, RANGE_MID, RANGE_FAR } range_t; typedef enum { ON_SIGHT, ON_ATTACK }; typedef enum { IGNORE, ATTACK, FLEE, } reaction_t; typedef enum { LIKES, // Will not fire at, even if attacked TOLERATES, // Will attack when attacked HATES, // Will attack on sight WARY, // Will flee when attacked FEARS, // Will flee on sight NUM_DISPOSITIONS } disposition_t; typedef enum { IS_INANIMATE, IS_MONSTER, IS_ENEMY, IS_CIVILIAN, IS_FRIEND, IS_ANIMAL, NUM_ACTORTYPES } actortype_t; #define AI_CANWALK 0x00000001 #define AI_CANSWIM 0x00000002 #define AI_CANFLY 0x00000004 #define WEAK_WEIGHT 0.5 #define WEAK_HEALTH 20 #define STRONGER_WEIGHT 0.9 #define VISIBLE_WEIGHT 0.5 #define NEWENEMY_WEIGHT 0.75 // if he's a new enemy //#define DAMAGE_WEIGHT 0.5 // If he's done a lot of damage to you //#define WEAPON_WEIGHT 1.5 // How much the weapon influences you class EXPORT_FROM_DLL StateInfo : public Class { public: CLASS_PROTOTYPE( StateInfo ); StateInfo(); str action; str response; qboolean ignore; virtual void Archive( Archiver &arc ); virtual void Unarchive( Archiver &arc ); }; inline EXPORT_FROM_DLL void StateInfo::Archive ( Archiver &arc ) { Class::Archive( arc ); arc.WriteString( action ); arc.WriteString( response ); arc.WriteBoolean( ignore ); } inline EXPORT_FROM_DLL void StateInfo::Unarchive ( Archiver &arc ) { Class::Unarchive( arc ); arc.ReadString( &action ); arc.ReadString( &response ); arc.ReadBoolean( &ignore ); } #ifdef EXPORT_TEMPLATE template class EXPORT_FROM_DLL Container; #endif class EXPORT_FROM_DLL ActorState : public Class { public: CLASS_PROTOTYPE( ActorState ); str name; str anim; Event *animDoneEvent; Behavior *behavior; PathPtr path; int thread; ThreadMarker marker; Container actionList; virtual void Archive( Archiver &arc ); virtual void Unarchive( Archiver &arc ); }; inline EXPORT_FROM_DLL void ActorState::Archive ( Archiver &arc ) { int i, num; Class::Archive( arc ); arc.WriteString( name ); arc.WriteString( anim ); arc.WriteEvent( *animDoneEvent ); //FIXME arc.WriteBoolean( behavior != NULL ); if ( behavior ) { arc.WriteObject( behavior ); } arc.WriteSafePointer( path ); arc.WriteInteger( thread ); arc.WriteObject( &marker ); num = actionList.NumObjects(); arc.WriteInteger( num ); for ( i = 1; i <= num; i++ ) { arc.WriteObject( actionList.ObjectAt( i ) ); } } inline EXPORT_FROM_DLL void ActorState::Unarchive ( Archiver &arc ) { Event * ev; int i, num; Class::Unarchive( arc ); arc.ReadString( &name ); arc.ReadString( &anim ); ev = new Event; arc.ReadEvent( ev ); animDoneEvent = ev; //FIXME behavior = NULL; if ( arc.ReadBoolean() ) { behavior = ( Behavior * )arc.ReadObject(); } arc.ReadSafePointer( &path ); arc.ReadInteger( &thread ); arc.ReadObject( &marker ); actionList.FreeObjectList(); arc.ReadInteger( &num ); for ( i = 1; i <= num; i++ ) { StateInfo * info; info = new StateInfo; arc.ReadObject( info ); actionList.AddObject( info ); } } // // Exported templated classes must be explicitly instantiated // #ifdef EXPORT_TEMPLATE template class EXPORT_FROM_DLL Container; template class EXPORT_FROM_DLL Stack; #endif class EXPORT_FROM_DLL Actor : public Sentient { public: str newanim; Event *newanimevent; int newanimnum; str spawngroup; int movement; stepmoveresult_t lastmove; float forwardspeed; actortype_t actortype; int attackmode; Vector standsize_min; Vector standsize_max; Vector crouchsize_min; Vector crouchsize_max; str state; str animname; Container actionList; int numonstack; Stack stateStack; BehaviorPtr behavior; str currentBehavior; PathPtr path; Container targetList; Container nearbyList; Container enemyList; EntityPtr currentEnemy; qboolean seenEnemy; range_t enemyRange; EntityPtr lastEnemy; float fov; float fovdot; float vision_distance; Vector startpos; Vector move; Vector movedir; float movespeed; Vector movevelocity; float totallen; float turnspeed; Vector animdir; float chattime; float nextsoundtime; qboolean hasalert; PathNodePtr movegoal; PathNodePtr soundnode; ThreadPtr thread; ThreadPtr actorthread; str actorscript; str actorstart; TouchFieldPtr trig; qboolean has_melee; float melee_damage; float melee_range; float aim; float pain_threshold; qboolean checkStrafe; float next_drown_time; float air_finished; float attack_range; float shots_per_attack; qboolean deathgib; str kill_thread; Vector eyeoffset; float last_jump_time; qboolean nodeathfade; qboolean nochatter; CLASS_PROTOTYPE( Actor ); // Initialization functions Actor(); ~Actor(); void Start( Event *ev ); // Vision functions range_t Range( Entity *ent ); qboolean InFOV( Vector pos ); qboolean InFOV( Entity *ent ); qboolean CanSeeFOV( Entity *ent ); qboolean CanSeeFrom( Vector pos, Entity *ent ); qboolean CanSee( Entity *ent ); int EnemyCanSeeMeFrom( Vector pos ); qboolean CanSeeEnemyFrom( Vector pos ); // Weapon functions qboolean WeaponReady( void ); void Attack( Event *ev ); virtual Vector GunPosition( void ); virtual Vector MyGunAngles( Vector muzzlepos, qboolean firing ); virtual void GetGunOrientation( Vector muzzlepos, Vector *forward, Vector *right, Vector *up ); virtual qboolean CanShootFrom( Vector pos, Entity *ent, qboolean usecurrentangles ); virtual qboolean CanShoot( Entity *ent, qboolean usecurrentangles ); // Actor type script commands void FriendEvent( Event *ev ); void CivilianEvent( Event *ev ); void EnemyEvent( Event *ev ); void InanimateEvent( Event *ev ); void MonsterEvent( Event *ev ); void AnimalEvent( Event *ev ); // Enemy management qboolean HasEnemies( void ); qboolean IsEnemy( Entity *ent ); void MakeEnemy( Entity *ent, qboolean force = false ); qboolean Likes( Entity *ent ); qboolean Hates( Entity *ent ); // Targeting functions qboolean GetVisibleTargets( void ); void TargetEnemies( Event *ev ); Entity *BestTarget( void ); Sentient *NearFriend( void ); qboolean CloseToEnemy( Vector pos, float howclose ); float AttackRange( void ); float MinimumAttackRange( void ); // State control functions void EnableState( str action ); void DisableState( str action ); StateInfo *SetResponse( str action, str response, qboolean ignore = false ); const char *GetResponse( str action, qboolean force = false ); StateInfo *GetState( str action ); // State stack management void ClearStateStack( void ); qboolean PopState( void ); void PushState( const char *newstate, ScriptThread *newthread = NULL, ThreadMarker *marker = NULL ); // State control script commands void DefineStateEvent( Event *ev ); void CopyStateEvent( Event *ev ); void IgnoreAllEvent( Event *ev ); void IgnoreEvent( Event *ev ); void RespondToAllEvent( Event *ev ); void RespondToEvent( Event *ev ); void ClearStateEvent( Event *ev ); void StateDoneEvent( Event *ev ); void SetStateEvent( Event *ev ); // Thread management void SetupThread( void ); qboolean DoAction( str name, qboolean force = false ); qboolean ForceAction( str name ); void ProcessScript( ScriptThread *thread, Event *ev = NULL ); void StartMove( Event *ev ); ScriptVariable *SetVariable( const char *name, float value ); ScriptVariable *SetVariable( const char *name, int value ); ScriptVariable *SetVariable( const char *name, const char *text ); ScriptVariable *SetVariable( const char *name, str &text ); ScriptVariable *SetVariable( const char *name, Entity *ent ); ScriptVariable *SetVariable( const char *name, Vector &vec ); // Thread based script commands void SetScript( Event *ev ); void SetThread( Event *ev ); // Behavior management void EndBehavior( void ); void SetBehaviorEvent( Event *ev ); void SetBehavior( Behavior *newbehavior, Event *argevent = NULL, ScriptThread *thread = NULL ); void FinishedBehavior( Event *ev ); void NotifyBehavior( Event *ev ); void ForwardBehaviorEvent( Event *ev ); // Path and node management void SetPath( Path *newpath ); void ReserveNodeEvent( Event *ev ); void ReleaseNodeEvent( Event *ev ); // Animation control functions void ChangeAnim( void ); qboolean SetAnim( str anim, Event *ev = NULL ); qboolean SetAnim( str anim, Event &ev ); void Anim( Event *ev ); // Script commands void CrouchSize( Event *ev ); void SetFov( Event *ev ); void SetVisionDistance( Event *ev ); void LookAt( Event *ev ); void TurnToEvent( Event *ev ); void IdleEvent( Event *ev ); void WalkTo( Event *ev ); void RunTo( Event *ev ); void AttackEntity( Event *ev ); void AttackPlayer( Event *ev ); void JumpToEvent( Event *ev ); void GotoEvent( Event *ev ); // Script conditionals void IfEnemyVisibleEvent( Event *ev ); void IfNearEvent( Event *ev ); void IfCanHideAtEvent( Event *ev ); void IfCanStrafeAttackEvent( Event *ev ); void IfCanMeleeAttackEvent( Event *ev ); void IfCanShootEvent( Event *ev ); void IfEnemyWithinEvent( Event *ev ); // Sound reaction functions void IgnoreSoundsEvent( Event *ev ); void RespondToSoundsEvent( Event *ev ); void InvestigateWeaponSound( Event *ev ); void InvestigateMovementSound( Event *ev ); void InvestigatePainSound( Event *ev ); void InvestigateDeathSound( Event *ev ); void InvestigateBreakingSound( Event *ev ); void InvestigateDoorSound( Event *ev ); void InvestigateMutantSound( Event *ev ); void InvestigateVoiceSound( Event *ev ); void InvestigateMachineSound( Event *ev ); void InvestigateRadioSound( Event *ev ); // Pain and death related functions void Pain( Event *ev ); void Dead( Event *ev ); void Killed( Event *ev ); void GibEvent( Event *ev ); void RemoveUselessBody( Event *ev ); // Movement functions void ForwardSpeedEvent( Event *ev ); void SwimEvent( Event *ev ); void FlyEvent( Event *ev ); void NotLandEvent( Event *ev ); qboolean CanMoveTo( Vector pos ); void Accelerate( Vector steering ); void CalcMove( void ); void setAngles( Vector ang ); stepmoveresult_t WaterMove( void ); stepmoveresult_t AirMove( void ); stepmoveresult_t TryMove( void ); void CheckWater( void ); virtual void setSize( Vector min, Vector max ); // Debug functions void ShowInfo( void ); // General functions virtual void Chatter( const char *sound, float chance = 10, float volume = 1.0f, int channel = CHAN_VOICE ); void ActivateEvent( Event *ev ); void UseEvent( Event *ev ); void Prethink( void ); virtual void Archive( Archiver &arc ); virtual void Unarchive( Archiver &arc ); void SetAim( Event *ev ); void SetMeleeRange( Event *ev ); void SetMeleeDamage( Event *ev ); void MeleeEvent( Event *ev ); void AttackFinishedEvent( Event *ev ); void CanStrafeEvent( Event *ev ); void NoStrafeEvent( Event *ev ); void SetPainThresholdEvent( Event *ev ); void SetKillThreadEvent( Event *ev ); void AttackRangeEvent( Event *ev ); void AttackModeEvent( Event *ev ); void ShotsPerAttackEvent( Event *ev ); void ClearEnemyEvent( Event *ev ); void SetHealth( Event *ev ); void ClearEnemies( void ); void EyeOffset( Event *ev ); void NoDeathFadeEvent( Event *ev ); void NoChatterEvent( Event *ev ); void TurnSpeedEvent( Event *ev ); qboolean HasWeapon( void ); float JumpTo( PathNode * goal, float speed ); float JumpTo( Entity * goal, float speed ); float JumpTo( Vector targ, float speed ); }; inline EXPORT_FROM_DLL void Actor::Archive ( Archiver &arc ) { int i, num; Stack tempStack; ActorState *s; Sentient::Archive( arc ); arc.WriteString( newanim ); arc.WriteEvent( *newanimevent ); arc.WriteInteger( newanimnum ); arc.WriteString( spawngroup ); arc.WriteInteger( movement ); // cast as stepmoveresult_t on read arc.WriteInteger( ( int )lastmove ); arc.WriteFloat( forwardspeed ); // cast as actortype_t on read arc.WriteInteger( ( int )actortype ); arc.WriteInteger( attackmode ); arc.WriteVector( standsize_min ); arc.WriteVector( standsize_max ); arc.WriteVector( crouchsize_min ); arc.WriteVector( crouchsize_max ); arc.WriteString( state ); arc.WriteString( animname ); num = actionList.NumObjects(); arc.WriteInteger( num ); for ( i = 1; i <= num; i++ ) { arc.WriteObject( actionList.ObjectAt( i ) ); } arc.WriteInteger( numonstack ); // We have to push all the states onto another stack in order to // save them out in the proper order and to restore them after // saving the game. for( i = 1; i <= numonstack; i++ ) { tempStack.Push( stateStack.Pop() ); } // put them back on the stateStack as we write them out. for( i = 1; i <= numonstack; i++ ) { s = tempStack.Pop(); stateStack.Push( s ); arc.WriteObject( s ); } // FIXME arc.WriteBoolean( behavior != NULL ); if ( behavior ) { arc.WriteObject( behavior ); } arc.WriteString( currentBehavior ); arc.WriteSafePointer( path ); num = targetList.NumObjects(); arc.WriteInteger( num ); for ( i = 1; i <= num; i++ ) { arc.WriteSafePointer( targetList.ObjectAt( i ) ); } num = nearbyList.NumObjects(); arc.WriteInteger( num ); for ( i = 1; i <= num; i++ ) { arc.WriteSafePointer( nearbyList.ObjectAt( i ) ); } num = enemyList.NumObjects(); arc.WriteInteger( num ); for ( i = 1; i <= num; i++ ) { arc.WriteSafePointer( enemyList.ObjectAt( i ) ); } arc.WriteSafePointer( currentEnemy ); arc.WriteBoolean( seenEnemy ); // cast as range_t on read arc.WriteInteger( ( int )enemyRange ); arc.WriteSafePointer( lastEnemy ); arc.WriteFloat( fov ); arc.WriteFloat( fovdot ); arc.WriteFloat( vision_distance ); arc.WriteVector( startpos ); arc.WriteVector( move ); arc.WriteVector( movedir ); arc.WriteFloat( movespeed ); arc.WriteVector( movevelocity ); arc.WriteFloat( totallen ); arc.WriteFloat( turnspeed ); arc.WriteVector( animdir ); arc.WriteFloat( chattime ); arc.WriteFloat( nextsoundtime ); arc.WriteBoolean( hasalert ); arc.WriteSafePointer( movegoal ); arc.WriteSafePointer( soundnode ); arc.WriteSafePointer( thread ); arc.WriteSafePointer( actorthread ); arc.WriteString( actorscript ); arc.WriteString( actorstart ); arc.WriteSafePointer( trig ); arc.WriteBoolean( has_melee ); arc.WriteFloat( melee_damage ); arc.WriteFloat( melee_range ); arc.WriteFloat( aim ); arc.WriteFloat( pain_threshold ); arc.WriteBoolean( checkStrafe ); arc.WriteFloat( next_drown_time ); arc.WriteFloat( air_finished ); arc.WriteFloat( attack_range ); arc.WriteFloat( shots_per_attack ); arc.WriteBoolean( deathgib ); arc.WriteString( kill_thread ); arc.WriteVector( eyeoffset ); arc.WriteFloat( last_jump_time ); arc.WriteBoolean( nodeathfade ); arc.WriteBoolean( nochatter ); } inline EXPORT_FROM_DLL void Actor::Unarchive ( Archiver &arc ) { Event * ev; int i, num, temp; Sentient::Unarchive( arc ); arc.ReadString( &newanim ); ev = new Event; arc.ReadEvent( ev ); newanimevent = ev; arc.ReadInteger( &newanimnum ); arc.ReadString( &spawngroup ); arc.ReadInteger( &movement ); // cast as stepmoveresult_t on read temp = arc.ReadInteger(); lastmove = ( stepmoveresult_t )temp; arc.ReadFloat( &forwardspeed ); // cast as actortype_t on read temp = arc.ReadInteger(); actortype = ( actortype_t )temp; arc.ReadInteger( &attackmode ); arc.ReadVector( &standsize_min ); arc.ReadVector( &standsize_max ); arc.ReadVector( &crouchsize_min ); arc.ReadVector( &crouchsize_max ); arc.ReadString( &state ); arc.ReadString( &animname ); arc.ReadInteger( &num ); for( i = 1; i <= num; i++ ) { StateInfo * info; info = new StateInfo; arc.ReadObject( info ); actionList.AddObject( info ); } arc.ReadInteger( &numonstack ); for( i = 1; i <= numonstack; i++ ) { ActorState * state; state = new ActorState; arc.ReadObject( state ); stateStack.Push( state ); } behavior = NULL; if ( arc.ReadBoolean() ) { behavior = ( Behavior * )arc.ReadObject(); } arc.ReadString( ¤tBehavior ); arc.ReadSafePointer( &path ); arc.ReadInteger( &num ); targetList.FreeObjectList(); targetList.Resize( num ); for( i = 1; i <= num; i++ ) { EntityPtr tmp, *ptr; targetList.AddObject( tmp ); ptr = targetList.AddressOfObjectAt( i ); arc.ReadSafePointer( ptr ); } arc.ReadInteger( &num ); nearbyList.FreeObjectList(); nearbyList.Resize( num ); for( i = 1; i <= num; i++ ) { EntityPtr tmp, *ptr; nearbyList.AddObject( tmp ); ptr = nearbyList.AddressOfObjectAt( i ); arc.ReadSafePointer( ptr ); } arc.ReadInteger( &num ); enemyList.FreeObjectList(); enemyList.Resize( num ); for( i = 1; i <= num; i++ ) { EntityPtr tmp, *ptr; enemyList.AddObject( tmp ); ptr = enemyList.AddressOfObjectAt( i ); arc.ReadSafePointer( ptr ); } arc.ReadSafePointer( ¤tEnemy ); arc.ReadBoolean( &seenEnemy ); // cast as range_t on read temp = arc.ReadInteger(); enemyRange = ( range_t )temp; arc.ReadSafePointer( &lastEnemy ); arc.ReadFloat( &fov ); arc.ReadFloat( &fovdot ); arc.ReadFloat( &vision_distance ); arc.ReadVector( &startpos ); arc.ReadVector( &move ); arc.ReadVector( &movedir ); arc.ReadFloat( &movespeed ); arc.ReadVector( &movevelocity ); arc.ReadFloat( &totallen ); arc.ReadFloat( &turnspeed ); arc.ReadVector( &animdir ); arc.ReadFloat( &chattime ); arc.ReadFloat( &nextsoundtime ); arc.ReadBoolean( &hasalert ); arc.ReadSafePointer( &movegoal ); arc.ReadSafePointer( &soundnode ); arc.ReadSafePointer( &thread ); arc.ReadSafePointer( &actorthread ); arc.ReadString( &actorscript ); arc.ReadString( &actorstart ); arc.ReadSafePointer( &trig ); arc.ReadBoolean( &has_melee ); arc.ReadFloat( &melee_damage ); arc.ReadFloat( &melee_range ); arc.ReadFloat( &aim ); arc.ReadFloat( &pain_threshold ); arc.ReadBoolean( &checkStrafe ); arc.ReadFloat( &next_drown_time ); arc.ReadFloat( &air_finished ); arc.ReadFloat( &attack_range ); arc.ReadFloat( &shots_per_attack ); arc.ReadBoolean( &deathgib ); arc.ReadString( &kill_thread ); arc.ReadVector( &eyeoffset ); arc.ReadFloat( &last_jump_time ); arc.ReadBoolean( &nodeathfade ); arc.ReadBoolean( &nochatter ); } class EXPORT_FROM_DLL MonsterStart : public PathNode { private: str spawngroup; MonsterStart *groupchain; MonsterStart *leader; static MonsterStart *GetGroupLeader( str& groupname ); public: CLASS_PROTOTYPE( MonsterStart ); MonsterStart(); static MonsterStart *GetRandomSpot( str& groupname ); virtual void Archive( Archiver &arc ); virtual void Unarchive( Archiver &arc ); }; inline EXPORT_FROM_DLL void MonsterStart::Archive ( Archiver &arc ) { PathNode::Archive( arc ); arc.WriteString( spawngroup ); arc.WriteObjectPointer( groupchain ); arc.WriteObjectPointer( leader ); } inline EXPORT_FROM_DLL void MonsterStart::Unarchive ( Archiver &arc ) { PathNode::Unarchive( arc ); arc.ReadString( &spawngroup ); arc.ReadObjectPointer( ( Class ** )&groupchain ); arc.ReadObjectPointer( ( Class ** )&leader ); } // Set destination to node with duck or cover set. Class will find a path to that node, or a closer one. class EXPORT_FROM_DLL FindCoverMovement : public StandardMovement { public: Actor *self; inline qboolean validpath ( PathNode *node, int i ) { pathway_t *path; PathNode *n; path = &node->Child[ i ]; if ( !StandardMovement::validpath( node, i ) ) { return false; } n = AI_GetNode( path->node ); if ( !n || self->CloseToEnemy( n->worldorigin, 128 ) ) { return false; } return true; } inline qboolean done ( PathNode *node, PathNode *end ) { if ( node == end ) { return true; } //if ( node->reject ) if ( node->reject || !( node->nodeflags & ( AI_DUCK | AI_COVER ) ) ) { return false; } if ( self ) { node->reject = self->CanSeeEnemyFrom( node->worldorigin ); return !node->reject; } return false; } }; // Set destination to node with flee set. Class will find a path to that node, or a closer one. class EXPORT_FROM_DLL FindFleeMovement : public StandardMovement { public: Actor *self; inline qboolean validpath ( PathNode *node, int i ) { pathway_t *path; PathNode *n; path = &node->Child[ i ]; if ( !StandardMovement::validpath( node, i ) ) { return false; } n = AI_GetNode( path->node ); if ( !n || self->CloseToEnemy( n->worldorigin, 128 ) ) { return false; } return true; } inline qboolean done ( PathNode *node, PathNode *end ) { if ( node == end ) { return true; } //if ( node->reject ) if ( node->reject || !( node->nodeflags & AI_FLEE ) ) { return false; } if ( self ) { node->reject = self->CanSeeEnemyFrom( node->worldorigin ); return !node->reject; } return false; } }; class EXPORT_FROM_DLL FindEnemyMovement : public StandardMovement { public: Actor *self; inline qboolean done ( PathNode *node, PathNode *end ) { if ( node == end ) { return true; } if ( node->reject ) { return false; } if ( self ) { if ( self->currentEnemy ) { node->reject = !self->CanShootFrom( node->worldorigin, self->currentEnemy, false ); } else { node->reject = false; } return !node->reject; } return false; } }; #ifdef EXPORT_TEMPLATE template class EXPORT_FROM_DLL PathFinder; template class EXPORT_FROM_DLL PathFinder; template class EXPORT_FROM_DLL PathFinder; #endif typedef PathFinder FindCoverPath; typedef PathFinder FindFleePath; typedef PathFinder FindEnemyPath; #endif /* actor.h */