|
|
1.1 ! root 1: ! 2: #include "qcommon.h" ! 3: ! 4: #define STEPSIZE 18 ! 5: ! 6: // all of the locals will be zeroed before each ! 7: // pmove, just to make damn sure we don't have ! 8: // any differences when running on client or server ! 9: ! 10: typedef struct ! 11: { ! 12: vec3_t origin; // full float precision ! 13: vec3_t velocity; // full float precision ! 14: ! 15: vec3_t forward, right, up; ! 16: float frametime; ! 17: ! 18: ! 19: csurface_t *groundsurface; ! 20: cplane_t groundplane; ! 21: int groundcontents; ! 22: ! 23: vec3_t previous_origin; ! 24: qboolean ladder; ! 25: } pml_t; ! 26: ! 27: pmove_t *pm; ! 28: pml_t pml; ! 29: ! 30: // movement parameters ! 31: float pm_stopspeed = 100; ! 32: float pm_maxspeed = 300; ! 33: float pm_duckspeed = 100; ! 34: float pm_accelerate = 10; ! 35: float pm_airaccelerate = 1; ! 36: float pm_wateraccelerate = 10; ! 37: float pm_friction = 6; ! 38: float pm_waterfriction = 1; ! 39: float pm_waterspeed = 400; ! 40: /* ! 41: walking up a step should kill some velocity ! 42: */ ! 43: /* ! 44: ================== ! 45: PM_ClipVelocity ! 46: Slide off of the impacting object ! 47: returns the blocked flags (1 = floor, 2 = step / wall) ! 48: ================== ! 49: */ ! 50: #define STOP_EPSILON 0.1 ! 51: void PM_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) ! 52: { ! 53: float backoff; ! 54: float change; ! 55: int i; ! 56: ! 57: backoff = DotProduct (in, normal) * overbounce; ! 58: for (i=0 ; i<3 ; i++) ! 59: { ! 60: change = normal[i]*backoff; ! 61: out[i] = in[i] - change; ! 62: if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) ! 63: out[i] = 0; ! 64: } ! 65: } ! 66: /* ! 67: ================== ! 68: PM_StepSlideMove ! 69: Each intersection will try to step over the obstruction instead of ! 70: sliding along it. ! 71: Returns a new origin, velocity, and contact entity ! 72: Does not modify any world state? ! 73: ================== ! 74: */ ! 75: #define MIN_STEP_NORMAL 0.7 // can't step up onto very steep slopes ! 76: #define MAX_CLIP_PLANES 5 ! 77: void PM_StepSlideMove_ (void) ! 78: { ! 79: int bumpcount, numbumps; ! 80: vec3_t dir; ! 81: float d, rub; ! 82: int numplanes; ! 83: vec3_t planes[MAX_CLIP_PLANES]; ! 84: vec3_t primal_velocity; ! 85: int i; ! 86: trace_t trace; ! 87: vec3_t end; ! 88: float time_left; ! 89: ! 90: numbumps = 4; ! 91: ! 92: VectorCopy (pml.velocity, primal_velocity); ! 93: numplanes = 0; ! 94: ! 95: time_left = pml.frametime; ! 96: for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) ! 97: { ! 98: for (i=0 ; i<3 ; i++) ! 99: end[i] = pml.origin[i] + time_left * pml.velocity[i]; ! 100: trace = pm->trace (pml.origin, pm->mins, pm->maxs, end); ! 101: if (trace.allsolid) ! 102: { // entity is trapped in another solid ! 103: pml.velocity[2] = 0; // don't build up falling damage ! 104: return; ! 105: } ! 106: if (trace.fraction > 0) ! 107: { // actually covered some distance ! 108: VectorCopy (trace.endpos, pml.origin); ! 109: numplanes = 0; ! 110: } ! 111: if (trace.fraction == 1) ! 112: break; // moved the entire distance ! 113: // save entity for contact ! 114: if (pm->numtouch < MAXTOUCH && trace.ent) ! 115: { ! 116: pm->touchents[pm->numtouch] = trace.ent; ! 117: pm->numtouch++; ! 118: } ! 119: ! 120: time_left -= time_left * trace.fraction; ! 121: // slide along this plane ! 122: if (numplanes >= MAX_CLIP_PLANES) ! 123: { // this shouldn't really happen ! 124: VectorCopy (vec3_origin, pml.velocity); ! 125: break; ! 126: } ! 127: VectorCopy (trace.plane.normal, planes[numplanes]); ! 128: numplanes++; ! 129: // ! 130: // modify velocity so it parallels all of the clip planes ! 131: // ! 132: if (numplanes == 1) ! 133: { // go along this plane ! 134: VectorCopy (pml.velocity, dir); ! 135: VectorNormalize (dir); ! 136: rub = 1.0 + 0.5 * DotProduct (dir, planes[0]); ! 137: ! 138: // slide along the plane ! 139: PM_ClipVelocity (pml.velocity, planes[0], pml.velocity, 1.01); ! 140: // rub some extra speed off on xy axis ! 141: // not on Z, or you can scrub down walls ! 142: pml.velocity[0] *= rub; ! 143: pml.velocity[1] *= rub; ! 144: pml.velocity[2] *= rub; ! 145: } ! 146: else if (numplanes == 2) ! 147: { // go along the crease ! 148: VectorCopy (pml.velocity, dir); ! 149: VectorNormalize (dir); ! 150: rub = 1.0 + 0.5 * DotProduct (dir, planes[0]); ! 151: ! 152: // slide along the plane ! 153: CrossProduct (planes[0], planes[1], dir); ! 154: d = DotProduct (dir, pml.velocity); ! 155: VectorScale (dir, d, pml.velocity); ! 156: // rub some extra speed off ! 157: VectorScale (pml.velocity, rub, pml.velocity); ! 158: } ! 159: else ! 160: { ! 161: // Con_Printf ("clip velocity, numplanes == %i\n",numplanes); ! 162: VectorCopy (vec3_origin, pml.velocity); ! 163: break; ! 164: } ! 165: // ! 166: // if velocity is against the original velocity, stop dead ! 167: // to avoid tiny occilations in sloping corners ! 168: // ! 169: if (DotProduct (pml.velocity, primal_velocity) <= 0) ! 170: { ! 171: VectorCopy (vec3_origin, pml.velocity); ! 172: break; ! 173: } ! 174: } ! 175: if (pm->s.pm_time) ! 176: { ! 177: VectorCopy (primal_velocity, pml.velocity); ! 178: } ! 179: } ! 180: ! 181: /* ! 182: ================== ! 183: PM_StepSlideMove ! 184: ! 185: ================== ! 186: */ ! 187: void PM_StepSlideMove (void) ! 188: { ! 189: vec3_t start_o, start_v; ! 190: vec3_t down_o, down_v; ! 191: trace_t trace; ! 192: float down_dist, up_dist; ! 193: vec3_t delta; ! 194: vec3_t up, down; ! 195: ! 196: VectorCopy (pml.origin, start_o); ! 197: VectorCopy (pml.velocity, start_v); ! 198: ! 199: PM_StepSlideMove_ (); ! 200: ! 201: VectorCopy (pml.origin, down_o); ! 202: VectorCopy (pml.velocity, down_v); ! 203: ! 204: VectorCopy (start_o, up); ! 205: up[2] += STEPSIZE; ! 206: ! 207: trace = pm->trace (up, pm->mins, pm->maxs, up); ! 208: if (trace.allsolid) ! 209: return; // can't step up ! 210: ! 211: // try sliding above ! 212: VectorCopy (up, pml.origin); ! 213: VectorCopy (start_v, pml.velocity); ! 214: ! 215: PM_StepSlideMove_ (); ! 216: ! 217: // push down the final amount ! 218: VectorCopy (pml.origin, down); ! 219: down[2] -= STEPSIZE; ! 220: trace = pm->trace (pml.origin, pm->mins, pm->maxs, down); ! 221: if (!trace.allsolid) ! 222: { ! 223: VectorCopy (trace.endpos, pml.origin); ! 224: } ! 225: ! 226: VectorSubtract (pml.origin, up, delta); ! 227: up_dist = DotProduct (delta, start_v); ! 228: ! 229: VectorSubtract (down_o, start_o, delta); ! 230: down_dist = DotProduct (delta, start_v); ! 231: ! 232: if (down_dist > up_dist || trace.plane.normal[2] < MIN_STEP_NORMAL) ! 233: { ! 234: VectorCopy (down_o, pml.origin); ! 235: VectorCopy (down_v, pml.velocity); ! 236: return; ! 237: } ! 238: ! 239: } ! 240: ! 241: /* ! 242: ================== ! 243: PM_Friction ! 244: Handles both ground friction and water friction ! 245: ================== ! 246: */ ! 247: void PM_Friction (void) ! 248: { ! 249: float *vel; ! 250: float speed, newspeed, control; ! 251: float friction; ! 252: float drop; ! 253: ! 254: vel = pml.velocity; ! 255: ! 256: speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1] + vel[2]*vel[2]); ! 257: if (speed < 1) ! 258: { ! 259: vel[0] = 0; ! 260: vel[1] = 0; ! 261: return; ! 262: } ! 263: drop = 0; ! 264: // apply ground friction ! 265: if ((pm->groundentity && pml.groundsurface && !(pml.groundsurface->flags & SURF_SLICK) ) || (pml.ladder) ) ! 266: { ! 267: friction = pm_friction; ! 268: control = speed < pm_stopspeed ? pm_stopspeed : speed; ! 269: drop += control*friction*pml.frametime; ! 270: } ! 271: // apply water friction ! 272: if (pm->waterlevel && !pml.ladder) ! 273: drop += speed*pm_waterfriction*pm->waterlevel*pml.frametime; ! 274: // scale the velocity ! 275: newspeed = speed - drop; ! 276: if (newspeed < 0) ! 277: { ! 278: newspeed = 0; ! 279: } ! 280: newspeed /= speed; ! 281: vel[0] = vel[0] * newspeed; ! 282: vel[1] = vel[1] * newspeed; ! 283: vel[2] = vel[2] * newspeed; ! 284: } ! 285: /* ! 286: ============== ! 287: PM_Accelerate ! 288: Handles user intended acceleration ! 289: ============== ! 290: */ ! 291: void PM_Accelerate (vec3_t wishdir, float wishspeed, float accel) ! 292: { ! 293: int i; ! 294: float addspeed, accelspeed, currentspeed; ! 295: ! 296: currentspeed = DotProduct (pml.velocity, wishdir); ! 297: addspeed = wishspeed - currentspeed; ! 298: if (addspeed <= 0) ! 299: return; ! 300: accelspeed = accel*pml.frametime*wishspeed; ! 301: if (accelspeed > addspeed) ! 302: accelspeed = addspeed; ! 303: ! 304: for (i=0 ; i<3 ; i++) ! 305: pml.velocity[i] += accelspeed*wishdir[i]; ! 306: } ! 307: /* ! 308: ============= ! 309: PM_AddCurrents ! 310: ============= ! 311: */ ! 312: void PM_AddCurrents (vec3_t wishvel) ! 313: { ! 314: vec3_t v; ! 315: float s; ! 316: // ! 317: // account for ladders ! 318: // ! 319: if (pml.ladder && fabs(pml.velocity[2]) <= 200) ! 320: { ! 321: if ((pm->viewangles[PITCH] <= -15) && (pm->cmd.forwardmove > 0)) ! 322: wishvel[2] = 200; ! 323: else if ((pm->viewangles[PITCH] >= 15) && (pm->cmd.forwardmove > 0)) ! 324: wishvel[2] = -200; ! 325: else if (pm->cmd.upmove > 0) ! 326: wishvel[2] = 200; ! 327: else if (pm->cmd.upmove < 0) ! 328: wishvel[2] = -200; ! 329: else ! 330: wishvel[2] = 0; ! 331: // limit horizontal speed when on a ladder ! 332: if (wishvel[0] < -25) ! 333: wishvel[0] = -25; ! 334: else if (wishvel[0] > 25) ! 335: wishvel[0] = 25; ! 336: if (wishvel[1] < -25) ! 337: wishvel[1] = -25; ! 338: else if (wishvel[1] > 25) ! 339: wishvel[1] = 25; ! 340: } ! 341: // ! 342: // add water currents ! 343: // ! 344: if (pm->watertype & MASK_CURRENT) ! 345: { ! 346: VectorClear (v); ! 347: if (pm->watertype & CONTENTS_CURRENT_0) ! 348: v[0] += 1; ! 349: if (pm->watertype & CONTENTS_CURRENT_90) ! 350: v[1] += 1; ! 351: if (pm->watertype & CONTENTS_CURRENT_180) ! 352: v[0] -= 1; ! 353: if (pm->watertype & CONTENTS_CURRENT_270) ! 354: v[1] -= 1; ! 355: if (pm->watertype & CONTENTS_CURRENT_UP) ! 356: v[2] += 1; ! 357: if (pm->watertype & CONTENTS_CURRENT_DOWN) ! 358: v[2] -= 1; ! 359: s = pm_waterspeed; ! 360: if ((pm->waterlevel == 1) && (pm->groundentity)) ! 361: s /= 2; ! 362: VectorMA (wishvel, s, v, wishvel); ! 363: } ! 364: // ! 365: // add conveyor belt velocities ! 366: // ! 367: if (pm->groundentity) ! 368: { ! 369: VectorClear (v); ! 370: if (pml.groundcontents & CONTENTS_CURRENT_0) ! 371: v[0] += 1; ! 372: if (pml.groundcontents & CONTENTS_CURRENT_90) ! 373: v[1] += 1; ! 374: if (pml.groundcontents & CONTENTS_CURRENT_180) ! 375: v[0] -= 1; ! 376: if (pml.groundcontents & CONTENTS_CURRENT_270) ! 377: v[1] -= 1; ! 378: if (pml.groundcontents & CONTENTS_CURRENT_UP) ! 379: v[2] += 1; ! 380: if (pml.groundcontents & CONTENTS_CURRENT_DOWN) ! 381: v[2] -= 1; ! 382: ! 383: VectorMA (wishvel, 100 /* pm->groundentity->speed */, v, wishvel); ! 384: } ! 385: } ! 386: /* ! 387: =================== ! 388: PM_WaterMove ! 389: =================== ! 390: */ ! 391: void PM_WaterMove (void) ! 392: { ! 393: int i; ! 394: vec3_t wishvel; ! 395: float wishspeed; ! 396: vec3_t wishdir; ! 397: // ! 398: // user intentions ! 399: // ! 400: for (i=0 ; i<3 ; i++) ! 401: wishvel[i] = pml.forward[i]*pm->cmd.forwardmove + pml.right[i]*pm->cmd.sidemove; ! 402: if (!pm->cmd.forwardmove && !pm->cmd.sidemove && !pm->cmd.upmove) ! 403: wishvel[2] -= 60; // drift towards bottom ! 404: else ! 405: wishvel[2] += pm->cmd.upmove; ! 406: PM_AddCurrents (wishvel); ! 407: VectorCopy (wishvel, wishdir); ! 408: wishspeed = VectorNormalize(wishdir); ! 409: if (wishspeed > pm_maxspeed) ! 410: { ! 411: VectorScale (wishvel, pm_maxspeed/wishspeed, wishvel); ! 412: wishspeed = pm_maxspeed; ! 413: } ! 414: wishspeed *= 0.5; ! 415: PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate); ! 416: PM_StepSlideMove (); ! 417: } ! 418: /* ! 419: =================== ! 420: PM_AirMove ! 421: =================== ! 422: */ ! 423: void PM_AirMove (void) ! 424: { ! 425: int i; ! 426: vec3_t wishvel; ! 427: float fmove, smove; ! 428: vec3_t wishdir; ! 429: float wishspeed; ! 430: float maxspeed; ! 431: fmove = pm->cmd.forwardmove; ! 432: smove = pm->cmd.sidemove; ! 433: ! 434: pml.forward[2] = 0; ! 435: pml.right[2] = 0; ! 436: VectorNormalize (pml.forward); ! 437: VectorNormalize (pml.right); ! 438: for (i=0 ; i<2 ; i++) ! 439: wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove; ! 440: wishvel[2] = 0; ! 441: PM_AddCurrents (wishvel); ! 442: VectorCopy (wishvel, wishdir); ! 443: wishspeed = VectorNormalize(wishdir); ! 444: // ! 445: // clamp to server defined max speed ! 446: // ! 447: maxspeed = (pm->s.pm_flags & PMF_DUCKED) ? pm_duckspeed : pm_maxspeed; ! 448: if (wishspeed > maxspeed) ! 449: { ! 450: VectorScale (wishvel, maxspeed/wishspeed, wishvel); ! 451: wishspeed = maxspeed; ! 452: } ! 453: ! 454: if ( pml.ladder ) ! 455: { ! 456: PM_Accelerate (wishdir, wishspeed, pm_accelerate); ! 457: if (!wishvel[2]) ! 458: { ! 459: if (pml.velocity[2] > 0) ! 460: { ! 461: pml.velocity[2] -= pm->s.gravity * pml.frametime; ! 462: if (pml.velocity[2] < 0) ! 463: pml.velocity[2] = 0; ! 464: } ! 465: else ! 466: { ! 467: pml.velocity[2] += pm->s.gravity * pml.frametime; ! 468: if (pml.velocity[2] > 0) ! 469: pml.velocity[2] = 0; ! 470: } ! 471: } ! 472: PM_StepSlideMove (); ! 473: } ! 474: else if ( pm->groundentity ) ! 475: { // walking on ground ! 476: PM_Accelerate (wishdir, wishspeed, pm_accelerate); ! 477: pml.velocity[2] = 0; ! 478: if (!pml.velocity[0] && !pml.velocity[1]) ! 479: return; ! 480: PM_StepSlideMove (); ! 481: } ! 482: else ! 483: { // not on ground, so little effect on velocity ! 484: PM_Accelerate (wishdir, wishspeed, pm_airaccelerate); ! 485: // add gravity ! 486: pml.velocity[2] -= pm->s.gravity * pml.frametime; ! 487: PM_StepSlideMove (); ! 488: } ! 489: } ! 490: /* ! 491: ============= ! 492: PM_CatagorizePosition ! 493: ============= ! 494: */ ! 495: void PM_CatagorizePosition (void) ! 496: { ! 497: vec3_t point; ! 498: int cont; ! 499: trace_t trace; ! 500: int sample1; ! 501: int sample2; ! 502: // if the player hull point one unit down is solid, the player ! 503: // is on ground ! 504: // see if standing on something solid ! 505: point[0] = pml.origin[0]; ! 506: point[1] = pml.origin[1]; ! 507: point[2] = pml.origin[2] - 0.25; ! 508: if (pml.velocity[2] > 100) ! 509: { ! 510: pm->s.pm_flags &= ~PMF_ON_GROUND; ! 511: pm->groundentity = NULL; ! 512: } ! 513: else ! 514: { ! 515: trace = pm->trace (pml.origin, pm->mins, pm->maxs, point); ! 516: pml.groundplane = trace.plane; ! 517: pml.groundsurface = trace.surface; ! 518: pml.groundcontents = trace.contents; ! 519: ! 520: if (!trace.ent || (trace.plane.normal[2] < 0.7 && !trace.startsolid) ) ! 521: { ! 522: pm->groundentity = NULL; ! 523: pm->s.pm_flags &= ~PMF_ON_GROUND; ! 524: } ! 525: else ! 526: { ! 527: pm->groundentity = trace.ent; ! 528: ! 529: // hitting solid ground will end a waterjump ! 530: if (pm->s.pm_flags & PMF_TIME_WATERJUMP) ! 531: { ! 532: pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT); ! 533: pm->s.pm_time = 0; ! 534: } ! 535: ! 536: if (! (pm->s.pm_flags & PMF_ON_GROUND) ) ! 537: { // just hit the ground ! 538: pm->s.pm_flags |= PMF_ON_GROUND; ! 539: // don't do landing time if we were just going down a slope ! 540: if (pml.velocity[2] < -200) ! 541: { ! 542: pm->s.pm_flags |= PMF_TIME_LAND; ! 543: // don't allow another jump for a little while ! 544: if (pml.velocity[2] < -400) ! 545: pm->s.pm_time = 25; ! 546: else ! 547: pm->s.pm_time = 18; ! 548: } ! 549: } ! 550: } ! 551: if (trace.fraction < 1.0 && trace.ent && pml.velocity[2] < 0) ! 552: pml.velocity[2] = 0; ! 553: ! 554: if (pm->numtouch < MAXTOUCH && trace.ent) ! 555: { ! 556: pm->touchents[pm->numtouch] = trace.ent; ! 557: pm->numtouch++; ! 558: } ! 559: } ! 560: // ! 561: // get waterlevel, accounting for ducking ! 562: // ! 563: pm->waterlevel = 0; ! 564: pm->watertype = 0; ! 565: sample2 = pm->viewheight - pm->mins[2]; ! 566: sample1 = sample2 / 2; ! 567: point[2] = pml.origin[2] + pm->mins[2] + 1; ! 568: cont = pm->pointcontents (point); ! 569: if (cont & MASK_WATER) ! 570: { ! 571: pm->watertype = cont; ! 572: pm->waterlevel = 1; ! 573: point[2] = pml.origin[2] + pm->mins[2] + sample1; ! 574: cont = pm->pointcontents (point); ! 575: if (cont & MASK_WATER) ! 576: { ! 577: pm->waterlevel = 2; ! 578: point[2] = pml.origin[2] + pm->mins[2] + sample2; ! 579: cont = pm->pointcontents (point); ! 580: if (cont & MASK_WATER) ! 581: pm->waterlevel = 3; ! 582: } ! 583: } ! 584: } ! 585: /* ! 586: ============= ! 587: PM_CheckJump ! 588: ============= ! 589: */ ! 590: void PM_CheckJump (void) ! 591: { ! 592: if (pm->s.pm_flags & PMF_TIME_LAND) ! 593: { // hasn't been long enough since landing to jump again ! 594: return; ! 595: } ! 596: if (pm->cmd.upmove < 10) ! 597: { // not holding jump ! 598: pm->s.pm_flags &= ~PMF_JUMP_HELD; ! 599: return; ! 600: } ! 601: ! 602: // must wait for jump to be released ! 603: if (pm->s.pm_flags & PMF_JUMP_HELD) ! 604: return; ! 605: ! 606: if (pm->s.pm_type == PM_DEAD) ! 607: return; ! 608: if (pm->waterlevel >= 2) ! 609: { // swimming, not jumping ! 610: pm->groundentity = NULL; ! 611: if (pml.velocity[2] <= -300) ! 612: return; ! 613: ! 614: if (pm->watertype == CONTENTS_WATER) ! 615: pml.velocity[2] = 100; ! 616: else if (pm->watertype == CONTENTS_SLIME) ! 617: pml.velocity[2] = 80; ! 618: else ! 619: pml.velocity[2] = 50; ! 620: return; ! 621: } ! 622: if (pm->groundentity == NULL) ! 623: return; // in air, so no effect ! 624: pm->s.pm_flags |= PMF_JUMP_HELD; ! 625: ! 626: pm->groundentity = NULL; ! 627: pml.velocity[2] = 270; ! 628: } ! 629: /* ! 630: ============= ! 631: PM_CheckSpecialMovement ! 632: ============= ! 633: */ ! 634: void PM_CheckSpecialMovement (void) ! 635: { ! 636: vec3_t spot; ! 637: int cont; ! 638: vec3_t flatforward; ! 639: trace_t trace; ! 640: ! 641: if (pm->s.pm_time) ! 642: return; ! 643: ! 644: pml.ladder = false; ! 645: // check for ladder ! 646: flatforward[0] = pml.forward[0]; ! 647: flatforward[1] = pml.forward[1]; ! 648: flatforward[2] = 0; ! 649: VectorNormalize (flatforward); ! 650: VectorMA (pml.origin, 1, flatforward, spot); ! 651: trace = pm->trace (pml.origin, pm->mins, pm->maxs, spot); ! 652: if ((trace.fraction < 1) && (trace.contents & CONTENTS_LADDER)) ! 653: pml.ladder = true; ! 654: // check for water jump ! 655: if (pm->waterlevel != 2) ! 656: return; ! 657: VectorMA (pml.origin, 30, flatforward, spot); ! 658: spot[2] += 4; ! 659: cont = pm->pointcontents (spot); ! 660: if (!(cont & CONTENTS_SOLID)) ! 661: return; ! 662: spot[2] += 16; ! 663: cont = pm->pointcontents (spot); ! 664: if (cont) ! 665: return; ! 666: // jump out of water ! 667: VectorScale (pml.forward, 200, pml.velocity); ! 668: pml.velocity[2] = 350; ! 669: ! 670: pm->s.pm_flags |= PMF_TIME_WATERJUMP; ! 671: pm->s.pm_time = 255; ! 672: } ! 673: /* ! 674: =============== ! 675: PM_NoclipMove ! 676: =============== ! 677: */ ! 678: void PM_NoclipMove (void) ! 679: { ! 680: float speed, drop, friction, control, newspeed; ! 681: float currentspeed, addspeed, accelspeed; ! 682: int i; ! 683: vec3_t wishvel; ! 684: float fmove, smove; ! 685: vec3_t wishdir; ! 686: float wishspeed; ! 687: ! 688: pm->viewheight = 22; ! 689: // friction ! 690: speed = VectorLength (pml.velocity); ! 691: if (speed < 1) ! 692: { ! 693: VectorCopy (vec3_origin, pml.velocity); ! 694: } ! 695: else ! 696: { ! 697: drop = 0; ! 698: friction = pm_friction*1.5; // extra friction ! 699: control = speed < pm_stopspeed ? pm_stopspeed : speed; ! 700: drop += control*friction*pml.frametime; ! 701: // scale the velocity ! 702: newspeed = speed - drop; ! 703: if (newspeed < 0) ! 704: newspeed = 0; ! 705: newspeed /= speed; ! 706: VectorScale (pml.velocity, newspeed, pml.velocity); ! 707: } ! 708: // accelerate ! 709: fmove = pm->cmd.forwardmove; ! 710: smove = pm->cmd.sidemove; ! 711: ! 712: VectorNormalize (pml.forward); ! 713: VectorNormalize (pml.right); ! 714: for (i=0 ; i<3 ; i++) ! 715: wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove; ! 716: wishvel[2] += pm->cmd.upmove; ! 717: VectorCopy (wishvel, wishdir); ! 718: wishspeed = VectorNormalize(wishdir); ! 719: // ! 720: // clamp to server defined max speed ! 721: // ! 722: if (wishspeed > pm_maxspeed) ! 723: { ! 724: VectorScale (wishvel, pm_maxspeed/wishspeed, wishvel); ! 725: wishspeed = pm_maxspeed; ! 726: } ! 727: currentspeed = DotProduct(pml.velocity, wishdir); ! 728: addspeed = wishspeed - currentspeed; ! 729: if (addspeed <= 0) ! 730: return; ! 731: accelspeed = pm_accelerate*pml.frametime*wishspeed; ! 732: if (accelspeed > addspeed) ! 733: accelspeed = addspeed; ! 734: ! 735: for (i=0 ; i<3 ; i++) ! 736: pml.velocity[i] += accelspeed*wishdir[i]; ! 737: // move ! 738: VectorMA (pml.origin, pml.frametime, pml.velocity, pml.origin); ! 739: } ! 740: /* ! 741: ============== ! 742: PM_CheckDuck ! 743: ! 744: Sets mins, maxs, and pm->viewheight ! 745: ============== ! 746: */ ! 747: void PM_CheckDuck (void) ! 748: { ! 749: trace_t trace; ! 750: ! 751: pm->mins[0] = -16; ! 752: pm->mins[1] = -16; ! 753: ! 754: pm->maxs[0] = 16; ! 755: pm->maxs[1] = 16; ! 756: if (pm->s.pm_type == PM_GIB) ! 757: { ! 758: pm->mins[2] = 0; ! 759: pm->maxs[2] = 16; ! 760: pm->viewheight = 8; ! 761: return; ! 762: } ! 763: ! 764: pm->mins[2] = -24; ! 765: ! 766: if (pm->s.pm_type == PM_DEAD) ! 767: { ! 768: pm->s.pm_flags |= PMF_DUCKED; ! 769: } ! 770: else if (pm->cmd.upmove < 0 && (pm->s.pm_flags & PMF_ON_GROUND) ) ! 771: { // duck ! 772: pm->s.pm_flags |= PMF_DUCKED; ! 773: } ! 774: else ! 775: { // stand up if possible ! 776: if (pm->s.pm_flags & PMF_DUCKED) ! 777: { ! 778: // try to stand up ! 779: pm->maxs[2] = 32; ! 780: trace = pm->trace (pml.origin, pm->mins, pm->maxs, pml.origin); ! 781: if (!trace.allsolid) ! 782: pm->s.pm_flags &= ~PMF_DUCKED; ! 783: } ! 784: } ! 785: ! 786: if (pm->s.pm_flags & PMF_DUCKED) ! 787: { ! 788: pm->maxs[2] = 4; ! 789: pm->viewheight = -2; ! 790: } ! 791: else ! 792: { ! 793: pm->maxs[2] = 32; ! 794: pm->viewheight = 22; ! 795: } ! 796: } ! 797: ! 798: /* ! 799: ============== ! 800: PM_DeadMove ! 801: ============== ! 802: */ ! 803: void PM_DeadMove (void) ! 804: { ! 805: float forward; ! 806: ! 807: if (!pm->groundentity) ! 808: return; ! 809: ! 810: // extra friction ! 811: ! 812: forward = VectorLength (pml.velocity); ! 813: forward -= 20; ! 814: if (forward <= 0) ! 815: { ! 816: VectorClear (pml.velocity); ! 817: } ! 818: else ! 819: { ! 820: VectorNormalize (pml.velocity); ! 821: VectorScale (pml.velocity, forward, pml.velocity); ! 822: } ! 823: } ! 824: ! 825: ! 826: qboolean PM_GoodPosition (void) ! 827: { ! 828: trace_t trace; ! 829: vec3_t origin, end; ! 830: int i; ! 831: ! 832: if (pm->s.pm_type == PM_SPECTATOR) ! 833: return true; ! 834: ! 835: for (i=0 ; i<3 ; i++) ! 836: origin[i] = end[i] = pm->s.origin[i]*0.125; ! 837: trace = pm->trace (origin, pm->mins, pm->maxs, end); ! 838: ! 839: return !trace.allsolid; ! 840: } ! 841: ! 842: /* ! 843: ================ ! 844: PM_SnapPosition ! 845: ! 846: On exit, the origin will have a value that is pre-quantized to the 0.125 ! 847: precision of the network channel and in a valid position. ! 848: ================ ! 849: */ ! 850: void PM_SnapPosition (void) ! 851: { ! 852: int sign[3]; ! 853: int i, j, bits; ! 854: short base[3]; ! 855: // try all single bits first ! 856: static int jitterbits[8] = {0,4,1,2,3,5,6,7}; ! 857: ! 858: // snap velocity to eigths ! 859: for (i=0 ; i<3 ; i++) ! 860: pm->s.velocity[i] = (int)(pml.velocity[i]*8); ! 861: ! 862: for (i=0 ; i<3 ; i++) ! 863: { ! 864: if (pml.origin[i] >= 0) ! 865: sign[i] = 1; ! 866: else ! 867: sign[i] = -1; ! 868: pm->s.origin[i] = (int)(pml.origin[i]*8); ! 869: if (pm->s.origin[i]*0.125 == pml.origin[i]) ! 870: sign[i] = 0; ! 871: } ! 872: VectorCopy (pm->s.origin, base); ! 873: ! 874: // try all combinations ! 875: for (j=0 ; j<8 ; j++) ! 876: { ! 877: bits = jitterbits[j]; ! 878: VectorCopy (base, pm->s.origin); ! 879: for (i=0 ; i<3 ; i++) ! 880: if (bits & (1<<i) ) ! 881: pm->s.origin[i] += sign[i]; ! 882: ! 883: if (PM_GoodPosition ()) ! 884: return; ! 885: } ! 886: ! 887: // go back to the last position ! 888: VectorCopy (pml.previous_origin, pm->s.origin); ! 889: // Com_DPrintf ("using previous_origin\n"); ! 890: } ! 891: ! 892: /* ! 893: ================ ! 894: PM_InitialSnapPosition ! 895: ! 896: ================ ! 897: */ ! 898: void PM_InitialSnapPosition (void) ! 899: { ! 900: int x, y, z; ! 901: short base[3]; ! 902: ! 903: VectorCopy (pm->s.origin, base); ! 904: ! 905: for (z=1 ; z>=-1 ; z--) ! 906: { ! 907: pm->s.origin[2] = base[2] + z; ! 908: for (y=1 ; y>=-1 ; y--) ! 909: { ! 910: pm->s.origin[1] = base[1] + y; ! 911: for (x=1 ; x>=-1 ; x--) ! 912: { ! 913: pm->s.origin[0] = base[0] + x; ! 914: if (PM_GoodPosition ()) ! 915: { ! 916: pml.origin[0] = pm->s.origin[0]*0.125; ! 917: pml.origin[1] = pm->s.origin[1]*0.125; ! 918: pml.origin[2] = pm->s.origin[2]*0.125; ! 919: VectorCopy (pm->s.origin, pml.previous_origin); ! 920: return; ! 921: } ! 922: } ! 923: } ! 924: } ! 925: ! 926: Com_DPrintf ("Bad InitialSnapPosition\n"); ! 927: } ! 928: ! 929: /* ! 930: ================ ! 931: PM_ClampAngles ! 932: ! 933: ================ ! 934: */ ! 935: void PM_ClampAngles (void) ! 936: { ! 937: short temp; ! 938: int i; ! 939: ! 940: if (pm->s.pm_flags & PMF_TIME_TELEPORT) ! 941: { ! 942: pm->viewangles[YAW] = SHORT2ANGLE(pm->cmd.angles[YAW] + pm->s.delta_angles[YAW]); ! 943: pm->viewangles[PITCH] = 0; ! 944: pm->viewangles[ROLL] = 0; ! 945: } ! 946: else ! 947: { ! 948: // circularly clamp the angles with deltas ! 949: for (i=0 ; i<3 ; i++) ! 950: { ! 951: temp = pm->cmd.angles[i] + pm->s.delta_angles[i]; ! 952: pm->viewangles[i] = SHORT2ANGLE(temp); ! 953: } ! 954: ! 955: // don't let the player look up or down more than 90 degrees ! 956: if (pm->viewangles[PITCH] > 89 && pm->viewangles[PITCH] < 180) ! 957: pm->viewangles[PITCH] = 89; ! 958: else if (pm->viewangles[PITCH] < 271 && pm->viewangles[PITCH] >= 180) ! 959: pm->viewangles[PITCH] = 271; ! 960: } ! 961: AngleVectors (pm->viewangles, pml.forward, pml.right, pml.up); ! 962: } ! 963: ! 964: /* ! 965: ================ ! 966: Pmove ! 967: ! 968: Can be called by either the server or the client ! 969: ================ ! 970: */ ! 971: void Pmove (pmove_t *pmove) ! 972: { ! 973: pm = pmove; ! 974: ! 975: // clear results ! 976: pm->numtouch = 0; ! 977: VectorClear (pm->viewangles); ! 978: pm->viewheight = 0; ! 979: pm->groundentity = 0; ! 980: pm->watertype = 0; ! 981: pm->waterlevel = 0; ! 982: ! 983: // clear all pmove local vars ! 984: memset (&pml, 0, sizeof(pml)); ! 985: ! 986: // convert origin and velocity to float values ! 987: pml.origin[0] = pm->s.origin[0]*0.125; ! 988: pml.origin[1] = pm->s.origin[1]*0.125; ! 989: pml.origin[2] = pm->s.origin[2]*0.125; ! 990: ! 991: pml.velocity[0] = pm->s.velocity[0]*0.125; ! 992: pml.velocity[1] = pm->s.velocity[1]*0.125; ! 993: pml.velocity[2] = pm->s.velocity[2]*0.125; ! 994: ! 995: // save old org in case we get stuck ! 996: VectorCopy (pm->s.origin, pml.previous_origin); ! 997: ! 998: pml.frametime = pm->cmd.msec * 0.001; ! 999: ! 1000: PM_ClampAngles (); ! 1001: ! 1002: if (pm->s.pm_type == PM_SPECTATOR) ! 1003: { ! 1004: PM_NoclipMove (); ! 1005: PM_SnapPosition (); ! 1006: return; ! 1007: } ! 1008: ! 1009: if (pm->s.pm_type >= PM_DEAD) ! 1010: { ! 1011: pm->cmd.forwardmove = 0; ! 1012: pm->cmd.sidemove = 0; ! 1013: pm->cmd.upmove = 0; ! 1014: } ! 1015: ! 1016: if (pm->s.pm_type == PM_FREEZE) ! 1017: return; // no movement at all ! 1018: ! 1019: // set mins, maxs, and viewheight ! 1020: PM_CheckDuck (); ! 1021: ! 1022: if (pm->snapinitial) ! 1023: PM_InitialSnapPosition (); ! 1024: ! 1025: // set groundentity, watertype, and waterlevel ! 1026: PM_CatagorizePosition (); ! 1027: ! 1028: if (pm->s.pm_type == PM_DEAD) ! 1029: PM_DeadMove (); ! 1030: ! 1031: PM_CheckSpecialMovement (); ! 1032: ! 1033: // drop timing counter ! 1034: if (pm->s.pm_time) ! 1035: { ! 1036: int msec; ! 1037: ! 1038: msec = pm->cmd.msec >> 3; ! 1039: if (!msec) ! 1040: msec = 1; ! 1041: if ( msec >= pm->s.pm_time) ! 1042: { ! 1043: pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT); ! 1044: pm->s.pm_time = 0; ! 1045: } ! 1046: else ! 1047: pm->s.pm_time -= msec; ! 1048: } ! 1049: ! 1050: if (pm->s.pm_flags & PMF_TIME_TELEPORT) ! 1051: { // teleport pause stays exactly in place ! 1052: } ! 1053: else if (pm->s.pm_flags & PMF_TIME_WATERJUMP) ! 1054: { // waterjump has no control, but falls ! 1055: pml.velocity[2] -= pm->s.gravity * pml.frametime; ! 1056: if (pml.velocity[2] < 0) ! 1057: { // cancel as soon as we are falling down again ! 1058: pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT); ! 1059: pm->s.pm_time = 0; ! 1060: } ! 1061: ! 1062: PM_StepSlideMove (); ! 1063: } ! 1064: else ! 1065: { ! 1066: PM_CheckJump (); ! 1067: ! 1068: PM_Friction (); ! 1069: ! 1070: if (pm->waterlevel >= 2) ! 1071: PM_WaterMove (); ! 1072: else ! 1073: PM_AirMove (); ! 1074: } ! 1075: ! 1076: // set groundentity, watertype, and waterlevel for final spot ! 1077: PM_CatagorizePosition (); ! 1078: ! 1079: PM_SnapPosition (); ! 1080: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.