|
|
1.1 ! root 1: /* ! 2: Copyright (C) 1996-1997 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: */ ! 20: // view.c -- player eye positioning ! 21: ! 22: #include "quakedef.h" ! 23: #include "r_local.h" ! 24: ! 25: /* ! 26: ! 27: The view is allowed to move slightly from it's true position for bobbing, ! 28: but if it exceeds 8 pixels linear distance (spherical, not box), the list of ! 29: entities sent from the server may not include everything in the pvs, especially ! 30: when crossing a water boudnary. ! 31: ! 32: */ ! 33: ! 34: cvar_t lcd_x = {"lcd_x", "0"}; // FIXME: make this work sometime... ! 35: ! 36: cvar_t cl_rollspeed = {"cl_rollspeed", "200"}; ! 37: cvar_t cl_rollangle = {"cl_rollangle", "2.0"}; ! 38: ! 39: cvar_t cl_bob = {"cl_bob","0.02", false}; ! 40: cvar_t cl_bobcycle = {"cl_bobcycle","0.6", false}; ! 41: cvar_t cl_bobup = {"cl_bobup","0.5", false}; ! 42: ! 43: cvar_t v_kicktime = {"v_kicktime", "0.5", false}; ! 44: cvar_t v_kickroll = {"v_kickroll", "0.6", false}; ! 45: cvar_t v_kickpitch = {"v_kickpitch", "0.6", false}; ! 46: ! 47: cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", false}; ! 48: cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", false}; ! 49: cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", false}; ! 50: cvar_t v_iyaw_level = {"v_iyaw_level", "0.3", false}; ! 51: cvar_t v_iroll_level = {"v_iroll_level", "0.1", false}; ! 52: cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", false}; ! 53: ! 54: cvar_t v_idlescale = {"v_idlescale", "0", false}; ! 55: ! 56: cvar_t crosshair = {"crosshair", "0", true}; ! 57: cvar_t crosshaircolor = {"crosshaircolor", "79", true}; ! 58: ! 59: cvar_t cl_crossx = {"cl_crossx", "0", true}; ! 60: cvar_t cl_crossy = {"cl_crossy", "0", true}; ! 61: ! 62: #ifdef GLQUAKE ! 63: cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false}; ! 64: #endif ! 65: ! 66: cvar_t v_contentblend = {"v_contentblend", "1", false}; ! 67: ! 68: float v_dmg_time, v_dmg_roll, v_dmg_pitch; ! 69: ! 70: extern int in_forward, in_forward2, in_back; ! 71: ! 72: frame_t *view_frame; ! 73: player_state_t *view_message; ! 74: ! 75: /* ! 76: =============== ! 77: V_CalcRoll ! 78: ! 79: =============== ! 80: */ ! 81: float V_CalcRoll (vec3_t angles, vec3_t velocity) ! 82: { ! 83: vec3_t forward, right, up; ! 84: float sign; ! 85: float side; ! 86: float value; ! 87: ! 88: AngleVectors (angles, forward, right, up); ! 89: side = DotProduct (velocity, right); ! 90: sign = side < 0 ? -1 : 1; ! 91: side = fabs(side); ! 92: ! 93: value = cl_rollangle.value; ! 94: ! 95: if (side < cl_rollspeed.value) ! 96: side = side * value / cl_rollspeed.value; ! 97: else ! 98: side = value; ! 99: ! 100: return side*sign; ! 101: ! 102: } ! 103: ! 104: ! 105: /* ! 106: =============== ! 107: V_CalcBob ! 108: ! 109: =============== ! 110: */ ! 111: float V_CalcBob (void) ! 112: { ! 113: static double bobtime; ! 114: static float bob; ! 115: float cycle; ! 116: ! 117: if (cl.spectator) ! 118: return 0; ! 119: ! 120: if (onground == -1) ! 121: return bob; // just use old value ! 122: ! 123: bobtime += host_frametime; ! 124: cycle = bobtime - (int)(bobtime/cl_bobcycle.value)*cl_bobcycle.value; ! 125: cycle /= cl_bobcycle.value; ! 126: if (cycle < cl_bobup.value) ! 127: cycle = M_PI * cycle / cl_bobup.value; ! 128: else ! 129: cycle = M_PI + M_PI*(cycle-cl_bobup.value)/(1.0 - cl_bobup.value); ! 130: ! 131: // bob is proportional to simulated velocity in the xy plane ! 132: // (don't count Z, or jumping messes it up) ! 133: ! 134: bob = sqrt(cl.simvel[0]*cl.simvel[0] + cl.simvel[1]*cl.simvel[1]) * cl_bob.value; ! 135: bob = bob*0.3 + bob*0.7*sin(cycle); ! 136: if (bob > 4) ! 137: bob = 4; ! 138: else if (bob < -7) ! 139: bob = -7; ! 140: return bob; ! 141: ! 142: } ! 143: ! 144: ! 145: //============================================================================= ! 146: ! 147: ! 148: cvar_t v_centermove = {"v_centermove", "0.15", false}; ! 149: cvar_t v_centerspeed = {"v_centerspeed","500"}; ! 150: ! 151: ! 152: void V_StartPitchDrift (void) ! 153: { ! 154: #if 1 ! 155: if (cl.laststop == cl.time) ! 156: { ! 157: return; // something else is keeping it from drifting ! 158: } ! 159: #endif ! 160: if (cl.nodrift || !cl.pitchvel) ! 161: { ! 162: cl.pitchvel = v_centerspeed.value; ! 163: cl.nodrift = false; ! 164: cl.driftmove = 0; ! 165: } ! 166: } ! 167: ! 168: void V_StopPitchDrift (void) ! 169: { ! 170: cl.laststop = cl.time; ! 171: cl.nodrift = true; ! 172: cl.pitchvel = 0; ! 173: } ! 174: ! 175: /* ! 176: =============== ! 177: V_DriftPitch ! 178: ! 179: Moves the client pitch angle towards cl.idealpitch sent by the server. ! 180: ! 181: If the user is adjusting pitch manually, either with lookup/lookdown, ! 182: mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped. ! 183: ! 184: Drifting is enabled when the center view key is hit, mlook is released and ! 185: lookspring is non 0, or when ! 186: =============== ! 187: */ ! 188: void V_DriftPitch (void) ! 189: { ! 190: float delta, move; ! 191: ! 192: if (view_message->onground == -1 || cls.demoplayback ) ! 193: { ! 194: cl.driftmove = 0; ! 195: cl.pitchvel = 0; ! 196: return; ! 197: } ! 198: ! 199: // don't count small mouse motion ! 200: if (cl.nodrift) ! 201: { ! 202: if ( fabs(cl.frames[(cls.netchan.outgoing_sequence-1)&UPDATE_MASK].cmd.forwardmove) < 200) ! 203: cl.driftmove = 0; ! 204: else ! 205: cl.driftmove += host_frametime; ! 206: ! 207: if ( cl.driftmove > v_centermove.value) ! 208: { ! 209: V_StartPitchDrift (); ! 210: } ! 211: return; ! 212: } ! 213: ! 214: delta = 0 - cl.viewangles[PITCH]; ! 215: ! 216: if (!delta) ! 217: { ! 218: cl.pitchvel = 0; ! 219: return; ! 220: } ! 221: ! 222: move = host_frametime * cl.pitchvel; ! 223: cl.pitchvel += host_frametime * v_centerspeed.value; ! 224: ! 225: //Con_Printf ("move: %f (%f)\n", move, host_frametime); ! 226: ! 227: if (delta > 0) ! 228: { ! 229: if (move > delta) ! 230: { ! 231: cl.pitchvel = 0; ! 232: move = delta; ! 233: } ! 234: cl.viewangles[PITCH] += move; ! 235: } ! 236: else if (delta < 0) ! 237: { ! 238: if (move > -delta) ! 239: { ! 240: cl.pitchvel = 0; ! 241: move = -delta; ! 242: } ! 243: cl.viewangles[PITCH] -= move; ! 244: } ! 245: } ! 246: ! 247: ! 248: ! 249: ! 250: ! 251: /* ! 252: ============================================================================== ! 253: ! 254: PALETTE FLASHES ! 255: ! 256: ============================================================================== ! 257: */ ! 258: ! 259: ! 260: cshift_t cshift_empty = { {130,80,50}, 0 }; ! 261: cshift_t cshift_water = { {130,80,50}, 128 }; ! 262: cshift_t cshift_slime = { {0,25,5}, 150 }; ! 263: cshift_t cshift_lava = { {255,80,0}, 150 }; ! 264: ! 265: cvar_t v_gamma = {"gamma", "1", true}; ! 266: ! 267: byte gammatable[256]; // palette is sent through this ! 268: ! 269: ! 270: #ifdef GLQUAKE ! 271: byte ramps[3][256]; ! 272: float v_blend[4]; // rgba 0.0 - 1.0 ! 273: #endif // GLQUAKE ! 274: ! 275: void BuildGammaTable (float g) ! 276: { ! 277: int i, inf; ! 278: ! 279: if (g == 1.0) ! 280: { ! 281: for (i=0 ; i<256 ; i++) ! 282: gammatable[i] = i; ! 283: return; ! 284: } ! 285: ! 286: for (i=0 ; i<256 ; i++) ! 287: { ! 288: inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5; ! 289: if (inf < 0) ! 290: inf = 0; ! 291: if (inf > 255) ! 292: inf = 255; ! 293: gammatable[i] = inf; ! 294: } ! 295: } ! 296: ! 297: /* ! 298: ================= ! 299: V_CheckGamma ! 300: ================= ! 301: */ ! 302: qboolean V_CheckGamma (void) ! 303: { ! 304: static float oldgammavalue; ! 305: ! 306: if (v_gamma.value == oldgammavalue) ! 307: return false; ! 308: oldgammavalue = v_gamma.value; ! 309: ! 310: BuildGammaTable (v_gamma.value); ! 311: vid.recalc_refdef = 1; // force a surface cache flush ! 312: ! 313: return true; ! 314: } ! 315: ! 316: ! 317: ! 318: /* ! 319: =============== ! 320: V_ParseDamage ! 321: =============== ! 322: */ ! 323: void V_ParseDamage (void) ! 324: { ! 325: int armor, blood; ! 326: vec3_t from; ! 327: int i; ! 328: vec3_t forward, right, up; ! 329: float side; ! 330: float count; ! 331: ! 332: armor = MSG_ReadByte (); ! 333: blood = MSG_ReadByte (); ! 334: for (i=0 ; i<3 ; i++) ! 335: from[i] = MSG_ReadCoord (); ! 336: ! 337: count = blood*0.5 + armor*0.5; ! 338: if (count < 10) ! 339: count = 10; ! 340: ! 341: cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame ! 342: ! 343: cl.cshifts[CSHIFT_DAMAGE].percent += 3*count; ! 344: if (cl.cshifts[CSHIFT_DAMAGE].percent < 0) ! 345: cl.cshifts[CSHIFT_DAMAGE].percent = 0; ! 346: if (cl.cshifts[CSHIFT_DAMAGE].percent > 150) ! 347: cl.cshifts[CSHIFT_DAMAGE].percent = 150; ! 348: ! 349: if (armor > blood) ! 350: { ! 351: cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200; ! 352: cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100; ! 353: cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100; ! 354: } ! 355: else if (armor) ! 356: { ! 357: cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220; ! 358: cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50; ! 359: cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50; ! 360: } ! 361: else ! 362: { ! 363: cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255; ! 364: cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0; ! 365: cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0; ! 366: } ! 367: ! 368: // ! 369: // calculate view angle kicks ! 370: // ! 371: VectorSubtract (from, cl.simorg, from); ! 372: VectorNormalize (from); ! 373: ! 374: AngleVectors (cl.simangles, forward, right, up); ! 375: ! 376: side = DotProduct (from, right); ! 377: v_dmg_roll = count*side*v_kickroll.value; ! 378: ! 379: side = DotProduct (from, forward); ! 380: v_dmg_pitch = count*side*v_kickpitch.value; ! 381: ! 382: v_dmg_time = v_kicktime.value; ! 383: } ! 384: ! 385: ! 386: /* ! 387: ================== ! 388: V_cshift_f ! 389: ================== ! 390: */ ! 391: void V_cshift_f (void) ! 392: { ! 393: cshift_empty.destcolor[0] = atoi(Cmd_Argv(1)); ! 394: cshift_empty.destcolor[1] = atoi(Cmd_Argv(2)); ! 395: cshift_empty.destcolor[2] = atoi(Cmd_Argv(3)); ! 396: cshift_empty.percent = atoi(Cmd_Argv(4)); ! 397: } ! 398: ! 399: ! 400: /* ! 401: ================== ! 402: V_BonusFlash_f ! 403: ! 404: When you run over an item, the server sends this command ! 405: ================== ! 406: */ ! 407: void V_BonusFlash_f (void) ! 408: { ! 409: cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; ! 410: cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186; ! 411: cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69; ! 412: cl.cshifts[CSHIFT_BONUS].percent = 50; ! 413: } ! 414: ! 415: /* ! 416: ============= ! 417: V_SetContentsColor ! 418: ! 419: Underwater, lava, etc each has a color shift ! 420: ============= ! 421: */ ! 422: void V_SetContentsColor (int contents) ! 423: { ! 424: if (!v_contentblend.value) { ! 425: cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; ! 426: return; ! 427: } ! 428: ! 429: switch (contents) ! 430: { ! 431: case CONTENTS_EMPTY: ! 432: cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; ! 433: break; ! 434: case CONTENTS_LAVA: ! 435: cl.cshifts[CSHIFT_CONTENTS] = cshift_lava; ! 436: break; ! 437: case CONTENTS_SOLID: ! 438: case CONTENTS_SLIME: ! 439: cl.cshifts[CSHIFT_CONTENTS] = cshift_slime; ! 440: break; ! 441: default: ! 442: cl.cshifts[CSHIFT_CONTENTS] = cshift_water; ! 443: } ! 444: } ! 445: ! 446: /* ! 447: ============= ! 448: V_CalcPowerupCshift ! 449: ============= ! 450: */ ! 451: void V_CalcPowerupCshift (void) ! 452: { ! 453: if (cl.stats[STAT_ITEMS] & IT_QUAD) ! 454: { ! 455: cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; ! 456: cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; ! 457: cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; ! 458: cl.cshifts[CSHIFT_POWERUP].percent = 30; ! 459: } ! 460: else if (cl.stats[STAT_ITEMS] & IT_SUIT) ! 461: { ! 462: cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; ! 463: cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; ! 464: cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; ! 465: cl.cshifts[CSHIFT_POWERUP].percent = 20; ! 466: } ! 467: else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) ! 468: { ! 469: cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; ! 470: cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; ! 471: cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; ! 472: cl.cshifts[CSHIFT_POWERUP].percent = 100; ! 473: } ! 474: else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) ! 475: { ! 476: cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; ! 477: cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; ! 478: cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; ! 479: cl.cshifts[CSHIFT_POWERUP].percent = 30; ! 480: } ! 481: else ! 482: cl.cshifts[CSHIFT_POWERUP].percent = 0; ! 483: } ! 484: ! 485: ! 486: /* ! 487: ============= ! 488: V_CalcBlend ! 489: ============= ! 490: */ ! 491: #ifdef GLQUAKE ! 492: void V_CalcBlend (void) ! 493: { ! 494: float r, g, b, a, a2; ! 495: int j; ! 496: ! 497: r = 0; ! 498: g = 0; ! 499: b = 0; ! 500: a = 0; ! 501: ! 502: for (j=0 ; j<NUM_CSHIFTS ; j++) ! 503: { ! 504: if (!gl_cshiftpercent.value) ! 505: continue; ! 506: ! 507: a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0; ! 508: ! 509: // a2 = (cl.cshifts[j].percent/2)/255.0; ! 510: if (!a2) ! 511: continue; ! 512: a = a + a2*(1-a); ! 513: //Con_Printf ("j:%i a:%f\n", j, a); ! 514: a2 = a2/a; ! 515: r = r*(1-a2) + cl.cshifts[j].destcolor[0]*a2; ! 516: g = g*(1-a2) + cl.cshifts[j].destcolor[1]*a2; ! 517: b = b*(1-a2) + cl.cshifts[j].destcolor[2]*a2; ! 518: } ! 519: ! 520: v_blend[0] = r/255.0; ! 521: v_blend[1] = g/255.0; ! 522: v_blend[2] = b/255.0; ! 523: v_blend[3] = a; ! 524: if (v_blend[3] > 1) ! 525: v_blend[3] = 1; ! 526: if (v_blend[3] < 0) ! 527: v_blend[3] = 0; ! 528: } ! 529: #endif ! 530: ! 531: /* ! 532: ============= ! 533: V_UpdatePalette ! 534: ============= ! 535: */ ! 536: #ifdef GLQUAKE ! 537: void V_UpdatePalette (void) ! 538: { ! 539: int i, j; ! 540: qboolean new; ! 541: byte *basepal, *newpal; ! 542: byte pal[768]; ! 543: float r,g,b,a; ! 544: int ir, ig, ib; ! 545: qboolean force; ! 546: ! 547: V_CalcPowerupCshift (); ! 548: ! 549: new = false; ! 550: ! 551: for (i=0 ; i<NUM_CSHIFTS ; i++) ! 552: { ! 553: if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent) ! 554: { ! 555: new = true; ! 556: cl.prev_cshifts[i].percent = cl.cshifts[i].percent; ! 557: } ! 558: for (j=0 ; j<3 ; j++) ! 559: if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j]) ! 560: { ! 561: new = true; ! 562: cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j]; ! 563: } ! 564: } ! 565: ! 566: // drop the damage value ! 567: cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150; ! 568: if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0) ! 569: cl.cshifts[CSHIFT_DAMAGE].percent = 0; ! 570: ! 571: // drop the bonus value ! 572: cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100; ! 573: if (cl.cshifts[CSHIFT_BONUS].percent <= 0) ! 574: cl.cshifts[CSHIFT_BONUS].percent = 0; ! 575: ! 576: force = V_CheckGamma (); ! 577: if (!new && !force) ! 578: return; ! 579: ! 580: V_CalcBlend (); ! 581: ! 582: //Con_Printf("b: %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]); ! 583: ! 584: a = v_blend[3]; ! 585: r = 255*v_blend[0]*a; ! 586: g = 255*v_blend[1]*a; ! 587: b = 255*v_blend[2]*a; ! 588: ! 589: a = 1-a; ! 590: for (i=0 ; i<256 ; i++) ! 591: { ! 592: ir = i*a + r; ! 593: ig = i*a + g; ! 594: ib = i*a + b; ! 595: if (ir > 255) ! 596: ir = 255; ! 597: if (ig > 255) ! 598: ig = 255; ! 599: if (ib > 255) ! 600: ib = 255; ! 601: ! 602: ramps[0][i] = gammatable[ir]; ! 603: ramps[1][i] = gammatable[ig]; ! 604: ramps[2][i] = gammatable[ib]; ! 605: } ! 606: ! 607: basepal = host_basepal; ! 608: newpal = pal; ! 609: ! 610: for (i=0 ; i<256 ; i++) ! 611: { ! 612: ir = basepal[0]; ! 613: ig = basepal[1]; ! 614: ib = basepal[2]; ! 615: basepal += 3; ! 616: ! 617: newpal[0] = ramps[0][ir]; ! 618: newpal[1] = ramps[1][ig]; ! 619: newpal[2] = ramps[2][ib]; ! 620: newpal += 3; ! 621: } ! 622: ! 623: VID_ShiftPalette (pal); ! 624: } ! 625: #else // !GLQUAKE ! 626: /* ! 627: ============= ! 628: V_UpdatePalette ! 629: ============= ! 630: */ ! 631: void V_UpdatePalette (void) ! 632: { ! 633: int i, j; ! 634: qboolean new; ! 635: byte *basepal, *newpal; ! 636: byte pal[768]; ! 637: int r,g,b; ! 638: qboolean force; ! 639: ! 640: V_CalcPowerupCshift (); ! 641: ! 642: new = false; ! 643: ! 644: for (i=0 ; i<NUM_CSHIFTS ; i++) ! 645: { ! 646: if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent) ! 647: { ! 648: new = true; ! 649: cl.prev_cshifts[i].percent = cl.cshifts[i].percent; ! 650: } ! 651: for (j=0 ; j<3 ; j++) ! 652: if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j]) ! 653: { ! 654: new = true; ! 655: cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j]; ! 656: } ! 657: } ! 658: ! 659: // drop the damage value ! 660: cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150; ! 661: if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0) ! 662: cl.cshifts[CSHIFT_DAMAGE].percent = 0; ! 663: ! 664: // drop the bonus value ! 665: cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100; ! 666: if (cl.cshifts[CSHIFT_BONUS].percent <= 0) ! 667: cl.cshifts[CSHIFT_BONUS].percent = 0; ! 668: ! 669: force = V_CheckGamma (); ! 670: if (!new && !force) ! 671: return; ! 672: ! 673: basepal = host_basepal; ! 674: newpal = pal; ! 675: ! 676: for (i=0 ; i<256 ; i++) ! 677: { ! 678: r = basepal[0]; ! 679: g = basepal[1]; ! 680: b = basepal[2]; ! 681: basepal += 3; ! 682: ! 683: for (j=0 ; j<NUM_CSHIFTS ; j++) ! 684: { ! 685: r += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[0]-r))>>8; ! 686: g += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[1]-g))>>8; ! 687: b += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[2]-b))>>8; ! 688: } ! 689: ! 690: newpal[0] = gammatable[r]; ! 691: newpal[1] = gammatable[g]; ! 692: newpal[2] = gammatable[b]; ! 693: newpal += 3; ! 694: } ! 695: ! 696: VID_ShiftPalette (pal); ! 697: } ! 698: ! 699: #endif // !GLQUAKE ! 700: ! 701: /* ! 702: ============================================================================== ! 703: ! 704: VIEW RENDERING ! 705: ! 706: ============================================================================== ! 707: */ ! 708: ! 709: float angledelta (float a) ! 710: { ! 711: a = anglemod(a); ! 712: if (a > 180) ! 713: a -= 360; ! 714: return a; ! 715: } ! 716: ! 717: /* ! 718: ================== ! 719: CalcGunAngle ! 720: ================== ! 721: */ ! 722: void CalcGunAngle (void) ! 723: { ! 724: float yaw, pitch, move; ! 725: static float oldyaw = 0; ! 726: static float oldpitch = 0; ! 727: ! 728: yaw = r_refdef.viewangles[YAW]; ! 729: pitch = -r_refdef.viewangles[PITCH]; ! 730: ! 731: yaw = angledelta(yaw - r_refdef.viewangles[YAW]) * 0.4; ! 732: if (yaw > 10) ! 733: yaw = 10; ! 734: if (yaw < -10) ! 735: yaw = -10; ! 736: pitch = angledelta(-pitch - r_refdef.viewangles[PITCH]) * 0.4; ! 737: if (pitch > 10) ! 738: pitch = 10; ! 739: if (pitch < -10) ! 740: pitch = -10; ! 741: move = host_frametime*20; ! 742: if (yaw > oldyaw) ! 743: { ! 744: if (oldyaw + move < yaw) ! 745: yaw = oldyaw + move; ! 746: } ! 747: else ! 748: { ! 749: if (oldyaw - move > yaw) ! 750: yaw = oldyaw - move; ! 751: } ! 752: ! 753: if (pitch > oldpitch) ! 754: { ! 755: if (oldpitch + move < pitch) ! 756: pitch = oldpitch + move; ! 757: } ! 758: else ! 759: { ! 760: if (oldpitch - move > pitch) ! 761: pitch = oldpitch - move; ! 762: } ! 763: ! 764: oldyaw = yaw; ! 765: oldpitch = pitch; ! 766: ! 767: cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw; ! 768: cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch); ! 769: } ! 770: ! 771: /* ! 772: ============== ! 773: V_BoundOffsets ! 774: ============== ! 775: */ ! 776: void V_BoundOffsets (void) ! 777: { ! 778: // absolutely bound refresh reletive to entity clipping hull ! 779: // so the view can never be inside a solid wall ! 780: ! 781: if (r_refdef.vieworg[0] < cl.simorg[0] - 14) ! 782: r_refdef.vieworg[0] = cl.simorg[0] - 14; ! 783: else if (r_refdef.vieworg[0] > cl.simorg[0] + 14) ! 784: r_refdef.vieworg[0] = cl.simorg[0] + 14; ! 785: if (r_refdef.vieworg[1] < cl.simorg[1] - 14) ! 786: r_refdef.vieworg[1] = cl.simorg[1] - 14; ! 787: else if (r_refdef.vieworg[1] > cl.simorg[1] + 14) ! 788: r_refdef.vieworg[1] = cl.simorg[1] + 14; ! 789: if (r_refdef.vieworg[2] < cl.simorg[2] - 22) ! 790: r_refdef.vieworg[2] = cl.simorg[2] - 22; ! 791: else if (r_refdef.vieworg[2] > cl.simorg[2] + 30) ! 792: r_refdef.vieworg[2] = cl.simorg[2] + 30; ! 793: } ! 794: ! 795: /* ! 796: ============== ! 797: V_AddIdle ! 798: ! 799: Idle swaying ! 800: ============== ! 801: */ ! 802: void V_AddIdle (void) ! 803: { ! 804: r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; ! 805: r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; ! 806: r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; ! 807: ! 808: cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; ! 809: cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; ! 810: cl.viewent.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; ! 811: } ! 812: ! 813: ! 814: /* ! 815: ============== ! 816: V_CalcViewRoll ! 817: ! 818: Roll is induced by movement and damage ! 819: ============== ! 820: */ ! 821: void V_CalcViewRoll (void) ! 822: { ! 823: float side; ! 824: ! 825: side = V_CalcRoll (cl.simangles, cl.simvel); ! 826: r_refdef.viewangles[ROLL] += side; ! 827: ! 828: if (v_dmg_time > 0) ! 829: { ! 830: r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll; ! 831: r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch; ! 832: v_dmg_time -= host_frametime; ! 833: } ! 834: ! 835: } ! 836: ! 837: ! 838: /* ! 839: ================== ! 840: V_CalcIntermissionRefdef ! 841: ! 842: ================== ! 843: */ ! 844: void V_CalcIntermissionRefdef (void) ! 845: { ! 846: entity_t *view; ! 847: float old; ! 848: ! 849: // view is the weapon model ! 850: view = &cl.viewent; ! 851: ! 852: VectorCopy (cl.simorg, r_refdef.vieworg); ! 853: VectorCopy (cl.simangles, r_refdef.viewangles); ! 854: view->model = NULL; ! 855: ! 856: // allways idle in intermission ! 857: old = v_idlescale.value; ! 858: v_idlescale.value = 1; ! 859: V_AddIdle (); ! 860: v_idlescale.value = old; ! 861: } ! 862: ! 863: /* ! 864: ================== ! 865: V_CalcRefdef ! 866: ! 867: ================== ! 868: */ ! 869: void V_CalcRefdef (void) ! 870: { ! 871: entity_t *view; ! 872: int i; ! 873: vec3_t forward, right, up; ! 874: float bob; ! 875: static float oldz = 0; ! 876: ! 877: V_DriftPitch (); ! 878: ! 879: // view is the weapon model (only visible from inside body) ! 880: view = &cl.viewent; ! 881: ! 882: bob = V_CalcBob (); ! 883: ! 884: // refresh position from simulated origin ! 885: VectorCopy (cl.simorg, r_refdef.vieworg); ! 886: ! 887: r_refdef.vieworg[2] += bob; ! 888: ! 889: // never let it sit exactly on a node line, because a water plane can ! 890: // dissapear when viewed with the eye exactly on it. ! 891: // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis ! 892: r_refdef.vieworg[0] += 1.0/16; ! 893: r_refdef.vieworg[1] += 1.0/16; ! 894: r_refdef.vieworg[2] += 1.0/16; ! 895: ! 896: VectorCopy (cl.simangles, r_refdef.viewangles); ! 897: V_CalcViewRoll (); ! 898: V_AddIdle (); ! 899: ! 900: if (view_message->flags & PF_GIB) ! 901: r_refdef.vieworg[2] += 8; // gib view height ! 902: else if (view_message->flags & PF_DEAD) ! 903: r_refdef.vieworg[2] -= 16; // corpse view height ! 904: else ! 905: r_refdef.vieworg[2] += 22; // view height ! 906: ! 907: if (view_message->flags & PF_DEAD) // PF_GIB will also set PF_DEAD ! 908: r_refdef.viewangles[ROLL] = 80; // dead view angle ! 909: ! 910: ! 911: // offsets ! 912: AngleVectors (cl.simangles, forward, right, up); ! 913: ! 914: // set up gun position ! 915: VectorCopy (cl.simangles, view->angles); ! 916: ! 917: CalcGunAngle (); ! 918: ! 919: VectorCopy (cl.simorg, view->origin); ! 920: view->origin[2] += 22; ! 921: ! 922: for (i=0 ; i<3 ; i++) ! 923: { ! 924: view->origin[i] += forward[i]*bob*0.4; ! 925: // view->origin[i] += right[i]*bob*0.4; ! 926: // view->origin[i] += up[i]*bob*0.8; ! 927: } ! 928: view->origin[2] += bob; ! 929: ! 930: // fudge position around to keep amount of weapon visible ! 931: // roughly equal with different FOV ! 932: if (scr_viewsize.value == 110) ! 933: view->origin[2] += 1; ! 934: else if (scr_viewsize.value == 100) ! 935: view->origin[2] += 2; ! 936: else if (scr_viewsize.value == 90) ! 937: view->origin[2] += 1; ! 938: else if (scr_viewsize.value == 80) ! 939: view->origin[2] += 0.5; ! 940: ! 941: if (view_message->flags & (PF_GIB|PF_DEAD) ) ! 942: view->model = NULL; ! 943: else ! 944: view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; ! 945: view->frame = view_message->weaponframe; ! 946: view->colormap = vid.colormap; ! 947: ! 948: // set up the refresh position ! 949: r_refdef.viewangles[PITCH] += cl.punchangle; ! 950: ! 951: // smooth out stair step ups ! 952: if ( (view_message->onground != -1) && (cl.simorg[2] - oldz > 0) ) ! 953: { ! 954: float steptime; ! 955: ! 956: steptime = host_frametime; ! 957: ! 958: oldz += steptime * 80; ! 959: if (oldz > cl.simorg[2]) ! 960: oldz = cl.simorg[2]; ! 961: if (cl.simorg[2] - oldz > 12) ! 962: oldz = cl.simorg[2] - 12; ! 963: r_refdef.vieworg[2] += oldz - cl.simorg[2]; ! 964: view->origin[2] += oldz - cl.simorg[2]; ! 965: } ! 966: else ! 967: oldz = cl.simorg[2]; ! 968: } ! 969: ! 970: /* ! 971: ============= ! 972: DropPunchAngle ! 973: ============= ! 974: */ ! 975: void DropPunchAngle (void) ! 976: { ! 977: cl.punchangle -= 10*host_frametime; ! 978: if (cl.punchangle < 0) ! 979: cl.punchangle = 0; ! 980: } ! 981: ! 982: /* ! 983: ================== ! 984: V_RenderView ! 985: ! 986: The player's clipping box goes from (-16 -16 -24) to (16 16 32) from ! 987: the entity origin, so any view position inside that will be valid ! 988: ================== ! 989: */ ! 990: extern vrect_t scr_vrect; ! 991: ! 992: void V_RenderView (void) ! 993: { ! 994: // if (cl.simangles[ROLL]) ! 995: // Sys_Error ("cl.simangles[ROLL]"); // DEBUG ! 996: cl.simangles[ROLL] = 0; // FIXME @@@ ! 997: ! 998: if (cls.state != ca_active) ! 999: return; ! 1000: ! 1001: view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; ! 1002: view_message = &view_frame->playerstate[cl.playernum]; ! 1003: ! 1004: DropPunchAngle (); ! 1005: if (cl.intermission) ! 1006: { // intermission / finale rendering ! 1007: V_CalcIntermissionRefdef (); ! 1008: } ! 1009: else ! 1010: { ! 1011: V_CalcRefdef (); ! 1012: } ! 1013: ! 1014: R_PushDlights (); ! 1015: R_RenderView (); ! 1016: ! 1017: #ifndef GLQUAKE ! 1018: if (crosshair.value) ! 1019: Draw_Crosshair(); ! 1020: #endif ! 1021: ! 1022: } ! 1023: ! 1024: //============================================================================ ! 1025: ! 1026: /* ! 1027: ============= ! 1028: V_Init ! 1029: ============= ! 1030: */ ! 1031: void V_Init (void) ! 1032: { ! 1033: Cmd_AddCommand ("v_cshift", V_cshift_f); ! 1034: Cmd_AddCommand ("bf", V_BonusFlash_f); ! 1035: Cmd_AddCommand ("centerview", V_StartPitchDrift); ! 1036: ! 1037: Cvar_RegisterVariable (&v_centermove); ! 1038: Cvar_RegisterVariable (&v_centerspeed); ! 1039: ! 1040: Cvar_RegisterVariable (&v_iyaw_cycle); ! 1041: Cvar_RegisterVariable (&v_iroll_cycle); ! 1042: Cvar_RegisterVariable (&v_ipitch_cycle); ! 1043: Cvar_RegisterVariable (&v_iyaw_level); ! 1044: Cvar_RegisterVariable (&v_iroll_level); ! 1045: Cvar_RegisterVariable (&v_ipitch_level); ! 1046: ! 1047: Cvar_RegisterVariable (&v_contentblend); ! 1048: ! 1049: Cvar_RegisterVariable (&v_idlescale); ! 1050: Cvar_RegisterVariable (&crosshaircolor); ! 1051: Cvar_RegisterVariable (&crosshair); ! 1052: Cvar_RegisterVariable (&cl_crossx); ! 1053: Cvar_RegisterVariable (&cl_crossy); ! 1054: #ifdef GLQUAKE ! 1055: Cvar_RegisterVariable (&gl_cshiftpercent); ! 1056: #endif ! 1057: ! 1058: Cvar_RegisterVariable (&cl_rollspeed); ! 1059: Cvar_RegisterVariable (&cl_rollangle); ! 1060: Cvar_RegisterVariable (&cl_bob); ! 1061: Cvar_RegisterVariable (&cl_bobcycle); ! 1062: Cvar_RegisterVariable (&cl_bobup); ! 1063: ! 1064: Cvar_RegisterVariable (&v_kicktime); ! 1065: Cvar_RegisterVariable (&v_kickroll); ! 1066: Cvar_RegisterVariable (&v_kickpitch); ! 1067: ! 1068: BuildGammaTable (1.0); // no gamma yet ! 1069: Cvar_RegisterVariable (&v_gamma); ! 1070: } ! 1071: ! 1072:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.