aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/include/g_bot_cl.h
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/include/g_bot_cl.h
downloadopenparsec-c068f22329d5cc722622a2183bbb22eef2093df7.tar.xz
openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.zip
initial importHEADmain
Diffstat (limited to 'src/parsec/include/g_bot_cl.h')
-rw-r--r--src/parsec/include/g_bot_cl.h404
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_