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