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