sin-2015/actor.h

1350 lines
35 KiB
C
Raw Permalink Normal View History

1999-04-22 00:00:00 +00:00
//-----------------------------------------------------------------------------
//
// $Logfile:: /Quake 2 Engine/Sin/code/game/actor.h $
// $Revision:: 89 $
// $Author:: Markd $
// $Date:: 11/09/98 6:23p $
//
// 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 $
//
// 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;
extern Event EV_Actor_GotoObject; //###
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<StateInfo *>;
#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<StateInfo *> 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<EntityPtr>;
template class EXPORT_FROM_DLL Stack<ActorState *>;
#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<StateInfo *> actionList;
int numonstack;
Stack<ActorState *> stateStack;
BehaviorPtr behavior;
str currentBehavior;
PathPtr path;
Container<EntityPtr> targetList;
Container<EntityPtr> nearbyList;
Container<EntityPtr> 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 );
// qboolean GetVisibleTargetsBetter( void );//### testing good shit here
void TargetEnemies( Event *ev );
// void TargetEnemiesBetter( void );//### testing one two three
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 );
void GotoObjectEvent(Event *ev); //###
};
inline EXPORT_FROM_DLL void Actor::Archive
(
Archiver &arc
)
{
int i, num;
Stack<ActorState *> 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( &currentBehavior );
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( &currentEnemy );
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 )
{
//### fixed a crashing bug by adding a check that self->currentEnemy is a valid target
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<FindCoverMovement>;
template class EXPORT_FROM_DLL PathFinder<FindFleeMovement>;
template class EXPORT_FROM_DLL PathFinder<FindEnemyMovement>;
#endif
typedef PathFinder<FindCoverMovement> FindCoverPath;
typedef PathFinder<FindFleeMovement> FindFleePath;
typedef PathFinder<FindEnemyMovement> FindEnemyPath;
#endif /* actor.h */