Author Topic: Question About Spawning a Bot in Quake 2  (Read 8564 times)

Offline Greenwood

  • Newbie
  • *
  • Posts: 30
    • View Profile
  • Rated:
Question About Spawning a Bot in Quake 2
« on: August 06, 2009, 10:56:59 AM »
Hi,

I've been experimenting with getting a bot to work in Quake 2, based on these tutorials:

http://www.quake2.com/dll/tutorials/bot/oak1.html
http://www.telefragged.com/thefatal/old/tut.htm

I've managed to get a bot to appear when I type in a command, but there are a few problems. When it spawns it, it doesn't appear on the scoreboard. To solve this, I tried messing around with the addbot function in the code I based on those tutorials. So instead of creating a bot by doing something like:

newOak = G_Spawn();
newOak->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME);

I tried this commenting out the first of those lines, and adding this:

for (i=0 ; i < maxclients->value ; i++) {
    cl_ent = g_edicts + 1 + i;
    if (!cl_ent->inuse) {
        G_InitEdict (cl_ent);
        newOak = cl_ent;
        break;
    }
}

I figured that would get the bot's score to display on the scoreboard, because the board only displays scores up to maxclients->value. To my surprise, it worked, and the bot's score displayed on there.

But as I said, there are problems. When the bot starts the game, it just kind of hovers in mid-air, as if it's stuck in the middle of a jumping frame. When I kill it and it respawns, it just keeps cycling through all it's animation frames endlessly- unlike before, when the bot would run over to you and start saluting. I altered the respawn function to include pain and die stuff, so I can kill it again, and it does pain appropriately, but that's all.

Anyway if anyone knows what the problem's likely to be here I'd appreciate any help you can give. I'm pretty new to this stuff, but I really enjoy it. Thanks guys.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline QwazyWabbit

  • Carpal Tunnel Member
  • ******
  • Posts: 1366
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #1 on: August 06, 2009, 04:50:28 PM »
Bots are not clients. Their client index is NULL. What you should probably do, if clients can spawn bots, is to add a pointer to the bot in the client's structure and a pointer to the owner client in the bot's structure. Then you can index to the bots from the client when enumating the scores. A pointer might be required for each bot so you'd have to have several pointers and hard limit the number of bots each owner can have. I did something similar to this in the LOX code for the decoys. The decoys don't have scores but they have mutual pointers for the owners.

If bots are spawned and have no owners then your scoreboard code would have to have a different method for identifying the bot entities. You could index thru the entities and use a structure member to ID whether they are bots and if so, add them to the scoreboard.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline Greenwood

  • Newbie
  • *
  • Posts: 30
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #2 on: August 07, 2009, 02:45:50 AM »
Thanks. I'm pretty new to this stuff though, so I have a couple of questions.

When you say "client index" do you mean "newOak->client" as in the following?

newOak->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME);

So from what you're saying that should be set to NULL? The above is from the original bot so I thought it would be the right way to do things.

Or alternately are you saying that using a for loop like this:

for (i=0 ; i < maxclients->value ; i++)

will make the bot seem like a client to the game, by affecting it's client index? If so is it ok to leave the previous line as it is?

I was thinking I could just alter the scoreboard code so that it reads from edict_t entities other than ones that are < maxclients->value. In other words, it looks for any bots with higher values. With that said I'll try what you said, because it sounds like I could learn something in the process. I'm just curious to understand how these things work.

Thanks.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline QwazyWabbit

  • Carpal Tunnel Member
  • ******
  • Posts: 1366
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #3 on: August 07, 2009, 08:23:42 AM »
This is a very rough outline of what I think you need to do based on my very rough understanding of what I think you are trying to do.

I downloaded the sources to be sure I was not making a mistake here by assuming bots were not spawned as clients in the tutorial.

I cannot find
newOak->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME);
anywhere in the linked original sources you showed in your first post.
It is an error to do this anyway.

Bots are monsters. Monsters and bots are of type edict_t (entities) NOT gclient_t (clients). A client can own an entity (their avatars for instance) but an entity is not a client, only clients (players) normally have scores and entities are mostly owned by world and have their own think functions (there are some exceptions). The server executes ClientThink on clients and it executes the think function pointed to by ent->think in the world think cycle. These world and client think cycles are separate. This is why your SP_Oak function has:

   newOak->think = oak_stand;
   newOak->nextthink = level.time + 0.1;

The oak_stand function is the initial thinking that the server will do for your bot. Trying to make the bot a client negates this, or at least makes it very messed up in the server and is the reason your bot is spazzing out.

What I would do is something like this. Add an array of pointers to edict_t to the client structure depending on how many bots you want to allow for each player. I'd start with 1 to keep it simple. Add a bot_score member for each bot (or you can add it to the edict_s structure) I am not sure at this point which would be more advantageous. This will be the bot's score, separate from the client score. Keep the bot code unmodified or more or less intact since it looks like normal monster AI and it's proven. In the SP_Oak function you have to add an owner or at least make sure the owning client has a pointer to the bot entity for the scoreboard to find it. The current code doesn't know who spawned the bot, this would have to be fixed. If adding bot_score to the edict_s, you would have to initialize it to 0 in the SP_Oak function. If adding it to the owner's client structure you would initialize the bot_score to 0 when putting the client into the server on connect.

Then you need to modify the scoreboard code to search for the bots in the edicts or better yet, to use the owner client to access the bot_score and post it as a sub score for the client when you print his score. (Just a suggestion.) You can also fill an array of bot scores and print them separately but access them through their owner's client structures.

As regards your confusion about clients and bots, I don't know how much OO coding you have done but think of the structures as objects or classes and think of the spawn functions as constructors. You have to fill in the objects and do the housekeeping yourself in the spawn functions and you must make sure you keep the classes separate in your mind. A client class is distinct from a monster class and they inherit from the entity class.

I would add the bots to my code, making sure they work and don't have side effects with respect to weapons and other features of your mod. Then I would add scores to the necessary structures and debug it again to make sure the scores were properly tracked (by breakpoints, or printf's into the console or DebugPrints into the debugger console when the bot scores a hit). Then I would modify the DMCreateScoreboard function to account for and print the bot scores by whatever method looks nice in the scoreboard.

I hope this helps.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline Greenwood

  • Newbie
  • *
  • Posts: 30
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #4 on: August 07, 2009, 10:52:38 AM »
Awesome, thanks for the detailed reply. I'll analyse that in detail as soon as I get a chance.

Actually the line:

Code: [Select]
newOak->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME);
is based on the old famke bot tutorial here:

http://www.telefragged.com/thefatal/old/tut.htm

Except in that code, it's

Code: [Select]
bot->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME); //sets bot client value so it can be used
I can't remember why I included it- I think it made it work when it otherwise wouldn't have, at some point. Anyway thanks again for your advice mate.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline quadz

  • Loquaciously Multiloquent Member
  • ****
  • Posts: 5352
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #5 on: August 07, 2009, 11:44:16 AM »
I cannot find
newOak->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME);
anywhere in the linked original sources you showed in your first post.
It is an error to do this anyway.

Interesting.  This is just an aside, as I've never written a Q2 bot.  But if I wanted a bot that 'pretended' to be a real client (like the Q3 arena bots do, for example), my first instinct would have been to make it a real client, so it would show up on the scoreboard, participate in death obituary messages, etc.  (Then I imagined adding some flag, similar to the existing 'spectator' value, which would indicate this is really a bot client, so that certain logic that truly only applies to real clients could be conditionally avoided.)

The hope would have been that making it a real client would require fewer special cases in the logic, than making it a monster.  (But maybe that turns out not to be the case?)

Anyway just rambling....


:dohdohdoh:
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus
"He knew all the tricks, dramatic irony, metaphor, bathos, puns, parody, litotes and... satire. He was vicious."

Offline peewee_RotA

  • Brobdingnagian Member
  • ***
  • Posts: 4152
  • Hi, I'm from the gov'ment and I'm here to help you
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #6 on: August 07, 2009, 11:57:31 AM »
I cannot find
newOak->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME);
anywhere in the linked original sources you showed in your first post.
It is an error to do this anyway.

Interesting.  This is just an aside, as I've never written a Q2 bot.  But if I wanted a bot that 'pretended' to be a real client (like the Q3 arena bots do, for example), my first instinct would have been to make it a real client, so it would show up on the scoreboard, participate in death obituary messages, etc.  (Then I imagined adding some flag, similar to the existing 'spectator' value, which would indicate this is really a bot client, so that certain logic that truly only applies to real clients could be conditionally avoided.)

The hope would have been that making it a real client would require fewer special cases in the logic, than making it a monster.  (But maybe that turns out not to be the case?)

Anyway just rambling....


:dohdohdoh:


Wasn't this the tutorial from Ninja of Comp? If I remember correctly that was based off of another tutorial which was for some kind of helper AI, possibly the faithful doggy tut from Maj. Bitch.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus
GOTO ROTAMODS (rocketgib)
GOTO ROTAMAPS (fireworks)
HappyFriar- q2server.fuzzylogicinc.com
 Tune in to the Tastycast!!!!  http://dna.zeliepa.net

Offline QwazyWabbit

  • Carpal Tunnel Member
  • ******
  • Posts: 1366
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #7 on: August 07, 2009, 08:59:53 PM »
I cannot find
newOak->client = gi.TagMalloc(sizeof(gclient_t), TAG_GAME);
anywhere in the linked original sources you showed in your first post.
It is an error to do this anyway.

Interesting.  This is just an aside, as I've never written a Q2 bot.  But if I wanted a bot that 'pretended' to be a real client (like the Q3 arena bots do, for example), my first instinct would have been to make it a real client, so it would show up on the scoreboard, participate in death obituary messages, etc.  (Then I imagined adding some flag, similar to the existing 'spectator' value, which would indicate this is really a bot client, so that certain logic that truly only applies to real clients could be conditionally avoided.)

The hope would have been that making it a real client would require fewer special cases in the logic, than making it a monster.  (But maybe that turns out not to be the case?)

Anyway just rambling....


:dohdohdoh:


You don't have to make it a monster but the original code does it that way. If you make it a client you would have to make sure you had some mechanism for handling ClientThink. In the tutorial it's coded like a monster or any other entity with an entity think. It would be much more elaborate to make it a client, but not impossible. Anyway, just got home after a long flight and a 5am wakeup so it's time for bed.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline Greenwood

  • Newbie
  • *
  • Posts: 30
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #8 on: August 08, 2009, 11:09:34 AM »
Alright!!! I just got it to display the bot's score on the scoreboard! I did it the way you suggested, QwazyWabbit- adding a pointer to the bot's entity in gclient_s. Thanks for the advice! I've been reading tutorials on C and Quake 2 for hours and hours the last couple of days and it's finally paid off.

Now I just need to figure out how to display it's name on there. I'm guessing that when the scoreboard comes up, "client" gets replaced by the bot's name in the following line. Is that right?

Com_sprintf (entry, sizeof(entry), "client %i %i %i %i %i %i ",
    x, y, sorted, cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe)/600);

Also another quick question. To get the address of the player's entity in the addbot function, I used the following. Is this the right way to do it, or is the player's entity ever at a point other than 0 in game.clients?

    gclient_t   *player;
    player = &game.clients[0];

Thanks again for the help. I can't believe I'm getting this stuff to work- it's like 10 years since I first wanted to be doing this kind of thing.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline QwazyWabbit

  • Carpal Tunnel Member
  • ******
  • Posts: 1366
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #9 on: August 08, 2009, 12:20:40 PM »
Alright!!! I just got it to display the bot's score on the scoreboard! I did it the way you suggested, QwazyWabbit- adding a pointer to the bot's entity in gclient_s. Thanks for the advice! I've been reading tutorials on C and Quake 2 for hours and hours the last couple of days and it's finally paid off.

Now I just need to figure out how to display it's name on there. I'm guessing that when the scoreboard comes up, "client" gets replaced by the bot's name in the following line. Is that right?

Com_sprintf (entry, sizeof(entry), "client %i %i %i %i %i %i ",
    x, y, sorted, cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe)/600);

Not quite. It's not automatic. You have to add the bot name string pointer to the edict_s and you have to initialize it in the spawn function. Then you can access it by adding the proper references in the Com_sprintf function that will list the bot scores by name. In other words, just as the client structure is used to access client name and score, you will use the pointer to the bot structure to access his name and score. (netname is only 16 characters long so only 15 can be printable due to the terminating 0 byte so you will have to do something to the bot name to keep it short.)

The initialization line in the spawn function will be just like the bot classname initialization, but you will probably want to make it unique for each bot by doing some string manipulation to make it read something like "Playername's bot". The code you need to write will be string concatination so you will have to add some string variables to the spawn function to access the player's name via his client structure and append the bot text into the space you allowed for the bot name. Remember to properly size your string space and prevent overflows.

Something to get you started:

newOak->classname = "bot";
newOak->botname = "Oakbot";  // every bot has the same name


There is actually an error in the Oakbot tutorial. He defines void SP_Oak(void) but in the "oak" command he calls it with SP_Oak(ent); calling the spawn function that expects no arguments with an edict_t argument. This is actually to your benefit because you need to pass the owner's entity to the spawn function anyway, see below.

Quote
Also another quick question. To get the address of the player's entity in the addbot function, I used the following. Is this the right way to do it, or is the player's entity ever at a point other than 0 in game.clients?

    gclient_t   *player;
    player = &game.clients[0];

Thanks again for the help. I can't believe I'm getting this stuff to work- it's like 10 years since I first wanted to be doing this kind of thing.

Using the above code will make every bot a child of the first player to connect, (game.client[0]) and when he disconnects many things can happen depending on how well you did your housekeeping. Either all the bots will de-rez when he quits or else the server will crash, spectacularly. (e.g., Remember to test ent->inuse before dereferencing a pointer member.)

If your intent is to allow players to spawn their own bots you need to redefine the spawn function to accept the entity of the player who is spawning the bot:

void SP_Oak(void);
becomes
void SP_Oak(edict_t *owner);

Now you can access the player's information thru the owner pointer, including his client data:

owner->client->pers.netname

Remember, you are dealing with all these structures and they interlock in strange ways. This is the hardest thing to keep straight, at least for me, when you are dealing with edict_s and client_s. Especially when clients can possess edicts and you are drilling down into the client structure to get at an edict member. :)

This is part of the mess that is structured programming vs object oriented programming and how they each handle inheritance.
« Last Edit: August 08, 2009, 12:34:43 PM by QwazyWabbit »
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline Greenwood

  • Newbie
  • *
  • Posts: 30
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #10 on: August 08, 2009, 03:16:58 PM »
Actually, when I said the following in the previous post, I meant to say that "client" gets replaced by the player's name, not the bot's name. Oops.

Com_sprintf (entry, sizeof(entry), "client %i %i %i %i %i %i ",
    x, y, sorted, cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe)/600);

I thought about that after I wrote it and realised that I wouldn't be outputting it in the same way as a client's name anyway. With that said, do you know what "client" in that line does exactly? I just tried taking it out of the line displaying the bot's score, and the picture disappeared on the scoreboard. Does this mean it's showing the picture for the current client entity? If so might the bots end up all having their parent player's picture next to their scores? Is there a way around this?

Maybe, when you're outputting each player's details on the scoreboard, you temporarily change the client's name/ picture to the one for the bot? And then just change it back straight after you've outputted each score?

Quote
There is actually an error in the Oakbot tutorial. He defines void SP_Oak(void) but in the "oak" command he calls it with SP_Oak(ent); calling the spawn function that expects no arguments with an edict_t argument.

Interesting. Yeah to get it to work I think I mixed up stuff from that and the famke bot tutorial here:

http://www.telefragged.com/thefatal/old/tut.htm

Anyway thanks for your help.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline QwazyWabbit

  • Carpal Tunnel Member
  • ******
  • Posts: 1366
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #11 on: August 08, 2009, 07:30:34 PM »
My turn to say oops. I got so wrapped up explaining the theory of objects in Q2 that I didn't recognize the Com_sprintf call for what it was. That line of code is forming a network message to the client to get it to display the scoreboard item for each player in the game. The "client %i %i %i %i %i %i " item is actually a string being passed to the Com_sprintf function that it uses to format the network message. The sorted argument is the index of the server client being displayed (his client number: 0 to game.max_clients, in sorted order, highest to lowest after the mod has decided the order of the player scores.

The server is going to transmit a message string containing a string something like "xv 0 yv 32 picn tag1 client 0 32 0 0 48 0" where the numbers indicate the position of the scoreboard item in x y, the token to identify what dogtag to use, the dogtag name, the word "client", his client number, the max number of server clients, his score, his ping, and his time in game. IIRC, the "client X" string is used by the game client code to find that client number and use its knowledge of the userinfo strings to display his name. This allows Q2 to send a scoreboard message in a very compact form. The problem with that scoreboard is that it is limited to the 12 highest scoring players, all others never get listed. This also why non-clients don't have names in your scoreboard.

If you want to send something other than Q2's default scoreboard you have to format and send it yourself using Q2's "string" net message. You have to fill in the message yourself using sprintf. The format of the string message is something like this:
            sprintf(string + strlen(string),
               "xv 0 yv %d string \"%5d %-15s %4d %4d\" ",
               48 + i * 8,
               sortedscores,
               game.clients[sorted].pers.netname,
               (level.framenum - game.clients[sorted].resp.enterframe)/600,
               ping);                 

In this case you are filling the buffer named "string" with the direct strings you need. For example, in LOX we have a scoreboard that doesn't use dogtags. The server admin is free to use the 12 player scoreboard or the tagless scoreboard for more players. The scoreboard message looks something like this:
xv 0 yv 32 string2 "Frags Player          Time Ping" xv 0 yv 40 string2 "----- --------------- ---- ----" xv 0 yv 48 string "    0 QwazyWabbitWOS     0    7"

Beware: you are limited to <1400 bytes in a netmessage block when using Q2's protocol 34 so you need to watch your byte count when forming that message block and prevent it from exceeding the limit. This is a network frame limitation in Q2's protocol due to the size of a UDP frame. (all Q2's messages must each fit inside one UDP frame)

Use the OutputDebugString() function in Microsoft's IDE to see the strings printed in the debugger console so you can see the message formed without stopping the server. You could also use dprintf() to print them in the server console or log file and I have used them both, depending on circumstances. The nice part of OutputDebugString is you don't have to comment it out when switching from debug to release mode and you can use #defines in the source modules to enable/disable them when you are done debugging that module so you don't clutter the debug console with messages you don't need.



As for the error in the Oakbot tut, yes, it's there in the web page but not in the source file archive. In the actual Oakbot project he calls OAK_Check_SP with the ent argument and he calls it from the user command parser:
...
   else if (Q_stricmp (cmd, "oak") == 0)
      OAK_Check_SP(ent);
...

I have not looked closely at the other tutorial.
« Last Edit: August 09, 2009, 12:23:43 PM by QwazyWabbit »
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline Greenwood

  • Newbie
  • *
  • Posts: 30
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #12 on: August 11, 2009, 02:41:27 AM »
Thanks.

There's something about the following I don't understand though.

sprintf(string + strlen(string),
               "xv 0 yv %d string \"%5d %-15s %4d %4d\" ",
               48 + i * 8,
               sortedscores,
               game.clients[sorted].pers.netname,
               (level.framenum - game.clients[sorted].resp.enterframe)/600,
               ping);

What's going on with the following part? "xv 0 yv %d string \"%5d %-15s %4d %4d\" ". It's almost like you've got three separate parameters- "xv 0 yv %d string \", then: %5d %-15s %4d %4d\, then: " ". Except there's no comma so it must only be one. Also I don't understand stuff like %5d. I understand that you use %d to output an int and %s to output a string but what do %5d or %-15s mean? Also what's the \ at the end for?

Thanks.
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline QwazyWabbit

  • Carpal Tunnel Member
  • ******
  • Posts: 1366
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #13 on: August 11, 2009, 03:46:11 AM »
The \ is the escape character in C. The same as in Perl or Ruby or half a dozen other languages (which are written in or owe their origins and practices to C). It means 'take the following character literally and insert it'. This is how you insert characters into a string when they would otherwise be interpreted as special tokens. We are using sprintf to format a string into a buffer that will be passed to the functions that transmit the contents of the string buffer to the client or will be used by the client as in string "...". This is actually the code that inserts:
string "    0 QwazyWabbitWOS     0    7"
into the buffer, putting spaces where there are no actual characters or digits to left or right justify the text as in my example above.

One thing I didn't show as part of the example of filling the string buffer for a custom scoreboard was the code to make it print a column header:

         strcpy(string,  "xv 0 yv 32 string2 \"Frags Player          Time Ping\" "
            "xv 0 yv 40 string2 \"----- --------------- ---- ----\" ");


We are formatting a string into a string argument for the sprintf function therefore if we want it to contain quotes we have to escape them so the C parser won't think the quoted text is ending. In C, if you want to print a quote character you have to do this:

printf("\"");

or for a double blackslash:

printf("\\\\");

The numbers are field widths. http://msdn.microsoft.com/en-us/library/56e442dc.aspx

The %-15s means it is left-aligned, 15 characters wide. This is the space occupied by the player name.

This is just an example of some of the fussing you have to do to get a C compiler to print a string in a particular way. They can't all be as easy as printf("Hello world!");

:)

« Last Edit: August 11, 2009, 07:33:17 AM by QwazyWabbit »
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus

Offline ReCycled

  • Carpal Tunnel Member
  • ******
  • Posts: 1690
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #14 on: August 11, 2009, 09:08:18 AM »
I've used an old bot program called EraserBot and it works fine. Displays all scores. you can choose the number of participants, adjust their skill (accuracy) and even "train" them on proper routes within the map. It's kind of funny to come across some orphan bot on the other side of the map, running in a corner. Bang! You're gone...
 :bigshades:
  • Insightful
    Informative
    Funny
    Nice Job / Good Work
    Rock On
    Flawless Logic
    Well-Reasoned Argument and/or Conclusion
    Demonstrates Exceptional Knowlege of the Game
    Appears Not to Comprehend Game Fundamentals
    Frag of the Week
    Frag Hall of Fame
    Jump of the Week
    Jump Hall of Fame
    Best Solution
    Wins The Internet
    Whoosh! You done missed the joke thar Cletus!
    Obvious Troll Is Obvious
    DO YOU EVEN LIFT?
    DEMO OR STFU
    Offtopic
    Flamebait
    Redundant
    Factually Challenged
    Preposterously Irrational Arguments
    Blindingly Obvious Logical Fallacies
    Absurd Misconstrual of Scientific Principles or Evidence
    Amazing Conspiracy Theory Bro
    Racist Ignoramus
“It is hard to make predictions, especially about the future.” – Yogi Berra

 

El Box de Shoutamente

Last 10 Shouts:

 

RyU

September 03, 2024, 05:15:49 PM
And wow Derrick is still playing lol
 

RyU

September 03, 2024, 05:15:15 PM
Just know yesterday is gone and soon tomorrow will be gone too  :)
 

Lejionator

August 08, 2024, 07:28:01 PM
It's tiem to QuakeCon!!!  ;)

https://www.youtube.com/watch?v=ThQd_UJaTys
 

ImperiusDamian

July 26, 2024, 09:34:53 PM
In nomine Quake II et Id Software et Spiritus John Carmack, Amen.
 

QuakeDuke

July 26, 2024, 05:10:30 PM
Hey, shout, summertime blues
Jump up and down in you blue suede shoes
Hey, did you rock and roll? Rock on!!  ...QD
 

Yotematoi

July 24, 2024, 01:31:20 PM
Ayer me mato 5 veces para robarme en la vida real hará lo mismo? [img]<iframe src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fzoloyoze.torito%2Fposts%2Fpfbid0wXU2VgS7atesBcSoMz5BWMJCJajeZFVT6GzSU6TtpJGddN9kLTvWNgcZaskkbKFQl&amp;show_text=true&amp;width=500
https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fzoloyoze.torito%2Fposts%2Fpfbid0wXU2VgS7atesBcSoMz5BWMJCJajeZFVT6GzSU6TtpJGddN9kLTvWNgcZaskkbKFQl&show_text=true&width=500" width="500"
 

Yotematoi

July 24, 2024, 01:25:59 PM
hi ya está la basura de Martin, se cambió el nombre es un ladron estupido, asi llegó a 10000[img]<iframe src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fzoloyoze.torito%2Fposts%2Fpfbid03hZrkDUBJPZKCuFgy5hRUy831ekKJYVRzC7ajXaKQbJ6xcPgKftLukUDfovFyEq3l&amp;show_text
https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fzoloyoze.torito%2Fposts%2Fpfbid03hZrkDUBJPZKCuFgy5hRUy831ekKJYVRzC7ajXaKQbJ6xcPgKftLukUDfovFyEq3l&show_text
 

Yotematoi

July 24, 2024, 01:25:59 PM
hi ya está la basura de Martin, se cambió el nombre es un ladron estupido, asi llegó a 10000[img]<iframe src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fzoloyoze.torito%2Fposts%2Fpfbid03hZrkDUBJPZKCuFgy5hRUy831ekKJYVRzC7ajXaKQbJ6xcPgKftLukUDfovFyEq3l&amp;show_text
https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fzoloyoze.torito%2Fposts%2Fpfbid03hZrkDUBJPZKCuFgy5hRUy831ekKJYVRzC7ajXaKQbJ6xcPgKftLukUDfovFyEq3l&show_text
 

-Unh0ly-

July 05, 2024, 05:20:36 AM

Show 50 latest
Welcome, Guest. Please login or register.
September 20, 2024, 02:38:41 PM

Login with username, password and session length