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