/* =================== PM_AirMove =================== */ static void PM_AirMove( void ) { int i; vec3_t wishvel; float fmove, smove; vec3_t wishdir; float wishspeed; float scale; usercmd_t cmd; PM_Friction(); fmove = pm->cmd.forwardmove; smove = pm->cmd.rightmove; cmd = pm->cmd; scale = PM_CmdScale( &cmd ); // set the movementDir so clients can rotate the legs for strafing PM_SetMovementDir(); // project moves down to flat plane pml.forward[2] = 0; pml.right[2] = 0; VectorNormalize (pml.forward); VectorNormalize (pml.right); for ( i = 0 ; i < 2 ; i++ ) { wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove; } wishvel[2] = 0; VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); wishspeed *= scale; // not on ground, so little effect on velocity PM_Accelerate (wishdir, wishspeed, pm_airaccelerate); // we may have a ground plane that is very steep, even // though we don't have a groundentity // slide along the steep plane if ( pml.groundPlane ) { PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP ); } #if 0 //ZOID: If we are on the grapple, try stair-stepping //this allows a player to use the grapple to pull himself //over a ledge if (pm->ps->pm_flags & PMF_GRAPPLE_PULL) PM_StepSlideMove ( qtrue ); else PM_SlideMove ( qtrue ); #endif PM_StepSlideMove ( qtrue ); }
/* =================== PM_LadderMove() by: Calrathan [Arthur Tomlin] Right now all I know is that this works for VERTICAL ladders. Ladders with angles on them (urban2 for AQ2) haven't been tested. =================== */ static void PM_LadderMove( void ) { int i; vec3_t wishvel; float wishspeed; vec3_t wishdir; float scale; float vel; PM_Friction (); scale = PM_CmdScale( &pm->cmd ); // user intentions [what the user is attempting to do] if ( !scale ) { wishvel[0] = 0; wishvel[1] = 0; wishvel[2] = 0; } else { // if they're trying to move... lets calculate it for (i=0 ; i<3 ; i++) wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove; wishvel[2] += scale * pm->cmd.upmove; } VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); if ( wishspeed > pm->ps->speed * pm_ladderScale ) { wishspeed = pm->ps->speed * pm_ladderScale; } PM_Accelerate (wishdir, wishspeed, pm_ladderAccelerate); // This SHOULD help us with sloped ladders, but it remains untested. if ( pml.groundPlane && DotProduct( pm->ps->velocity, pml.groundTrace.plane.normal ) < 0 ) { vel = VectorLength(pm->ps->velocity); // slide along the ground plane [the ladder section under our feet] PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP ); VectorNormalize(pm->ps->velocity); VectorScale(pm->ps->velocity, vel, pm->ps->velocity); } PM_SlideMove( qfalse ); // move without gravity }
/* ================== PM_StepSlideMove ================== */ qboolean PM_StepSlideMove( qboolean gravity, qboolean predictive ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; vec3_t normal; vec3_t step_v, step_vNormal; vec3_t up, down; float stepSize; qboolean stepped = qfalse; BG_GetClientNormal( pm->ps, normal ); VectorCopy( pm->ps->origin, start_o ); VectorCopy( pm->ps->velocity, start_v ); if ( PM_SlideMove( gravity ) == 0 ) { VectorCopy( start_o, down ); VectorMA( down, -STEPSIZE, normal, down ); pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); //we can step down if ( trace.fraction > 0.01f && trace.fraction < 1.0f && !trace.allsolid && pml.groundPlane != qfalse ) { if ( pm->debugLevel > 1 ) { Com_Printf( "%d: step down\n", c_pmove ); } stepped = qtrue; } } else { VectorCopy( start_o, down ); VectorMA( down, -STEPSIZE, normal, down ); pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); // never step up when you still have up velocity if ( DotProduct( trace.plane.normal, pm->ps->velocity ) > 0.0f && ( trace.fraction == 1.0f || DotProduct( trace.plane.normal, normal ) < 0.7f ) ) { return stepped; } VectorCopy( pm->ps->origin, down_o ); VectorCopy( pm->ps->velocity, down_v ); VectorCopy( start_o, up ); VectorMA( up, STEPSIZE, normal, up ); // test the player position if they were a stepheight higher pm->trace( &trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask ); if ( trace.allsolid ) { if ( pm->debugLevel > 1 ) { Com_Printf( "%i:bend can't step\n", c_pmove ); } return stepped; // can't step up } VectorSubtract( trace.endpos, start_o, step_v ); VectorCopy( step_v, step_vNormal ); VectorNormalize( step_vNormal ); stepSize = DotProduct( normal, step_vNormal ) * VectorLength( step_v ); // try slidemove from this position VectorCopy( trace.endpos, pm->ps->origin ); VectorCopy( start_v, pm->ps->velocity ); if ( PM_SlideMove( gravity ) == 0 ) { if ( pm->debugLevel > 1 ) { Com_Printf( "%d: step up\n", c_pmove ); } stepped = qtrue; } // push down the final amount VectorCopy( pm->ps->origin, down ); VectorMA( down, -stepSize, normal, down ); pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); if ( !trace.allsolid ) { VectorCopy( trace.endpos, pm->ps->origin ); } if ( trace.fraction < 1.0f ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity ); } } if ( !predictive && stepped ) { PM_StepEvent( start_o, pm->ps->origin, normal ); } return stepped; }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove(qboolean gravity) { vec3_t start_o, start_v; // vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; float stepSize; VectorCopy(pm->ps->origin, start_o); VectorCopy(pm->ps->velocity, start_v); if (PM_SlideMove(gravity) == 0) { return; // we got exactly where we wanted to go first try } VectorCopy(start_o, down); down[2] -= STEPSIZE; pm->trace(&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if (pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } //VectorCopy (pm->ps->origin, down_o); //VectorCopy (pm->ps->velocity, down_v); VectorCopy(start_o, up); up[2] += STEPSIZE; // test the player position if they were a stepheight higher pm->trace(&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if (trace.allsolid) { if (pm->debugLevel) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } stepSize = trace.endpos[2] - start_o[2]; // try slidemove from this position VectorCopy(trace.endpos, pm->ps->origin); VectorCopy(start_v, pm->ps->velocity); PM_SlideMove(gravity); // push down the final amount VectorCopy(pm->ps->origin, down); down[2] -= stepSize; pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if (!trace.allsolid) { VectorCopy(trace.endpos, pm->ps->origin); } if (trace.fraction < 1.0) { PM_ClipVelocity(pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP); } #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if (trace.fraction == 1.0) { // use the original move VectorCopy(down_o, pm->ps->origin); VectorCopy(down_v, pm->ps->velocity); if (pm->debugLevel) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if (delta > 2) { if (delta < 7) { PM_AddEvent(EV_STEP_4); } else if (delta < 11) { PM_AddEvent(EV_STEP_8); } else if (delta < 15) { PM_AddEvent(EV_STEP_12); } else { PM_AddEvent(EV_STEP_16); } } if (pm->debugLevel) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* =================== PM_WaterMove =================== */ static void PM_WaterMove( void ) { int i; vec3_t wishvel; float wishspeed; vec3_t wishdir; float scale; float vel; if ( PM_CheckWaterJump() ) { PM_WaterJumpMove(); return; } #if 0 // jump = head for surface if ( pm->cmd.upmove >= 10 ) { if (pm->ps->velocity[2] > -300) { if ( pm->watertype == CONTENTS_WATER ) { pm->ps->velocity[2] = 100; } else if (pm->watertype == CONTENTS_SLIME) { pm->ps->velocity[2] = 80; } else { pm->ps->velocity[2] = 50; } } } #endif PM_Friction (); scale = PM_CmdScale( &pm->cmd ); // // user intentions // if ( !scale ) { wishvel[0] = 0; wishvel[1] = 0; wishvel[2] = -60; // sink towards bottom } else { for (i=0 ; i<3 ; i++) wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove; wishvel[2] += scale * pm->cmd.upmove; } VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); if ( wishspeed > pm->ps->speed * pm_swimScale ) { wishspeed = pm->ps->speed * pm_swimScale; } PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate); // make sure we can go up slopes easily under water if ( pml.groundPlane && DotProduct( pm->ps->velocity, pml.groundTrace.plane.normal ) < 0 ) { vel = VectorLength(pm->ps->velocity); // slide along the ground plane PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP ); VectorNormalize(pm->ps->velocity); VectorScale(pm->ps->velocity, vel, pm->ps->velocity); } PM_SlideMove( qfalse ); }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( qboolean gravity ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; float stepSize; qboolean isGiant = qfalse; bgEntity_t *pEnt; qboolean skipStep = qfalse; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( BG_InReboundHold( pm->ps->legsAnim ) ) { gravity = qfalse; } if ( PM_SlideMove( gravity ) == 0 ) { return; // we got exactly where we wanted to go first try } pEnt = pm_entSelf; if (pm->ps->clientNum >= MAX_CLIENTS) { if (pEnt && pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->hoverHeight > 0) { return; } } VectorCopy(start_o, down); down[2] -= STEPSIZE; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); if (pm->ps->clientNum >= MAX_CLIENTS) { // apply ground friction, even if on ladder if (pEnt && pEnt->s.NPC_class == CLASS_ATST || (pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->type == VH_WALKER) ) {//AT-STs can step high up[2] += 66.0f; isGiant = qtrue; } else if ( pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//also can step up high up[2] += 64.0f; isGiant = qtrue; } else { up[2] += STEPSIZE; } } else { up[2] += STEPSIZE; } // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if ( trace.allsolid ) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } stepSize = trace.endpos[2] - start_o[2]; // try slidemove from this position VectorCopy (trace.endpos, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); PM_SlideMove( gravity ); // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if ( pm->stepSlideFix ) { if ( pm->ps->clientNum < MAX_CLIENTS && trace.plane.normal[2] < MIN_WALK_NORMAL ) {//normal players cannot step up slopes that are too steep to walk on! vec3_t stepVec; //okay, the step up ends on a slope that it too steep to step up onto, //BUT: //If the step looks like this: // (B)\__ // \_____(A) //Then it might still be okay, so we figure out the slope of the entire move //from (A) to (B) and if that slope is walk-upabble, then it's okay VectorSubtract( trace.endpos, down_o, stepVec ); VectorNormalize( stepVec ); if ( stepVec[2] > (1.0f-MIN_WALK_NORMAL) ) { skipStep = qtrue; } } } if ( !trace.allsolid && !skipStep ) //normal players cannot step up slopes that are too steep to walk on! { if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//Rancor don't step on clients if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } /* else if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_ATST && OnSameTeam( pEnt, traceEnt) ) {//NPC AT-ST's don't step up on allies VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } */ else { VectorCopy (trace.endpos, pm->ps->origin); if ( pm->stepSlideFix ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } } else { if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } } if ( !pm->stepSlideFix ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( float gravMod ) { vec3_t start_o, start_v; vec3_t down_o, down_v; vec3_t slideMove, stepUpMove; trace_t trace; vec3_t up, down; qboolean cantStepUpFwd, isATST = qfalse;; int stepSize = STEPSIZE; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( PM_SlideMove( gravMod ) == 0 ) { return; // we got exactly where we wanted to go first try }//else Bumped into something, see if we can step over it if ( pm->gent && pm->gent->client && pm->gent->client->NPC_class == CLASS_ATST) { isATST = qtrue; stepSize = 66;//hack for AT-ST stepping, slightly taller than a standing stormtrooper } else if ( pm->maxs[2] <= 0 ) {//short little guys can't go up steps... FIXME: just make this a flag for certain NPCs- especially ones that roll? stepSize = 4; } //Q3Final addition... VectorCopy(start_o, down); down[2] -= stepSize; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, G2_NOCOLLIDE, 0); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } if ( !pm->ps->velocity[0] && !pm->ps->velocity[1] ) {//All our velocity was cancelled sliding return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); up[2] += stepSize; // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, G2_NOCOLLIDE, 0); if ( trace.allsolid || trace.startsolid || trace.fraction == 0) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } // try slidemove from this position VectorCopy (trace.endpos, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); cantStepUpFwd = PM_SlideMove( gravMod ); //compare the initial slidemove and this slidemove from a step up position VectorSubtract( down_o, start_o, slideMove ); VectorSubtract( trace.endpos, pm->ps->origin, stepUpMove ); if ( fabs(stepUpMove[0]) < 0.1 && fabs(stepUpMove[1]) < 0.1 && VectorLengthSquared( slideMove ) > VectorLengthSquared( stepUpMove ) ) { //slideMove was better, use it VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, G2_NOCOLLIDE, 0); if ( !trace.allsolid ) { if ( pm->ps->clientNum && isATST && g_entities[trace.entityNum].client && g_entities[trace.entityNum].client->playerTeam == pm->gent->client->playerTeam ) {//AT-ST's don't step up on allies } else { VectorCopy( trace.endpos, pm->ps->origin ); } } if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } /* if(cantStepUpFwd && pm->ps->origin[2] < start_o[2] + stepSize && pm->ps->origin[2] >= start_o[2]) {//We bumped into something we could not step up pm->ps->pm_flags |= PMF_BLOCKED; } else {//We did step up, clear the bumped flag pm->ps->pm_flags &= ~PMF_BUMPED; } */ #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
void PM_StepSlideMove( qboolean gravity ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; float stepSize; qboolean isGiant = qfalse; bgEntity_t *pEnt; qboolean skipStep = qfalse; int NEW_STEPSIZE = STEPSIZE; const int moveStyle = PM_GetMovePhysics(); if (moveStyle == MV_CPM || moveStyle == MV_Q3 || moveStyle == MV_WSW || moveStyle == MV_RJQ3 || moveStyle == MV_RJCPM || moveStyle == MV_SLICK || moveStyle == MV_BOTCPM) { if (pm->ps->velocity[2] > 0 && pm->cmd.upmove > 0) { int jumpHeight = pm->ps->origin[2] - pm->ps->fd.forceJumpZStart; if (jumpHeight > 48) jumpHeight = 48; else if (jumpHeight < 22) jumpHeight = 22; NEW_STEPSIZE = 48 - jumpHeight + 22; //trap->SendServerCommand(-1, va("print \"new stepsize: %i, expected max end height: %i\n\"", NEW_STEPSIZE, NEW_STEPSIZE + (int)(pm->ps->origin[2] - pm->ps->fd.forceJumpZStart))); //This means that we can always clip things up to 48 units tall, if we are moving up when we hit it and from a bhop.. //It means we can sometimes clip things up to 70 units tall, if we hit it in right part of jump //Should it be higher..? some of the things in q3 are 56 units tall.. //NEW_STEPSIZE = 46; //Make stepsize equal to.. our current 48 - our current jumpheight ? } else NEW_STEPSIZE = 22; } VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( BG_InReboundHold( pm->ps->legsAnim ) ) { gravity = qfalse; } if ( PM_SlideMove( gravity ) == 0 ) { return; // we got exactly where we wanted to go first try, nospeed ramp returns here maybe } pEnt = pm_entSelf; if (pm->ps->clientNum >= MAX_CLIENTS) { if (pEnt && pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->hoverHeight > 0) { return; } } VectorCopy(start_o, down); down[2] -= NEW_STEPSIZE; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); if (pm->ps->clientNum >= MAX_CLIENTS) { // apply ground friction, even if on ladder if (pEnt && (pEnt->s.NPC_class == CLASS_ATST || (pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->type == VH_WALKER) ) ) {//AT-STs can step high up[2] += 66.0f; isGiant = qtrue; } else if ( pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//also can step up high up[2] += 64.0f; isGiant = qtrue; } else { up[2] += NEW_STEPSIZE; } } else { up[2] += NEW_STEPSIZE; } // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if ( trace.allsolid ) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up, nospeed ramp returns here maybe } stepSize = trace.endpos[2] - start_o[2]; // try slidemove from this position VectorCopy (trace.endpos, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); PM_SlideMove( gravity ); pml.clipped = qtrue; //nospeed ramp fix, if we made it to this point there wont be a nospeed ramp // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if ( pm->stepSlideFix ) { if ( pm->ps->clientNum < MAX_CLIENTS && trace.plane.normal[2] < MIN_WALK_NORMAL ) {//normal players cannot step up slopes that are too steep to walk on! vec3_t stepVec; //okay, the step up ends on a slope that it too steep to step up onto, //BUT: //If the step looks like this: // (B)\__ // \_____(A) //Then it might still be okay, so we figure out the slope of the entire move //from (A) to (B) and if that slope is walk-upabble, then it's okay VectorSubtract( trace.endpos, down_o, stepVec ); VectorNormalize( stepVec ); if ( stepVec[2] > (1.0f-MIN_WALK_NORMAL) ) { skipStep = qtrue; } } } if ( !trace.allsolid && !skipStep ) //normal players cannot step up slopes that are too steep to walk on! { if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//Rancor don't step on clients if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } /* else if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_ATST && OnSameTeam( pEnt, traceEnt) ) {//NPC AT-ST's don't step up on allies VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } */ else { VectorCopy (trace.endpos, pm->ps->origin); if (pm->stepSlideFix) { if (trace.fraction < 1.0) { if (moveStyle == MV_WSW || moveStyle == MV_SLICK) { //Make Warsow Rampjump not slow down your XY speed vec3_t oldVel, clipped_velocity, newVel; float oldSpeed, newSpeed; VectorCopy(pm->ps->velocity, oldVel); oldSpeed = oldVel[0] * oldVel[0] + oldVel[1] * oldVel[1]; PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, clipped_velocity, OVERCLIP ); //WSW RAMPJUMP 3 VectorCopy(clipped_velocity, newVel); newVel[2] = 0; newSpeed = newVel[0] * newVel[0] + newVel[1] * newVel[1]; if (newSpeed > oldSpeed) VectorCopy(clipped_velocity, pm->ps->velocity); } else { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } } } else { if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } } if ( !pm->stepSlideFix ) { if ( trace.fraction < 1.0 ) { if (moveStyle == MV_WSW || moveStyle == MV_SLICK) { vec3_t oldVel, clipped_velocity, newVel; float oldSpeed, newSpeed; VectorCopy(pm->ps->velocity, oldVel); oldSpeed = oldVel[0] * oldVel[0] + oldVel[1] * oldVel[1]; PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, clipped_velocity, OVERCLIP ); //WSW RAMPJUMP 2 VectorCopy(clipped_velocity, newVel); newVel[2] = 0; newSpeed = newVel[0] * newVel[0] + newVel[1] * newVel[1]; if (newSpeed > oldSpeed) VectorCopy(clipped_velocity, pm->ps->velocity); } else { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( float gravMod ) { vec3_t start_o, start_v; vec3_t down_o, down_v; vec3_t slideMove, stepUpMove; trace_t trace; vec3_t up, down; qboolean cantStepUpFwd, isGiant = qfalse;; int stepSize = STEPSIZE; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( PM_InReboundHold( pm->ps->legsAnim ) ) { gravMod = 0.0f; } if ( PM_SlideMove( gravMod ) == 0 ) { return; // we got exactly where we wanted to go first try }//else Bumped into something, see if we can step over it if ( pm->gent && pm->gent->client && pm->gent->client->NPC_class == CLASS_VEHICLE && pm->gent->m_pVehicle->m_pVehicleInfo->hoverHeight > 0 ) {//Hovering vehicles don't do steps //FIXME: maybe make hovering vehicles go up steps, but not down them? return; } if ( pm->gent && pm->gent->client && (pm->gent->client->NPC_class == CLASS_ATST||pm->gent->client->NPC_class == CLASS_RANCOR) ) { isGiant = qtrue; if ( pm->gent->client->NPC_class == CLASS_RANCOR ) { if ( (pm->gent->spawnflags&1) ) { stepSize = 64;//hack for Mutant Rancor stepping } else { stepSize = 48;//hack for Rancor stepping } } else { stepSize = 70;//hack for AT-ST stepping, slightly taller than a standing stormtrooper } } else if ( pm->maxs[2] <= 0 ) {//short little guys can't go up steps... FIXME: just make this a flag for certain NPCs- especially ones that roll? stepSize = 4; } //Q3Final addition... VectorCopy(start_o, down); down[2] -= stepSize; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } if ( !pm->ps->velocity[0] && !pm->ps->velocity[1] ) {//All our velocity was cancelled sliding return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); up[2] += stepSize; // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if ( trace.allsolid || trace.startsolid || trace.fraction == 0) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } if ( pm->debugLevel ) { G_DebugLine(start_o,trace.endpos,2000,0xffffff,qtrue); } //===Another slidemove forward================================================================================ // try slidemove from this position VectorCopy( trace.endpos, pm->ps->origin ); VectorCopy( start_v, pm->ps->velocity ); cantStepUpFwd = PM_SlideMove( gravMod ); //===Another slidemove forward================================================================================ if ( pm->debugLevel ) { G_DebugLine(trace.endpos,pm->ps->origin,2000,0xffffff,qtrue); } //compare the initial slidemove and this slidemove from a step up position VectorSubtract( down_o, start_o, slideMove ); VectorSubtract( trace.endpos, pm->ps->origin, stepUpMove ); if ( fabs(stepUpMove[0]) < 0.1 && fabs(stepUpMove[1]) < 0.1 && VectorLengthSquared( slideMove ) > VectorLengthSquared( stepUpMove ) ) { //slideMove was better, use it VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { qboolean skipStep = qfalse; // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if ( pm->debugLevel ) { G_DebugLine(pm->ps->origin,trace.endpos,2000,0xffffff,qtrue); } if ( g_stepSlideFix->integer ) { if ( pm->ps->clientNum < MAX_CLIENTS && trace.plane.normal[2] < MIN_WALK_NORMAL ) {//normal players cannot step up slopes that are too steep to walk on! vec3_t stepVec; //okay, the step up ends on a slope that it too steep to step up onto, //BUT: //If the step looks like this: // (B)\__ // \_____(A) //Then it might still be okay, so we figure out the slope of the entire move //from (A) to (B) and if that slope is walk-upabble, then it's okay VectorSubtract( trace.endpos, down_o, stepVec ); VectorNormalize( stepVec ); if ( stepVec[2] > (1.0f-MIN_WALK_NORMAL) ) { if ( pm->debugLevel ) { G_DebugLine(down_o,trace.endpos,2000,0x0000ff,qtrue); } skipStep = qtrue; } } } if ( !trace.allsolid && !skipStep ) //normal players cannot step up slopes that are too steep to walk on! { if ( pm->ps->clientNum && isGiant && g_entities[trace.entityNum].client && pm->gent && pm->gent->client && pm->gent->client->NPC_class == CLASS_RANCOR ) {//Rancor don't step on clients if ( g_stepSlideFix->integer ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } else if ( pm->ps->clientNum && isGiant && g_entities[trace.entityNum].client && g_entities[trace.entityNum].client->playerTeam == pm->gent->client->playerTeam ) {//AT-ST's don't step up on allies if ( g_stepSlideFix->integer ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } else { VectorCopy( trace.endpos, pm->ps->origin ); if ( g_stepSlideFix->integer ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } } else { if ( g_stepSlideFix->integer ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } } if ( !g_stepSlideFix->integer ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } /* if(cantStepUpFwd && pm->ps->origin[2] < start_o[2] + stepSize && pm->ps->origin[2] >= start_o[2]) {//We bumped into something we could not step up pm->ps->pm_flags |= PMF_BLOCKED; } else {//We did step up, clear the bumped flag } */ #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( qboolean gravity ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( pm->debugLevel ) { qboolean wassolid, slidesucceed; PM_TraceAll( &trace, pm->ps->origin, pm->ps->origin ); wassolid = trace.allsolid; slidesucceed = (PM_SlideMove( gravity ) == 0) ? qtrue : qfalse; PM_TraceAll( &trace, pm->ps->origin, pm->ps->origin ); if (trace.allsolid && !wassolid) Com_Printf("%i:PM_SlideMove solidified! (%f %f %f) -> (%f %f %f)\n", c_pmove, start_o[0], start_o[1], start_o[2], pm->ps->origin[0], pm->ps->origin[1], pm->ps->origin[2] ); if (slidesucceed) return; } else { if ( PM_SlideMove( gravity ) == 0 ) { return; // we got exactly where we wanted to go first try } } if ( pm->debugLevel ) { Com_Printf("%i:stepping\n", c_pmove); } VectorCopy(start_o, down); down[2] -= STEPSIZE; PM_TraceAll( &trace, start_o, down ); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); up[2] += STEPSIZE; // test the player position if they were a stepheight higher PM_TraceAll( &trace, up, up ); if ( trace.allsolid ) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } // try slidemove from this position VectorCopy (up, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); PM_SlideMove( gravity ); // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= STEPSIZE; // check legs separately if ( pm->ps->eFlags & (EF_PRONE|EF_PLAYDEAD) ) { PM_TraceLegs( &trace, NULL, pm->ps->origin, down, NULL, pm->ps->viewangles, pm->trace, pm->ps->clientNum, pm->tracemask, (pm->ps->eFlags & EF_PRONE) ? true : false ); if ( trace.allsolid ) { // legs don't step, just fuzz. VectorCopy( down_o, pm->ps->origin ); VectorCopy( down_v, pm->ps->velocity ); if ( pm->debugLevel ) { Com_Printf("%i:legs unsteppable\n", c_pmove); } return; } } pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); if ( !trace.allsolid ) { VectorCopy (trace.endpos, pm->ps->origin); } if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } #if 0 // if the down trace can trace back to the original position directly, don't step PM_TraceAll( &trace, pm->ps->origin, start_o ); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ bool PM_StepSlideMove( bool gravity, bool predictive ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; vec3_t normal; vec3_t step_v, step_vNormal; vec3_t up, down; float stepSize; bool stepped = false; if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) { if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) VectorSet( normal, 0.0f, 0.0f, -1.0f ); else VectorCopy( pm->ps->grapplePoint, normal ); } else VectorSet( normal, 0.0f, 0.0f, 1.0f ); VectorCopy( pm->ps->origin, start_o ); VectorCopy( pm->ps->velocity, start_v ); if( PM_SlideMove( gravity ) == 0 ) { VectorCopy( start_o, down ); VectorMA( down, -STEPSIZE, normal, down ); pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); //we can step down if( trace.fraction > 0.01f && trace.fraction < 1.0f && !trace.allsolid && pml.groundPlane != false ) { if( pm->debugLevel ) Com_Printf( "%d: step down\n", c_pmove ); stepped = true; } } else { VectorCopy( start_o, down ); VectorMA( down, -STEPSIZE, normal, down ); pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); // never step up when you still have up velocity if( DotProduct( trace.plane.normal, pm->ps->velocity ) > 0.0f && ( trace.fraction == 1.0f || DotProduct( trace.plane.normal, normal ) < 0.7f ) ) { return stepped; } VectorCopy( pm->ps->origin, down_o ); VectorCopy( pm->ps->velocity, down_v ); VectorCopy( start_o, up ); VectorMA( up, STEPSIZE, normal, up ); // test the player position if they were a stepheight higher pm->trace( &trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask ); if( trace.allsolid ) { if( pm->debugLevel ) Com_Printf( "%i:bend can't step\n", c_pmove ); return stepped; // can't step up } VectorSubtract( trace.endpos, start_o, step_v ); VectorCopy( step_v, step_vNormal ); VectorNormalize( step_vNormal ); stepSize = DotProduct( normal, step_vNormal ) * VectorLength( step_v ); // try slidemove from this position VectorCopy( trace.endpos, pm->ps->origin ); VectorCopy( start_v, pm->ps->velocity ); if( PM_SlideMove( gravity ) == 0 ) { if( pm->debugLevel ) Com_Printf( "%d: step up\n", c_pmove ); stepped = true; } // push down the final amount VectorCopy( pm->ps->origin, down ); VectorMA( down, -stepSize, normal, down ); pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); if( !trace.allsolid ) VectorCopy( trace.endpos, pm->ps->origin ); if( trace.fraction < 1.0f ) PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } if( !predictive && stepped ) PM_StepEvent( start_o, pm->ps->origin, normal ); return stepped; }
void PM_StepSlideMove(Pmove *pm, Pml *pml, qbool gravity) { Vec3 start_o, start_v; /* Vec3 down_o, down_v; */ Trace trace; /* float down_dist, up_dist; * Vec3 delta, delta2; */ Vec3 up, down; float stepSize; float delta; copyv3 (pm->ps->origin, start_o); copyv3 (pm->ps->velocity, start_v); if(PM_SlideMove(pm, pml, gravity) == 0) return; /* we got exactly where we wanted to go first try */ copyv3(start_o, down); down[2] -= STEPSIZE; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); setv3(up, 0, 0, 1); /* never step up when you still have up velocity */ if(pm->ps->velocity[2] > 0 && (trace.fraction == 1.0f || dotv3(trace.plane.normal, up) < 0.7f)) return; /* copyv3 (pm->ps->origin, down_o); * copyv3 (pm->ps->velocity, down_v); */ copyv3 (start_o, up); up[2] += STEPSIZE; /* test the player position if they were a stepheight higher */ pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if(trace.allsolid){ if(pm->debugLevel) comprintf("%u:bend can't step\n", cnt); return; /* can't step up */ } stepSize = trace.endpos[2] - start_o[2]; /* try slidemove from this position */ copyv3 (trace.endpos, pm->ps->origin); copyv3 (start_v, pm->ps->velocity); PM_SlideMove(pm, pml, gravity); /* push down the final amount */ copyv3 (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if(!trace.allsolid) copyv3 (trace.endpos, pm->ps->origin); if(trace.fraction < 1.0f) PM_ClipVelocity(pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP); #if 0 /* if the down trace can trace back to the original position directly, don't step */ pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if(trace.fraction == 1.0f){ /* use the original move */ copyv3 (down_o, pm->ps->origin); copyv3 (down_v, pm->ps->velocity); if(pm->debugLevel) comprintf("%u:bend\n", cnt); }else #endif /* use the step move */ delta = pm->ps->origin[2] - start_o[2]; if(delta > 2){ if(delta < 7) PM_AddEvent(pm, pml, EV_STEP_4); else if(delta < 11) PM_AddEvent(pm, pml, EV_STEP_8); else if(delta < 15) PM_AddEvent(pm, pml, EV_STEP_12); else PM_AddEvent(pm, pml, EV_STEP_16); } if(pm->debugLevel) comprintf("%u:stepped\n", cnt); }
/* ================== PM_StepSlideMove ================== */ bool PM_StepSlideMove( bool gravity, bool predictive ) { vec3_t start_o, start_v; #ifndef UNREALARENA vec3_t down_o, down_v; #endif trace_t trace; #ifndef UNREALARENA vec3_t normal; vec3_t step_v, step_vNormal; #endif vec3_t up, down; float stepSize; bool stepped = false; #ifndef UNREALARENA BG_GetClientNormal( pm->ps, normal ); #endif VectorCopy( pm->ps->origin, start_o ); VectorCopy( pm->ps->velocity, start_v ); if ( !PM_SlideMove( gravity ) ) { #ifdef UNREALARENA return stepped; // we got exactly where we wanted to go first try #else VectorCopy( start_o, down ); VectorMA( down, -STEPSIZE, normal, down ); pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, 0 ); //we can step down if ( trace.fraction > 0.01f && trace.fraction < 1.0f && !trace.allsolid && pml.groundPlane ) { if ( pm->debugLevel > 1 ) { Log::Notice( "%d: step down\n", c_pmove ); } stepped = true; } #endif } else { VectorCopy( start_o, down ); #ifdef UNREALARENA down[ 2 ] -= STEPSIZE; #else VectorMA( down, -STEPSIZE, normal, down ); #endif pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, 0 ); #ifdef UNREALARENA VectorSet( up, 0.0f, 0.0f, 1.0f ); #endif // never step up when you still have up velocity #ifdef UNREALARENA if ( pm->ps->velocity[ 2 ] > 0.0f && ( trace.fraction == 1.0f || DotProduct( trace.plane.normal, up ) < 0.7f ) ) #else if ( DotProduct( trace.plane.normal, pm->ps->velocity ) > 0.0f && ( trace.fraction == 1.0f || DotProduct( trace.plane.normal, normal ) < 0.7f ) ) #endif { return stepped; } #ifndef UNREALARENA // never step up when flying upwards with the jetpack if ( pm->ps->velocity[ 2 ] > 0.0f && ( pm->ps->stats[ STAT_STATE2 ] & SS2_JETPACK_ACTIVE ) ) { return stepped; } VectorCopy( pm->ps->origin, down_o ); VectorCopy( pm->ps->velocity, down_v ); #endif VectorCopy( start_o, up ); #ifdef UNREALARENA up[ 2 ] += STEPSIZE; #else VectorMA( up, STEPSIZE, normal, up ); #endif // test the player position if they were a stepheight higher pm->trace( &trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, 0 ); if ( trace.allsolid ) { if ( pm->debugLevel > 1 ) { Log::Notice( "%i:bend can't step\n", c_pmove ); } return stepped; // can't step up } #ifdef UNREALARENA stepSize = trace.endpos[ 2 ] - start_o[ 2 ]; // if the new position is falling then do nothing if ( PM_CheckFallingFromLedge( trace.endpos ) ) { VectorCopy( start_o, pm->ps->origin ); return stepped; } #else VectorSubtract( trace.endpos, start_o, step_v ); VectorCopy( step_v, step_vNormal ); VectorNormalize( step_vNormal ); stepSize = DotProduct( normal, step_vNormal ) * VectorLength( step_v ); #endif // try slidemove from this position VectorCopy( trace.endpos, pm->ps->origin ); VectorCopy( start_v, pm->ps->velocity ); #ifdef UNREALARENA PM_SlideMove( gravity, stepSize ); #else if ( PM_SlideMove( gravity ) == 0 ) { if ( pm->debugLevel > 1 ) { Log::Notice( "%d: step up\n", c_pmove ); } stepped = true; } #endif // push down the final amount VectorCopy( pm->ps->origin, down ); #ifdef UNREALARENA down[ 2 ] -= stepSize; #else VectorMA( down, -stepSize, normal, down ); #endif pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, 0 ); if ( !trace.allsolid ) { #ifdef UNREALARENA // if the new position is falling then do nothing if ( PM_CheckFallingFromLedge( trace.endpos ) ) { VectorCopy( start_o, pm->ps->origin ); return stepped; } #endif VectorCopy( trace.endpos, pm->ps->origin ); } if ( trace.fraction < 1.0f ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity ); } } #ifdef UNREALARENA if ( !predictive ) { stepped = true; // use the step move float delta; delta = pm->ps->origin[ 2 ] - start_o[ 2 ]; if ( delta > 2.0f ) { if ( delta < 7.0f ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11.0f ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15.0f ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel > 1 ) { Log::Notice( "%i:stepped\n", c_pmove ); } } #else if ( !predictive && stepped ) { PM_StepEvent( start_o, pm->ps->origin, normal ); } #endif return stepped; }