Quake II RTX doxygen  1.0 dev
p_hud.c File Reference
#include "g_local.h"

Go to the source code of this file.

Functions

void MoveClientToIntermission (edict_t *ent)
 
void BeginIntermission (edict_t *targ)
 
void DeathmatchScoreboardMessage (edict_t *ent, edict_t *killer)
 
void DeathmatchScoreboard (edict_t *ent)
 
void Cmd_Score_f (edict_t *ent)
 
void HelpComputer (edict_t *ent)
 
void Cmd_Help_f (edict_t *ent)
 
void G_SetStats (edict_t *ent)
 
void G_CheckChaseStats (edict_t *ent)
 
void G_SetSpectatorStats (edict_t *ent)
 

Function Documentation

◆ BeginIntermission()

void BeginIntermission ( edict_t *  targ)

Definition at line 70 of file p_hud.c.

71 {
72  int i, n;
73  edict_t *ent, *client;
74 
76  return; // already activated
77 
78  game.autosaved = qfalse;
79 
80  // respawn any dead clients
81  for (i = 0 ; i < maxclients->value ; i++) {
82  client = g_edicts + 1 + i;
83  if (!client->inuse)
84  continue;
85  if (client->health <= 0)
86  respawn(client);
87  }
88 
90  level.changemap = targ->map;
91 
92  if (strstr(level.changemap, "*")) {
93  if (coop->value) {
94  for (i = 0 ; i < maxclients->value ; i++) {
95  client = g_edicts + 1 + i;
96  if (!client->inuse)
97  continue;
98  // strip players of all keys between units
99  for (n = 0; n < MAX_ITEMS; n++) {
100  if (itemlist[n].flags & IT_KEY)
101  client->client->pers.inventory[n] = 0;
102  }
103  }
104  }
105  } else {
106  if (!deathmatch->value) {
107  level.exitintermission = 1; // go immediately to the next level
108  return;
109  }
110  }
111 
113 
114  // find an intermission spot
115  ent = G_Find(NULL, FOFS(classname), "info_player_intermission");
116  if (!ent) {
117  // the map creator forgot to put in an intermission point...
118  ent = G_Find(NULL, FOFS(classname), "info_player_start");
119  if (!ent)
120  ent = G_Find(NULL, FOFS(classname), "info_player_deathmatch");
121  } else {
122  // chose one of four spots
123  i = rand() & 3;
124  while (i--) {
125  ent = G_Find(ent, FOFS(classname), "info_player_intermission");
126  if (!ent) // wrap around the list
127  ent = G_Find(ent, FOFS(classname), "info_player_intermission");
128  }
129  }
130 
131  VectorCopy(ent->s.origin, level.intermission_origin);
132  VectorCopy(ent->s.angles, level.intermission_angle);
133 
134  // move all clients to the intermission point
135  for (i = 0 ; i < maxclients->value ; i++) {
136  client = g_edicts + 1 + i;
137  if (!client->inuse)
138  continue;
139  MoveClientToIntermission(client);
140  }
141 }

Referenced by EndDMLevel(), and use_target_changelevel().

◆ Cmd_Help_f()

void Cmd_Help_f ( edict_t *  ent)

Definition at line 324 of file p_hud.c.

325 {
326  // this is for backwards compatability
327  if (deathmatch->value) {
328  Cmd_Score_f(ent);
329  return;
330  }
331 
332  ent->client->showinventory = qfalse;
333  ent->client->showscores = qfalse;
334 
335  if (ent->client->showhelp && (ent->client->pers.game_helpchanged == game.helpchanged)) {
336  ent->client->showhelp = qfalse;
337  return;
338  }
339 
340  ent->client->showhelp = qtrue;
341  ent->client->pers.helpchanged = 0;
342  HelpComputer(ent);
343 }

Referenced by ClientCommand(), and player_die().

◆ Cmd_Score_f()

void Cmd_Score_f ( edict_t *  ent)

Definition at line 255 of file p_hud.c.

256 {
257  ent->client->showinventory = qfalse;
258  ent->client->showhelp = qfalse;
259 
260  if (!deathmatch->value && !coop->value)
261  return;
262 
263  if (ent->client->showscores) {
264  ent->client->showscores = qfalse;
265  return;
266  }
267 
268  ent->client->showscores = qtrue;
270 }

Referenced by ClientCommand(), and Cmd_Help_f().

◆ DeathmatchScoreboard()

void DeathmatchScoreboard ( edict_t *  ent)

Definition at line 241 of file p_hud.c.

242 {
243  DeathmatchScoreboardMessage(ent, ent->enemy);
244  gi.unicast(ent, qtrue);
245 }

Referenced by Cmd_Score_f().

◆ DeathmatchScoreboardMessage()

void DeathmatchScoreboardMessage ( edict_t *  ent,
edict_t *  killer 
)

Definition at line 150 of file p_hud.c.

151 {
152  char entry[1024];
153  char string[1400];
154  int stringlength;
155  int i, j, k;
156  int sorted[MAX_CLIENTS];
157  int sortedscores[MAX_CLIENTS];
158  int score, total;
159  int x, y;
160  gclient_t *cl;
161  edict_t *cl_ent;
162  char *tag;
163 
164  // sort the clients by score
165  total = 0;
166  for (i = 0 ; i < game.maxclients ; i++) {
167  cl_ent = g_edicts + 1 + i;
168  if (!cl_ent->inuse || game.clients[i].resp.spectator)
169  continue;
170  score = game.clients[i].resp.score;
171  for (j = 0 ; j < total ; j++) {
172  if (score > sortedscores[j])
173  break;
174  }
175  for (k = total ; k > j ; k--) {
176  sorted[k] = sorted[k - 1];
177  sortedscores[k] = sortedscores[k - 1];
178  }
179  sorted[j] = i;
180  sortedscores[j] = score;
181  total++;
182  }
183 
184  // print level name and exit rules
185  string[0] = 0;
186 
187  stringlength = strlen(string);
188 
189  // add the clients in sorted order
190  if (total > 12)
191  total = 12;
192 
193  for (i = 0 ; i < total ; i++) {
194  cl = &game.clients[sorted[i]];
195  cl_ent = g_edicts + 1 + sorted[i];
196 
197  x = (i >= 6) ? 160 : 0;
198  y = 32 + 32 * (i % 6);
199 
200  // add a dogtag
201  if (cl_ent == ent)
202  tag = "tag1";
203  else if (cl_ent == killer)
204  tag = "tag2";
205  else
206  tag = NULL;
207  if (tag) {
208  Q_snprintf(entry, sizeof(entry),
209  "xv %i yv %i picn %s ", x + 32, y, tag);
210  j = strlen(entry);
211  if (stringlength + j > 1024)
212  break;
213  strcpy(string + stringlength, entry);
214  stringlength += j;
215  }
216 
217  // send the layout
218  Q_snprintf(entry, sizeof(entry),
219  "client %i %i %i %i %i %i ",
220  x, y, sorted[i], cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe) / 600);
221  j = strlen(entry);
222  if (stringlength + j > 1024)
223  break;
224  strcpy(string + stringlength, entry);
225  stringlength += j;
226  }
227 
228  gi.WriteByte(svc_layout);
229  gi.WriteString(string);
230 }

Referenced by ClientEndServerFrame(), DeathmatchScoreboard(), and MoveClientToIntermission().

◆ G_CheckChaseStats()

void G_CheckChaseStats ( edict_t *  ent)

Definition at line 485 of file p_hud.c.

486 {
487  int i;
488  gclient_t *cl;
489 
490  for (i = 1; i <= maxclients->value; i++) {
491  cl = g_edicts[i].client;
492  if (!g_edicts[i].inuse || cl->chase_target != ent)
493  continue;
494  memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats));
496  }
497 }

Referenced by ClientEndServerFrame().

◆ G_SetSpectatorStats()

void G_SetSpectatorStats ( edict_t *  ent)

Definition at line 504 of file p_hud.c.

505 {
506  gclient_t *cl = ent->client;
507 
508  if (!cl->chase_target)
509  G_SetStats(ent);
510 
511  cl->ps.stats[STAT_SPECTATOR] = 1;
512 
513  // layouts are independant in spectator
514  cl->ps.stats[STAT_LAYOUTS] = 0;
515  if (cl->pers.health <= 0 || level.intermissiontime || cl->showscores)
516  cl->ps.stats[STAT_LAYOUTS] |= 1;
517  if (cl->showinventory && cl->pers.health > 0)
518  cl->ps.stats[STAT_LAYOUTS] |= 2;
519 
520  if (cl->chase_target && cl->chase_target->inuse)
521  cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS +
522  (cl->chase_target - g_edicts) - 1;
523  else
524  cl->ps.stats[STAT_CHASE] = 0;
525 }

Referenced by ClientEndServerFrame(), and G_CheckChaseStats().

◆ G_SetStats()

void G_SetStats ( edict_t *  ent)

Definition at line 353 of file p_hud.c.

354 {
355  gitem_t *item;
356  int index, cells;
357  int power_armor_type;
358 
359  //
360  // health
361  //
362  ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health;
363  ent->client->ps.stats[STAT_HEALTH] = ent->health;
364 
365  //
366  // ammo
367  //
368  if (!ent->client->ammo_index /* || !ent->client->pers.inventory[ent->client->ammo_index] */) {
369  ent->client->ps.stats[STAT_AMMO_ICON] = 0;
370  ent->client->ps.stats[STAT_AMMO] = 0;
371  } else {
372  item = &itemlist[ent->client->ammo_index];
373  ent->client->ps.stats[STAT_AMMO_ICON] = gi.imageindex(item->icon);
374  ent->client->ps.stats[STAT_AMMO] = ent->client->pers.inventory[ent->client->ammo_index];
375  }
376 
377  //
378  // armor
379  //
380  power_armor_type = PowerArmorType(ent);
381  if (power_armor_type) {
382  cells = ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))];
383  if (cells == 0) {
384  // ran out of cells for power armor
385  ent->flags &= ~FL_POWER_ARMOR;
386  gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
387  power_armor_type = 0;;
388  }
389  }
390 
391  index = ArmorIndex(ent);
392  if (power_armor_type && (!index || (level.framenum & 8))) {
393  // flash between power armor and other armor icon
394  ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex("i_powershield");
395  ent->client->ps.stats[STAT_ARMOR] = cells;
396  } else if (index) {
397  item = GetItemByIndex(index);
398  ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex(item->icon);
399  ent->client->ps.stats[STAT_ARMOR] = ent->client->pers.inventory[index];
400  } else {
401  ent->client->ps.stats[STAT_ARMOR_ICON] = 0;
402  ent->client->ps.stats[STAT_ARMOR] = 0;
403  }
404 
405  //
406  // pickup message
407  //
408  if (level.time > ent->client->pickup_msg_time) {
409  ent->client->ps.stats[STAT_PICKUP_ICON] = 0;
410  ent->client->ps.stats[STAT_PICKUP_STRING] = 0;
411  }
412 
413  //
414  // timers
415  //
416  if (ent->client->quad_framenum > level.framenum) {
417  ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_quad");
418  ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum) / 10;
419  } else if (ent->client->invincible_framenum > level.framenum) {
420  ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_invulnerability");
421  ent->client->ps.stats[STAT_TIMER] = (ent->client->invincible_framenum - level.framenum) / 10;
422  } else if (ent->client->enviro_framenum > level.framenum) {
423  ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_envirosuit");
424  ent->client->ps.stats[STAT_TIMER] = (ent->client->enviro_framenum - level.framenum) / 10;
425  } else if (ent->client->breather_framenum > level.framenum) {
426  ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_rebreather");
427  ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum) / 10;
428  } else {
429  ent->client->ps.stats[STAT_TIMER_ICON] = 0;
430  ent->client->ps.stats[STAT_TIMER] = 0;
431  }
432 
433  //
434  // selected item
435  //
436  if (ent->client->pers.selected_item == -1)
437  ent->client->ps.stats[STAT_SELECTED_ICON] = 0;
438  else
439  ent->client->ps.stats[STAT_SELECTED_ICON] = gi.imageindex(itemlist[ent->client->pers.selected_item].icon);
440 
441  ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item;
442 
443  //
444  // layouts
445  //
446  ent->client->ps.stats[STAT_LAYOUTS] = 0;
447 
448  if (deathmatch->value) {
449  if (ent->client->pers.health <= 0 || level.intermissiontime
450  || ent->client->showscores)
451  ent->client->ps.stats[STAT_LAYOUTS] |= 1;
452  if (ent->client->showinventory && ent->client->pers.health > 0)
453  ent->client->ps.stats[STAT_LAYOUTS] |= 2;
454  } else {
455  if (ent->client->showscores || ent->client->showhelp)
456  ent->client->ps.stats[STAT_LAYOUTS] |= 1;
457  if (ent->client->showinventory && ent->client->pers.health > 0)
458  ent->client->ps.stats[STAT_LAYOUTS] |= 2;
459  }
460 
461  //
462  // frags
463  //
464  ent->client->ps.stats[STAT_FRAGS] = ent->client->resp.score;
465 
466  //
467  // help icon / current weapon if not shown
468  //
469  if (ent->client->pers.helpchanged && (level.framenum & 8))
470  ent->client->ps.stats[STAT_HELPICON] = gi.imageindex("i_help");
471  else if ((ent->client->pers.hand == CENTER_HANDED || ent->client->ps.fov > 91)
472  && ent->client->pers.weapon)
473  ent->client->ps.stats[STAT_HELPICON] = gi.imageindex(ent->client->pers.weapon->icon);
474  else
475  ent->client->ps.stats[STAT_HELPICON] = 0;
476 
477  ent->client->ps.stats[STAT_SPECTATOR] = 0;
478 }

Referenced by ClientEndServerFrame(), and G_SetSpectatorStats().

◆ HelpComputer()

void HelpComputer ( edict_t *  ent)

Definition at line 280 of file p_hud.c.

281 {
282  char string[1024];
283  char *sk;
284 
285  if (skill->value == 0)
286  sk = "easy";
287  else if (skill->value == 1)
288  sk = "medium";
289  else if (skill->value == 2)
290  sk = "hard";
291  else
292  sk = "hard+";
293 
294  // send the layout
295  Q_snprintf(string, sizeof(string),
296  "xv 32 yv 8 picn help " // background
297  "xv 202 yv 12 string2 \"%s\" " // skill
298  "xv 0 yv 24 cstring2 \"%s\" " // level name
299  "xv 0 yv 54 cstring2 \"%s\" " // help 1
300  "xv 0 yv 110 cstring2 \"%s\" " // help 2
301  "xv 50 yv 164 string2 \" kills goals secrets\" "
302  "xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ",
303  sk,
310 
311  gi.WriteByte(svc_layout);
312  gi.WriteString(string);
313  gi.unicast(ent, qtrue);
314 }

Referenced by Cmd_Help_f().

◆ MoveClientToIntermission()

void MoveClientToIntermission ( edict_t *  ent)

Definition at line 30 of file p_hud.c.

31 {
32  if (deathmatch->value || coop->value)
33  ent->client->showscores = qtrue;
34  VectorCopy(level.intermission_origin, ent->s.origin);
35  ent->client->ps.pmove.origin[0] = level.intermission_origin[0] * 8;
36  ent->client->ps.pmove.origin[1] = level.intermission_origin[1] * 8;
37  ent->client->ps.pmove.origin[2] = level.intermission_origin[2] * 8;
38  VectorCopy(level.intermission_angle, ent->client->ps.viewangles);
39  ent->client->ps.pmove.pm_type = PM_FREEZE;
40  ent->client->ps.gunindex = 0;
41  ent->client->ps.blend[3] = 0;
42  ent->client->ps.rdflags &= ~RDF_UNDERWATER;
43 
44  // clean up powerup info
45  ent->client->quad_framenum = 0;
46  ent->client->invincible_framenum = 0;
47  ent->client->breather_framenum = 0;
48  ent->client->enviro_framenum = 0;
49  ent->client->grenade_blew_up = qfalse;
50  ent->client->grenade_time = 0;
51 
52  ent->viewheight = 0;
53  ent->s.modelindex = 0;
54  ent->s.modelindex2 = 0;
55  ent->s.modelindex3 = 0;
56  ent->s.modelindex = 0;
57  ent->s.effects = 0;
58  ent->s.sound = 0;
59  ent->solid = SOLID_NOT;
60 
61  // add the layout
62 
63  if (deathmatch->value || coop->value) {
64  DeathmatchScoreboardMessage(ent, NULL);
65  gi.unicast(ent, qtrue);
66  }
67 
68 }

Referenced by BeginIntermission(), ClientBegin(), and ClientBeginDeathmatch().

FindItem
gitem_t * FindItem(char *pickup_name)
Definition: g_items.c:98
gi
game_import_t gi
Definition: g_main.c:23
Cmd_Score_f
void Cmd_Score_f(edict_t *ent)
Definition: p_hud.c:255
level_locals_t::pic_health
int pic_health
Definition: g_local.h:321
deathmatch
cvar_t * deathmatch
Definition: g_main.c:33
game_locals_t::helpmessage1
char helpmessage1[512]
Definition: g_local.h:268
maxclients
cvar_t * maxclients
Definition: g_main.c:42
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
DeathmatchScoreboard
void DeathmatchScoreboard(edict_t *ent)
Definition: p_hud.c:241
PowerArmorType
int PowerArmorType(edict_t *ent)
Definition: g_items.c:655
game_locals_t::helpchanged
int helpchanged
Definition: g_local.h:270
ITEM_INDEX
#define ITEM_INDEX(x)
Definition: g_local.h:600
FL_POWER_ARMOR
#define FL_POWER_ARMOR
Definition: g_local.h:71
G_Find
edict_t * G_Find(edict_t *from, int fieldofs, char *match)
Definition: g_utils.c:43
FOFS
#define FOFS(x)
Definition: g_local.h:498
ArmorIndex
int ArmorIndex(edict_t *ent)
Definition: g_items.c:563
g_edicts
edict_t * g_edicts
Definition: g_main.c:31
itemlist
gitem_t itemlist[]
Definition: g_items.c:1063
gitem_s::icon
char * icon
Definition: g_local.h:244
level_locals_t::level_name
char level_name[MAX_QPATH]
Definition: g_local.h:301
IT_KEY
#define IT_KEY
Definition: g_local.h:215
MoveClientToIntermission
void MoveClientToIntermission(edict_t *ent)
Definition: p_hud.c:30
level_locals_t::intermission_origin
vec3_t intermission_origin
Definition: g_local.h:309
game_locals_t::helpmessage2
char helpmessage2[512]
Definition: g_local.h:269
level_locals_t::total_secrets
int total_secrets
Definition: g_local.h:323
level_locals_t::total_goals
int total_goals
Definition: g_local.h:326
level_locals_t::found_secrets
int found_secrets
Definition: g_local.h:324
level_locals_t::killed_monsters
int killed_monsters
Definition: g_local.h:330
game_locals_t::clients
gclient_t * clients
Definition: g_local.h:273
game
game_locals_t game
Definition: g_main.c:21
respawn
void respawn(edict_t *ent)
Definition: p_client.c:957
skill
cvar_t * skill
Definition: g_main.c:36
level_locals_t::framenum
int framenum
Definition: g_local.h:298
HelpComputer
void HelpComputer(edict_t *ent)
Definition: p_hud.c:280
game_locals_t::autosaved
qboolean autosaved
Definition: g_local.h:289
level_locals_t::exitintermission
int exitintermission
Definition: g_local.h:308
cl
client_state_t cl
Definition: main.c:99
level_locals_t::time
float time
Definition: g_local.h:299
coop
cvar_t * coop
Definition: g_main.c:34
level_locals_t::intermissiontime
float intermissiontime
Definition: g_local.h:306
G_SetSpectatorStats
void G_SetSpectatorStats(edict_t *ent)
Definition: p_hud.c:504
level_locals_t::changemap
char * changemap
Definition: g_local.h:307
CENTER_HANDED
#define CENTER_HANDED
Definition: g_local.h:163
level_locals_t::found_goals
int found_goals
Definition: g_local.h:327
level
level_locals_t level
Definition: g_main.c:22
GetItemByIndex
gitem_t * GetItemByIndex(int index)
Definition: g_items.c:61
level_locals_t::total_monsters
int total_monsters
Definition: g_local.h:329
G_SetStats
void G_SetStats(edict_t *ent)
Definition: p_hud.c:353
svc_layout
#define svc_layout
Definition: g_local.h:39
DeathmatchScoreboardMessage
void DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer)
Definition: p_hud.c:150
level_locals_t::intermission_angle
vec3_t intermission_angle
Definition: g_local.h:310
gitem_s
Definition: g_local.h:232
game_locals_t::maxclients
int maxclients
Definition: g_local.h:280