|
|
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->client->ps.rdflags &= ~RDF_IRGOGGLES; // PGM ! 36: ent->client->ir_framenum = 0; // PGM ! 37: ent->client->nuke_framenum = 0; // PMM ! 38: ent->client->double_framenum = 0; // PMM ! 39: ! 40: ent->viewheight = 0; ! 41: ent->s.modelindex = 0; ! 42: ent->s.modelindex2 = 0; ! 43: ent->s.modelindex3 = 0; ! 44: ent->s.modelindex = 0; ! 45: ent->s.effects = 0; ! 46: ent->s.sound = 0; ! 47: ent->solid = SOLID_NOT; ! 48: ! 49: // add the layout ! 50: ! 51: if (deathmatch->value || coop->value) ! 52: { ! 53: DeathmatchScoreboardMessage (ent, NULL); ! 54: gi.unicast (ent, true); ! 55: } ! 56: ! 57: } ! 58: ! 59: void BeginIntermission (edict_t *targ) ! 60: { ! 61: int i, n; ! 62: edict_t *ent, *client; ! 63: ! 64: if (level.intermissiontime) ! 65: return; // already activated ! 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: // sort the clients by score ! 166: total = 0; ! 167: for (i=0 ; i<game.maxclients ; i++) ! 168: { ! 169: cl_ent = g_edicts + 1 + i; ! 170: if (!cl_ent->inuse || game.clients[i].resp.spectator) ! 171: continue; ! 172: score = game.clients[i].resp.score; ! 173: for (j=0 ; j<total ; j++) ! 174: { ! 175: if (score > sortedscores[j]) ! 176: break; ! 177: } ! 178: for (k=total ; k>j ; k--) ! 179: { ! 180: sorted[k] = sorted[k-1]; ! 181: sortedscores[k] = sortedscores[k-1]; ! 182: } ! 183: sorted[j] = i; ! 184: sortedscores[j] = score; ! 185: total++; ! 186: } ! 187: ! 188: // print level name and exit rules ! 189: string[0] = 0; ! 190: ! 191: stringlength = strlen(string); ! 192: ! 193: // add the clients in sorted order ! 194: if (total > 12) ! 195: total = 12; ! 196: ! 197: for (i=0 ; i<total ; i++) ! 198: { ! 199: cl = &game.clients[sorted[i]]; ! 200: cl_ent = g_edicts + 1 + sorted[i]; ! 201: ! 202: picnum = gi.imageindex ("i_fixme"); ! 203: x = (i>=6) ? 160 : 0; ! 204: y = 32 + 32 * (i%6); ! 205: ! 206: // add a dogtag ! 207: if (cl_ent == ent) ! 208: tag = "tag1"; ! 209: else if (cl_ent == killer) ! 210: tag = "tag2"; ! 211: else ! 212: tag = NULL; ! 213: ! 214: //=============== ! 215: //ROGUE ! 216: // allow new DM games to override the tag picture ! 217: if (gamerules && gamerules->value) ! 218: { ! 219: if(DMGame.DogTag) ! 220: DMGame.DogTag(cl_ent, killer, &tag); ! 221: } ! 222: //ROGUE ! 223: //=============== ! 224: ! 225: if (tag) ! 226: { ! 227: Com_sprintf (entry, sizeof(entry), ! 228: "xv %i yv %i picn %s ",x+32, y, tag); ! 229: j = strlen(entry); ! 230: if (stringlength + j > 1024) ! 231: break; ! 232: strcpy (string + stringlength, entry); ! 233: stringlength += j; ! 234: } ! 235: ! 236: // send the layout ! 237: Com_sprintf (entry, sizeof(entry), ! 238: "client %i %i %i %i %i %i ", ! 239: x, y, sorted[i], cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe)/600); ! 240: j = strlen(entry); ! 241: if (stringlength + j > 1024) ! 242: break; ! 243: strcpy (string + stringlength, entry); ! 244: stringlength += j; ! 245: } ! 246: ! 247: gi.WriteByte (svc_layout); ! 248: gi.WriteString (string); ! 249: } ! 250: ! 251: ! 252: /* ! 253: ================== ! 254: DeathmatchScoreboard ! 255: ! 256: Draw instead of help message. ! 257: Note that it isn't that hard to overflow the 1400 byte message limit! ! 258: ================== ! 259: */ ! 260: void DeathmatchScoreboard (edict_t *ent) ! 261: { ! 262: DeathmatchScoreboardMessage (ent, ent->enemy); ! 263: gi.unicast (ent, true); ! 264: } ! 265: ! 266: ! 267: /* ! 268: ================== ! 269: Cmd_Score_f ! 270: ! 271: Display the scoreboard ! 272: ================== ! 273: */ ! 274: void Cmd_Score_f (edict_t *ent) ! 275: { ! 276: ent->client->showinventory = false; ! 277: ent->client->showhelp = false; ! 278: ! 279: if (!deathmatch->value && !coop->value) ! 280: return; ! 281: ! 282: if (ent->client->showscores) ! 283: { ! 284: ent->client->showscores = false; ! 285: return; ! 286: } ! 287: ! 288: ent->client->showscores = true; ! 289: DeathmatchScoreboard (ent); ! 290: } ! 291: ! 292: ! 293: /* ! 294: ================== ! 295: HelpComputer ! 296: ! 297: Draw help computer. ! 298: ================== ! 299: */ ! 300: void HelpComputer (edict_t *ent) ! 301: { ! 302: char string[1024]; ! 303: char *sk; ! 304: ! 305: if (skill->value == 0) ! 306: sk = "easy"; ! 307: else if (skill->value == 1) ! 308: sk = "medium"; ! 309: else if (skill->value == 2) ! 310: sk = "hard"; ! 311: else ! 312: sk = "hard+"; ! 313: ! 314: // send the layout ! 315: Com_sprintf (string, sizeof(string), ! 316: "xv 32 yv 8 picn help " // background ! 317: "xv 202 yv 12 string2 \"%s\" " // skill ! 318: "xv 0 yv 24 cstring2 \"%s\" " // level name ! 319: "xv 0 yv 54 cstring2 \"%s\" " // help 1 ! 320: "xv 0 yv 110 cstring2 \"%s\" " // help 2 ! 321: "xv 50 yv 164 string2 \" kills goals secrets\" " ! 322: "xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ", ! 323: sk, ! 324: level.level_name, ! 325: game.helpmessage1, ! 326: game.helpmessage2, ! 327: level.killed_monsters, level.total_monsters, ! 328: level.found_goals, level.total_goals, ! 329: level.found_secrets, level.total_secrets); ! 330: ! 331: gi.WriteByte (svc_layout); ! 332: gi.WriteString (string); ! 333: gi.unicast (ent, true); ! 334: } ! 335: ! 336: ! 337: /* ! 338: ================== ! 339: Cmd_Help_f ! 340: ! 341: Display the current help message ! 342: ================== ! 343: */ ! 344: void Cmd_Help_f (edict_t *ent) ! 345: { ! 346: // this is for backwards compatability ! 347: if (deathmatch->value) ! 348: { ! 349: Cmd_Score_f (ent); ! 350: return; ! 351: } ! 352: ! 353: ent->client->showinventory = false; ! 354: ent->client->showscores = false; ! 355: ! 356: if (ent->client->showhelp && (ent->client->pers.game_helpchanged == game.helpchanged)) ! 357: { ! 358: ent->client->showhelp = false; ! 359: return; ! 360: } ! 361: ! 362: ent->client->showhelp = true; ! 363: ent->client->pers.helpchanged = 0; ! 364: HelpComputer (ent); ! 365: } ! 366: ! 367: ! 368: //======================================================================= ! 369: ! 370: /* ! 371: =============== ! 372: G_SetStats ! 373: =============== ! 374: */ ! 375: void G_SetStats (edict_t *ent) ! 376: { ! 377: gitem_t *item; ! 378: int index, cells; ! 379: int power_armor_type; ! 380: ! 381: // ! 382: // health ! 383: // ! 384: ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health; ! 385: ent->client->ps.stats[STAT_HEALTH] = ent->health; ! 386: ! 387: // ! 388: // ammo ! 389: // ! 390: if (!ent->client->ammo_index /* || !ent->client->pers.inventory[ent->client->ammo_index] */) ! 391: { ! 392: ent->client->ps.stats[STAT_AMMO_ICON] = 0; ! 393: ent->client->ps.stats[STAT_AMMO] = 0; ! 394: } ! 395: else ! 396: { ! 397: item = &itemlist[ent->client->ammo_index]; ! 398: ent->client->ps.stats[STAT_AMMO_ICON] = gi.imageindex (item->icon); ! 399: ent->client->ps.stats[STAT_AMMO] = ent->client->pers.inventory[ent->client->ammo_index]; ! 400: } ! 401: ! 402: // ! 403: // armor ! 404: // ! 405: power_armor_type = PowerArmorType (ent); ! 406: if (power_armor_type) ! 407: { ! 408: cells = ent->client->pers.inventory[ITEM_INDEX(FindItem ("cells"))]; ! 409: if (cells == 0) ! 410: { // ran out of cells for power armor ! 411: ent->flags &= ~FL_POWER_ARMOR; ! 412: gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0); ! 413: power_armor_type = 0;; ! 414: } ! 415: } ! 416: ! 417: index = ArmorIndex (ent); ! 418: if (power_armor_type && (!index || (level.framenum & 8) ) ) ! 419: { // flash between power armor and other armor icon ! 420: ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex ("i_powershield"); ! 421: ent->client->ps.stats[STAT_ARMOR] = cells; ! 422: } ! 423: else if (index) ! 424: { ! 425: item = GetItemByIndex (index); ! 426: ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex (item->icon); ! 427: ent->client->ps.stats[STAT_ARMOR] = ent->client->pers.inventory[index]; ! 428: } ! 429: else ! 430: { ! 431: ent->client->ps.stats[STAT_ARMOR_ICON] = 0; ! 432: ent->client->ps.stats[STAT_ARMOR] = 0; ! 433: } ! 434: ! 435: // ! 436: // pickup message ! 437: // ! 438: if (level.time > ent->client->pickup_msg_time) ! 439: { ! 440: ent->client->ps.stats[STAT_PICKUP_ICON] = 0; ! 441: ent->client->ps.stats[STAT_PICKUP_STRING] = 0; ! 442: } ! 443: ! 444: // ! 445: // timers ! 446: // ! 447: if (ent->client->quad_framenum > level.framenum) ! 448: { ! 449: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_quad"); ! 450: ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum)/10; ! 451: } ! 452: // PMM ! 453: else if (ent->client->double_framenum > level.framenum) ! 454: { ! 455: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_double"); ! 456: ent->client->ps.stats[STAT_TIMER] = (ent->client->double_framenum - level.framenum)/10; ! 457: } ! 458: // PMM ! 459: else if (ent->client->invincible_framenum > level.framenum) ! 460: { ! 461: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_invulnerability"); ! 462: ent->client->ps.stats[STAT_TIMER] = (ent->client->invincible_framenum - level.framenum)/10; ! 463: } ! 464: else if (ent->client->enviro_framenum > level.framenum) ! 465: { ! 466: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_envirosuit"); ! 467: ent->client->ps.stats[STAT_TIMER] = (ent->client->enviro_framenum - level.framenum)/10; ! 468: } ! 469: else if (ent->client->breather_framenum > level.framenum) ! 470: { ! 471: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_rebreather"); ! 472: ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum)/10; ! 473: } ! 474: // PGM ! 475: else if (ent->client->owned_sphere) ! 476: { ! 477: if(ent->client->owned_sphere->spawnflags == 1) // defender ! 478: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_defender"); ! 479: else if(ent->client->owned_sphere->spawnflags == 2) // hunter ! 480: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_hunter"); ! 481: else if(ent->client->owned_sphere->spawnflags == 4) // vengeance ! 482: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_vengeance"); ! 483: else // error case ! 484: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("i_fixme"); ! 485: ! 486: ent->client->ps.stats[STAT_TIMER] = (int)(ent->client->owned_sphere->wait - level.time); ! 487: } ! 488: else if (ent->client->ir_framenum > level.framenum) ! 489: { ! 490: ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_ir"); ! 491: ent->client->ps.stats[STAT_TIMER] = (ent->client->ir_framenum - level.framenum)/10; ! 492: } ! 493: // PGM ! 494: else ! 495: { ! 496: ent->client->ps.stats[STAT_TIMER_ICON] = 0; ! 497: ent->client->ps.stats[STAT_TIMER] = 0; ! 498: } ! 499: ! 500: // ! 501: // selected item ! 502: // ! 503: if (ent->client->pers.selected_item == -1) ! 504: ent->client->ps.stats[STAT_SELECTED_ICON] = 0; ! 505: else ! 506: ent->client->ps.stats[STAT_SELECTED_ICON] = gi.imageindex (itemlist[ent->client->pers.selected_item].icon); ! 507: ! 508: ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item; ! 509: ! 510: // ! 511: // layouts ! 512: // ! 513: ent->client->ps.stats[STAT_LAYOUTS] = 0; ! 514: ! 515: if (deathmatch->value) ! 516: { ! 517: if (ent->client->pers.health <= 0 || level.intermissiontime ! 518: || ent->client->showscores) ! 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: else ! 524: { ! 525: if (ent->client->showscores || ent->client->showhelp) ! 526: ent->client->ps.stats[STAT_LAYOUTS] |= 1; ! 527: if (ent->client->showinventory && ent->client->pers.health > 0) ! 528: ent->client->ps.stats[STAT_LAYOUTS] |= 2; ! 529: } ! 530: ! 531: // ! 532: // frags ! 533: // ! 534: ent->client->ps.stats[STAT_FRAGS] = ent->client->resp.score; ! 535: ! 536: // ! 537: // help icon / current weapon if not shown ! 538: // ! 539: if (ent->client->pers.helpchanged && (level.framenum&8) ) ! 540: ent->client->ps.stats[STAT_HELPICON] = gi.imageindex ("i_help"); ! 541: else if ( (ent->client->pers.hand == CENTER_HANDED || ent->client->ps.fov > 91) ! 542: && ent->client->pers.weapon) ! 543: ent->client->ps.stats[STAT_HELPICON] = gi.imageindex (ent->client->pers.weapon->icon); ! 544: else ! 545: ent->client->ps.stats[STAT_HELPICON] = 0; ! 546: ! 547: ent->client->ps.stats[STAT_SPECTATOR] = 0; ! 548: } ! 549: ! 550: /* ! 551: =============== ! 552: G_CheckChaseStats ! 553: =============== ! 554: */ ! 555: void G_CheckChaseStats (edict_t *ent) ! 556: { ! 557: int i; ! 558: gclient_t *cl; ! 559: ! 560: for (i = 1; i <= maxclients->value; i++) ! 561: { ! 562: cl = g_edicts[i].client; ! 563: if (!g_edicts[i].inuse || cl->chase_target != ent) ! 564: continue; ! 565: memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats)); ! 566: G_SetSpectatorStats(g_edicts + i); ! 567: } ! 568: } ! 569: ! 570: /* ! 571: =============== ! 572: G_SetSpectatorStats ! 573: =============== ! 574: */ ! 575: void G_SetSpectatorStats (edict_t *ent) ! 576: { ! 577: gclient_t *cl = ent->client; ! 578: ! 579: if (!cl->chase_target) ! 580: G_SetStats (ent); ! 581: ! 582: cl->ps.stats[STAT_SPECTATOR] = 1; ! 583: ! 584: // layouts are independant in spectator ! 585: cl->ps.stats[STAT_LAYOUTS] = 0; ! 586: if (cl->pers.health <= 0 || level.intermissiontime || cl->showscores) ! 587: cl->ps.stats[STAT_LAYOUTS] |= 1; ! 588: if (cl->showinventory && cl->pers.health > 0) ! 589: cl->ps.stats[STAT_LAYOUTS] |= 2; ! 590: ! 591: if (cl->chase_target && cl->chase_target->inuse) ! 592: { ! 593: cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS + ! 594: (cl->chase_target - g_edicts) - 1; ! 595: } ! 596: else ! 597: cl->ps.stats[STAT_CHASE] = 0; ! 598: } ! 599:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.