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