View Single Post
Re: Independed Thinking Machine
Old
  (#11)
Whistler
Whistler
 
Whistler's Avatar
 
Status: Offline
Posts: 1,493
Join Date: Feb 2004
Location: P. R. China
Default Re: Independed Thinking Machine - 22-12-2004

well I also has made a "engine independant" structure for my new bot, but it's not very advanced; I just stuffed most of engine specific stuff in classes. Here's my bot.cpp file:
PHP Code:
/*
 * The GINA Bot - a computer opponent for Valve Software's game Half-Life
 * Copyright (c) 2004, Wei Mingzhi <whistler_wmz@users.sf.net>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * In addition, as a special exception, the author gives permission to
 * link the code of this program with the Half-Life Game Engine ("HL
 * Engine") and Modified Game Libraries ("MODs") developed by Valve,
 * L.L.C ("Valve").  You must obey the GNU General Public License in all
 * respects for all of the code used other than the HL Engine and MODs
 * from Valve.  If you modify this file, you may extend this exception
 * to your version of the file, but you are not obligated to do so.  If
 * you do not wish to do so, delete this exception statement from your
 * version.
 *
 * [In other words, you are welcome to use, share and improve this
 * program. You are forbidden to forbid anyone else to use, share
 * and improve what you give them.]
 */

//
// bot.cpp
//
// Basic bot handling.
//

#include "main.h"

CBaseBot::CBaseBot():
m_iStartAction(0),
m_flMoveSpeed(0),
m_flSideMoveSpeed(0),
m_flUpMoveSpeed(0),
m_fIsStarted(false),
m_fNeedToInitialize(true),
m_flTimeThink(0),
m_flTimePrevThink(0),
m_iPrevHealth(0),
m_pAINode(NULL)
{
   
bi.actionflags 0;
   
bi.dir g_vecZero;
   
bi.idealangles g_vecZero;
   
bi.weapon 0;

   
// initialize subsystems...
   
nav = new CBotNav(this);
   
chat = new CBotChat(this);
   if (!
nav || !chat)
      
g_General.TerminateOnError("Memory allocation error !");
}

CBaseBot::~CBaseBot()
{
   
// delete subsystems...
   
delete nav;
   
delete chat;

   if (
m_pAINode)
      
delete m_pAINode// free memory allocated for current AI node

   
m_pProfile->is_used false// this profile is not used now
}

void CBaseBot::BotThink()
{
   if (!
IsValid() || !GetNetName()[0]) {
      
g_General.TerminateOnError("BotThink(): Bot entity is invalid!");
   }

   
MarkAsBot(); // mark this entity as a bot

   
if (!m_fIsStarted) {
      
// if the bot hasn't selected stuff to start the game yet, go do that...
      
StartGame();
   } else if (!
IsAlive()) {
      
// if the bot is dead, run the dead think code (MOD specific)
      
DeadThink();
      
m_fNeedToInitialize true;
      
// delete the AI node data if exist
      
if (m_pAINode)
         
delete m_pAINode;
      
m_pAINode NULL;
   } else {
      if (
m_fNeedToInitialize) {
         
SpawnInit(); // initialize if we need to
         
m_fNeedToInitialize false;
      }

      if (
m_flTimeThink g_pServer->GetTime()) {
         
BotAI(); // run the main bot AI routine at 10Hz

         
m_flTimePrevThink g_pServer->GetTime();
         
m_flTimeThink g_pServer->GetTime() + 0.1;
      }
   }

   
PerformMovement(); // Pass through the engine
}

void CBaseBot::DeadThink()
{
   
// press fire to respawn...
   // NOTE: For some MODs like CS, we needn't press fire.
   // so leave this virtual...
   
bi.actionflags |= ACTION_RESPAWN;
}

void CBaseBot::SpawnInit()
{
   
ResetState();

   
AIEnter(new CAINode_Normal(this)); // enter the normal AI node
}

void CBaseBot::FacePosition(const Vector &vecPos)
{
   
// Adjust bots ideal angles to face an absolute vector
   
bi.idealangles VecToAngles(vecPos GetGunPosition());
   
bi.idealangles.*= -1.0// invert for engine

   
ClampAngles(bi.idealangles);
}

void CBaseBot::TranslateBotInput()
{
   
float flMoveSpeed GetMaxspeed();

   
ReleaseAllButtons();
   
m_flMoveSpeed 0;
   
m_flSideMoveSpeed 0;
   
m_flUpMoveSpeed 0;

   
// if bot is pressing the walk button...
   
if (bi.actionflags ACTION_WALK) {
      
PushButton(IN_RUN); // push the walk button
      
flMoveSpeed *= 0.3// reduce his move speed
   
}

   
// bot want to respawn?
   
if (bi.actionflags ACTION_RESPAWN) {
      
// push attack randomly to respawn
      
if (RandomLong(01))
         
PushButton(IN_ATTACK);
   }

   
// bot want to fire?
   
if (bi.actionflags ACTION_ATTACK) {
      
PushButton(IN_ATTACK); // push attack to fire
   
}

   
// bot want to use secondary attack?
   
if (bi.actionflags ACTION_ATTACK2) {
      
PushButton(IN_ATTACK2); // push attack to fire
   
}

   
// bot want to reload?
   
if (bi.actionflags ACTION_RELOAD) {
      
PushButton(IN_RELOAD); // push the reload button
   
}

   
// bot want to use something?
   
if (bi.actionflags ACTION_USE) {
      
PushButton(IN_USE);
   }

   
// Change bots body angle and view angle
   
float turn_skill 0.3 GetSkill() / 100speed;

   
// if bot is aiming at something, aim fast, else take our time...
   
if (m_pEnemy)
      
speed 0.7 turn_skill// fast aim
   
else
      
speed 0.2 turn_skill 2// slow aim

   
ChangeAngles(bi.idealanglesspeed); // change bot angles

   
float forwardspeed 0sidespeed 0;

   
// bot want to move forward?
   
if (bi.actionflags ACTION_MOVEFORWARD) {
      
PushButton(IN_FORWARD); // push the forward button
      
forwardspeed += flMoveSpeed// set the move speed
   
}

   
// bot want to move back?
   
if (bi.actionflags ACTION_MOVEBACK) {
      
PushButton(IN_BACK); // push the moveback button
      
forwardspeed -= flMoveSpeed// set the move speed
   
}

   
// bot want to move left?
   
if (bi.actionflags ACTION_MOVELEFT) {
      
PushButton(IN_MOVELEFT);
      
sidespeed -= flMoveSpeed// set the sidemove speed
   
}

   
// bot want to move right?
   
if (bi.actionflags ACTION_MOVERIGHT) {
      
PushButton(IN_MOVERIGHT); // press the button
      
sidespeed += flMoveSpeed// set the sidemove speed
   
}

   
// if move direction is specified...
   
if (bi.dir != g_vecZero) {
      
// set the view independent movement
      
Vector vecDirectionNormal bi.dir.Normalize();
      
vecDirectionNormal.0;

      
// movement is relative to the REAL bot angles
      
Vector forward;
      
AngleVectors(Vector(0GetViewAngles().y0), &forwardNULLNULL);

      
// calculate movement speed
      
float flCos DotProduct(forwardvecDirectionNormal);
      
float flSin sqrt(flCos flCos);
      
m_flMoveSpeed flCos forwardspeed;
      
m_flMoveSpeed -=  flSin sidespeed;
      
m_flSideMoveSpeed flCos sidespeed;
      
m_flSideMoveSpeed += flSin forwardspeed;
   } else {
      
m_flMoveSpeed forwardspeed;
      
m_flSideMoveSpeed sidespeed;
   }

   
// bot want to jump ?
   
if (bi.actionflags ACTION_JUMP) {
      
PushButton(IN_JUMP); // press the button
      
m_flUpMoveSpeed += flMoveSpeed// set the upmove speed
   
}

   
// bot want to crouch ?
   
if (bi.actionflags ACTION_CROUCH) {
      
PushButton(IN_DUCK); // press the button
      
m_flUpMoveSpeed -= flMoveSpeed// set the upmove speed
   
}

   
// switch to correct weapon
   
if (bi.weapon != 0)
      
SelectWeapon(bi.weapon);
}

void CBaseBot::SelectWeapon(int iId)
{
   if (
iId != m_iCurrentWeaponId) {
      
// is the specified weapon ID valid ?
      
if (iId || iId MAX_WEAPONS) {
         
g_General.TerminateOnError("CBaseBot::SelectWeapon(): Invalid weapon ID !\n");
      }

      
// issue a client command to select this weapon...
      
g_General.FakeClientCommand(thisg_General.GetWeaponName(iId));
   }
}

void CBaseBot::PerformMovement()
{
   
// Translate bot input
   
TranslateBotInput();

   
// pass to the engine
   
g_engfuncs.pfnRunPlayerMove(edict(), (float *)GetViewAngles(), m_flMoveSpeed,
                               
m_flSideMoveSpeedm_flUpMoveSpeedpev->button,
                               
pev->impulseg_pServer->GetMsec());
}

void CBaseBot::ResetState()
{
   
// reset bot input parameters
   
bi.actionflags 0;
   
bi.dir g_vecZero;
   
bi.idealangles g_vecZero;
   
bi.weapon 0;

   
m_iPrevHealth 0;

   
m_pEnemy NULL// null out the enemy pointer
   
m_vecEnemy g_vecZero;
   
m_ucVisibility 0;

   
Nav()->Init(); // initialize the navigation system
}

void CBaseBot::DebugMsg(int flag, const char *fmt, ...)
{
#ifndef _DEBUG
   
if (!g_Debug.IsDebugOn(flag))
      return; 
// debug for this flag is off; don't proceed
#endif

   
va_list     argptr;
   
char        string[256];

   
va_start(argptrfmt);
   
_vsnprintf(stringsizeof(string), fmtargptr);
   
va_end(argptr);

   
printf("[BOT DEBUG] %s: %s\n"GetNetName(), string); // print this message to the console
   
g_Debug.DebugLog(flag"(%s) %s"GetNetName(), string); // also store it to the log file

  
Reply With Quote