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

Offline Greenwood

  • Newbie
  • *
  • Posts: 30
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #15 on: August 11, 2009, 03:04:07 PM »
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!");

:)



Right. I didn't realise this was stuff that was used by C in general, or I would have looked it up.

I've been messing around a bit more with this, and have got it to display the bot's name, score, ping and time. Well, at least I know how to get it to display the bot's ping and time- right now I'm just displaying the player's as a temporary substitute. I'm doing the formatting in the standard Quake 2 way, to see if I can do that first. Obviously I would replace 32/ 64/ 72 etc. with %i and some variables, and then get it to calculate the positions for multiple scores.

sprintf (string + strlen(string),
            "xv 32 yv 64 string %s yv 72 string \"%-6s %i\" yv 80 string \"%-6s %i\" yv 88 string \"%-6s %i\" ",
            temp_bot_ent->bot_name, "Score:", temp_bot_ent->bot_score,
            "Ping:", cl->ping, "Time:", (level.framenum - cl->resp.enterframe)/600);

So yeah, thanks for your help with this, I seem to be making some progress. I'm wondering about the pictures though. Is there any way to get it to display your character's portrait on the scoreboard using sprintf? I noticed they do this to display the tag in the background, with tag just being set to "tag1" or "tag2":

Com_sprintf (entry, sizeof(entry),  "xv %i yv %i picn %s ",x+32, y, tag);

You may know this already but they're in the pics directory in pak0.pak- I know because I looked in there with QuArK. I can get Quake2 to display any of the other pictures in there in the game, just by replacing tag with whatever their name is. But is there any way to get it to display pictures or textures that aren't in that directory?

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 Paril

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
  • Rated:
Re: Question About Spawning a Bot in Quake 2
« Reply #16 on: August 11, 2009, 03:11:54 PM »
It is somewhat hard to do that because it would be dependant on the servers' files. You'd have to find his skin and model, and insert an _i in there.
Not sure though, because this might index the model, and you'd overflow pretty quickly if everyone had a different model.

-P
  • 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 #17 on: August 11, 2009, 05:57:39 PM »
Tag1 and tag2 are the dogtag images, I think one is the normal dogtag and the other is the killed/killer tag you get in the scoreboard when you get fragged.

As far as the portrait is concerned I believe it's based on the client's knowledge of the client index for each player in the scoreboard. From the client index, it looks up the portrait it has on file for that player's model and displays it from there. As Paril correctly stated, it comes from the model and the portrait is actually the *_i.pcx file for that model. If the client doesn't have the skin it uses the male/female grunt portraits based on the sex on the clientinfo each client has for every player. The server is not involved in that process except that it communicates the client numbers. You will have to look at the client code (like r1ch's version) to see how it does it. When a player joins a server everyone receives a client information frame from the server that informs them of that client model, name, sex, score and other info and that is what the clients use in the scoreboard displays.
« Last Edit: August 11, 2009, 06:00:51 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 #18 on: August 12, 2009, 01:19:33 PM »
It is somewhat hard to do that because it would be dependant on the servers' files. You'd have to find his skin and model, and insert an _i in there.
Not sure though, because this might index the model, and you'd overflow pretty quickly if everyone had a different model.

-P

Thanks for the reply, but I'm not sure if I follow you here. I mean, say you wanted to output a particular portrait using sprintf, and it was one of the default male or female player skins. How would you go about finding the skin and model, and then outputting it?

As far as the portrait is concerned I believe it's based on the client's knowledge of the client index for each player in the scoreboard. From the client index, it looks up the portrait it has on file for that player's model and displays it from there.

I just want to get some fundamental things clarified in my mind here.

First, this might sound like a stupid question, but when you say "the client's knowledge of the client index for each player", do you mean that the client index is the appropriate element of game.clients for the required player? And then the knowledge is contained within that gclient_t entity?

Also, in the code, I've noticed that sometimes, the player will be referred to as an edict_t, and at other times, as a gclient_t. My understanding of this is that each player in the game has information about them contained in both an edict_t entity, and a gclient_t entity. Is this right? Again this might sound like a stupid question but I figured it would be worth getting this kind of thing understood properly.

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 #19 on: August 12, 2009, 11:38:51 PM »
I just want to get some fundamental things clarified in my mind here.

First, this might sound like a stupid question, but when you say "the client's knowledge of the client index for each player", do you mean that the client index is the appropriate element of game.clients for the required player? And then the knowledge is contained within that gclient_t entity?

By client index, I mean the client number, the "i' in game.clients.

Quote
Also, in the code, I've noticed that sometimes, the player will be referred to as an edict_t, and at other times, as a gclient_t. My understanding of this is that each player in the game has information about them contained in both an edict_t entity, and a gclient_t entity. Is this right? Again this might sound like a stupid question but I figured it would be worth getting this kind of thing understood properly.

This is the confusion I talked about. Everything that exists in the game is an entity. The edict_s is the server side structure that contains everything the server knows about an entity. If the entity is a player (aka, client) the ent->client pointer is not null and points to the client_s belonging to that entity. This is why a player entity will be typed as edict_t *ent and you will access his client structure members as ent->client->member. If you see a pointer to gclient_t it would be used mostly (I think) to shorten up the references and access the client structure directly, rather than through it's entity, in all cases you will probably see it used like this:

...
edict_t *ent;   // pointer to some entity owning a client (usually passed as argument to a function)
...
gclient_t   *client; // a pointer to a client struct
...
   client = ent->client; // set the client pointer so we don't have to type ent->client->stuff all day
...
    client->member = ...

The usage above is somewhat idomatic IMO, depending on who coded it I suppose, since for all the time it takes to copy the pointer in the game when it's running you may as well have typed it out. The only time where I have seen it pay off for the programmer is in functions like InitClientPersistant where you are dealing with the client "constructor" and writing ent->client->member would be just tedious.

It is VERY important that you make sure that you properly initialize your client pointers or your server will crash when you try to dereference them. To see if an entity owns a client you can test ent->client != NULL since the client pointer is supposed to be NULL for non-player entities.

The client_s contains pointers to that client's player_state_t, client_persistant_t, client_respawn_t structures. The very first members of the client_persistant_t structure are the stuff the server needs to communicate to the clients whenever a new player connects, some of these are the userinfo array, netname string, health and other stuff that persists across levels as long as the player remains connected.

The userinfo strings are what the clients know about each other. This contains the gender, fov, skin name, netname, handedness of the players. The client software needs to know these things in order to select the correct avatar to display in the graphic view. The data doesn't change very often so the server sends it only when a client first connects or when a client changes it, like a skin change. Once the essential data is communicated to the client, the server only needs to refer to the player by client number when informing a client about the state of another player. This saves bandwidth and processing time and allows the client to handle all the graphics on it's own without having to wait for updates from the server. Once the data exist the server says "client 12 did something" and the clients access the userinfo for client 12 and make the avatar do something. The client's client_t and the server's client_t are very different.

The client side doesn't need all the other entity information and this is what allows the game to be a server-side mod and allows clients to connect and use the game without installing special mod code.

I hope this clarifies it somewhat from my own limited understanding of the original design.

"If you think you understand a subject, try to teach it. It will teach you how little you really know."
« Last Edit: August 12, 2009, 11:48:13 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 #20 on: August 20, 2009, 06:37:53 AM »
So if you have your bots as edict_t entities, rather than gclient_t entities, how do you go about changing their skins? Are you stuck with the default ones? I noticed that if you used something like this, you will get the male model and it's default skin.

Code: [Select]
newOak->model = "players/male/tris.md2";
newOak->s.modelindex = 255;
newOak->s.modelindex2 = 255;

But if changing skins is normally done via userinfo strings, how could you change the skin for a player model that's not a client?

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 #21 on: August 20, 2009, 07:31:11 PM »
The 255 model index is OK for a hack but that won't work in a real mod. It will eventually crash. You MUST use the gi.modelindex import function to properly allocate the model, something like this:

   self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2");

I faced a similar problem in LOX. LOX has decoys and there were several problems with them. One of the problems was that they were monster skins and hardly a "decoy" since nobody uses those skins. The solution was to spawn the decoy with the same skin as the owner. Only one per customer, however.

Since the player models are already indexed when they were spawned it was safe to use the same index as long as the decoys are destroyed with their owner when he disconnects. The key is the pointers from the owner to the decoy and the decoy to his owner. So here is the LOX spawn function for a decoy with monster think functions and the skin of the owner's client who spawned the decoy:

Code: [Select]
void spawn_decoy (edict_t *owner)
{
edict_t *self;
vec3_t forward, up;

self = G_Spawn();

// Place decoy 100 units forward and 25 units up from our current view angle
AngleVectors(owner->client->v_angle, forward, NULL, up);
VectorMA(owner->s.origin, 100, forward, self->s.origin);
VectorMA(self->s.origin, 25, up, self->s.origin);

/*
//QW// If used, the following line will spawn a decoy with
the same client ID as its owner.  This makes the owner immune to
fire from the decoy and the decoy immune to fire from the owner.
This was my first solution to the decoy/tracker crash bug
but some people said decoy hostility toward their owners was a feature. ;)
Compiling without this line will spawn a clientless decoy
and the code is now fixed in the rockets, weapon, angels and tracker modules to
ignore decoys with NULL client ID's.  Use this option only to grant
friendly fire immunity to decoys/owners.
*/
#ifdef DO_CLIENT_SPAWN
self->client = owner->client;  //QW//
#endif

//Link two entities together
owner->decoy = self; //for the owner, this is a pointer to the decoy
self->creator = owner; //for the decoy, this is a pointer to the owner

//Use same model and skin as the person creating decoy
self->model = owner->model;
self->s.skinnum = owner->s.skinnum;
self->s.modelindex = owner->s.modelindex;
self->s.modelindex2 = owner->s.modelindex2;
self->s.modelindex3 = owner->s.modelindex3;
self->s.modelindex4 = owner->s.modelindex4;
self->s.number = self - g_edicts;

self->s.effects = 0;
self->s.frame = 0;
self->classname = "decoy";
self->classnum = CN_DECOY;
self->health = 100;  //QW//  give decoys a little more strength
self->gib_health = -30;
self->max_health = 100;

self->monsterinfo.scale = MODEL_SCALE;
VectorSet (self->mins, -16, -16, -24);
VectorSet (self->maxs, 16, 16, 32);
self->movetype = MOVETYPE_STEP;
self->solid = SOLID_BBOX;
self->clipmask = MASK_PLAYERSOLID;
self->takedamage = DAMAGE_AIM;

self->mass = 100;
self->pain = decoy_pain;
self->die = decoy_die;
self->monsterinfo.stand = decoy_stand;
self->monsterinfo.walk = NULL;
self->monsterinfo.run = decoy_run;
self->monsterinfo.dodge = NULL;
self->monsterinfo.attack = decoy_attack;
self->monsterinfo.melee = NULL;
self->monsterinfo.sight = decoy_sight;
owner->decoytime = level.framenum + 60; // 6x10fps, can't toggle decoys more often than this //QW//

//Dont attack anything to start with
// (WI: errr, never attack anything?)
//self->monsterinfo.aiflags |= AI_GOOD_GUY;

//Set up sounds
sound_idle =    gi.soundindex ("soldier/solidle1.wav");
sound_sight1 =  gi.soundindex ("soldier/solsght1.wav");
sound_sight2 =  gi.soundindex ("soldier/solsrch1.wav");
sound_pain = gi.soundindex ("soldier/solpain1.wav");
sound_death = gi.soundindex ("misc/keyuse.wav");
gi.soundindex ("soldier/solatck1.wav");

// Face the decoy the same direction as player
self->s.angles[PITCH] = owner->s.angles[PITCH];
self->s.angles[YAW] = owner->s.angles[YAW];
self->s.angles[ROLL] = owner->s.angles[ROLL];

gi.linkentity (self);

// First animation sequence
self->monsterinfo.stand (self);

//Let monster code control this decoy
walkmonster_start (self);

gi.cprintf (owner, PRINT_MEDIUM, "Decoy created.\n");
}

void free_decoy (edict_t *self)
{
if (self->decoy)
{
G_FreeEdict (self->decoy);
self->decoy = NULL;  //redundant? dangerous? already null? see: G_FreeEdict
}
}

Decoys do not appear in the scoreboards and they also don't live very long. Being wimps, they have a very low survival rate in LOX. Your bots will have to have client ID's to be counted in the scoreboard or else you need to modify the scoreboard code to identify bots and count their scores separately from players, so maybe the DO_CLIENT_SPAWN bit would be a solution for you. This would make your bots not inflict damage on their owners. Your bot attack functions would be different of course, but you get the idea. For multiple bots per client, you will have to add multiple pointers to the bots by adding pointers to the edict_s to contain those references. Perhaps an array would work here.

    edict_t *decoy;    // explicit pointer to multiple decoys
    edict_t *decoy1;
    edict_t *decoy2;
    edict_t *decoy3;
    edict_t *creator;

or

    edict_t *decoy[4];   // array of pointers to decoys
    edict_t *creator;

LOX owes parts of it's decoy code to the Weapon Factory mod, I believe. You might search for them in the old tutorials for more tips. I was interested in solving a different set of problems in LOX but we are in the process of adding bots to LOX and we will be going down this road soon. Let me know how you are doing.

You begin to see a hint of the problem you are dealing with, the owner edict contains a pointer to an edict. Result, you have nested edicts and pointers pointing to structures. Debugging and keeping track of which level you are at can be great fun.
« Last Edit: August 20, 2009, 09:17:24 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 #22 on: August 21, 2009, 09:29:36 AM »
Thanks. But doesn't that mean that all your bots would have to have the same skin as the player? How could you get around that? You must be able to because the eraser bots, for example, all have different skins.

By the way, if you're coding bots, maybe you'd find the following page interesting. It's about the code for the bots in Quake 3, which has been made available to the public:

https://aigamedev.com/open/highlights/quake3-engine/

Maybe you could use some of that code for your bots. If not the hpb bot for half-life is also open source. Dunno if you're interested but I thought I'd mention that stuff in case.
  • 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 #23 on: August 21, 2009, 02:51:59 PM »
That question sent me back to the tutorials you cited in your first post. Answer: They're doing it wrong.

You have to remember that many of these tutorials were written before the Q2 engine code was released and none of the internals of the engine were known. Many of the mods shared code and there were many hacks involved with getting stuff to work in a mod that was based on the original vanilla Deathmatch DLL from idSoftware. The only "description" of what the code was supposed to be doing was the code itself and the comments were few and far between. As I recall, Zoid was responsible for getting the engine code "cleaned up" and prepared for public release and all the stuff it needed for porting to Linux.

255 is the max index a model can have. You should never actually reach that limit and if you exceed that number of models in game the server will crash from overwriting the adjacent data to the modelindex array. Both tutorials do it the same way and both of them are latent bugs waiting to crash your server or do wierd things in it. This kind of cross-pollenation was common in mod code. But following this practice is just plain wrong and if you want to learn you need to learn to do it right so you don't have a bunch of mystery crashes of your server.

If you are going to spawn various bots with different skins and weapons vs players then you should index the models from the model path using gi.modelindex and then set the modelindexes as needed.

Do this:
   newOak->model = "players/male/tris.md2";                              // the model name
   newOak->s.modelindex = gi.modelindex (newOak->model);    // we get new index if model didn't exist

The point of gi.modelindex is to allow the engine to allocate the models dynamically and to prepare it for the configstring data the client needs to render the model. This space is finite, there are only so many configstrings allocated for models, so if you hard code one without telling the server core you run the risk of crashing. It also means you can't use that 255 model index for a different skin if you had more than one bot skin. By using gi.modelindex the server controls the allocations. If the model exists, it assigns the index immediately from the "cached" models since the model is active. If, not it assigns the space it needs for the new model out the unused configstrings and adds it to the index array. When the model ceases to be used, the index is freed for another model. Hard coding model indexes in your mod is a bad idea.

The server sends the configstrings infrequently to the clients, it refers to the configstrings by sending a net message containing the index number and update flags. The client renders the object according to the precached configstring and the class of model it is supposed to be. Get these wrong and the client renders it wrong.

That Q3 bot stuff looks promising. Smarter AI would be nice since ordinary monsters aren't much of a challenge anymore.
  • 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

 

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:35:25 PM

Login with username, password and session length