diff options
Diffstat (limited to 'src/parsec/include/g_bot_cl.h')
| -rw-r--r-- | src/parsec/include/g_bot_cl.h | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/src/parsec/include/g_bot_cl.h b/src/parsec/include/g_bot_cl.h new file mode 100644 index 0000000..66e3871 --- /dev/null +++ b/src/parsec/include/g_bot_cl.h @@ -0,0 +1,404 @@ +#ifndef G_BOT_CL_H_ +#define G_BOT_CL_H_ + +// simple timeout handling ---------------------------------------------------- +// +class UTL_RefFrameTimeout +{ +protected: + refframe_t m_RefFrames; + refframe_t m_Base; + refframe_t m_Timeout; + +public: + // ctors + UTL_RefFrameTimeout() + { + m_Timeout = 0; + Reset(); + } + UTL_RefFrameTimeout( refframe_t _Timeout ) + { + Set( _Timeout ); + } + + // set the timeout value + void Set( refframe_t _Timeout ) + { + m_Timeout = _Timeout; + Reset(); + } + + // reset timeout + void Reset() + { + m_RefFrames = m_Timeout; + m_Base = SYSs_GetRefFrameCount(); + } + + // check for timeout + bool_t IsTimeout() + { + refframe_t diff = SYSs_GetRefFrameCount() - m_Base; + m_RefFrames -= diff; + if ( m_RefFrames < 0 ) { + m_RefFrames += m_Timeout; + return true; + } else { + return false; + } + } +}; + + +// **************************************************************************** +// **************************************************************************** +// **************************************************************************** +//FIXME: +// this belongs into seperate OCT module +// **************************************************************************** +// **************************************************************************** +// **************************************************************************** + +// object control orientations ------------------------------------------------ +// +#define OCT_PITCH_UP -1 +#define OCT_PITCH_DOWN +1 +#define OCT_YAW_LEFT +1 +#define OCT_YAW_RIGHT -1 +#define OCT_ROLL_LEFT +1 +#define OCT_ROLL_RIGHT -1 +#define OCT_ACCELERATE +1 +#define OCT_DECELERATE -1 + +// object control structure --------------------------------------------------- +// +struct object_control_s +{ + ShipObject* pShip; + + float rot_x; // do a rotation around the x axis - PITCH - ( -1 = divedown, +1 = pullup ) + float rot_y; // do a rotation around the y axis - YAW - ( -1 = left, +1 = right ) + float rot_z; // do a rotation around the z axis - ROLL - ( -1 = right, +1 = left ) + float accel; // accel control ( +1 accelerate, -1 decelerate ) + + //FIXME: slide horiz/vert + + //FIXME: numerically sane versions + bool_t IsPitch() const { return rot_x != 0.0f; } + bool_t IsYaw() const { return rot_y != 0.0f; } + bool_t IsRoll() const { return rot_z != 0.0f; } + bool_t IsMove() const { return accel != 0.0f; } +}; + +// do the desired object control +int OCT_DoControl( object_control_s* objctl ); + +// dump an object control to the console +void OCT_Dump(object_control_s* objctl ); + +// **************************************************************************** +// **************************************************************************** +// **************************************************************************** + + + + +// ---------------------------------------------------------------------------- +// +class UTL_LocomotionController +{ +protected: + + int m_nRelaxedHeadingAngle; + int m_nFullSpeedHeading; + float m_fMinSpeedTurn; // min. speed to keep when doing a sharp turn + +public: + // standard ctor + UTL_LocomotionController() + { + m_nRelaxedHeadingAngle = 5; + m_nFullSpeedHeading = 30; + m_fMinSpeedTurn = FIXED_TO_FLOAT( 500 ); + } + + // set the max. degrees the heading and the desired heading can differ + void SetRelaxedHeadingAngle( int nRelaxedHeadingAngle ) + { + m_nRelaxedHeadingAngle = nRelaxedHeadingAngle; + } + + // set the heading at which we should go full speed again after a turn + void SetFullSpeedHeading( int nFullSpeedHeading ) + { + m_nFullSpeedHeading = nFullSpeedHeading; + } + + // set the min. speed to keep during a turn + void SetMinSpeedTurn( fixed_t _MinSpeedTurn ) + { + m_fMinSpeedTurn = FIXED_TO_FLOAT( _MinSpeedTurn ); + } + + void ControlOjbect( object_control_s* pObjctl, Vector3* pDesiredVelocity, fixed_t _DesiredSpeed ); +}; + + +// bot character properties --------------------------------------------------- +// +class BOT_Character +{ +protected: + float m_fPlanInterval; // planning interval in secs + float m_fGoalCheckInterval; // goal checking interval in secs + float m_fInputChangeInterval; // input change interval in secs + +public: + + //ctor + BOT_Character(); + + // reset to defaults + void Reset(); + + // select the attack target + ShipObject* SelectAttackTarget( ShipObject* pAttacker ); + ExtraObject* SelectEnergyObject(); + ExtraObject* SelectRepairObject(); + + // getters + float GetPlanInterval_sec() const { return m_fPlanInterval; } + float GetGoalCheckInterval_sec() const { return m_fGoalCheckInterval; } + float GetInputChangeInterval_sec() const { return m_fInputChangeInterval; } + + // friend functions + friend void RealizeBotChar(); +}; + +// bot goal ------------------------------------------------------------------- +// +class BOT_Goal +{ +protected: + Vector3 m_Pos; + GenObject* m_pObject; + +public: + BOT_Goal() + { + Reset(); + } + + void Reset() + { + memset( &m_Pos, 0, sizeof( Vector3 ) ); + m_pObject = NULL; + } + + // get the position the goal is at + Vector3* GetGoalPosition() + { + return &m_Pos; + } + + // set/get target object + void SetTargetObject( GenObject* pObject ) { m_pObject = pObject; } + GenObject* GetTargetObject() const { return m_pObject; } +}; + + +// current state of the bot --------------------------------------------------- +// +class BOT_State +{ +protected: + BOT_Goal m_CurGoal; + object_control_s m_oc; +public: + + BOT_State() + { + } + + // reset the dynamic state of the bot + void Reset( ShipObject* pShip ) + { + m_CurGoal.Reset(); + memset( &m_oc, 0, sizeof( object_control_s ) ); + m_oc.pShip = pShip; + } + + BOT_Goal* GetCurGoal() { return &m_CurGoal; } + object_control_s* GetObjectControl() { return &m_oc; } +}; + + +// type specifying the agent modes -------------------------------------------- +// +enum agentmode_t { + AGENTMODE_IDLE = 1, + AGENTMODE_POWERUP = 2, + AGENTMODE_ATTACK = 3, + AGENTMODE_RETREAT = 4, + + AGENTMODE_MAX = AGENTMODE_RETREAT +}; + +// main class for handling the bot AI ----------------------------------------- +// +class BOT_AI +{ +protected: + agentmode_t m_nAgentMode; + BOT_State m_State; + BOT_Character m_Character; + ShipObject* m_pShip; + + UTL_RefFrameTimeout m_PlanTimeout; + UTL_RefFrameTimeout m_GoalCheckTimeout; + UTL_RefFrameTimeout m_InputTimeout; + + Vector3 m_AgentPos; + +public: + + BOT_AI() + { + Reset(); + } + + // reset the bot AI + void Reset() + { + //m_nAgentMode = AGENTMODE_IDLE; + m_nAgentMode = AGENTMODE_ATTACK; + m_pShip = NULL; + m_State.Reset( m_pShip ); + + m_PlanTimeout.Set ( (refframe_t)m_Character.GetPlanInterval_sec() * FRAME_MEASURE_TIMEBASE ); + m_GoalCheckTimeout.Set ( (refframe_t)m_Character.GetGoalCheckInterval_sec() * FRAME_MEASURE_TIMEBASE ); + m_InputTimeout.Set ( (refframe_t)m_Character.GetInputChangeInterval_sec() * FRAME_MEASURE_TIMEBASE ); + } + + // set the ship object we want to control + void SetShipObject( ShipObject* pShip ) + { + m_pShip = pShip; + m_State.Reset( pShip ); + } + + + + // main think function, called every render or sim frame ( client or server ) + void DoThink(); + + // get the character of the bot + BOT_Character* GetCharacter() { return &m_Character; } + +protected: + + void _DoPlan(); + + void _GoalCheck_AgentMode_Idle(); + void _GoalCheck_AgentMode_Powerup(); + void _GoalCheck_AgentMode_Attack(); + void _GoalCheck_AgentMode_Retreat(); + + void _SteerToPosition( Vector3* targetPos, object_control_s* pObjctl ); +}; + + + +// easy access to the singleton ----------------------------------------------- +// +#define TheBot ( BOT_ClientSide::GetClientSideBot() ) + + +// forward decls -------------------------------------------------------------- +// +PRIVATE int BOT_CallThink( void* param ); + +// the timeout in refframes to wait between status checks --------------------- +// +#define BOT_STATUS_CHECK_TIMEOUT DEFAULT_REFFRAME_FREQUENCY + +// class for the client-side bot ---------------------------------------------- +// +class BOT_ClientSide : public BOT_AI +{ +protected: + + // standard ctor + BOT_ClientSide() : + m_Started( FALSE ), + m_bWantToBeConnected( TRUE ), + m_bWantToBeJoined( TRUE ), + m_NextStatusCheckRefFrame( 0 ) + { + memset( m_szServer, 0, MAX_SERVER_NAME * sizeof( char ) ); + } + + // standard dtor + ~BOT_ClientSide() + { + } + + // check whether current status (connected/joined etc. ) matches the desired one + void _CheckStatus(); + +protected: + int m_Started; + char m_szServer[ MAX_SERVER_NAME ]; + + int m_bWantToBeConnected; + int m_bWantToBeJoined; + + // next refframe, we check for connect/disconnect/joined/unjoined + refframe_t m_NextStatusCheckRefFrame; + +public: + // SINGLETON pattern + static BOT_ClientSide* GetClientSideBot() + { + static BOT_ClientSide _TheClientSideBot; + return &_TheClientSideBot; + } + + // set/get of status flags + int GetDesiredConnStatus() const { return m_bWantToBeConnected; } + int GetDesiredJoinStatus() const { return m_bWantToBeJoined; } + void SetDesiredConnStatus( int bWantToBeConnected ) { m_bWantToBeConnected = bWantToBeConnected; } + void SetDesiredJoinStatus( int bWantToBeJoined ) { m_bWantToBeJoined = bWantToBeJoined; } + + // overwritten think method to allow special client-side things + void DoThink(); + + // start the bot + void Start(); + + // stop the bot + void Stop(); + + // get the servername the client bot should connect to + char* GetConnectServer() + { + return m_szServer; + } + + // set the server we want to connect to + void SetConnectServer( char* pszServer ) + { + // trim left + char *p = NULL; + for( p = pszServer; *p == ' '; p++ ); + + if ( strncmp( p, "\"\"", 2 ) == 0 ) { + m_szServer[ 0 ] = '\0'; + } else { + strncpy( m_szServer, p, MAX_SERVER_NAME ); + } + } +}; + +#endif // G_BOT_CL_H_ |
