Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Fri Jul 30, 2010 10:02 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 239 posts ]  Go to page 1, 2, 3, 4, 5 ... 12  Next
Author Message
 Post subject: Spawning Bots in Doom III (Fake Client bots)
PostPosted: Wed Apr 13, 2005 9:26 pm 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
Gone are the days of hacked monsters for bots!

In order to create bots in server side doom, here's what I'm doing:-

1) Wrapping the idNetworkSystem API, so that calls to send packets to bot-clients does not happen. This is why previous attempts within the community seem to have failed, as doom 3 does not private a true mechanism for setting a client to be fake (i.e. bot)

2) Code in multiplayerGame's Run() function to call each bot in the game and run it's think() function.

3) A cvar to spawn a bot using one of the upper half of the client numbers (the SDK code defines MAX_CLIENTs as 32, so bot 1 spawns as client 16, so it doesnt conflict with spawning players, who will take up the bottom 8 id's)

In game_local.cpp, swap the line 69:

networkSystem = import->networkSystem;

for:-

networkSystem = new botNetworkSystem(import->networkSystem);

and add:

#include "../botNetwork.h"

to the top after the #pragma hdrstop

Create this file (botNetwork.h) defining your network wrapper class:-
Code:
#ifndef __BOTNETWORK__
#define __BOTNETWORK__ 1

#define BOT_START_INDEX      16

class botNetworkSystem
{
public:
   botNetworkSystem (idNetworkSystem *networkSystem);

   void         ServerSendReliableMessage( int clientNum, const idBitMsg &msg );
   void         ServerSendReliableMessageExcluding( int clientNum, const idBitMsg &msg );
   int            ServerGetClientPing( int clientNum );
   int            ServerGetClientPrediction( int clientNum );
   int            ServerGetClientTimeSinceLastPacket( int clientNum );
   int            ServerGetClientTimeSinceLastInput( int clientNum );
   int            ServerGetClientOutgoingRate( int clientNum );
   int            ServerGetClientIncomingRate( int clientNum );
   float         ServerGetClientIncomingPacketLoss( int clientNum );

   void         ClientSendReliableMessage( const idBitMsg &msg );
   int            ClientGetPrediction( void );
   int            ClientGetTimeSinceLastPacket( void );
   int            ClientGetOutgoingRate( void );
   int            ClientGetIncomingRate( void );
   float         ClientGetIncomingPacketLoss( void );

private:
   idNetworkSystem   *network;
};

extern botNetworkSystem * networkSystem;

#endif __BOTNETWORK__



Create this file (botNetwork.cpp) defining your network wrapper functions:-

Code:
botNetworkSystem::botNetworkSystem(idNetworkSystem *networkSystem)
{
   network = networkSystem;
}

float botNetworkSystem::ClientGetIncomingPacketLoss()
{
   return network->ClientGetIncomingPacketLoss();
}

int botNetworkSystem::ClientGetIncomingRate()
{
   return network->ClientGetIncomingRate();
}

int botNetworkSystem::ClientGetPrediction()
{
   return network->ClientGetPrediction();
}

int botNetworkSystem::ClientGetTimeSinceLastPacket()
{
   return network->ClientGetTimeSinceLastPacket();
}

int botNetworkSystem::ClientGetOutgoingRate()
{
   return network->ClientGetOutgoingRate();
}

float botNetworkSystem::ServerGetClientIncomingPacketLoss(int clientNum)
{
   if (clientNum >= BOT_START_INDEX)
      return 0;
   return network->ServerGetClientIncomingPacketLoss(clientNum);
}

int botNetworkSystem::ServerGetClientIncomingRate(int clientNum)
{
   if (clientNum >= BOT_START_INDEX)
      return 0;
   return network->ServerGetClientIncomingRate(clientNum);
}

int  botNetworkSystem::ServerGetClientOutgoingRate(int clientNum)
{
   if (clientNum >= BOT_START_INDEX)
      return 0;
   return network->ServerGetClientOutgoingRate(clientNum);
}


int botNetworkSystem::ServerGetClientPing(int clientNum)
{
   if (clientNum >= BOT_START_INDEX)
      return 50;   // Steve:: Can we make this random to emulate bot latency?
   return network->ServerGetClientPing(clientNum);
}

int botNetworkSystem::ServerGetClientTimeSinceLastInput(int clientNum)
{
   if (clientNum >= BOT_START_INDEX)
      return 0; // Steve:: What are the effects of this?
   return network->ServerGetClientTimeSinceLastInput(clientNum);
}


int botNetworkSystem::ServerGetClientTimeSinceLastPacket(int clientNum)
{
   if (clientNum >= BOT_START_INDEX)
      return 0; // Steve:: What are the effects of this?
   return network->ServerGetClientTimeSinceLastPacket(clientNum);
}


int botNetworkSystem::ServerGetClientPrediction(int clientNum)
{
   if (clientNum >= BOT_START_INDEX)
      return 0;
   return network->ServerGetClientPrediction(clientNum);
}

void botNetworkSystem::ServerSendReliableMessage(int clientNum, const idBitMsg &msg)
{
   if (clientNum >= BOT_START_INDEX)
      return;
   network->ServerSendReliableMessage(clientNum, msg);
}

void botNetworkSystem::ServerSendReliableMessageExcluding(int clientNum, const idBitMsg &msg)
{
   if (clientNum >= BOT_START_INDEX)
      return;
   network->ServerSendReliableMessageExcluding(clientNum, msg);
}

void botNetworkSystem::ClientSendReliableMessage(const idBitMsg &msg)
{
   network->ClientSendReliableMessage(msg);
}


If you get compile errors regarding networkSystem being defined as idNetworkSystem, you need to edit src/framework/asynch/networksystem.h and remove the reference to extern idNetworkSystem * networkSystem.

Next up, you simply add cvar commands to call methods on your bot class, which in turn call the functions of idGameLocal:

ServerClientConnect(clientID)
ServerClientBegin(clientID)

and so forth. You take the client ID from the upper half the client array, since real players will never be allocated into these ids.

As for where you hook your Think() on your bot class, my recommendation is Run() in idMultiplayergame.

I'll release more code as I polish it, but hopefully people can see how I'm doing this now.

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 12:33 am 
Offline
picked up 100 armour

Joined: Sat Dec 18, 2004 5:21 pm
Posts: 104
hello i like bots.

did you try SaBot for Doom3 by TinMan ?

cant wait to try out your bot once a compile is ready :-)
:D


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 12:40 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
Tinmans bot isn't a bot per-say, it's an admirable effort though since it's a hack of unparralleled magnitude. What I'm doing is the way it "should" be done ideally, since this way the bot uses existing game logic to do things, having a true inventory and only being able to move as a client could.

Tinman essentially created a "monster" bot, and hacked to enable monsters in multiplayer. His pitfall then became that he had to manually animate the bot, and then implement his own logic for picking up items and so forth. It's not a bad way to do it, but it's a longer and more burdonsome road. But in the long run he cant get it onto the scoreboard without rewriting that too, powerups need manual programming etc, whereas the server side solution I propose simply touches them, and then the server will automatically adjust the statistics of the bot, since as far as it's concerned it's just another player.

Right now I've got one or two pics:-

Image
Image

The name is "New Player" since thats the default for the entity-dictionary from what I can see, and the connecting status flag is because I need to pass a dummy network message to say the bot is connected.

They're running AIBot::Think() (my own class for bots) once every 50msec and printing out that message. you see in shot two.
[/img]

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 12:46 am 
Offline
picked up 100 armour

Joined: Sat Dec 18, 2004 5:21 pm
Posts: 104
Interesting Stuff.

ill like to give it a run.

being as i compiled a whole load of AAS files for the Mp maps i have for SaBot :cry:

im pretty sure SaBot doesnt run on Lan/Internet.
im guessing that youres will.

cant wait to try it im a Big Bot Fan :shock: .


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:04 am 
Offline
missed 400 shots

Joined: Thu Dec 30, 2004 11:38 pm
Posts: 454
Location: Minnesota US
Holy shit you just saved me a month :D

You say you are interested in sharing more, i would love to take a look at what you are doing, even help out.

let me know K?

Awsome work, thanks for sharing this.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:14 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
I'll probably have the whole source code out as soon as I've got something that can at least run around the level (even if it's wall bouncing).

However, I'm at the early stages, and you'd loose little from implementing it yourself at this stage.

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:21 am 
Offline
missed 400 shots

Joined: Thu Dec 30, 2004 11:38 pm
Posts: 454
Location: Minnesota US
OK, will do :roll:

Have you looked into the AAS system at all or are you planning on rolling your own navigation logic?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:26 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
Don't worry about AAS now for gods sake, you've got much more important things to worry about. AAS is not a navigation system unto itself, and until you've got the first 90% of the code written, I'd stick with waypoints.

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:31 am 
Offline
missed 400 shots

Joined: Thu Dec 30, 2004 11:38 pm
Posts: 454
Location: Minnesota US
Doom3 is my first modding escapade :oops:

but it seemed to me that AAS was more of a navigation system than you are saying. Give it a goal position and it will get you there. I haven't gotten as far as coding it yet. Just doing a ton of research and getting familiar with how it works.

I was until i read this post using the same approach as tinman and mainly for single player (waiting for you to come around i guess with the multiplayer spawn)

more thoughts?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:31 am 
Offline
picked up 100 armour

Joined: Sat Dec 18, 2004 5:21 pm
Posts: 104
i remeber from quake3 days there wasnt much you could do with the aas system you always had to work around it cause there wasnt any code available for that area in the exe.

same probably applies here in doom3.

but having no coding experience besides reading about it
this is all from what ive read.

difficult to code around or not ive always liked the Quake3 bots
and now the Ai in Doom3.

Mr.Elusive i figure is most likely the hero here.
he did quake3 bots. i know he also had alot to do with the physic system too.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:38 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
There's some issues that were unexpected, namely that:-

1) Spawning the bot causes it's default state to be looking upward and jumping constantly, I'm guessing this is since the entire bot struct is zeroed with a memset before spawn, and I'm not issuing commands to set otherwise.

2) The string "connecting" on the leaderboard must be set somewhere, I still cant find where. If I can find when and why it's set, I can clean up the spawn code (right now I clientconnect, clientbegin and player->spawn to put them in, then player->Spectate(false)).

Here's a funny pic

Image

Anyone got any ideas about how to go about fixing these? I'm going to continue playing, but any more experienced modders are welcome to say what I'm not seeing :)

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:48 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
The spawn routine I use, please not it refers to code for a "bot list" that isnt shown. If anyone has ideas on what I can call in AIBot::Think() to make it move, and set it's status so it's connected properly, I'd appreciate it.

Code:
void Bot_AddBot(const idCmdArgs &args )
{
   // Try to find an ID in the bots list
   int botID = Bot_GetFree();
   
   // If we dont have a bot ID, return and show an error
   if (botID == -1)
   {
      gameLocal.Printf("^1ERROR: The maximum number of bots are already in the game.\n");
      return;
   }

   // Set up our class
   bots[botID].used = true;
   bots[botID].aiBot = new AIBot();
   bots[botID].clientID = BOT_START_INDEX + botID;

   gameLocal.Printf("Spawning bot \"%s\" as client %d\n", botNames[botID], bots[botID].clientID);

   // Put this bot in the server
   gameLocal.ServerClientConnect(bots[botID].clientID);
   gameLocal.ServerClientBegin(bots[botID].clientID);
   gameLocal.Printf("Bot has been connected, and client has begun.\n");

   // Spawn
   idPlayer *p = static_cast< idPlayer * >( gameLocal.entities[ bots[botID].clientID ] );
   p->Spawn();
   p->Spectate(false);

                // Print our dictionary, I'm wondering if things are in here
   gameLocal.Printf("Listing keys:-\n");
   p->GetUserInfo()->ListKeys_f(args);
   gameLocal.Printf("Listing values:\n");
   p->GetUserInfo()->ListValues_f(args);

                // We've changed
   p->UserInfoChanged();
}


_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 1:52 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
My latest theory for the "connecting" issue is that I'm not calling some function somewhere that "completes" the spawn process properly on the server for the bot, In half-life this was called ClientPutInServer or something.

Also, maybe the string is loaded from an internationalization resource file, thats why I cant find it using Visual Studio search....

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 2:19 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
Now they're on the ground, spawning correctly (Apart from the "connecting" bug), and not jumping around like spastics. Here's another picture:-

Image

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 5:01 am 
Offline
picked up 100 armour

Joined: Sun Jan 02, 2005 8:46 pm
Posts: 141
Well Cobalt, I think you are making assumptions regarding TinMan's SABot that are not true. First thing is, it's not merely a hacked up monster script. Instead it uses many changes to the SDK. There is a bot inventory class and a bot class that derives from the idAI class. TinMan simply has not had the time to make a hook in the multiplayer code because of work on another mod: Supremacy. In fact some of the code that is going into Supremacy will get recycled into his SABot mod.

So while I commend your beginnings of a bot, saying "Tinmans bot isn't a bot per-say, it's an admirable effort though since it's a hack of unparralleled magnitude." really isn't true. TinMan's bot really is a bot.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 5:36 am 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
Just so we're clear, I'm not dissing what he's achieved, it's what inspired me to do this. What I'm not too sure is a good idea is the way he's done it, since it creates so much duplication just to provide the most basic functionality, and would require massive hacking to work fully like a player. Ask him yourself, and you'll see why this approach is indeed preferable, plus it aids greatly by making the bots game dependancies smaller (No replication/emulation of game logic to apply to the bots).

It's in fact possible to export this whole set of code into a moderating dll that sits between doom3 and the game dll, and then can perform its magic there, meaning once this is achieved, we can have a bot spawn in closed source modifications, such as ROE, or perhaps even D3F when it comes out. This endgame, combined with the burdon of pursuing the monster-bot route means fake-clients are the way to go.

Additionally, Looking through those SABot scripts there hundreds of places where theres no clear certainty whats going on, because of the complexity of cloning players in that fashion and basing it off existing scripts, and to top it all of it wont even show on the scoreboard without script sayso. It's a hacked up "monster" script alright, an admirable one, but as you've pointed out he's got to clone everything in order to walk that long route, even the inventory. Whereas server side fakeclient bots have none of these concerns, since to the engine they're just regular players, and will trigger events such as pickups merely be moving around, an automatically updated inventory by the engine to boot!

In short, no hard coded animation references, nothing, just the direction you're moving, the keys you're pressing and the way you're aiming. For inventory, I can just use the direct pointer to the player information structure, and read off the data without writing any new classes to accomplish that.

I dont know where you got the idea this took me a lot of time either, I only downloaded the SDK this evening, I literally wrote my first line of code after I posted the other thread, and I've stopped the last few hours to do other work. This relative ease of development is the difference between "monsters" and "fake clients", and only really required the initial steps be made.

How I did this is public knowledge now, so theres no reason that Tinman couldnt implement these changes, and have his bot back to it's current progress position in three or four hours and a fraction of the code.

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 10:11 am 
Offline
picked up a pistol

Joined: Sat Aug 14, 2004 2:52 am
Posts: 72
Been wondering when this would be done, works quite similar to quake 2 way of doing it.
Good luck with the rest!

And perhaps, maybe, make the bot logic seperate to the game code, as in, all AI is in script?
Nah, c++ will make it run faster, but it would be nice to have scripted elements for customizing.

For the player name problem, maybe try and hook it into script and get it to search for a, say, botnames.cfg and grab a name from that, format could be:

bot1: default
bot2: itsabotname
bot3: Randombot
...

So you could have a set list of max, 50 bots, each has their charaturistics in the bot.cfg, and is parsed by using bot1,2,3,4.. to grab the info and bung it in an array of sorts...


This is going to keep me up for a while in the weekend. :?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 2:16 pm 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
Guess what I've just gotten working:-

Image

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 2:26 pm 
Offline
picked up 100 armour

Joined: Sat Dec 18, 2004 5:21 pm
Posts: 104
Cobalt : awesome !! looks as if he has spotted you !!
but being a marine and all fragging hundreds [if not thousands] of monsters
this frag should be no different. 8)

im admiring really the work put in here. you say you developed this that quickly. but you have coded bots for other games so you know most of what your looking for.

Id woulda put bots in as a feature and XYZ but they had best tighten up everything not accessable to modders/coders in the exe etc the other half of the code.

truly inspiring work.
what tools do you use ? ms Visual Studio ?
which one ? a friend of mine wanted to dabble in Doom3 SDK.
i know there are countless threads.

i :Heart: Bots


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 14, 2005 3:21 pm 
Offline
has joined the game

Joined: Wed Apr 13, 2005 5:57 pm
Posts: 30
Location: Bath, UK
AIBot::TargetFilter:

Code:

/**
* Perform targetting actions
**/
void AIBot::TargetFilter()
{
   // Dont clip
   playerEnt->GetPhysics()->DisableClip();

   // For all spawned entities
   for (idEntity *ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() )
   {
      // If this is a player, and not ourself
      if ((ent->IsType( idPlayer::Type )) && (playerEnt != ent) && (ent->health > 0))
      {
         
         // Trace a line from our eyes to them
         trace_t traceResult;   
         gameLocal.clip.TracePoint(traceResult,    playerEnt->GetPhysics()->GetOrigin() + playerEnt->EyeOffset(), ent->GetPhysics()->GetOrigin(), MASK_SHOT_BOUNDINGBOX, playerEnt);
         
         // Did we hit this player?
         if (gameLocal.GetTraceEntity(traceResult) == ent)   
         {
               gameLocal.Printf("I can see an enemy.\n");
      
               // Set our view angles
               idAngles lookTo = (ent->GetPhysics()->GetOrigin() - playerEnt->GetPhysics()->GetOrigin()).ToAngles();
               playerEnt->SetViewAngles(lookTo);

               // Attack!
               gameLocal.usercmds[ clientID ].buttons = BUTTON_ATTACK;
               gameLocal.usercmds[ clientID ].forwardmove = 20.0f;

               // We can clip again
               playerEnt->GetPhysics()->EnableClip();

               return;
            
         }      
      }
   }
   
   // We can clip again
   playerEnt->GetPhysics()->EnableClip();
}


As for experience, I suppose it does help me targetting functionality that needs implementing first. As for IDE, I use Visual Studio .NET[/code]

_________________
Steven "Cobalt" Gray
Pleasing Taste, Some Monsterism.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 239 posts ]  Go to page 1, 2, 3, 4, 5 ... 12  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Oneofthe8devilz and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group