/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ TM_CALLABLE void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; // regular thinking if (!SV_RunThink (ent)) return; if (ent->v.velocity[2] > 0) ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; // if onground, return without moving if ( ((int)ent->v.flags & FL_ONGROUND) ) return; SV_CheckVelocity (ent); // add gravity if (ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE) SV_AddGravity (ent, 1.0); // move angles VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); // move origin VectorScale (ent->v.velocity, host_frametime, move); trace = SV_PushEntity (ent, move); if (trace.fraction == 1) return; if (ent->free) return; if (ent->v.movetype == MOVETYPE_BOUNCE) backoff = 1.5; else backoff = 1; ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); // stop if on ground if (trace.plane.normal[2] > 0.7) { if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE ) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = EDICT_TO_PROG(trace.ent); VectorCopy (vec3_origin, ent->v.velocity); VectorCopy (vec3_origin, ent->v.avelocity); } } // check for in water SV_CheckWaterTransition (ent); }
void LE_Physics_Toss (localent_t *ent) { trace_t tr; vec3_t vel; //copy old origin FastVectorCopy (ent->ent.origin, ent->ent.oldorigin); //FIXME: properly scale this to client FPS. ent->velocity[2] -= 1; //scale velocity based on something stupid FastVectorCopy (ent->velocity, vel); VectorScale (vel, cl.lerpfrac, vel); //add velocity to origin VectorAdd (ent->ent.origin, vel, ent->ent.origin); //check we didn't hit the world tr = CM_BoxTrace (ent->ent.oldorigin, ent->ent.origin, ent->mins, ent->maxs, 0, MASK_SOLID); if (tr.fraction != 1.0f) { //vec3_t down; //if we did, back off. FastVectorCopy (tr.endpos, ent->ent.origin); if (ent->touch) ent->touch (ent, &tr.plane, tr.surface); //check for stop ClipVelocity (ent->velocity, tr.plane.normal, ent->velocity, ent->movetype == MOVETYPE_BOUNCE ? 1.7f : 1.0f); if ((tr.plane.normal[2] > 0.7f && ent->movetype == MOVETYPE_TOSS) || ((ent->velocity[2] < 0.01f && ent->velocity[2] > -0.01f) && ent->movetype == MOVETYPE_BOUNCE)) ent->movetype = MOVETYPE_NONE; } //note!! this only clips to entities that we currently know about (as the client). //this means if a localent is outside the PVS of a client, it will only clip to //the world. //fixme: do we want this? /*CL_ClipMoveToEntities (ent->ent.oldorigin, ent->mins, ent->maxs, ent->ent.origin, &tr); if (tr.ent) { if (ent->touch) ent->touch (ent, &tr.plane, tr.surface); VectorCopy (tr.endpos, ent->ent.origin); //check for stop ClipVelocity (ent->velocity, tr.plane.normal, ent->velocity, ent->movetype == MOVETYPE_BOUNCE ? 1.7 : 1); if (tr.plane.normal[2] > 0.7f && ent->movetype == MOVETYPE_TOSS || ((ent->velocity[2] < 0.01f && ent->velocity[2] > -0.01f) && ent->movetype == MOVETYPE_BOUNCE)) ent->movetype = MOVETYPE_NONE; }*/ }
/* Toss, bounce, and fly movement. When onground, do nothing. */ void Physics_Toss(edict_t *ent) { trace_t trace; vec3_t move; float backoff; // Regular thinking if(!Server_RunThink(ent) || (ent->v.flags & FL_ONGROUND)) return; Game->Physics_CheckVelocity(ent); // Add gravity if(ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE && ent->v.movetype != MOVETYPE_FLYBOUNCE) Game->Physics_SetGravity(ent); // Move angles Math_VectorMA(ent->v.angles,host_frametime,ent->v.avelocity,ent->v.angles); // Move origin Math_VectorScale(ent->v.velocity,host_frametime,move); trace = SV_PushEntity(ent, move); if(trace.fraction == 1.0f || ent->free) return; if(ent->v.movetype == MOVETYPE_FLYBOUNCE) backoff = 2.0f; else if (ent->v.movetype == MOVETYPE_BOUNCE) backoff = 1.5f; else backoff = 1.0f; ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); // Stop if on ground if(trace.plane.normal[2] > 0.7 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_FLYBOUNCE)) if(ent->v.velocity[2] < 60.0f) { ent->v.flags = ent->v.flags | FL_ONGROUND; ent->v.groundentity = trace.ent; Math_VectorCopy(mv3Origin,ent->v.velocity); Math_VectorCopy(mv3Origin,ent->v.avelocity); } Game->Physics_CheckWaterTransition(ent); }
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) { int bumpcount, numbumps; vec3_t dir; float d; int numplanes; vec3_t planes[MAX_CLIP_PLANES]; vec3_t primal_velocity, original_velocity, new_velocity; int i, j; trace_t trace; vec3_t end; float time_left; int blocked; numbumps = 4; blocked = 0; VectorCopy (ent->v.velocity, original_velocity); VectorCopy (ent->v.velocity, primal_velocity); numplanes = 0; time_left = time; for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) { if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2]) break; for (i=0 ; i<3 ; i++) end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); if (trace.allsolid) { // entity is trapped in another solid VectorCopy (vec3_origin, ent->v.velocity); return 3; } if (trace.fraction > 0) { // actually covered some distance VectorCopy (trace.endpos, ent->v.origin); VectorCopy (ent->v.velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance if (!trace.ent) Sys_Error ("SV_FlyMove: !trace.ent"); if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if (trace.ent->v.solid == SOLID_BSP) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = ((int)EDICT_TO_PROG(trace.ent)); } } if (!trace.plane.normal[2]) { blocked |= 2; // step if (steptrace) *steptrace = trace; // save for player extrafriction } // // run the impact function // SV_Impact (ent, trace.ent); if (ent->free) break; // removed by the impact function time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen VectorCopy (vec3_origin, ent->v.velocity); return 3; } VectorCopy (trace.plane.normal, planes[numplanes]); numplanes++; // // modify original_velocity so it parallels all of the clip planes // for (i=0 ; i<numplanes ; i++) { ClipVelocity (original_velocity, planes[i], new_velocity, 1); for (j=0 ; j<numplanes ; j++) if (j != i) { if (DotProduct (new_velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) { // go along this plane VectorCopy (new_velocity, ent->v.velocity); } else { // go along the crease if (numplanes != 2) { // Con_Printf ("clip velocity, numplanes == %i\n",numplanes); VectorCopy (vec3_origin, ent->v.velocity); return 7; } CrossProduct (planes[0], planes[1], dir); d = DotProduct (dir, ent->v.velocity); VectorScale (dir, d, ent->v.velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (DotProduct (ent->v.velocity, primal_velocity) <= 0) { VectorCopy (vec3_origin, ent->v.velocity); return blocked; } } return blocked; }
/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; #ifdef QUAKE2 edict_t *groundentity; groundentity = PROG_TO_EDICT(ent->v.groundentity); if ((int)groundentity->v.flags & FL_CONVEYOR) VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity); else VectorCopy(vec_origin, ent->v.basevelocity); SV_CheckWater (ent); #endif // regular thinking if (!SV_RunThink (ent)) return; #ifdef QUAKE2 if (ent->v.velocity[2] > 0) ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; if ( ((int)ent->v.flags & FL_ONGROUND) ) //@@ if (VectorCompare(ent->v.basevelocity, vec_origin)) return; SV_CheckVelocity (ent); // add gravity if (! ((int)ent->v.flags & FL_ONGROUND) && ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_BOUNCEMISSILE && ent->v.movetype != MOVETYPE_FLYMISSILE) SV_AddGravity (ent); #else // if onground, return without moving if ( ((int)ent->v.flags & FL_ONGROUND) ) return; SV_CheckVelocity (ent); // add gravity if (ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE) SV_AddGravity (ent); #endif // move angles VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); // move origin #ifdef QUAKE2 VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); #endif VectorScale (ent->v.velocity, host_frametime, move); trace = SV_PushEntity (ent, move); #ifdef QUAKE2 VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); #endif if (trace.fraction == 1) return; if (ent->free) return; if (ent->v.movetype == MOVETYPE_BOUNCE) backoff = 1.5; #ifdef QUAKE2 else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE) backoff = 2.0; #endif else backoff = 1; ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); // stop if on ground if (trace.plane.normal[2] > 0.7) { #ifdef QUAKE2 if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE)) #else if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE) #endif { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = ((int)EDICT_TO_PROG(trace.ent)); VectorCopy (vec3_origin, ent->v.velocity); VectorCopy (vec3_origin, ent->v.avelocity); } } // check for in water SV_CheckWaterTransition (ent); }
/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; edict_t *slave; qboolean wasinwater; qboolean isinwater; vec3_t old_origin; // regular thinking SV_RunThink (ent); // if not a team captain, so movement will be handled elsewhere if ( ent->flags & FL_TEAMSLAVE) return; if (ent->velocity[2] > 0) ent->groundentity = NULL; // check for the groundentity going away if (ent->groundentity) if (!ent->groundentity->inuse) ent->groundentity = NULL; // if onground, return without moving if ( ent->groundentity && ent->gravity > 0.0) // PGM - gravity hack return; VectorCopy (ent->s.origin, old_origin); SV_CheckVelocity (ent); // add gravity if (ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE) SV_AddGravity (ent); // move angles VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); // move origin VectorScale (ent->velocity, FRAMETIME, move); trace = SV_PushEntity (ent, move); if (!ent->inuse) return; if (trace.fraction < 1) { if (ent->movetype == MOVETYPE_BOUNCE) backoff = 1.5; else backoff = 1; ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff); // stop if on ground if (trace.plane.normal[2] > 0.7) { if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE ) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy (vec3_origin, ent->velocity); VectorCopy (vec3_origin, ent->avelocity); } } // if (ent->touch) // ent->touch (ent, trace.ent, &trace.plane, trace.surface); } // check for water transition wasinwater = (ent->watertype & MASK_WATER); ent->watertype = gi.pointcontents (ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) ent->waterlevel = 1; else ent->waterlevel = 0; if (!wasinwater && isinwater) gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); else if (wasinwater && !isinwater) gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); // move teamslaves for (slave = ent->teamchain; slave; slave = slave->teamchain) { VectorCopy (ent->s.origin, slave->s.origin); gi.linkentity (slave); } }
int SV_FlyMove (edict_t *ent, float time, int mask) { edict_t *hit; int bumpcount, numbumps; vec3_t dir; float d; int numplanes; vec3_t planes[MAX_CLIP_PLANES]; vec3_t primal_velocity, original_velocity, new_velocity; int i, j; trace_t trace; vec3_t end; float time_left; int blocked; numbumps = 4; blocked = 0; VectorCopy (ent->velocity, original_velocity); VectorCopy (ent->velocity, primal_velocity); numplanes = 0; time_left = time; ent->groundentity = NULL; for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) { for (i=0 ; i<3 ; i++) end[i] = ent->s.origin[i] + time_left * ent->velocity[i]; trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask); if (trace.allsolid) { // entity is trapped in another solid VectorCopy (vec3_origin, ent->velocity); return 3; } if (trace.fraction > 0) { // actually covered some distance VectorCopy (trace.endpos, ent->s.origin); VectorCopy (ent->velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance hit = trace.ent; if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if ( hit->solid == SOLID_BSP) { ent->groundentity = hit; ent->groundentity_linkcount = hit->linkcount; } } if (!trace.plane.normal[2]) { blocked |= 2; // step } // // run the impact function // SV_Impact (ent, &trace); if (!ent->inuse) break; // removed by the impact function time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen VectorCopy (vec3_origin, ent->velocity); return 3; } VectorCopy (trace.plane.normal, planes[numplanes]); numplanes++; // // modify original_velocity so it parallels all of the clip planes // for (i=0 ; i<numplanes ; i++) { ClipVelocity (original_velocity, planes[i], new_velocity, 1); for (j=0 ; j<numplanes ; j++) if ((j != i) && !VectorCompare (planes[i], planes[j])) { if (DotProduct (new_velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) { // go along this plane VectorCopy (new_velocity, ent->velocity); } else { // go along the crease if (numplanes != 2) { // gi.dprintf ("clip velocity, numplanes == %i\n",numplanes); VectorCopy (vec3_origin, ent->velocity); return 7; } CrossProduct (planes[0], planes[1], dir); d = DotProduct (dir, ent->velocity); VectorScale (dir, d, ent->velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (DotProduct (ent->velocity, primal_velocity) <= 0) { VectorCopy (vec3_origin, ent->velocity); return blocked; } } return blocked; }
int CASW_Drone_Movement::TryMove( Vector *pFirstDest, trace_t *pFirstTrace ) { int bumpcount, numbumps; Vector dir; float d; int numplanes; Vector planes[MAX_CLIP_PLANES]; Vector primal_velocity, original_velocity; Vector new_velocity; int i, j; trace_t pm; Vector end; float time_left, allFraction; int blocked; numbumps = 4; // Bump up to four times blocked = 0; // Assume not blocked numplanes = 0; // and not sliding along any planes VectorCopy (mv->m_vecVelocity, original_velocity); // Store original velocity VectorCopy (mv->m_vecVelocity, primal_velocity); allFraction = 0; time_left = m_flInterval; // Total time for this movement operation. new_velocity.Init(); // set the last wall normal z high, so any planes found are 'more upright' m_LastHitWallNormal.z = 2.0f; for (bumpcount=0 ; bumpcount < numbumps; bumpcount++) { if ( mv->m_vecVelocity.Length() == 0.0 ) break; // Assume we can move all the way from the current origin to the // end point. VectorMA( mv->GetAbsOrigin(), time_left, mv->m_vecVelocity, end ); // See if we can make it from origin to end point. if ( g_bMovementOptimizations ) { // If their velocity Z is 0, then we can avoid an extra trace here during WalkMove. if ( pFirstDest && end == *pFirstDest ) pm = *pFirstTrace; else UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), end, MASK_NPCSOLID, &pm ); //TraceBBox( mv->GetAbsOrigin(), end, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), pm ); } else { UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), end, MASK_NPCSOLID, &pm ); //TraceBBox( mv->GetAbsOrigin(), end, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), pm ); } allFraction += pm.fraction; // If we started in a solid object, or we were in solid space // the whole way, zero out our velocity and return that we // are blocked by floor and wall. if (pm.allsolid) { // entity is trapped in another solid VectorCopy (vec3_origin, mv->m_vecVelocity); return 4; } if (pm.fraction < 1.0f) // we've hit something, store the most wall-ish normal { // store the most upright plane if (m_LastHitWallNormal.z > pm.plane.normal.z) VectorCopy(pm.plane.normal, m_LastHitWallNormal); } // If we moved some portion of the total distance, then // copy the end position into the pmove.origin and // zero the plane counter. if( pm.fraction > 0 ) { // actually covered some distance mv->SetAbsOrigin(pm.endpos); VectorCopy (mv->m_vecVelocity, original_velocity); numplanes = 0; } // If we covered the entire distance, we are done // and can return. if (pm.fraction == 1) { break; // moved the entire distance } // Save entity that blocked us (since fraction was < 1.0) // for contact // Add it if it's not already in the list!!! //MoveHelper( )->AddToTouched( pm, mv->m_vecVelocity ); // If the plane we hit has a high z component in the normal, then // it's probably a floor if (pm.plane.normal[2] > 0.7) { blocked |= 1; // floor } // If the plane has a zero z component in the normal, then it's a // step or wall if (!pm.plane.normal[2]) { blocked |= 2; // step / wall } // Reduce amount of m_flFrameTime left by total time left * fraction // that we covered. time_left -= time_left * pm.fraction; // Did we run out of planes to clip against? if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen // Stop our movement if so. VectorCopy (vec3_origin, mv->m_vecVelocity); //Con_DPrintf("Too many planes 4\n"); break; } // Set up next clipping plane VectorCopy (pm.plane.normal, planes[numplanes]); numplanes++; // modify original_velocity so it parallels all of the clip planes // // relfect npc velocity // Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place // and pressing forward and nobody was really using this bounce/reflection feature anyway... if ( numplanes == 1 && m_pNPC->GetMoveType() == MOVETYPE_WALK && m_pNPC->GetGroundEntity() == NULL ) { for ( i = 0; i < numplanes; i++ ) { if ( planes[i][2] > 0.7 ) { // floor or slope ClipVelocity( original_velocity, planes[i], new_velocity, 1 ); VectorCopy( new_velocity, original_velocity ); } else { ClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + sv_bounce.GetFloat() * (1 - m_surfaceFriction) ); } } VectorCopy( new_velocity, mv->m_vecVelocity ); VectorCopy( new_velocity, original_velocity ); } else { for (i=0 ; i < numplanes ; i++) { ClipVelocity ( original_velocity, planes[i], mv->m_vecVelocity, 1); for (j=0 ; j<numplanes ; j++) if (j != i) { // Are we now moving against this plane? if (mv->m_vecVelocity.Dot(planes[j]) < 0) break; // not ok } if (j == numplanes) // Didn't have to clip, so we're ok break; } // Did we go all the way through plane set if (i != numplanes) { // go along this plane // pmove.velocity is set in clipping call, no need to set again. ; } else { // go along the crease if (numplanes != 2) { VectorCopy (vec3_origin, mv->m_vecVelocity); break; } CrossProduct (planes[0], planes[1], dir); d = dir.Dot(mv->m_vecVelocity); VectorScale (dir, d, mv->m_vecVelocity ); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // d = mv->m_vecVelocity.Dot(primal_velocity); if (d <= 0) { //Con_DPrintf("Back\n"); VectorCopy (vec3_origin, mv->m_vecVelocity); break; } } } if ( allFraction == 0 ) { VectorCopy (vec3_origin, mv->m_vecVelocity); } return blocked; }
/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; edict_t *slave; qboolean wasinwater; qboolean isinwater; vec3_t old_origin; // regular thinking SV_RunThink (ent); // if not a team captain, so movement will be handled elsewhere if ( ent->flags & FL_TEAMSLAVE) return; if (ent->velocity[2] > 0) ent->groundentity = NULL; // check for the groundentity going away if (ent->groundentity) if (!ent->groundentity->inuse) ent->groundentity = NULL; // if onground, return without moving if ( ent->groundentity && ent->movetype != MOVETYPE_TOSS_SLIDE ) { // JOSEPH 7-OCT-98 if (ent->fallerflag) { // JOSEPH 22-JAN-99 // If the object just hit the floor if (ent->fallingflag) { ent->fallingflag = 0; if (!strcmp(ent->classname, "props_trashcanA")) { gi.sound (ent, CHAN_AUTO, gi.soundindex ("world/trash2.wav"), 1, ATTN_NORM, 0); } else if (!strcmp(ent->classname, "props_crate")) { gi.sound (ent, CHAN_AUTO, gi.soundindex ("world/crate2.wav"), 1, ATTN_NORM, 0); } } // END JOSEPH // Fix if sitting off center ent->movetype = MOVETYPE_STEP; think_checkedges(ent); } // END JOSEPH return; } VectorCopy (ent->s.origin, old_origin); SV_CheckVelocity (ent); // add gravity if (ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE) SV_AddGravity (ent); // move angles VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); // move origin VectorScale (ent->velocity, FRAMETIME, move); trace = SV_PushEntity (ent, move); if (!ent->inuse) return; if (trace.fraction < 1) { // RAFAEL if (ent->movetype == MOVETYPE_WALLBOUNCE) backoff = 2.0; // RAFAEL ( else ) else if (ent->movetype == MOVETYPE_BOUNCE) backoff = 1.5; // Ridah, testing else if (ent->velocity[2] > -120) backoff = 1; else backoff = 1.3; ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff); // RAFAEL if (ent->movetype == MOVETYPE_WALLBOUNCE) vectoangles (ent->velocity, ent->s.angles); // stop if on ground // RAFAEL if (trace.plane.normal[2] > 0.7 && ent->movetype != MOVETYPE_WALLBOUNCE && ent->movetype != MOVETYPE_TOSS_SLIDE) // Ridah, testing { if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE ) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy (vec3_origin, ent->velocity); VectorCopy (vec3_origin, ent->avelocity); } } // Ridah, testing if (trace.plane.normal[2] > 0.0 && ent->movetype == MOVETYPE_TOSS_SLIDE) // Ridah, testing { VectorMA( ent->velocity, -0.07, ent->velocity, ent->velocity ); // add some friction ent->velocity[2] += ent->gravity * sv_gravity->value * FRAMETIME * trace.plane.normal[2]; if (trace.fraction <= 0.1) { float oldpitch; oldpitch = ent->s.angles[PITCH]; vectoangles (ent->velocity, ent->s.angles); ent->s.angles[PITCH] = oldpitch; VectorCopy (vec3_origin, ent->avelocity); ent->avelocity[PITCH] = -300 * VectorLength(ent->velocity)/800; // roll in direction we're going SV_Physics_Toss(ent); return; } } // if (ent->touch) // ent->touch (ent, trace.ent, &trace.plane, trace.surface); } // check for water transition wasinwater = (ent->watertype & MASK_WATER); ent->watertype = gi.pointcontents (ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) ent->waterlevel = 1; else ent->waterlevel = 0; // JOSEPH 13-MAY-99 /*if (!wasinwater && isinwater) gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); else if (wasinwater && !isinwater) gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);*/ // END JOSEPH // move teamslaves for (slave = ent->teamchain; slave; slave = slave->teamchain) { VectorCopy (ent->s.origin, slave->s.origin); gi.linkentity (slave); } }
int SV_FlyMove (edict_t *ent, float time, int mask) { edict_t *hit; int bumpcount, numbumps; vec3_t dir; float d; int numplanes; vec3_t planes[MAX_CLIP_PLANES]; vec3_t primal_velocity, original_velocity, new_velocity; int i, j; trace_t trace; vec3_t end; float time_left; int blocked; numbumps = 4; blocked = 0; VectorCopy (ent->velocity, original_velocity); VectorCopy (ent->velocity, primal_velocity); numplanes = 0; time_left = time; ent->groundentity = NULL; for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) { for (i=0 ; i<3 ; i++) end[i] = ent->s.origin[i] + time_left * ent->velocity[i]; trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask); if (trace.allsolid) { // entity is trapped in another solid // if (bumpcount == 0) // gi.dprintf( "WARNING: %s is stuck inside %s at (%s)\n", ent->classname, trace.ent->classname, vtos(ent->s.origin) ); VectorCopy (vec3_origin, ent->velocity); return 3; } if ((trace.fraction > 0) && !(trace.ent->svflags & SVF_MONSTER) && !trace.ent->client) { // covered some distance VectorCopy (trace.endpos, ent->s.origin); VectorCopy (ent->velocity, original_velocity); numplanes = 0; } else if ((trace.ent->svflags & SVF_MONSTER) || trace.ent->client) // stay well clear of other characters { // Ridah, don't climb beneath another character if (ent->flags & FL_FLY) { // abort climbing AngleVectors( ent->s.angles, ent->velocity, NULL, NULL ); VectorScale( ent->velocity, -32, ent->velocity ); ent->velocity[2] = 0; ent->flags &= ~FL_FLY; if (ent->cast_info.move_end_climb) ent->cast_info.currentmove = ent->cast_info.move_end_climb; } else if (ent->s.origin[2] > (trace.ent->s.origin[2] + trace.ent->maxs[2])) { // they're below us, jump randomly to get off VectorSet (ent->velocity, random()*128, random()*128, 220); return 20; } else { VectorCopy (vec3_origin, ent->velocity); } return 3; } if (trace.fraction == 1) { blocked = -1; break; // moved the entire distance } hit = trace.ent; if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if ( hit->solid == SOLID_BSP) { ent->groundentity = hit; ent->groundentity_linkcount = hit->linkcount; } } if (!trace.plane.normal[2]) { blocked |= 2; // step } // // run the impact function // SV_Impact (ent, &trace); if (!ent->inuse) break; // removed by the impact function time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen VectorCopy (vec3_origin, ent->velocity); return 3; } VectorCopy (trace.plane.normal, planes[numplanes]); numplanes++; // // modify original_velocity so it parallels all of the clip planes // for (i=0 ; i<numplanes ; i++) { ClipVelocity (original_velocity, planes[i], new_velocity, 1); for (j=0 ; j<numplanes ; j++) if ((j != i) && !VectorCompare (planes[i], planes[j])) { if (DotProduct (new_velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) { // go along this plane //gi.dprintf( "Adjusting velocity for %s\n", ent->classname ); VectorCopy (new_velocity, ent->velocity); // Xatrix/Ridah, help Cast members's jump up to ledges if ( ent->velocity[2] > 60 && !(ent->flags & FL_FLY) ) ent->velocity[2] += (sv_gravity->value*FRAMETIME*0.5); // Xatrix/Ridah, help grunt's jump up to ledges } else { // go along the crease if (numplanes != 2) { // gi.dprintf ("clip velocity, numplanes == %i\n",numplanes); VectorCopy (vec3_origin, ent->velocity); return 7; } CrossProduct (planes[0], planes[1], dir); d = DotProduct (dir, ent->velocity); VectorScale (dir, d, ent->velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (DotProduct (ent->velocity, primal_velocity) <= 0) { //gi.dprintf( "Clearing velocity for occilations for %s\n", ent->classname ); VectorCopy (vec3_origin, ent->velocity); return blocked; } } // Ridah, trying to fix jumping onto ledges problem in SR1 (for example) // ent->velocity[0] = primal_velocity[0]; // ent->velocity[1] = primal_velocity[1]; return blocked; }
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) { int bumpcount, numbumps; vec3_t dir; float d; int numplanes; vec3_t planes[MAX_CLIP_PLANES]; vec3_t primal_velocity, original_velocity, new_velocity; int i, j; trace_t trace; vec3_t end; float time_left; int blocked; numbumps = 4; blocked = 0; Math_VectorCopy (ent->v.velocity, original_velocity); Math_VectorCopy (ent->v.velocity, primal_velocity); numplanes = 0; time_left = time; for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) { if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2]) break; for (i=0 ; i<3 ; i++) end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, FALSE, ent); if(trace.bAllSolid) { // Entity is trapped in another solid Math_VectorCopy(mv3Origin, ent->v.velocity); return 3; } if (trace.fraction > 0) { // Actually covered some distance Math_VectorCopy (trace.endpos, ent->v.origin); Math_VectorCopy (ent->v.velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance if(!trace.ent) { Sys_Error ("SV_FlyMove: !trace.ent"); return 0; } if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if (trace.ent->Physics.iSolid == SOLID_BSP) { ent->v.flags |= FL_ONGROUND; ent->v.groundentity = trace.ent; } } if (!trace.plane.normal[2]) { blocked |= 2; // step if (steptrace) *steptrace = trace; // save for player extrafriction } // Run the impact function Physics_Impact(ent,trace.ent); if (ent->free) break; // removed by the impact function time_left -= time_left * trace.fraction; // Cliped to another plane if(numplanes >= MAX_CLIP_PLANES) { // This shouldn't really happen Math_VectorCopy(mv3Origin, ent->v.velocity); return 3; } Math_VectorCopy (trace.plane.normal, planes[numplanes]); numplanes++; // Modify original_velocity so it parallels all of the clip planes for(i = 0; i < numplanes; i++) { ClipVelocity (original_velocity, planes[i], new_velocity, 1); for (j=0 ; j<numplanes ; j++) if (j != i) { if(Math_DotProduct(new_velocity,planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) Math_VectorCopy (new_velocity, ent->v.velocity); else { // Go along the crease if (numplanes != 2) { Math_VectorCopy(mv3Origin, ent->v.velocity); return 7; } Math_CrossProduct(planes[0], planes[1], dir); d = Math_DotProduct(dir, ent->v.velocity); Math_VectorScale(dir, d, ent->v.velocity); } // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners if(Math_DotProduct(ent->v.velocity,primal_velocity) <= 0) { Math_VectorCopy(mv3Origin,ent->v.velocity); return blocked; } } return blocked; }
//----------------------------------------------------------------------------- // Purpose: // Output : int //----------------------------------------------------------------------------- int CHL2WarsGameMovement::TryStrategicMove( Vector *pFirstDest, trace_t *pFirstTrace ) { int bumpcount, numbumps; Vector dir; float d; int numplanes; Vector planes[MAX_CLIP_PLANES]; Vector primal_velocity, original_velocity; Vector new_velocity; int i, j; trace_t pm; Vector end; float time_left, allFraction; int blocked; numbumps = 4; // Bump up to four times blocked = 0; // Assume not blocked numplanes = 0; // and not sliding along any planes VectorCopy (mv->m_vecVelocity, original_velocity); // Store original velocity VectorCopy (mv->m_vecVelocity, primal_velocity); allFraction = 0; time_left = gpGlobals->frametime; // Total time for this movement operation. new_velocity.Init(); for (bumpcount=0 ; bumpcount < numbumps; bumpcount++) { if ( mv->m_vecVelocity.Length() == 0.0 ) break; // Assume we can move all the way from the current origin to the // end point. VectorMA( mv->GetAbsOrigin(), time_left, mv->m_vecVelocity, end ); // See if we can make it from origin to end point. TracePlayerBBox( mv->GetAbsOrigin(), end, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); allFraction += pm.fraction; // If we started in a solid object, or we were in solid space // the whole way, zero out our velocity and return that we // are blocked by floor and wall. if (pm.allsolid) { #if defined( PLAYER_GETTING_STUCK_TESTING ) Msg( "Trapped!!! :(\n" ); #endif // entity is trapped in another solid VectorCopy (vec3_origin, mv->m_vecVelocity); return 4; } // If we moved some portion of the total distance, then // copy the end position into the pmove.origin and // zero the plane counter. if( pm.fraction > 0 ) { if ( numbumps > 0 && pm.fraction == 1 ) { // There's a precision issue with terrain tracing that can cause a swept box to successfully trace // when the end position is stuck in the triangle. Re-run the test with an uswept box to catch that // case until the bug is fixed. // If we detect getting stuck, don't allow the movement trace_t stuck; TracePlayerBBox( pm.endpos, pm.endpos, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, stuck ); if ( stuck.startsolid || stuck.fraction != 1.0f ) { //Msg( "Player will become stuck!!!\n" ); VectorCopy (vec3_origin, mv->m_vecVelocity); break; } } #if defined( PLAYER_GETTING_STUCK_TESTING ) trace_t foo; TracePlayerBBox( pm.endpos, pm.endpos, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, foo ); if ( foo.startsolid || foo.fraction != 1.0f ) { Msg( "Player will become stuck!!!\n" ); } #endif // actually covered some distance mv->SetAbsOrigin( pm.endpos); VectorCopy (mv->m_vecVelocity, original_velocity); numplanes = 0; } // If we covered the entire distance, we are done // and can return. if (pm.fraction == 1) { break; // moved the entire distance } // Save entity that blocked us (since fraction was < 1.0) // for contact // Add it if it's not already in the list!!! MoveHelper( )->AddToTouched( pm, mv->m_vecVelocity ); // If the plane we hit has a high z component in the normal, then // it's probably a floor if (pm.plane.normal[2] > 0.7) { blocked |= 1; // floor } // If the plane has a zero z component in the normal, then it's a // step or wall if (!pm.plane.normal[2]) { blocked |= 2; // step / wall } // Reduce amount of m_flFrameTime left by total time left * fraction // that we covered. time_left -= time_left * pm.fraction; // Did we run out of planes to clip against? if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen // Stop our movement if so. VectorCopy (vec3_origin, mv->m_vecVelocity); //Con_DPrintf("Too many planes 4\n"); break; } // Set up next clipping plane VectorCopy (pm.plane.normal, planes[numplanes]); numplanes++; // modify original_velocity so it parallels all of the clip planes // // reflect player velocity // Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place // and pressing forward and nobody was really using this bounce/reflection feature anyway... if ( numplanes == 1 && player->GetMoveType() == MOVETYPE_WALK && player->GetGroundEntity() == NULL ) { for ( i = 0; i < numplanes; i++ ) { if ( planes[i][2] > 0.7 ) { // floor or slope ClipVelocity( original_velocity, planes[i], new_velocity, 1 ); VectorCopy( new_velocity, original_velocity ); } else { ClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + sv_bounce.GetFloat() * (1 - player->m_surfaceFriction) ); } } VectorCopy( new_velocity, mv->m_vecVelocity ); VectorCopy( new_velocity, original_velocity ); } else { for (i=0 ; i < numplanes ; i++) { ClipVelocity ( original_velocity, planes[i], mv->m_vecVelocity, 1); for (j=0 ; j<numplanes ; j++) if (j != i) { // Are we now moving against this plane? if (mv->m_vecVelocity.Dot(planes[j]) < 0) break; // not ok } if (j == numplanes) // Didn't have to clip, so we're ok break; } // Did we go all the way through plane set if (i != numplanes) { // go along this plane // pmove.velocity is set in clipping call, no need to set again. ; } else { // go along the crease if (numplanes != 2) { VectorCopy (vec3_origin, mv->m_vecVelocity); break; } CrossProduct (planes[0], planes[1], dir); dir.NormalizeInPlace(); d = dir.Dot(mv->m_vecVelocity); VectorScale (dir, d, mv->m_vecVelocity ); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // d = mv->m_vecVelocity.Dot(primal_velocity); if (d <= 0) { //Con_DPrintf("Back\n"); VectorCopy (vec3_origin, mv->m_vecVelocity); break; } } } if ( allFraction == 0 ) { VectorCopy (vec3_origin, mv->m_vecVelocity); } #if 0 // Check if they slammed into a wall float fSlamVol = 0.0f; float fLateralStoppingAmount = primal_velocity.Length2D() - mv->m_vecVelocity.Length2D(); if ( fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED * 2.0f ) { fSlamVol = 1.0f; } else if ( fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED ) { fSlamVol = 0.85f; } PlayerRoughLandingEffects( fSlamVol ); #endif // 0 return blocked; }
/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; edict_t *slave; qboolean wasinwater; qboolean isinwater; vec3_t old_origin; qboolean forcethrough = false; // regular thinking SV_RunThink (ent); // if not a team captain, so movement will be handled elsewhere if ( ent->flags & FL_TEAMSLAVE) return; if (ent->velocity[2] > 0) ent->groundentity = NULL; // check for the groundentity going away if (ent->groundentity) if (!ent->groundentity->inuse) ent->groundentity = NULL; // if onground, return without moving if (ent->groundentity) { V_TouchSolids(ent); return; } VectorCopy (ent->s.origin, old_origin); SV_CheckVelocity (ent); // add gravity if (ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE && ent->movetype != MOVETYPE_SLIDE // RAFAEL // move type for rippergun projectile && ent->movetype != MOVETYPE_WALLBOUNCE) SV_AddGravity (ent); // move angles VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); // move origin VectorScale (ent->velocity, FRAMETIME, move); if(ent->classname[0] == 'R' && (ent->classname[6] == 'X' || ent->classname[6] == '3')) { ent->groundentity = ent->union_ent; ent->groundentity_linkcount = ent->union_ent->linkcount; VectorCopy (ent->union_ent->velocity, ent->velocity); VectorCopy (ent->union_ent->avelocity, ent->avelocity); VectorAdd(ent->union_ent->s.origin,ent->moveinfo.dir,ent->s.origin); } trace = SV_PushEntity (ent, move); if (!ent->inuse) return; if (trace.fraction < 1 && !forcethrough) { // RAFAEL if (ent->movetype == MOVETYPE_WALLBOUNCE) backoff = 2.0; // RAFAEL ( else ) else if (ent->movetype == MOVETYPE_BOUNCE) backoff = 1.5; else backoff = 1; ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff); // spikeball never stops bouncing if (ent->mtype == M_SPIKEBALL) { float delta = 275 - ent->velocity[2]; // don't get stuck on the ceiling if (trace.plane.normal[2] != -1.0) ent->velocity[2] += delta; // always bounce away from the wall VectorMA(ent->velocity, 100, trace.plane.normal, ent->velocity); } // RAFAEL if (ent->movetype == MOVETYPE_WALLBOUNCE) vectoangles (ent->velocity, ent->s.angles); // stop if on ground // RAFAEL //K03 Begin if (trace.plane.normal[2] > 0.95 && ent->movetype != MOVETYPE_WALLBOUNCE && ent->movetype != MOVETYPE_SLIDE)//was 0.7 { if (ent->velocity[2] < 30/*60*/ || ent->movetype != MOVETYPE_BOUNCE ) //K03 End { // gi.dprintf("SV_Physics_Toss() stopped the entity\n"); ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy (vec3_origin, ent->velocity); VectorCopy (vec3_origin, ent->avelocity); } } // if (ent->touch) // ent->touch (ent, trace.ent, &trace.plane, trace.surface); } // check for water transition wasinwater = (ent->watertype & MASK_WATER); ent->watertype = gi.pointcontents (ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) ent->waterlevel = 1; else ent->waterlevel = 0; if (!wasinwater && isinwater) gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); else if (wasinwater && !isinwater) gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); // move teamslaves for (slave = ent->teamchain; slave; slave = slave->teamchain) { VectorCopy (ent->s.origin, slave->s.origin); gi.linkentity (slave); } }
/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; edict_t *slave; qboolean wasinwater; qboolean isinwater; vec3_t old_origin; if (!ent) { return; } /* regular thinking */ SV_RunThink(ent); /* if not a team captain, so movement will be handled elsewhere */ if (ent->flags & FL_TEAMSLAVE) { return; } if (ent->velocity[2] > 0) { ent->groundentity = NULL; } /* check for the groundentity going away */ if (ent->groundentity) { if (!ent->groundentity->inuse) { ent->groundentity = NULL; } } /* if onground, return without moving */ if (ent->groundentity) { return; } VectorCopy(ent->s.origin, old_origin); SV_CheckVelocity(ent); /* add gravity */ if ((ent->movetype != MOVETYPE_FLY) && (ent->movetype != MOVETYPE_FLYMISSILE) && (ent->movetype != MOVETYPE_WALLBOUNCE)) { SV_AddGravity(ent); } /* move angles */ VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); /* move origin */ VectorScale(ent->velocity, FRAMETIME, move); trace = SV_PushEntity(ent, move); if (!ent->inuse) { return; } if (trace.fraction < 1) { if (ent->movetype == MOVETYPE_WALLBOUNCE) { backoff = 2.0; } else if (ent->movetype == MOVETYPE_BOUNCE) { backoff = 1.5; } else { backoff = 1; } ClipVelocity(ent->velocity, trace.plane.normal, ent->velocity, backoff); if (ent->movetype == MOVETYPE_WALLBOUNCE) { vectoangles(ent->velocity, ent->s.angles); } /* stop if on ground */ if ((trace.plane.normal[2] > 0.7) && (ent->movetype != MOVETYPE_WALLBOUNCE)) { if ((ent->velocity[2] < 60) || (ent->movetype != MOVETYPE_BOUNCE)) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy(vec3_origin, ent->velocity); VectorCopy(vec3_origin, ent->avelocity); } } } /* check for water transition */ wasinwater = (ent->watertype & MASK_WATER); ent->watertype = gi.pointcontents(ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) { ent->waterlevel = 1; } else { ent->waterlevel = 0; } if (!wasinwater && isinwater) { gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); } else if (wasinwater && !isinwater) { gi.positioned_sound(ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); } /* move teamslaves */ for (slave = ent->teamchain; slave; slave = slave->teamchain) { VectorCopy(ent->s.origin, slave->s.origin); gi.linkentity(slave); } }
/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; // regular thinking if (!SV_RunThink (ent)) return; // if onground, return without moving if (((int)ent->v.flags & FL_ONGROUND)) return; SV_CheckVelocity (ent); // add gravity if (ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE) #ifdef HEXEN2_SUPPORT if ( (!hexen2) || (ent->v.movetype != MOVETYPE_BOUNCEMISSILE && ent->v.movetype != MOVETYPE_SWIM)) #endif SV_AddGravity (ent); // move anglesy VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); // move origin VectorScale (ent->v.velocity, host_frametime, move); trace = SV_PushEntity (ent, move); if (trace.fraction == 1) return; if (ent->free) return; if (ent->v.movetype == MOVETYPE_BOUNCE) backoff = 1.5; #ifdef HEXEN2_SUPPORT else if (hexen2 && (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)) { if ((ent->v.solid == SOLID_PHASE) && (((int) trace.ent->v.flags & FL_MONSTER) || ((int) trace.ent->v.movetype == MOVETYPE_WALK))) { return; // Solid phased missiles don't bounce on monsters or players } backoff = 2.0; } #endif else backoff = 1; ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); // stop if on ground if (trace.plane.normal[2] > 0.7) { #ifdef HEXEN2_SUPPORT if ((!hexen2) || (ent->v.movetype != MOVETYPE_BOUNCEMISSILE)) #endif if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = EDICT_TO_PROG(trace.ent); VectorCopy (vec3_origin, ent->v.velocity); VectorCopy (vec3_origin, ent->v.avelocity); } } // check for in water SV_CheckWaterTransition (ent); }
SCollisionResult CMovement::Trace( CArray<STriangle> &triangles, Vector3 start, Vector3 bboxMax, Vector3 boxdir[3], Vector3 displacement ) { float fraction = 1.0f; SCollisionResult trace, closest; float dist, mindist = 99999.0f; CArray<STriangle> colliding; ZeroMemory(&closest, sizeof(closest)); ZeroMemory(&trace, sizeof(trace)); // Find the collisions with the closest triangles for (int i=0; i<triangles.Size(); i++) { STriangle &t = triangles[i]; CArray<Vector3> vlist; vlist.AddToTail(t.v[0]); vlist.AddToTail(t.v[1]); vlist.AddToTail(t.v[2]); if ( CCollision::OBBPolygon( vlist, start, bboxMax, boxdir, displacement, OUT trace ) ) { if ( trace.fraction <= fraction + 0.1f ) { //if ( trace.fraction < fraction + 0.1f ) colliding.Clear(); // check if all points of our bbox are in front of the face SPlane plane = SPlane( t.v[0], t.v[1], t.v[2] ); Vector3 size = bboxMax * 2.0f; Vector3 min = start - bboxMax; Vector3 max = start + bboxMax; //Debug("collided: %f %f %f", plane.normal.x, plane.normal.y, plane.normal.z); if ( plane.GetSide( min, OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max, OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( min + Vector3( size.x, 0, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( min + Vector3( 0, size.y, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( min + Vector3( 0, 0, size.z ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max - Vector3( size.x, 0, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max - Vector3( 0, size.y, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max - Vector3( 0, 0, size.z ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; fraction = trace.fraction; closest = trace; t.normal = -(t.v[2] - t.v[0]).Cross(t.v[1] - t.v[0]).Normalize(); closest.normal = t.normal; colliding.AddToTail( t ); // add triangle to colliding triangles list //triangleList.Add( t ); //Debug("COLLIDED!"); } } } Vector3 dir = displacement; Vector3 normal = closest.normal; Vector3 endpoint = start; // If collided, process the collision if ( fraction < 1 ) { // OK float m = 0.005f; // distance from the surface float f = closest.fraction; // fraction of the full dir distance to the contact point Vector3 dirNorm = dir; dirNorm.Normalize(); if ( Vector3::Dot( -dir, normal ) != 0 ) { // PERFECT !!! float ndir = dir.Length() * (m / Vector3::Dot( -dir, normal )); float x = (f * dir.Length() - ndir); // distance we move along the dir direction to stay away from the surface //Debug.WriteLine( "normal: " + closest.normal + " x: " + x + " f: " + f + " ndir: " + ndir + " distance to surf: " + mindist + " ndir.Y: " ); endpoint = start + dirNorm * x; Vector3 slide = ClipVelocity( dir, closest.normal, 1.00f ); float left = 1.0f - (f - ndir / dir.Length()); closest.slide = slide * left; } } else endpoint = start + dir; closest.collision = fraction != 1.0f; closest.endpoint = endpoint; return closest; }