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.aspxThe %-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!");
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
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.
newOak->model = "players/male/tris.md2";newOak->s.modelindex = 255;newOak->s.modelindex2 = 255;
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 }}