.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   Half-Life 2 SDK (http://forums.bots-united.com/forumdisplay.php?f=62)
-   -   I don't like this! (http://forums.bots-united.com/showthread.php?t=3281)

stefanhendriks 26-12-2004 22:50

I don't like this!
 
http://www.chatbear.com/board.plm?a=...4991&v=flatold

check the latest post of botman... :'(

Lazy 26-12-2004 23:27

Re: I don't like this!
 
I don't have the HL2 SDK yet ( Hl2 disc 4 came broken, bah ) but does this mean bots cannot be made with a plugin but they can if they are built into the mod?

Wouldn't CBaseEntity be broken only on mods that break the offsets of existing members? like...

original:
+0 m_pEnemy
+4 m_iPlayerclass

Other:
+0 m_iAlwaysnull
+4 m_pEnemy
+8 m_iPlayerclass

Too bad only people who bought hl2 can get the sdk, I would like to read it while I wait to get my replacement copy of hl2.

Pierre-Marie Baty 27-12-2004 01:58

Re: I don't like this!
 
I don't understand what botman says (maybe because I don't have the SDK yet). Is he meaning that they took the equivalents of CreateFakeClient and RunPlayerMove out of the "enginefuncs" or whatever it is called now ?

I want to ignore all that server plugin stuff. I see an engine and a server gamedll. Both of them exchange stuff: data, functions. There's an interface to both. If we were to realize a hook DLL, first HPB_bot style, WHAT would we get ? Is it possible, first ? I strongly believe it is. The function we need to find to create a bot don't even count up to ten. And the only game DLL hook we need to get started is StartFrame, or whatever it is called. Does anyone have a clue how the engine attaches its DLLs, and couldn't we make a simple hook DLL featuring a transparent interface, for a start ?

Just tossing. Perhaps I need to finish downloading HL2 before rambling around like that.

stefanhendriks 27-12-2004 08:38

Re: I don't like this!
 
well, you can do CreateFakeClient, but thats about it. YOu can't have access to player data as much as you used to.

i tried cexports.exe already on the server.dll and client.dll on hl2 , but they only give me either 1 (exportinterface) or 3 'exports'... :S

i bet the exportinterface that is exposed, is the same as you hook in with your serverplugin thingy, but don't count me on that.

stefanhendriks 27-12-2004 08:45

Re: I don't like this!
 
* rofl, look at the latest post of botman there

Quote:

I believe it can be done, but bots written as plugins for Half-Life2 won't be as easy as they were for Half-Life1 (and those took me 3-4 months to get running with hundreds of engine crashes along the way).


@$3.1415rin 27-12-2004 10:39

Re: I don't like this!
 
sad news :/

I still don't get why mods have to modify the CBasePlayer, since they can derive another class and then modify it ... so there would be a nice and suitable way to access the data for each player ... but let's see what botman gets to know, somehow I always have the feeling that he got quite some more info than all of us :P

stefanhendriks 27-12-2004 11:45

Re: I don't like this!
 
same here, but when he says that, i am afraid its not something we should think to easily about. I think this will be pretty tough.

botman 27-12-2004 15:49

Re: I don't like this!
 
"Is he meaning that they took the equivalents of CreateFakeClient and RunPlayerMove out of the "enginefuncs" or whatever it is called now ?"

CreateFakeClient() is still an engine function pfnRunPlayerMove() became PlayerRunCommand() and is now part of the player.cpp file. Player movement is handled by something called MoveHelperServer() whos code is now part of the game DLL (not part of the engine). It looks like all of the engine functions that handled player movement are now handled in the game DLL. I believe that all collision checking is still handled in the engine (but I haven't researched this yet).

"If we were to realize a hook DLL, first HPB_bot style, WHAT would we get ? Is it possible, first ?"

No, it's not. Here's why. Under Half-Life1, you renamed the game DLL (mp.dll or hl.dll), you copied your hook DLL into the 'dlls' folder and your hook DLL loaded the game DLL. Remember everytime you upgraded a MOD, you had to go through this step all over again? With Steam, the server.dll (which replaced mp.dll or hl.dll) is updated almost once a week (there have been updates constantly since Half-Life2 was released). The frequency of the updates to server.dll will decrease over time, but each time the server.dll is updated, it will overwrite your hook server.dll and the player will have to re-install things.

The game DLL to engine interface is COMPLETELY different for Half-Life2. In Half-Life2, you have ONE function exported from the game DLL (called CreateInterface). Here's the output from 'dumpbin' on server.dll
Code:

Dump of file server.dll
 
  File Type: DLL
 
    Section contains the following exports for server.dll
 
          00000000 characteristics
          41AD220F time date stamp Tue Nov 30 19:44:47 2004
                  0.00 version
                    1 ordinal base
                    1 number of functions
                    1 number of names
 
          ordinal hint RVA          name
 
                    1        0 0016A490 CreateInterface
 
    Summary
 
            9F000 .data
            98000 .rdata
            53000 .reloc
            2B4000 .text

The CreateInterface function is used by the engine to pass in an "interface factory" function pointer. This "interface factory" is used to obtain function pointers to engine interfaces. You basically pass in a ID number of the type of interface you want and the engine returns you a pointer to the interface that matches what you asked for. For example, if you want an engine interface called "IGameEventManager" (which notifies you of game events like, player deaths, flag captures, etc), you might pass in 0x507 as the ID for the Game Event Manager (this ID is defined in the SDK header files). You get back a pointer to this interface so that you can call functions on that interface. Now let's say Valve decides to add a new function to this interface but doesn't want to break any existing MODs. They create interface 0x508 which has a different set of functions that 0x507 did. MODs that ask for interface 0x507 get that. Newer MODs that ask for interface 0x508 get it and can use the new functions. This allows the engine to be easily upgraded without breaking ANY existing MODs.

So you no longer have a 1-to-1 interface between the game DLL and the engine code. You have an N-to-N interface since your hook has to support all the latest and greatest engine interfaces in order to not break newer MODs (and this problem existed previously with bots in Half-Life1, but the engine interface RARELY changed, with Steam, the engine interface could be changing on a weekly basis).

Like I said on VERC, I believe that a server plugin type bot DLL would be possible, but it will be EXTREMELY difficult to get at the information that bots will need (it's difficult right now just to get at the other player's origin and angles).

botman

sfx1999 27-12-2004 17:22

Re: I don't like this!
 
But here is what I was thinking. What if you make the bots actual monsters, and find a way to get them on the scoreboard?

botman 27-12-2004 18:48

Re: I don't like this!
 
Why would that be any easier? The hard part is getting plugins to be able to collect information about real players AND to be able to get some entity (bot or monster) moving around in the world properly. Bot or monster makes no difference here.

botman

stefanhendriks 27-12-2004 22:47

Re: I don't like this!
 
i mailed Alfred about bots and such;

he replied!

Quote:

> So basicly:

> 1) Any news on Bots with HL2DM? (crash on fakeclient creation)

I haven't managed to look at this yes (Christmas and all).

> 2) Any hints for us bot creators about any update functions or

> something alike

We are working on a document describing to how implement bots in Mods, you could use that information also.

>3) Any other hints on future things we can expect?

> (ie, we certainly hope we *can* create bots on Source... Though i

>have seen some frustrated members on forums talking about 'its

> impossible'.. )

>

You can make bots, its just not trivial from plugins. We are working out now how best to support plugins.




botman 28-12-2004 01:19

Re: I don't like this!
 
Well, as far as his answer to #2...

bot.h file...

Code:

  //=============================================================================//
    //
    // bot.h - bot header file (Copyright 2004, Jeffrey "botman" Broome)
    //
    //=============================================================================//
   
    #ifndef BOT_H
    #define BOT_H
   
    typedef struct
    {
            CSDKPlayer*        pPlayer;
    } bot_t;
   
    #endif // BOT_H

bot.cpp file...

Code:

  //=============================================================================//
    //
    // bot.cpp - bot source code file (Copyright 2004, Jeffrey "botman" Broome)
    //
    //=============================================================================//
   
    #include "cbase.h"
    #include "entitylist.h"
    #include "mapentities_shared.h"
    //#include "isaverestore.h"
    //#include "eventqueue.h"
    //#include "entityinput.h"
    //#include "entityoutput.h"
    //#include "mempool.h"
    //#include "vstdlib/strtools.h"
    //#include "engine/IVEngineCache.h"
   
    //#include "tier0/vprof.h"
   
    #include "client.h"
    #include "sdk_player.h"
    #include "movehelper_server.h"
    #include "in_buttons.h"
    #include "bot.h"
   
    // memdbgon must be the last include file in a .cpp file!!!
    #include "tier0/memdbgon.h"
   
    // private data for each bot
    static bot_t gBots[32];
   
   
    void BotThink(CSDKPlayer* pBot);
   
   
    CSDKPlayer* CreateBot(const char* name)
    {
            edict_t *pEdict = engine->CreateFakeClient( name );
   
            if (!pEdict)
            {
                    Msg("CreateBot: ERROR - Counldn't create a bot!!!\n");
                    return NULL;
            }
   
    //        ClientPutInServer(pEdict, name);  // you don't need this for bots in Source
   
            CSDKPlayer *pPlayer = ((CSDKPlayer *)CBaseEntity::Instance( pEdict ));
            pPlayer->ClearFlags();
            pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT );
   
            bot_t *pBot = &gBots[ engine->IndexOfEdict(pEdict) - 1 ];
   
            // initialize any private bot data here...
            pBot->pPlayer = pPlayer;
   
            Msg("CreateBot: bot was added successfully to server\n");
   
            return pPlayer;
    }
   
    void AddBot( void )
    {
            Msg("AddBot: Adding a bot...\n");
   
            CreateBot("Player");  // create a bot named "Player"
    }
   
    ConCommand addbot( "addbot", AddBot, "add a bot to the game." );
   
   
    // called by GameStartFrame() at the start of every frame, let's the bots Think...
    void BotStartFrame(void)
    {
            for ( int i = 1; i <= gpGlobals->maxClients; i++ )
            {
                    CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( i ) );
   
                if ((pPlayer != NULL) && (pPlayer->GetFlags() & FL_FAKECLIENT))
                    {
                            BotThink( pPlayer );
                    }
            }
    }
   
    // see CBasePlayer::RunNullCommand() for example of PlayerRunCommand()...
    void BotRunPlayerMove(CSDKPlayer* pPlayer)
    {
            CUserCmd cmd;
   
            // Store off the globals.. they're gonna get whacked
            float flOldFrametime = gpGlobals->frametime;
            float flOldCurtime = gpGlobals->curtime;
   
            pPlayer->pl.fixangle = FIXANGLE_NONE;
            cmd.viewangles = pPlayer->EyeAngles();
   
            float flTimeBase = gpGlobals->curtime;
            pPlayer->SetTimeBase( flTimeBase );
   
            cmd.forwardmove = 200.0f;
            cmd.sidemove = 0;
            cmd.upmove = 0;
            cmd.buttons = IN_JUMP;
            cmd.impulse = 0;
   
            if ( pPlayer->IsDead() ) // respawn dead players
            {
                    if (RandomInt(0,1))
                            cmd.buttons = 0;
                    else
                            cmd.buttons = IN_ATTACK;
            }
   
            MoveHelperServer()->SetHost( pPlayer );
            pPlayer->PlayerRunCommand( &cmd, MoveHelperServer() );
   
            // save off the last good usercmd
            pPlayer->SetLastUserCommand( cmd );
   
            // Restore the globals..
            gpGlobals->frametime = flOldFrametime;
            gpGlobals->curtime = flOldCurtime;
    }
   
    void BotThink(CSDKPlayer* pPlayer)
    {
            bot_t *pBot = &gBots[ engine->IndexOfEdict(pPlayer->edict()) - 1 ];
   
            pPlayer->AddFlag( FL_FAKECLIENT );  // make sure this is set every frame
   
            BotRunPlayerMove(pPlayer);
    }

You can just drop those 2 files into the 'dlls' folder of your Half-Life2 MOD (mine's called "MyMod"), so it would be MyMod\src\dlls\bot.h and MyMod\src\dlls\bot.cpp. Add bot.cpp to the list of source files in the Solution Explorer, build the DLLs and you can spawn a bot using "addbot" in the console.

EDIT: Opps, you also have to add...

void BotStartFrame(void);

...after line 38 of sdk_client.cpp in the dlls\sdk folder and add this...

BotStartFrame();

...at the very end of the "void GameStartFrame( void )" function in that same file (sdk_client.cpp).

botman

dub 28-12-2004 05:36

Re: I don't like this!
 
nice work botman:D.
P.S any news from valve about the plugin interface for bots from first impressions it seems like all the engine functions will need to be written into the plugin for a working bot:(.

stefanhendriks 28-12-2004 07:52

Re: I don't like this!
 
i just hope that valve will make a better answer then botman has, although its very nice to see how you can just use 2 files for a bot in your mod. I don't think this 'sollution' will be very fruitful.

*Edit:
Actually reading the response from nr 3, i don't think we should expect real support for bots @ plugins soon. Though, it would be great if they would make it easier for us (or even, possible).

stefanhendriks 28-12-2004 19:06

Re: I don't like this!
 
I have mailed Alfred again; with some sort of request if he *might* have a chance to give us some more info, or some hope about any developments for bots in plugins...

Quote:

Alfred,
Thank you for your reply; i already got response on it from Bots-United members. Basicly put we are a bit concerned about bot support. I understand that bot support is a good thing, especially via documentation or alike. However, what would be most ideal is to be able to code bots, seperated from the mod source. Botman already gave us an example of 2 files you can simply put in your mod and voila, you have bots. This is not exactly what we are looking for.

I understand that bot support is not trivial for plugins right now; though i'd think the functionalities for other plugins also require some access to certain variables (cBaseEntity/Player, etc) which is hard (or impossible) at this moment. For bots itself we only need some kind of updating function, so we can pass through the results of the think routine.

A good source i can give (about this subject and our concerns) is: http://forums.bots-united.com/showth...0987#post30987
Thanks again,
===============================================
Stefan Hendriks
FunDynamic & RealBot
http://www.fundynamic.nl
http://realbot.bots-united.com
http://www.bots-united.com
===============================================


sfx1999 28-12-2004 21:51

Re: I don't like this!
 
Are you sure you can't hook it anymore? What if you hooked the interfaces, and allowed new interfaces to still go through?

botman 28-12-2004 22:29

Re: I don't like this!
 
You can still hook "CreateInterface" if you want to (at least until the next Steam update wipes out your custom server.dll file).

Once you have hooked "CreateInterface", you can intercept requests from the game DLL code (old server.dll) to the engine. These requests will all be wanting engine interface function pointers. If you simply return the engine interface function pointers to the game DLL code, the game DLL code will bypass your hook DLL (because the function pointers point to the engine code). You will have to substitute YOUR version of these function pointers for the engine's function pointers and pass those back to the game DLL code so that the game DLL code will call your version of the functions. This is the same as it was in Half-Life1, where you had to recreate all of the engine functions and pass the game DLL code your version of those engine functions).

This is where the difficult part comes. You have to maintain a list of ALL possible versions of the engines interface function definitions (i.e. if the engine has gone through 5 different versions of the IGameEventManager interface function, your hook code would need to support all of those versions to be compatible with different MODs). If you only wanted focus on a single MOD (say CS), you would only need to support whichever version that MOD required (updating as necessary when the MOD updates or the engine updates).

Even after doing this, you STILL don't have access to player origins and angles, because this information isn't stored in the Half-Life2 engine like it was in Half-Life1. This data is now stored in the CBaseEntity class (which you don't have access to without doing some mucking around with pointers to PrivateData).

Like I said before, if the engine is handling collisions, then some of this data is passed from the game DLL code to the engine (the origin for example), but rotation (angles) is not used in player collisions (since HL1 and HL2 use axis-aligned bounding boxes for player collision). So even if the game DLL code is telling the engine what the origin of players is, the game DLL code might not be telling the engine what the rotation (angles) currently is (since the engine doesn't need this).

Other clients, obviously DO need this, so somewhere the CBaseEntity data has to be replicated from the server game DLL to all client. Perhaps intercepting this mechanism will allow you to get at the data you need.

botman

stefanhendriks 29-12-2004 18:39

Re: I don't like this!
 
sounds like a big project to come , just to get bots working for HL2 as 'we' want it.

I got an answer from Alfred:

Quote:

Okay, I have found the bug in HL2MP that causes fakeclients to crash. The next HL2MP release should contain a fix (I don't have an ETA, sometime in January).

We are still working on the document describing how to make bots work (it will answer your runcommand question).

- Alfred


i sincerely hope that the document he is talking about, is sufficient for us.

cannonfodder 30-12-2004 17:30

Re: I don't like this!
 
I have been looking at the same sort of issue for other reasons and I'm not sure why you would need to hook the game DLL.

There must be something obvious I'm missing but when you call createfakeclient it gives you an edict and through that edict I would think you can access the csdkplayer info.

The problem I see is that to access it you need to understand the csdkplayer class which means you need the class definition for this which pretty much then requires the entire game.dll to be compiled into your server plugin. And even this isn't enough since you now need to go through the the game.dll code you added and make sure any local calls to interface functions in this code use the real interface functions into the real game.dll (since the engine won't call yours).

So am I totally off base here ?? I can't believe Valve would make it this hard, but I can't see how you can do anything without full access to the csdkplayer class.

stefanhendriks 30-12-2004 18:24

Re: I don't like this!
 
the problem also is, to run the command to make players move, which are game dll specific. So even if you could gain acces, you should somehow find a way to run this function.

I saw a 'hack' about this, so you can acces cBaseEntity or something, but its ugly as hell.

stefanhendriks 30-12-2004 18:27

Re: I don't like this!
 
ah, in the VERC thread , where i posted about the bot document. Someone actually confirmed he got bots working (AND WALKING!) .. in his mod. So thats including mod source, but always nice to hear someone got it to work.

http://www.chatbear.com/board.plm?a=...4991&v=flatold

cannonfodder 30-12-2004 19:40

Re: I don't like this!
 
That's one of the things I guess I don't understand. Assuming you somehow have access to the basentity (and EVERYTHING that goes with it), why can't you include your own code for the runcommand ?

On the other hand, can't you create usercmds's and call into the servers processusercmds (which appears to be what a normal client does).

BTW, I think in that thread he did it the same way botman did, by including code in the server.dll.

BTW2, botman mentioned that you can't get angles, but I'm not sure what he ment there. The client gets the angles through the engine->GetViewAngles. This should also be available to a fakeclient.

stefanhendriks 30-12-2004 20:00

Re: I don't like this!
 
lemme search that link:
http://www.hl2coding.com/forums/viewtopic.php?t=74

its for server plugins...

i tried the processusercmds thingy before, but i ended up in some trouble. I thought the function itself also needed a cBasePlayer? Dunno what it was exactly.

cannonfodder 30-12-2004 20:33

Re: I don't like this!
 
Sorry, I meant theones posting on verc about getting bots working. I think he
is doing it in the server.dll.

processusercmds needs the edict which you got from createfakeclient and a buffer of commands. It then gets the cbaseentity from cbaseentity::instance(edict). The serverplugin can also do this by calling server->EdictToBasEntity, assuming it understands cbaseentity.

stefanhendriks 30-12-2004 20:58

Re: I don't like this!
 
i tried some more, and for a moment i thought i could get it working (compiling). But nope, it does not want to work:

Code:

          CUserCmd cmd; // create command
          bf_read *buf = NULL;        // the buffer
          bf_write *write_buf = NULL; // write buf?
          cmd.Reset();
          // Write it into buf
          WriteUsercmd( write_buf, &cmd, &cmd ); //
         
          // put cmd into buf somehow
         
          gameclients->ProcessUsercmds(clients[iClients].pEdict, buf, 1, 1, -1, false, false);

the WriteUserCmd cannot be compiled with the server plugin. So, in other words, i cannot seem to fill the buffer; unless i write some own magical function to compress it so HL2 understands it. This seems to be a tough one though.

botman 31-12-2004 00:36

Re: I don't like this!
 
WriteUsercmd is used on the client to send user key presses to the server so the server can process them.

Since bots don't have a network connection, they can't send packets to the server. :(

botman

cannonfodder 31-12-2004 00:39

Re: I don't like this!
 
What does a network connection have to do with it ? The plugin code can call processusercmds directly through the interface. Isn't it just a matter of formatting it correctly ?

botman 31-12-2004 00:48

Re: I don't like this!
 
The only place I see WriteUsercmd being used anywhere in the SDK source code is in...

cl_dll\in_main.cpp

All the 'cl_dll' code is stuff that runs on the client.

EDIT: Doooh! I didn't see that you were talking about ProcessUsercmds. Yes, that does seem to be available in the IServerGameClients interface and IServerGameClients is available to plugins. Hmmmmmm....

botman

cannonfodder 31-12-2004 01:02

Re: I don't like this!
 
I tooks botmans code and I was able to compile it into a plugin (by defining GAME_DLL). First I thought I need to use serverents->EdictToBaseEntity to get at the baseentity, but when I try to open an interface to serverents it won't let me.

So I tried cbaseentity::instance which does return an entity, but eveything is 0's. So I'm assuming that what it returned is not the real baseentity, but only what my code thinks is the real base entity (Since my code thinks it's the server.dll).

When I run it, it does create a bot, but I don't have the think code working yet so it doesn't move.

So.. Anyone have an idea how to get at the baseentity for the bot edict ????

botman 31-12-2004 01:07

Re: I don't like this!
 
That's the problem. You CAN'T access CBaseEntity or CBasePlayer from a plugin.

botman

botman 31-12-2004 02:50

Re: I don't like this!
 
No worries mate...

http://forums.bots-united.com/showthread.php?t=3301

botman

Pierre-Marie Baty 02-01-2005 16:46

Re: I don't like this!
 
*screams* look at that, I go for 1 week holiday, and all the fun happens while I'm away!! meh :'( that's unfair :(

I got your CDs Stefan :) I'm putting together HL2 right now, then Steam will maybe FINALLY allow me to download that SDK :) cantwaitcantwaitcantwait

@$3.1415rin 03-01-2005 12:05

Re: I don't like this!
 
Quote:

Originally Posted by Pierre-Marie Baty
*screams* look at that, I go for 1 week holiday, and all the fun happens while I'm away!! meh :'( that's unfair :(

lol, same here. well i'm online, but I'm sitting in front of a computer with a little screen, a celeron466 and a geforce2mx AND a 56k connection ... anyway, you might have seen I fixed something with my aiming algorithm :P

getting back home to a p4 3Ghz, 1gig ram, TFT, DSL, next week :)

stefanhendriks 03-01-2005 14:31

Re: I don't like this!
 
rofl, well progress goes with some leaps it seems. Something works, and then its silent... then something works and it silent again.

I bet the next time botman comes here with a new 'revolution' thread, he will present us a fully working template... :)


All times are GMT +2. The time now is 06:17.

Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.