19 #include "shared/shared.h"
20 #include "common/pmove.h"
47 static pmoveParams_t *
pmp;
71 #define STOP_EPSILON 0.1
73 static void PM_ClipVelocity(vec3_t in, vec3_t normal, vec3_t out,
float overbounce)
79 backoff = DotProduct(in, normal) * overbounce;
81 for (i = 0; i < 3; i++) {
82 change = normal[i] * backoff;
83 out[i] = in[i] - change;
103 #define MIN_STEP_NORMAL 0.7 // can't step up onto very steep slopes
104 #define MAX_CLIP_PLANES 5
107 int bumpcount, numbumps;
112 vec3_t primal_velocity;
125 for (bumpcount = 0; bumpcount < numbumps; bumpcount++) {
126 for (i = 0; i < 3; i++)
131 if (trace.allsolid) {
137 if (trace.fraction > 0) {
143 if (trace.fraction == 1)
147 if (
pm->numtouch < MAXTOUCH && trace.ent) {
148 pm->touchents[
pm->numtouch] = trace.ent;
152 time_left -= time_left * trace.fraction;
161 VectorCopy(trace.plane.normal, planes[numplanes]);
167 for (i = 0; i < numplanes; i++) {
169 for (j = 0; j < numplanes; j++)
178 if (i != numplanes) {
182 if (numplanes != 2) {
187 CrossProduct(planes[0], planes[1], dir);
196 if (DotProduct(
pml.
velocity, primal_velocity) <= 0) {
215 vec3_t start_o, start_v;
216 vec3_t down_o, down_v;
218 float down_dist, up_dist;
230 VectorCopy(start_o,
up);
233 trace =
pm->trace(
up,
pm->mins,
pm->maxs,
up);
247 if (!trace.allsolid) {
254 down_dist = (down_o[0] - start_o[0]) * (down_o[0] - start_o[0])
255 + (down_o[1] - start_o[1]) * (down_o[1] - start_o[1]);
256 up_dist = (
up[0] - start_o[0]) * (
up[0] - start_o[0])
257 + (
up[1] - start_o[1]) * (
up[1] - start_o[1]);
280 float speed, newspeed, control;
286 speed = sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);
297 friction =
pmp->friction;
307 newspeed = speed - drop;
313 vel[0] = vel[0] * newspeed;
314 vel[1] = vel[1] * newspeed;
315 vel[2] = vel[2] * newspeed;
329 float addspeed, accelspeed, currentspeed;
332 addspeed = wishspeed - currentspeed;
336 if (accelspeed > addspeed)
337 accelspeed = addspeed;
339 for (i = 0; i < 3; i++)
346 float addspeed, accelspeed, currentspeed, wishspd = wishspeed;
351 addspeed = wishspd - currentspeed;
355 if (accelspeed > addspeed)
356 accelspeed = addspeed;
358 for (i = 0; i < 3; i++)
377 if ((
pm->viewangles[PITCH] <= -15) && (
pm->cmd.forwardmove > 0))
379 else if ((
pm->viewangles[PITCH] >= 15) && (
pm->cmd.forwardmove > 0))
381 else if (
pm->cmd.upmove > 0)
383 else if (
pm->cmd.upmove < 0)
389 if (wishvel[0] < -25)
391 else if (wishvel[0] > 25)
394 if (wishvel[1] < -25)
396 else if (wishvel[1] > 25)
405 if (
pm->watertype & MASK_CURRENT) {
408 if (
pm->watertype & CONTENTS_CURRENT_0)
410 if (
pm->watertype & CONTENTS_CURRENT_90)
412 if (
pm->watertype & CONTENTS_CURRENT_180)
414 if (
pm->watertype & CONTENTS_CURRENT_270)
416 if (
pm->watertype & CONTENTS_CURRENT_UP)
418 if (
pm->watertype & CONTENTS_CURRENT_DOWN)
422 if ((
pm->waterlevel == 1) && (
pm->groundentity))
425 VectorMA(wishvel, s, v, wishvel);
432 if (
pm->groundentity) {
448 VectorMA(wishvel, 100 , v, wishvel);
469 for (i = 0; i < 3; i++)
472 if (!
pm->cmd.forwardmove && !
pm->cmd.sidemove && !
pm->cmd.upmove)
475 wishvel[2] +=
pm->cmd.upmove;
479 VectorCopy(wishvel, wishdir);
482 if (wishspeed >
pmp->maxspeed) {
483 VectorScale(wishvel,
pmp->maxspeed / wishspeed, wishvel);
484 wishspeed =
pmp->maxspeed;
486 wishspeed *=
pmp->watermult;
509 fmove =
pm->cmd.forwardmove;
510 smove =
pm->cmd.sidemove;
520 for (i = 0; i < 2; i++)
526 VectorCopy(wishvel, wishdir);
534 if (wishspeed > maxspeed) {
535 VectorScale(wishvel, maxspeed / wishspeed, wishvel);
536 wishspeed = maxspeed;
553 }
else if (
pm->groundentity) {
561 if (
pm->s.gravity > 0)
572 if (
pmp->airaccelerate)
605 pm->s.pm_flags &= ~PMF_ON_GROUND;
606 pm->groundentity = NULL;
613 if (!trace.ent || (trace.plane.normal[2] < 0.7 && !trace.startsolid)) {
614 pm->groundentity = NULL;
615 pm->s.pm_flags &= ~PMF_ON_GROUND;
617 pm->groundentity = trace.ent;
620 if (
pm->s.pm_flags & PMF_TIME_WATERJUMP) {
621 pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
625 if (!(
pm->s.pm_flags & PMF_ON_GROUND)) {
627 pm->s.pm_flags |= PMF_ON_GROUND;
630 pm->s.pm_flags |= PMF_TIME_LAND;
640 if (
pm->numtouch < MAXTOUCH && trace.ent) {
641 pm->touchents[
pm->numtouch] = trace.ent;
652 sample2 =
pm->viewheight -
pm->mins[2];
653 sample1 = sample2 / 2;
656 cont =
pm->pointcontents(point);
658 if (cont & MASK_WATER) {
659 pm->watertype = cont;
662 cont =
pm->pointcontents(point);
663 if (cont & MASK_WATER) {
666 cont =
pm->pointcontents(point);
667 if (cont & MASK_WATER)
682 if (
pm->s.pm_flags & PMF_TIME_LAND) {
687 if (
pm->cmd.upmove < 10) {
689 pm->s.pm_flags &= ~PMF_JUMP_HELD;
694 if (
pm->s.pm_flags & PMF_JUMP_HELD)
697 if (
pm->s.pm_type == PM_DEAD)
700 if (
pm->waterlevel >= 2) {
702 pm->groundentity = NULL;
712 if (
pm->watertype == CONTENTS_WATER)
714 else if (
pm->watertype == CONTENTS_SLIME)
721 if (
pm->groundentity == NULL)
724 pm->s.pm_flags |= PMF_JUMP_HELD;
726 pm->groundentity = NULL;
727 pm->s.pm_flags &= ~PMF_ON_GROUND;
757 VectorMA(
pml.
origin, 1, flatforward, spot);
759 if ((trace.fraction < 1) && (trace.contents & CONTENTS_LADDER))
763 if (
pm->waterlevel != 2)
766 VectorMA(
pml.
origin, 30, flatforward, spot);
768 cont =
pm->pointcontents(spot);
769 if (!(cont & CONTENTS_SOLID))
773 cont =
pm->pointcontents(spot);
780 pm->s.pm_flags |= PMF_TIME_WATERJUMP;
792 float speed, drop, friction, control, newspeed;
793 float currentspeed, addspeed, accelspeed;
810 friction =
pmp->flyfriction;
815 newspeed = speed - drop;
824 fmove =
pm->cmd.forwardmove;
825 smove =
pm->cmd.sidemove;
830 for (i = 0; i < 3; i++)
832 wishvel[2] +=
pm->cmd.upmove;
834 VectorCopy(wishvel, wishdir);
840 if (wishspeed >
pmp->maxspeed) {
841 VectorScale(wishvel,
pmp->maxspeed / wishspeed, wishvel);
842 wishspeed =
pmp->maxspeed;
846 addspeed = wishspeed - currentspeed;
853 if (accelspeed > addspeed)
854 accelspeed = addspeed;
856 for (i = 0; i < 3; i++)
862 for (i = 0; i < 3; i++)
894 if (
pm->s.pm_type == PM_GIB) {
903 if (
pm->s.pm_type == PM_DEAD) {
904 pm->s.pm_flags |= PMF_DUCKED;
905 }
else if (
pm->cmd.upmove < 0 && (
pm->s.pm_flags & PMF_ON_GROUND)) {
907 pm->s.pm_flags |= PMF_DUCKED;
910 if (
pm->s.pm_flags & PMF_DUCKED) {
915 pm->s.pm_flags &= ~PMF_DUCKED;
919 if (
pm->s.pm_flags & PMF_DUCKED) {
938 if (!
pm->groundentity)
960 if (
pm->s.pm_type == PM_SPECTATOR)
963 for (i = 0; i < 3; i++)
964 origin[i] = end[i] =
pm->s.origin[i] * 0.125;
967 return !trace.allsolid;
984 static const byte jitterbits[8] = {0, 4, 1, 2, 3, 5, 6, 7};
987 for (i = 0; i < 3; i++)
990 for (i = 0; i < 3; i++) {
999 VectorCopy(
pm->s.origin, base);
1002 for (j = 0; j < 8; j++) {
1003 bits = jitterbits[j];
1004 VectorCopy(base,
pm->s.origin);
1005 for (i = 0; i < 3; i++)
1006 if (bits & (1 << i))
1007 pm->s.origin[i] += sign[i];
1018 void PM_HackedSnapPosition(
void)
1022 static const int offset[3] = { 0, -1, 1 };
1026 for (i = 0; i < 3; i++)
1029 for (i = 0; i < 3; i++)
1032 VectorCopy(
pm->s.origin, base);
1034 for (z = 0; z < 3; z++) {
1035 pm->s.origin[2] = base[2] + offset[z];
1036 for (y = 0; y < 3; y++) {
1037 pm->s.origin[1] = base[1] + offset[y];
1038 for (x = 0; x < 3; x++) {
1039 pm->s.origin[0] = base[0] + offset[x];
1067 static const short offset[3] = { 0, -1, 1 };
1069 VectorCopy(
pm->s.origin, base);
1071 for (z = 0; z < 3; z++) {
1072 pm->s.origin[2] = base[2] + offset[z];
1073 for (y = 0; y < 3; y++) {
1074 pm->s.origin[1] = base[1] + offset[y];
1075 for (x = 0; x < 3; x++) {
1076 pm->s.origin[0] = base[0] + offset[x];
1100 if (
pm->s.pm_flags & PMF_TIME_TELEPORT) {
1101 pm->viewangles[YAW] = SHORT2ANGLE(
pm->cmd.angles[YAW] +
pm->s.delta_angles[YAW]);
1102 pm->viewangles[PITCH] = 0;
1103 pm->viewangles[ROLL] = 0;
1106 for (i = 0; i < 3; i++) {
1107 temp =
pm->cmd.angles[i] +
pm->s.delta_angles[i];
1108 pm->viewangles[i] = SHORT2ANGLE(temp);
1112 if (
pm->viewangles[PITCH] > 89 &&
pm->viewangles[PITCH] < 180)
1113 pm->viewangles[PITCH] = 89;
1114 else if (
pm->viewangles[PITCH] < 271 &&
pm->viewangles[PITCH] >= 180)
1115 pm->viewangles[PITCH] = 271;
1127 void Pmove(pmove_t *pmove, pmoveParams_t *params)
1134 VectorClear(
pm->viewangles);
1136 pm->groundentity = NULL;
1141 memset(&
pml, 0,
sizeof(
pml));
1152 if (
pm->s.pm_type == PM_SPECTATOR) {
1161 if (
pm->s.pm_type >= PM_DEAD) {
1162 pm->cmd.forwardmove = 0;
1163 pm->cmd.sidemove = 0;
1167 if (
pm->s.pm_type == PM_FREEZE)
1173 if (
pm->snapinitial)
1179 if (
pm->s.pm_type == PM_DEAD)
1185 if (
pm->s.pm_time) {
1188 msec =
pm->cmd.msec >> 3;
1191 if (msec >=
pm->s.pm_time) {
1192 pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
1195 pm->s.pm_time -= msec;
1198 if (
pm->s.pm_flags & PMF_TIME_TELEPORT) {
1200 }
else if (
pm->s.pm_flags & PMF_TIME_WATERJUMP) {
1205 pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
1215 if (
pm->waterlevel >= 2)
1220 VectorCopy(
pm->viewangles, angles);
1221 if (angles[PITCH] > 180)
1222 angles[PITCH] = angles[PITCH] - 360;
1240 memset(
pmp, 0,
sizeof(*
pmp));
1243 pmp->watermult = 0.5f;
1244 pmp->maxspeed = 300;
1246 pmp->waterfriction = 1;
1247 pmp->flyfriction = 9;
1252 pmp->qwmode = qtrue;
1253 pmp->watermult = 0.7f;
1254 pmp->maxspeed = 320;
1257 pmp->waterfriction = 4;
1258 pmp->airaccelerate = qtrue;