sof-sdk/Source/Game/gamecpp/ai_decisions.h
2000-06-15 00:00:00 +00:00

663 lines
No EOL
28 KiB
C++

typedef enum
{
DECISION,
BASE_DECISION,
PURSUE_DECISION,
POINTCOMBAT_DECISION,
SEARCH_DECISION,
DODGE_DECISION,
RETREAT_DECISION,
PATHIDLE_DECISION,
PATHCOMBAT_DECISION,
SCRIPTED_DECISION,
ORDER_DECISION,
DEKKER1_DECISION,
DEKKER2_DECISION,
DEKKER3_DECISION,
DEKKER4_DECISION,
};
#define LEADERFLAG_RECRUIT 0x00000001//leader will look for a new group to lead if he doesn't have one
#define LEADERFLAG_PHYSICAL 0x00000002//leader physically leads--formations assume leader as front member
#define ORDER_PRIORITY_ROOT 25
#define SCRIPTED_PRIORITY_ROOT 25//fixme: script decision shouldn't be worrying about adding its own actions at all usually--should just worry about recovering from actions that didn't work?????
typedef enum
{
NONE = 0,
ATTACK,
MOVE,
FOLLOW,
WAIT,
} goal_e;
typedef enum
{
NI_IDEALPOSITION,
NI_TOOFAR,
NI_TOOCLOSE,
NI_NOTCLEAR,
NI_FLEEING,
NI_DUCKING, //used in certain fleeing cases
NI_DODGING, //used in certain fleeing cases
NI_TOOFAR_SEARCHING, //this one won't attack
} nonIdealSituation;
/**********************************************************************************
**********************************************************************************/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////
/////// base decision branch
///////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class decision_c
{
private:
protected:
float last_dilution_time;
//priority is a combination of whether immediate conditions
//are favorable for this decision, and whether this decision has a track record for working
int priority;
int priority_base;
//validity keeps track of how successful this decision has been in the past;
//considering monsters won't last too long, this will be weighted pretty heavily toward
//most recent result, and will slowly edge into neutral territory;
//range is 0 to 1
float validity;
float timeout_time;
qboolean allow_timeout;
qboolean ClearShot(ai_c &which_ai, edict_t &monster, vec3_t goalpos, edict_t *ignore, bbox_preset testbbox, float *orgPos = 0, int *blockingGuy = 0);
float lastClearTime;
qboolean isClear;
//errr, not so sure i dig this. --ss
float GetGroupPosition(ai_c &which_ai, edict_t &monster, vec3_t relativeTo);
virtual qboolean AtGroupFront(ai_c &which_ai, edict_t &monster, vec3_t dest, vec3_t face);
virtual void UpdateValidity(float adjustValue){validity = validity*0.75+adjustValue*0.25;}//weight heavily toward new value
virtual void UpdateValidity(void);
virtual qboolean IsAdversary(edict_t &monster, edict_t *otherGuy);
qboolean IsTimedOut(void);
public:
virtual mmove_t *GetSequenceForMovement(ai_c &which_ai, edict_t &monster, vec3_t dest, vec3_t face, mmove_t *preferred_move=NULL, int reject_actionflags=0);
virtual mmove_t *GetSequenceForStand(ai_c &which_ai, edict_t &monster, vec3_t dest=vec3_origin, vec3_t face=vec3_origin, mmove_t *preferred_move=NULL, int reject_actionflags=0);
virtual mmove_t *GetSequenceForJump(ai_c &which_ai, edict_t &monster, vec3_t dest, vec3_t face, mmove_t *preferred_move=NULL, int reject_actionflags=0);
virtual mmove_t *GetSequenceForAttack(ai_c &which_ai, edict_t &monster, vec3_t dest, vec3_t face, edict_t *target, mmove_t *preferred_move=NULL, int reject_actionflags=0);
virtual mmove_t *GetSequenceForDodge(ai_c &which_ai, edict_t &monster, vec3_t dest, vec3_t face, edict_t *target, mmove_t *preferred_move=NULL, int leftSide = 0, int reject_actionflags=0);
//will return one of the above, depending on the code passed in.
virtual mmove_t *GetSequenceForActionCode(ai_c &which_ai, edict_t &monster, action_code the_code, vec3_t dest=vec3_origin, vec3_t face=vec3_origin, edict_t *target=NULL, mmove_t *preferred_move=NULL, int reject_actionflags=0);
virtual action_c *AddActionForSequence(ai_c &which_ai, edict_t &monster, mmove_t *move, vec3_t dest=vec3_origin, vec3_t face=vec3_origin, edict_t *target=NULL, action_c *owneraction=NULL, bool shouldKill = false, int NullTarget = 0, float timeoutTime = 0.0f);
virtual action_c *ForceNextActionForSequence(ai_c &which_ai, edict_t &monster, mmove_t *move, vec3_t dest=vec3_origin, vec3_t face=vec3_origin, edict_t *target=NULL, action_c *owneraction=NULL){return NULL;};
decision_c(int priority_root = 0, float timeout = 0, edict_t* ScriptOwner = NULL);
virtual ~decision_c(void) {}
//ScriptEnt is the entity containing a script for use with scripting
int Priority(void) { return priority+priority_base; }
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
virtual void Perform(ai_c &which_ai, edict_t &monster);
virtual void ActionCompleted(action_c &which_action, ai_c &which_ai, edict_t &monster, float percent_success) {}
virtual void FinishScript(){return;};
virtual qboolean SafeToRemove(edict_t &monster){return true;}
//HEY!!! THIS BETTER BE FALSE UNLESS YOU'RE A SCRIPTED DECISION!!!!!
virtual bool MatchScriptEnt(edict_t* Entity){return false;}
virtual void SetGoalType(goal_e theGoal){};
virtual void SetGoalTarget(edict_t *theTarget){};
virtual void SetGoalLocation(vec3_t theLocation){};
virtual void SetGoalTime(float theTime){};
virtual goal_e GetGoalType(){return NONE;};
virtual edict_t* GetGoalTarget(){return NULL;};
virtual void GetGoalLocattion(vec3_t theLocation){};
virtual float GetGoalTime(){return 0;};
virtual void UsePathfinding(ai_c &which_ai, edict_t &monster){};
virtual void SetInfoForDodge(vec3_t start, vec3_t end){}
virtual void SetInfoForReply(vec3_t start, vec3_t end){}
virtual void AddFear(float amount, vec3_t center){}
decision_c(decision_c *orig);
void Evaluate(decision_c *orig);
virtual void Write() { assert(0); }
virtual void Read() { assert(0); }
virtual int GetClassCode(void){return DECISION;}//this should be different for everybody in this class family
static decision_c *NewClassForCode(int code);
};
/**********************************************************************************
**********************************************************************************/
class base_decision : public decision_c
{
public:
base_decision(int priority_root = 0, float timeout = 0, edict_t* ScriptOwner = NULL)
:decision_c(priority_root, timeout, ScriptOwner){}
base_decision(base_decision *orig);
void Evaluate(base_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return BASE_DECISION; }
};
/**********************************************************************************
**********************************************************************************/
typedef enum
{
//these are just examples...
USETYPE_PUSH,//push a door open
USETYPE_FLIP,//flip a switch
USETYPE_MISC//well? do something, at least...
} useType_t;
typedef struct
{
vec3_t usePos;
vec3_t useDir;
useType_t useType;
edict_t *useEnt;
} brushUseInfo_t;
typedef struct
{
vec3_t pos;//get this value from the raw point info
vec3_t direction;//ick, this is currently only used by temp use-points
edict_t *targetEnt;//ick, this is currently only used by temp use-points
bool valid;
unsigned temp_type;
float time;
} ai_pathpoint_t;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////
/////// path decision branch
///////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//also fixme: to change waypoints so they don't have to be ents, temp point stuff has to be changed (all pretty centralized in anticipation)
class path_decision : public decision_c
{
private:
protected:
float last_jump_time;
float path_fail_time;
vec3_t path_fail_dir;
ai_pathpoint_t path_nextpoint;//the waypoint i'm currently moving toward
edict_t *path_goalentity;//the entity i'm trying to reach--a player, generally
vec3_t path_goalpos;//the place i'm trying to reach--a player's origin, generally
float path_goal_updatedtime;
vec3_t newMoveDir;
float lastCheckTime;
nonIdealSituation nonIdealReason;
int blockingEnemy;
float lastDuckInvalidateTime;
float lastDuckValidTime;
vec3_t aimWanderVec;//whilst i'm aiming, i think i'll take a little stroll...
qboolean stuckNonIdeal;//enemy isn't close enough to be in range, but he has no movement options, so try to shoot anyway (you know, what the hell)
//HOWEVER - you should probably have crap accuracy because you're so far away, yeah? I say YEAH!
virtual void RecalcMoveVec(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void SetGoalPosition(ai_c &which_ai, edict_t &monster);
virtual qboolean GetGoalPosition(ai_c &which_ai, edict_t &monster, vec3_t goal);
virtual qboolean NextPointInPath(ai_c &which_ai, edict_t &monster, vec3_t position);//this sets path_nextpoint (and path_endpoint if path finished), checks path_nextpoint
qboolean EvaluatePathEndpoint(ai_c &which_ai, edict_t &monster, ai_pathpoint_t endpoint_candidate, vec3_t goalpos);//sets nothing, uses nothing other than inputs
//returns false if path is not valid,
//true if path is valid (or if path will be ignored)
//fixme: when pathfinding in, should totally focus on ent avoidance
void TempPointCreate(vec3_t position, edict_t &monster);
void AvoidPointCreate(vec3_t normal, edict_t &monster);
void PoliteAvoidPointCreate(vec3_t normal, edict_t &monster);
void UsePointCreate(brushUseInfo_t &useeInfo, edict_t &monster);
void JumpPointCreate(vec3_t position, edict_t &monster);//subclass of temppoints made specifically for jumping over things
void FallPointCreate(vec3_t position, edict_t &monster);//subclass of temppoints made specifically for intentional falling
void PerformAvoidance(ai_c &which_ai, edict_t &monster);
//use this to adjust movement for groups, and check pathfinding (?) to make sure direction is valid--moveVec comes in uninit'ed
virtual void GetMovementVector(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual qboolean IsIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t curPos, vec3_t goalPos, vec3_t moveVec);
virtual void AddActionIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void AddAction(ai_c &which_ai, edict_t &monster);
virtual qboolean AddSpecialPathAction(ai_c &which_ai, edict_t &monster);//called from AddAction--depending on the type of path point path_nextpoint is, add appropriate action
public:
path_decision(edict_t *goalent = NULL, int priority_root = 0, float timeout = 0, edict_t* ScriptOwner = NULL);
virtual ~path_decision(void){}
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
virtual void Perform(ai_c &which_ai, edict_t &monster);
virtual void ActionCompleted(action_c &which_action, ai_c &which_ai, edict_t &monster, float percent_success);
virtual void FinishScript(){return;};
path_decision(path_decision *orig);
virtual void Evaluate(path_decision *orig);
};
/////////////////////////////////////////////////////////////////////////////////////////////
//pursue decision
/////////////////////////////////////////////////////////////////////////////////////////////
class pursue_decision : public path_decision
{
public:
pursue_decision(edict_t *goalent = NULL, int priority_root = 0, float timeout = 0, edict_t* ScriptOwner = NULL)
:path_decision(goalent, priority_root, timeout, ScriptOwner){}
pursue_decision(pursue_decision *orig);
void Evaluate(pursue_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return PURSUE_DECISION; }
};
/////////////////////////////////////////////////////////////////////////////////////////////
//dekker1 decision
/////////////////////////////////////////////////////////////////////////////////////////////
class dekker1_decision : public path_decision
{
protected:
virtual void AddAction(ai_c &which_ai, edict_t &monster);
virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void AddDekkerActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec, float speed);
public:
dekker1_decision(edict_t *goalent = NULL, int priority_root = 10, float timeout = 0, edict_t* ScriptOwner = NULL)
:path_decision(goalent, priority_root, timeout, ScriptOwner){}
dekker1_decision(dekker1_decision *orig);
void Evaluate(dekker1_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return DEKKER1_DECISION; }
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
};
/////////////////////////////////////////////////////////////////////////////////////////////
//dekker1 decision
/////////////////////////////////////////////////////////////////////////////////////////////
class dekker2_decision : public dekker1_decision
{
protected:
// virtual void GetMovementVector(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
//ARGHHH!--this was supposed to be a simple override to adjust dekker's speed for the various stages, and now it's a huge bloated mess.
virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void AddAction(ai_c &which_ai, edict_t &monster);
public:
dekker2_decision(edict_t *goalent = NULL, int priority_root = 8, float timeout = 0, edict_t* ScriptOwner = NULL)
:dekker1_decision(goalent, priority_root, timeout, ScriptOwner){}
dekker2_decision(dekker2_decision *orig);
void Evaluate(dekker2_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return DEKKER2_DECISION; }
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
};
/////////////////////////////////////////////////////////////////////////////////////////////
//dekker3 decision
/////////////////////////////////////////////////////////////////////////////////////////////
class dekker3_decision : public path_decision
{
protected:
qboolean reachedDest;
virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual qboolean IsIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t curPos, vec3_t goalPos, vec3_t moveVec);
virtual qboolean GetGoalPosition(ai_c &which_ai, edict_t &monster, vec3_t goal);
virtual void AddAction(ai_c &which_ai, edict_t &monster);
public:
dekker3_decision(edict_t *goalent = NULL, int priority_root = 5, float timeout = 0, edict_t* ScriptOwner = NULL)
:path_decision(goalent, priority_root, timeout, ScriptOwner){reachedDest=false;}
dekker3_decision(dekker3_decision *orig);
void Evaluate(dekker3_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return DEKKER3_DECISION; }
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
};
/////////////////////////////////////////////////////////////////////////////////////////////
//dekker4 decision
/////////////////////////////////////////////////////////////////////////////////////////////
class dekker4_decision : public path_decision
{
protected:
qboolean reachedDest;
virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual qboolean IsIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t curPos, vec3_t goalPos, vec3_t moveVec);
virtual qboolean GetGoalPosition(ai_c &which_ai, edict_t &monster, vec3_t goal);
virtual void AddAction(ai_c &which_ai, edict_t &monster);
public:
dekker4_decision(edict_t *goalent = NULL, int priority_root = 2, float timeout = 0, edict_t* ScriptOwner = NULL)
:path_decision(goalent, priority_root, timeout, ScriptOwner){reachedDest=false;}
dekker4_decision(dekker4_decision *orig);
void Evaluate(dekker4_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return DEKKER4_DECISION; }
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
};
/////////////////////////////////////////////////////////////////////////////////////////////
//path decision refitted to use combat points
/////////////////////////////////////////////////////////////////////////////////////////////
class pointcombat_decision : public path_decision
{
protected:
int current_point;
vec3_t current_point_pos;
vec3_t current_point_dest;
int current_point_type;
int current_point_subtype;
vec3_t current_point_dir;
int last_point_trans;//time of the last transition for points that oscillate
int last_consider_time;//some guys don't think to do this all that often
virtual void SetGoalPosition(ai_c &which_ai, edict_t &monster);
virtual qboolean GetGoalPosition(ai_c &which_ai, edict_t &monster, vec3_t goal);
virtual qboolean IsIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t curPos, vec3_t goalPos, vec3_t moveVec);
// virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void AddActionIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
public:
pointcombat_decision(edict_t *goalent = NULL, int priority_root = 0, float timeout = 0, edict_t* ScriptOwner = NULL);
// virtual ~pointcombat_decision(void){path_decision::~path_decision();}
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
void GetMovementVector(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
pointcombat_decision(pointcombat_decision *orig);
void Evaluate(pointcombat_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return POINTCOMBAT_DECISION; }
};
/**********************************************************************************
**********************************************************************************/
//approach takes precedence over pursuit, pursuit takes precedence over wandering
//approach==go to where target last was, stop when i get there
//pursuit==go the direction that target was last seen going, stop when i hit something
class search_decision : public path_decision
{
protected:
qboolean pursuit_search, approach_search;
vec3_t pursuit_dir;
float last_fired_time;
vec3_t firedSpot;
vec3_t trail1, trail2, trail3;
virtual void SetGoalPosition(ai_c &which_ai, edict_t &monster);
virtual qboolean GetGoalPosition(ai_c &which_ai, edict_t &monster, vec3_t goal);
virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual qboolean IsIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t curPos, vec3_t goalPos, vec3_t moveVec);
public:
search_decision(edict_t *goalent = NULL, int priority_root = 0, float timeout = 0);
virtual ~search_decision(void){}
virtual void ActionCompleted(action_c &which_action, ai_c &which_ai, edict_t &monster, float percent_success);
search_decision(search_decision *orig);
void Evaluate(search_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return SEARCH_DECISION; }
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
virtual void SetInfoForDodge(vec3_t start, vec3_t end);
virtual void SetInfoForReply(vec3_t start, vec3_t end){SetInfoForDodge(start, end);}
};
/**********************************************************************************
**********************************************************************************/
//this is a path_decision that should look for cover & hop around sideways
class dodge_decision : public path_decision
{
private:
int prev_health;
protected:
float last_dodge_time;
float last_shotat_time;
int dodgeSide;
vec3_t shotStart;//need this info to determine which way to dodge
vec3_t shotEnd;//need this info to determine which way to dodge
virtual void AddAction(ai_c &which_ai, edict_t &monster);
public:
dodge_decision(int priority_root = 0, float timeout = 0);
virtual ~dodge_decision(void){}
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
virtual void ActionCompleted(action_c &which_action, ai_c &which_ai, edict_t &monster, float percent_success);
dodge_decision(dodge_decision *orig);
void Evaluate(dodge_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return DODGE_DECISION; }
virtual void SetInfoForDodge(vec3_t start, vec3_t end);
};
/**********************************************************************************
**********************************************************************************/
//this is a path_decision that should look for a path Away from target
class retreat_decision : public path_decision
{
private:
int prev_health;
float fearIndex;
bool haveFleeDest;
int spookStyle;
int spookTime;
vec3_t spookCenter;
protected:
virtual qboolean GetGoalPosition(ai_c &which_ai, edict_t &monster, vec3_t goal);
virtual qboolean IsIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t curPos, vec3_t goalPos, vec3_t moveVec);
virtual void AddActionIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual qboolean IsAdversary(edict_t &monster, edict_t *otherGuy);
public:
retreat_decision(int priority_root = 0, float timeout = 0);
virtual ~retreat_decision(void){}
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
virtual void AddFear(float amount, vec3_t center);
virtual void SetInfoForDodge(vec3_t start, vec3_t end);
retreat_decision(retreat_decision *orig);
void Evaluate(retreat_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return RETREAT_DECISION; }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////
/////// pathcorner-traversing decision branch
///////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
//path decision refitted to follow path_corner trail--gets rid of itself if path_corner trail ends.
/////////////////////////////////////////////////////////////////////////////////////////////
class pathcorner_decision : public path_decision
{
protected:
float reactivate_time;
edict_t *oldTarget;
int curWaitActionNum;
qboolean firstActionAtWait;
qboolean isAtCorner;
mmove_t *curMoveAction;//store off the moveAction for path_corners when i pass them
virtual void SetGoalPosition(ai_c &which_ai, edict_t &monster);
virtual qboolean GetGoalPosition(ai_c &which_ai, edict_t &monster, vec3_t goal);
virtual void GetMovementVector(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual qboolean IsIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t curPos, vec3_t goalPos, vec3_t moveVec);
virtual void AddActionNonIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void AddActionIdealPosition(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void FinishPathPoint(ai_c &which_ai, edict_t &monster);
public:
pathcorner_decision(edict_t *goalent=NULL, int priority_root=0, float timeout=0, edict_t* ScriptOwner=NULL);
virtual ~pathcorner_decision(void){path_decision::~path_decision();}
virtual void ActionCompleted(action_c &which_action, ai_c &which_ai, edict_t &monster, float percent_success);
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
pathcorner_decision(pathcorner_decision *orig);
virtual void Evaluate(pathcorner_decision *orig);
};
class pathidle_decision : public pathcorner_decision
{
public:
pathidle_decision(edict_t *goalent=NULL, int priority_root=0, float timeout=0, edict_t* ScriptOwner=NULL)
:pathcorner_decision(goalent, priority_root, timeout, ScriptOwner){}
pathidle_decision(pathidle_decision *orig);
void Evaluate(pathidle_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return PATHIDLE_DECISION; }
};
/////////////////////////////////////////////////////////////////////////////////////////////
//path_corner decision refitted to follow point_combat trail--gets rid of itself if point_combat trail ends.
/////////////////////////////////////////////////////////////////////////////////////////////
class pathcombat_decision : public pathcorner_decision
{
protected:
virtual void GetMovementVector(ai_c &which_ai, edict_t &monster, vec3_t goalPos, vec3_t moveVec);
virtual void FinishPathPoint(ai_c &which_ai, edict_t &monster);
public:
virtual qboolean Consider(ai_c &which_ai, edict_t &monster);
pathcombat_decision(edict_t *goalent=NULL, int priority_root=0, float timeout=0, edict_t* ScriptOwner=NULL):pathcorner_decision(goalent,priority_root,timeout,ScriptOwner){}
pathcombat_decision(pathcombat_decision *orig);
void Evaluate(pathcombat_decision *orig);
virtual void Write();
virtual void Read();
virtual int GetClassCode(void) { return PATHCOMBAT_DECISION; }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////
/////// scripted/queued order decision branch
///////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**********************************************************************************
**********************************************************************************/
//this is a path_decision that doesn't necessarily use any path stuff
//although, it Could use the path stuff to attack a civilian, run to an elevator, etc.
class scriptOrder_c
{
public:
mmove_t *preferredMove;//NULL if no preference...
float holdTime;//time to hold (for idles, static stuff)
vec3_t turnVec;
vec3_t destVec;
qboolean absoluteDest;//whether the destination is absolute or relative.
bool kill;//whether an attack order should be an automatic kill
action_code actionType;//what do i want to be doing here?
int flags;
Event *SignalEvent;
float speed;
edict_t *target;
int NullTarget; // targeted null in a script
int Emotion;
scriptOrder_c(void);
scriptOrder_c(scriptOrder_c *orig);
void Evaluate(scriptOrder_c *orig);
void Write(void);
void Read(void);
};
class scripted_decision : public path_decision
{
private:
protected:
qboolean scriptDone;
edict_t *self;
qboolean ignorePreferred;
float orderStartTime;
vec3_t oldPosition;//where i should be at the start of current order
vec3_t actDest;
vec3_t actDestDir;//for more reliable testing of whether i've gotten close enough to destination--this is the vector to actDest when I start out;
//when the vector to the actDest is closer to the inverse of this than to this, i've passed my destination
mmove_t *lastMove;
edict_t *ScriptEnt;
#define SCRIPTED_DECISION_END (offsetof(scripted_decision, ScriptEnt) + sizeof(ScriptEnt))
list<scriptOrder_c *> orders;
// virtual void AddAction(ai_c &which_ai, edict_t &monster);
public:
scripted_decision(edict_t *goalent = NULL, int priority_root = SCRIPTED_PRIORITY_ROOT, float timeout = 0, edict_t* ScriptOwner = NULL);
virtual ~scripted_decision(void);
virtual void Perform(ai_c &which_ai, edict_t &monster);
virtual void FinishScript(){scriptDone = true;};
virtual qboolean Consider(ai_c &which_ai, edict_t &monster){priority=15; return scriptDone;};
virtual bool MatchScriptEnt(edict_t* Entity);
virtual void AddOrder(ai_c &which_ai, edict_t &monster, scriptOrder_c &this_order);
virtual void ActionCompleted(action_c &which_action, ai_c &which_ai, edict_t &monster, float percent_success);
scripted_decision(scripted_decision *orig);
void Evaluate(scripted_decision *orig);
virtual void Read();
virtual void Write();
virtual int GetClassCode(void) { return SCRIPTED_DECISION; }
};
// end