|
|
1.1 root 1: #include "g_local.h"
2:
3:
4:
5: /*
6: ======================================================================
7:
8: INTERMISSION
9:
10: ======================================================================
11: */
12:
13: void MoveClientToIntermission (edict_t *ent)
14: {
15: if (deathmatch->value || coop->value)
16: ent->client->showscores = true;
17: VectorCopy (level.intermission_origin, ent->s.origin);
18: ent->client->ps.pmove.origin[0] = level.intermission_origin[0]*8;
19: ent->client->ps.pmove.origin[1] = level.intermission_origin[1]*8;
20: ent->client->ps.pmove.origin[2] = level.intermission_origin[2]*8;
21: VectorCopy (level.intermission_angle, ent->client->ps.viewangles);
22: ent->client->ps.pmove.pm_type = PM_FREEZE;
23: ent->client->ps.gunindex = 0;
24: ent->client->ps.blend[3] = 0;
25: ent->client->ps.rdflags &= ~RDF_UNDERWATER;
26:
27: // clean up powerup info
28: ent->client->quad_framenum = 0;
29: ent->client->invincible_framenum = 0;
30: ent->client->breather_framenum = 0;
31: ent->client->enviro_framenum = 0;
32: ent->client->grenade_blew_up = false;
33: ent->client->grenade_time = 0;
34:
35: ent->viewheight = 0;
36: ent->s.modelindex = 0;
37: ent->s.modelindex2 = 0;
38: ent->s.modelindex3 = 0;
39: ent->s.modelindex = 0;
40: ent->s.effects = 0;
41: ent->s.sound = 0;
42: ent->solid = SOLID_NOT;
43:
44: // add the layout
45:
46: if (deathmatch->value || coop->value)
47: {
48: DeathmatchScoreboardMessage (ent, NULL);
49: gi.unicast (ent, true);
50: }
51:
52: }
53:
54: void BeginIntermission (edict_t *targ)
55: {
56: int i, n;
57: edict_t *ent, *client;
58:
59: if (level.intermissiontime)
60: return; // already activated
61:
62: game.autosaved = false;
63:
64: // respawn any dead clients
65: for (i=0 ; i<maxclients->value ; i++)
66: {
67: client = g_edicts + 1 + i;
68: if (!client->inuse)
69: continue;
70: if (client->health <= 0)
71: respawn(client);
72: }
73:
74: level.intermissiontime = level.time;
75: level.changemap = targ->map;
76:
77: if (strstr(level.changemap, "*"))
78: {
79: if (coop->value)
80: {
81: for (i=0 ; i<maxclients->value ; i++)
82: {
83: client = g_edicts + 1 + i;
84: if (!client->inuse)
85: continue;
86: // strip players of all keys between units
87: for (n = 0; n < MAX_ITEMS; n++)
88: {
89: if (itemlist[n].flags & IT_KEY)
90: client->client->pers.inventory[n] = 0;
91: }
92: }
93: }
94: }
95: else
96: {
97: if (!deathmatch->value)
98: {
99: level.exitintermission = 1; // go immediately to the next level
100: return;
101: }
102: }
103:
104: level.exitintermission = 0;
105:
106: // find an intermission spot
107: ent = G_Find (NULL, FOFS(classname), "info_player_intermission");
108: if (!ent)
109: { // the map creator forgot to put in an intermission point...
110: ent = G_Find (NULL, FOFS(classname), "info_player_start");
111: if (!ent)
112: ent = G_Find (NULL, FOFS(classname), "info_player_deathmatch");
113: }
114: else
115: { // chose one of four spots
116: i = rand() & 3;
117: while (i--)
118: {
119: ent = G_Find (ent, FOFS(classname), "info_player_intermission");
120: if (!ent) // wrap around the list
121: ent = G_Find (ent, FOFS(classname), "info_player_intermission");
122: }
123: }
124:
125: VectorCopy (ent->s.origin, level.intermission_origin);
126: VectorCopy (ent->s.angles, level.intermission_angle);
127:
128: // move all clients to the intermission point
129: for (i=0 ; i<maxclients->value ; i++)
130: {
131: client = g_edicts + 1 + i;
132: if (!client->inuse)
133: continue;
134: MoveClientToIntermission (client);
135: }
136: }
137:
138:
139: /*
140: ==================
141: DeathmatchScoreboardMessage
142:
143: ==================
144: */
145: void DeathmatchScoreboardMessage (edict_t *ent, edict_t *killer)
146: {
147: char entry[1024];
148: char string[1400];
149: int stringlength;
150: int i, j, k;
151: int sorted[MAX_CLIENTS];
152: int sortedscores[MAX_CLIENTS];
153: int score, total;
154: int picnum;
155: int x, y;
156: gclient_t *cl;
157: edict_t *cl_ent;
158: char *tag;
159:
160: // sort the clients by score
161: total = 0;
162: for (i=0 ; i<game.maxclients ; i++)
163: {
164: cl_ent = g_edicts + 1 + i;
1.1.1.2 ! root 165: if (!cl_ent->inuse || game.clients[i].resp.spectator)
1.1 root 166: continue;
167: score = game.clients[i].resp.score;
168: for (j=0 ; j<total ; j++)
169: {
170: if (score > sortedscores[j])
171: break;
172: }
173: for (k=total ; k>j ; k--)
174: {
175: sorted[k] = sorted[k-1];
176: sortedscores[k] = sortedscores[k-1];
177: }
178: sorted[j] = i;
179: sortedscores[j] = score;
180: total++;
181: }
182:
183: // print level name and exit rules
184: string[0] = 0;
185:
186: stringlength = strlen(string);
187:
188: // add the clients in sorted order
189: if (total > 12)
190: total = 12;
191:
192: for (i=0 ; i<total ; i++)
193: {
194: cl = &game.clients[sorted[i]];
195: cl_ent = g_edicts + 1 + sorted[i];
196:
197: picnum = gi.imageindex ("i_fixme");
198: x = (i>=6) ? 160 : 0;
199: y = 32 + 32 * (i%6);
200:
201: // add a dogtag
202: if (cl_ent == ent)
203: tag = "tag1";
204: else if (cl_ent == killer)
205: tag = "tag2";
206: else
207: tag = NULL;
208: if (tag)
209: {
210: Com_sprintf (entry, sizeof(entry),
211: "xv %i yv %i picn %s ",x+32, y, tag);
212: j = strlen(entry);
213: if (stringlength + j > 1024)
214: break;
215: strcpy (string + stringlength, entry);
216: stringlength += j;
217: }
218:
219: // send the layout
220: Com_sprintf (entry, sizeof(entry),
221: "client %i %i %i %i %i %i ",
222: x, y, sorted[i], cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe)/600);
223: j = strlen(entry);
224: if (stringlength + j > 1024)
225: break;
226: strcpy (string + stringlength, entry);
227: stringlength += j;
228: }
229:
230: gi.WriteByte (svc_layout);
231: gi.WriteString (string);
232: }
233:
234:
235: /*
236: ==================
237: DeathmatchScoreboard
238:
239: Draw instead of help message.
240: Note that it isn't that hard to overflow the 1400 byte message limit!
241: ==================
242: */
243: void DeathmatchScoreboard (edict_t *ent)
244: {
245: DeathmatchScoreboardMessage (ent, ent->enemy);
246: gi.unicast (ent, true);
247: }
248:
249:
250: /*
251: ==================
252: Cmd_Score_f
253:
254: Display the scoreboard
255: ==================
256: */
257: void Cmd_Score_f (edict_t *ent)
258: {
259: ent->client->showinventory = false;
260: ent->client->showhelp = false;
261:
262: if (!deathmatch->value && !coop->value)
263: return;
264:
265: if (ent->client->showscores)
266: {
267: ent->client->showscores = false;
268: return;
269: }
270:
271: ent->client->showscores = true;
272: DeathmatchScoreboard (ent);
273: }
274:
275:
276: /*
277: ==================
278: HelpComputer
279:
280: Draw help computer.
281: ==================
282: */
283: void HelpComputer (edict_t *ent)
284: {
285: char string[1024];
286: char *sk;
287:
288: if (skill->value == 0)
289: sk = "easy";
290: else if (skill->value == 1)
291: sk = "medium";
292: else if (skill->value == 2)
293: sk = "hard";
294: else
295: sk = "hard+";
296:
297: // send the layout
298: Com_sprintf (string, sizeof(string),
299: "xv 32 yv 8 picn help " // background
300: "xv 202 yv 12 string2 \"%s\" " // skill
301: "xv 0 yv 24 cstring2 \"%s\" " // level name
302: "xv 0 yv 54 cstring2 \"%s\" " // help 1
303: "xv 0 yv 110 cstring2 \"%s\" " // help 2
304: "xv 50 yv 164 string2 \" kills goals secrets\" "
305: "xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ",
306: sk,
307: level.level_name,
308: game.helpmessage1,
309: game.helpmessage2,
310: level.killed_monsters, level.total_monsters,
311: level.found_goals, level.total_goals,
312: level.found_secrets, level.total_secrets);
313:
314: gi.WriteByte (svc_layout);
315: gi.WriteString (string);
316: gi.unicast (ent, true);
317: }
318:
319:
320: /*
321: ==================
322: Cmd_Help_f
323:
324: Display the current help message
325: ==================
326: */
327: void Cmd_Help_f (edict_t *ent)
328: {
329: // this is for backwards compatability
330: if (deathmatch->value)
331: {
332: Cmd_Score_f (ent);
333: return;
334: }
335:
336: ent->client->showinventory = false;
337: ent->client->showscores = false;
338:
339: if (ent->client->showhelp && (ent->client->pers.game_helpchanged == game.helpchanged))
340: {
341: ent->client->showhelp = false;
342: return;
343: }
344:
345: ent->client->showhelp = true;
346: ent->client->pers.helpchanged = 0;
347: HelpComputer (ent);
348: }
349:
350:
351: //=======================================================================
352:
353: /*
354: ===============
355: G_SetStats
356: ===============
357: */
358: void G_SetStats (edict_t *ent)
359: {
360: gitem_t *item;
361: int index, cells;
362: int power_armor_type;
363:
364: //
365: // health
366: //
367: ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health;
368: ent->client->ps.stats[STAT_HEALTH] = ent->health;
369:
370: //
371: // ammo
372: //
373: if (!ent->client->ammo_index /* || !ent->client->pers.inventory[ent->client->ammo_index] */)
374: {
375: ent->client->ps.stats[STAT_AMMO_ICON] = 0;
376: ent->client->ps.stats[STAT_AMMO] = 0;
377: }
378: else
379: {
380: item = &itemlist[ent->client->ammo_index];
381: ent->client->ps.stats[STAT_AMMO_ICON] = gi.imageindex (item->icon);
382: ent->client->ps.stats[STAT_AMMO] = ent->client->pers.inventory[ent->client->ammo_index];
383: }
384:
385: //
386: // armor
387: //
388: power_armor_type = PowerArmorType (ent);
389: if (power_armor_type)
390: {
391: cells = ent->client->pers.inventory[ITEM_INDEX(FindItem ("cells"))];
392: if (cells == 0)
393: { // ran out of cells for power armor
394: ent->flags &= ~FL_POWER_ARMOR;
395: gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
396: power_armor_type = 0;;
397: }
398: }
399:
400: index = ArmorIndex (ent);
401: if (power_armor_type && (!index || (level.framenum & 8) ) )
402: { // flash between power armor and other armor icon
403: ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex ("i_powershield");
404: ent->client->ps.stats[STAT_ARMOR] = cells;
405: }
406: else if (index)
407: {
408: item = GetItemByIndex (index);
409: ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex (item->icon);
410: ent->client->ps.stats[STAT_ARMOR] = ent->client->pers.inventory[index];
411: }
412: else
413: {
414: ent->client->ps.stats[STAT_ARMOR_ICON] = 0;
415: ent->client->ps.stats[STAT_ARMOR] = 0;
416: }
417:
418: //
419: // pickup message
420: //
421: if (level.time > ent->client->pickup_msg_time)
422: {
423: ent->client->ps.stats[STAT_PICKUP_ICON] = 0;
424: ent->client->ps.stats[STAT_PICKUP_STRING] = 0;
425: }
426:
427: //
428: // timers
429: //
430: if (ent->client->quad_framenum > level.framenum)
431: {
432: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_quad");
433: ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum)/10;
434: }
435: else if (ent->client->invincible_framenum > level.framenum)
436: {
437: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_invulnerability");
438: ent->client->ps.stats[STAT_TIMER] = (ent->client->invincible_framenum - level.framenum)/10;
439: }
440: else if (ent->client->enviro_framenum > level.framenum)
441: {
442: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_envirosuit");
443: ent->client->ps.stats[STAT_TIMER] = (ent->client->enviro_framenum - level.framenum)/10;
444: }
445: else if (ent->client->breather_framenum > level.framenum)
446: {
447: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_rebreather");
448: ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum)/10;
449: }
450: else
451: {
452: ent->client->ps.stats[STAT_TIMER_ICON] = 0;
453: ent->client->ps.stats[STAT_TIMER] = 0;
454: }
455:
456: //
457: // selected item
458: //
459: if (ent->client->pers.selected_item == -1)
460: ent->client->ps.stats[STAT_SELECTED_ICON] = 0;
461: else
462: ent->client->ps.stats[STAT_SELECTED_ICON] = gi.imageindex (itemlist[ent->client->pers.selected_item].icon);
463:
464: ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item;
465:
466: //
467: // layouts
468: //
469: ent->client->ps.stats[STAT_LAYOUTS] = 0;
470:
471: if (deathmatch->value)
472: {
473: if (ent->client->pers.health <= 0 || level.intermissiontime
474: || ent->client->showscores)
475: ent->client->ps.stats[STAT_LAYOUTS] |= 1;
476: if (ent->client->showinventory && ent->client->pers.health > 0)
477: ent->client->ps.stats[STAT_LAYOUTS] |= 2;
478: }
479: else
480: {
481: if (ent->client->showscores || ent->client->showhelp)
482: ent->client->ps.stats[STAT_LAYOUTS] |= 1;
483: if (ent->client->showinventory && ent->client->pers.health > 0)
484: ent->client->ps.stats[STAT_LAYOUTS] |= 2;
485: }
486:
487: //
488: // frags
489: //
490: ent->client->ps.stats[STAT_FRAGS] = ent->client->resp.score;
491:
492: //
493: // help icon / current weapon if not shown
494: //
495: if (ent->client->pers.helpchanged && (level.framenum&8) )
496: ent->client->ps.stats[STAT_HELPICON] = gi.imageindex ("i_help");
497: else if ( (ent->client->pers.hand == CENTER_HANDED || ent->client->ps.fov > 91)
498: && ent->client->pers.weapon)
499: ent->client->ps.stats[STAT_HELPICON] = gi.imageindex (ent->client->pers.weapon->icon);
500: else
501: ent->client->ps.stats[STAT_HELPICON] = 0;
1.1.1.2 ! root 502:
! 503: ent->client->ps.stats[STAT_SPECTATOR] = 0;
! 504: }
! 505:
! 506: /*
! 507: ===============
! 508: G_CheckChaseStats
! 509: ===============
! 510: */
! 511: void G_CheckChaseStats (edict_t *ent)
! 512: {
! 513: int i;
! 514: gclient_t *cl;
! 515:
! 516: for (i = 1; i <= maxclients->value; i++) {
! 517: cl = g_edicts[i].client;
! 518: if (!g_edicts[i].inuse || cl->chase_target != ent)
! 519: continue;
! 520: memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats));
! 521: G_SetSpectatorStats(g_edicts + i);
! 522: }
! 523: }
! 524:
! 525: /*
! 526: ===============
! 527: G_SetSpectatorStats
! 528: ===============
! 529: */
! 530: void G_SetSpectatorStats (edict_t *ent)
! 531: {
! 532: gclient_t *cl = ent->client;
! 533:
! 534: if (!cl->chase_target)
! 535: G_SetStats (ent);
! 536:
! 537: cl->ps.stats[STAT_SPECTATOR] = 1;
! 538:
! 539: // layouts are independant in spectator
! 540: cl->ps.stats[STAT_LAYOUTS] = 0;
! 541: if (cl->pers.health <= 0 || level.intermissiontime || cl->showscores)
! 542: cl->ps.stats[STAT_LAYOUTS] |= 1;
! 543: if (cl->showinventory && cl->pers.health > 0)
! 544: cl->ps.stats[STAT_LAYOUTS] |= 2;
! 545:
! 546: if (cl->chase_target && cl->chase_target->inuse)
! 547: cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS +
! 548: (cl->chase_target - g_edicts) - 1;
! 549: else
! 550: cl->ps.stats[STAT_CHASE] = 0;
1.1 root 551: }
552:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.