void PmoveSingle (pmove_t *pmove) { pm = pmove; // this counter lets us debug movement problems with a journal // by setting a conditional breakpoint fot the previous frame c_pmove++; // clear results pm->numtouch = 0; pm->watertype = 0; pm->waterlevel = 0; if ( pm->ps->stats[STAT_HEALTH] <= 0 ) { pm->tracemask &= ~CONTENTS_BODY; // corpses can fly through bodies } // make sure walking button is clear if they are running, to avoid // proxy no-footsteps cheats if ( abs( pm->cmd.forwardmove ) > 64 || abs( pm->cmd.rightmove ) > 64 ) { pm->cmd.buttons &= ~BUTTON_WALKING; } // set the talk balloon flag if ( pm->cmd.buttons & BUTTON_TALK ) { pm->ps->eFlags |= EF_TALK; } else { pm->ps->eFlags &= ~EF_TALK; } // set the firing flag for continuous beam weapons if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && pm->ps->pm_type != PM_NOCLIP && ( pm->cmd.buttons & BUTTON_ATTACK ) && pm->ps->ammo[ pm->ps->weapon ] ) { pm->ps->eFlags |= EF_FIRING; } else { pm->ps->eFlags &= ~EF_FIRING; } // clear the respawned flag if attack and use are cleared if ( pm->ps->stats[STAT_HEALTH] > 0 && !( pm->cmd.buttons & (BUTTON_ATTACK | BUTTON_USE_HOLDABLE) ) ) { pm->ps->pm_flags &= ~PMF_RESPAWNED; } // if talk button is down, dissallow all other input // this is to prevent any possible intercept proxy from // adding fake talk balloons if ( pmove->cmd.buttons & BUTTON_TALK ) { // keep the talk button set tho for when the cmd.serverTime > 66 msec // and the same cmd is used multiple times in Pmove pmove->cmd.buttons = BUTTON_TALK; pmove->cmd.forwardmove = 0; pmove->cmd.rightmove = 0; pmove->cmd.upmove = 0; } // clear all pmove local vars memset (&pml, 0, sizeof(pml)); // determine the time pml.msec = pmove->cmd.serverTime - pm->ps->commandTime; if ( pml.msec < 1 ) { pml.msec = 1; } else if ( pml.msec > 200 ) { pml.msec = 200; } pm->ps->commandTime = pmove->cmd.serverTime; // save old org in case we get stuck VectorCopy (pm->ps->origin, pml.previous_origin); // save old velocity for crashlanding VectorCopy (pm->ps->velocity, pml.previous_velocity); pml.frametime = pml.msec * 0.001; // update the viewangles PM_UpdateViewAngles( pm->ps, &pm->cmd ); AngleVectors (pm->ps->viewangles, pml.forward, pml.right, pml.up); if ( pm->cmd.upmove < 10 ) { // not holding jump pm->ps->pm_flags &= ~PMF_JUMP_HELD; } // decide if backpedaling animations should be used if ( pm->cmd.forwardmove < 0 ) { pm->ps->pm_flags |= PMF_BACKWARDS_RUN; } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { pm->ps->pm_flags &= ~PMF_BACKWARDS_RUN; } if ( pm->ps->pm_type >= PM_DEAD ) { pm->cmd.forwardmove = 0; pm->cmd.rightmove = 0; pm->cmd.upmove = 0; } if ( pm->ps->pm_type == PM_SPECTATOR ) { PM_CheckDuck (); PM_FlyMove (); PM_DropTimers (); return; } if ( pm->ps->pm_type == PM_NOCLIP ) { PM_NoclipMove (); PM_DropTimers (); return; } if (pm->ps->pm_type == PM_FREEZE) { return; // no movement at all } if ( pm->ps->pm_type == PM_INTERMISSION || pm->ps->pm_type == PM_SPINTERMISSION) { return; // no movement at all } // set watertype, and waterlevel PM_SetWaterLevel(); pml.previous_waterlevel = pmove->waterlevel; // set mins, maxs, and viewheight PM_CheckDuck (); // set groundentity PM_GroundTrace(); if ( pm->ps->pm_type == PM_DEAD ) { PM_DeadMove (); } PM_DropTimers(); #ifdef MISSIONPACK if ( pm->ps->powerups[PW_INVULNERABILITY] ) { PM_InvulnerabilityMove(); } else #endif if ( pm->ps->powerups[PW_FLIGHT] ) { // flight powerup doesn't allow jump and has different friction PM_FlyMove(); } else if (pm->ps->pm_flags & PMF_GRAPPLE_PULL) { PM_GrappleMove(); // We can wiggle a bit PM_AirMove(); } else if (pm->ps->pm_flags & PMF_TIME_WATERJUMP) { PM_WaterJumpMove(); } else if ( pm->waterlevel > 1 ) { // swimming PM_WaterMove(); } else if ( pml.walking ) { // walking on ground PM_WalkMove(); } else { // airborne PM_AirMove(); } PM_Animate(); // set groundentity, watertype, and waterlevel PM_GroundTrace(); PM_SetWaterLevel(); // weapons PM_Weapon(); // torso animation PM_TorsoAnimation(); // footstep events / legs animations PM_Footsteps(); // entering / leaving water splashes PM_WaterEvents(); // snap some parts of playerstate to save network bandwidth trap_SnapVector( pm->ps->velocity ); }
/* * Can be called by either the server or the client */ void Pmove (pmove_t *pmove) { #if !defined(DEDICATED_ONLY) && defined(USE_OPENAL) static int underwater; #endif pm = pmove; /* clear results */ pm->numtouch = 0; VectorClear (pm->viewangles); pm->viewheight = 0; pm->groundentity = 0; pm->watertype = 0; pm->waterlevel = 0; /* clear all pmove local vars */ memset (&pml, 0, sizeof(pml)); /* convert origin and velocity to float values */ pml.origin[0] = pm->s.origin[0]*0.125f; pml.origin[1] = pm->s.origin[1]*0.125f; pml.origin[2] = pm->s.origin[2]*0.125f; pml.velocity[0] = pm->s.velocity[0]*0.125f; pml.velocity[1] = pm->s.velocity[1]*0.125f; pml.velocity[2] = pm->s.velocity[2]*0.125f; /* save old org in case we get stuck */ VectorCopy (pm->s.origin, pml.previous_origin); pml.frametime = pm->cmd.msec * 0.001f; PM_ClampAngles (); if (pm->s.pm_type == PM_SPECTATOR) { PM_FlyMove (false); PM_SnapPosition (); return; } if (pm->s.pm_type >= PM_DEAD) { pm->cmd.forwardmove = 0; pm->cmd.sidemove = 0; pm->cmd.upmove = 0; } if (pm->s.pm_type == PM_FREEZE) return; /* no movement at all */ /* set mins, maxs, and viewheight */ PM_CheckDuck (); if (pm->snapinitial) PM_InitialSnapPosition (); /* set groundentity, watertype, and waterlevel */ PM_CatagorizePosition (); if (pm->s.pm_type == PM_DEAD) PM_DeadMove (); PM_CheckSpecialMovement (); /* drop timing counter */ if (pm->s.pm_time) { int msec; msec = pm->cmd.msec >> 3; if (!msec) msec = 1; if ( msec >= pm->s.pm_time) { pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT); pm->s.pm_time = 0; } else pm->s.pm_time -= msec; }
/* ================ Pmove Can be called by either the server or the client ================ */ void Pmove (pmove_t *pmove) { pm = pmove; // clear results pm->numtouch = 0; VectorClear (pm->viewangles); pm->viewheight = 0; pm->groundentity = 0; pm->watertype = 0; pm->waterlevel = 0; // clear all pmove local vars memset (&pml, 0, sizeof(pml)); // convert origin and velocity to float values pml.origin[0] = pm->s.origin[0]*0.125; pml.origin[1] = pm->s.origin[1]*0.125; pml.origin[2] = pm->s.origin[2]*0.125; pml.velocity[0] = pm->s.velocity[0]*0.125; pml.velocity[1] = pm->s.velocity[1]*0.125; pml.velocity[2] = pm->s.velocity[2]*0.125; // save old org in case we get stuck VectorCopy (pm->s.origin, pml.previous_origin); pml.frametime = pm->cmd.msec * 0.001; PM_ClampAngles (); if (pm->s.pm_type == PM_SPECTATOR) { PM_FlyMove (false); PM_SnapPosition (); return; } if (pm->s.pm_type >= PM_DEAD) { pm->cmd.forwardmove = 0; pm->cmd.sidemove = 0; pm->cmd.upmove = 0; } if (pm->s.pm_type == PM_FREEZE) return; // no movement at all // set mins, maxs, and viewheight PM_CheckDuck (); if (pm->snapinitial) PM_InitialSnapPosition (); // set groundentity, watertype, and waterlevel PM_CatagorizePosition (); if (pm->s.pm_type == PM_DEAD) PM_DeadMove (); PM_CheckSpecialMovement (); // drop timing counter if (pm->s.pm_time) { int msec; msec = pm->cmd.msec >> 3; if (!msec) msec = 1; if ( msec >= pm->s.pm_time) { // pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT); // pm->s.pm_time = 0; byte_write(&pm->s.pm_time, 0); byte_write(&pm->s.pm_flags, pm->s.pm_flags & ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT)); } else pm->s.pm_time -= msec; }