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