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