|
|
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.