void SV_Physics_Step (edict_t *ent) { qboolean wasonground; qboolean hitsound = false; float *vel; float speed, newspeed, control; float friction; edict_t *groundentity; int mask; // airborn monsters should always check for ground if (!ent->groundentity) M_CheckGround (ent); groundentity = ent->groundentity; SV_CheckVelocity (ent); if (groundentity) wasonground = true; else wasonground = false; if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) SV_AddRotationalFriction (ent); // add gravity except: // flying monsters // swimming monsters who are in the water if (! wasonground) if (!(ent->flags & FL_FLY)) if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) { if (ent->velocity[2] < sv_gravity->value*-0.1) hitsound = true; if (ent->waterlevel == 0) SV_AddGravity (ent); } // friction for flying monsters that have been given vertical velocity if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; friction = sv_friction/3; newspeed = speed - (FRAMETIME * control * friction); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent->velocity[2] *= newspeed; } // friction for flying monsters that have been given vertical velocity if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent->velocity[2] *= newspeed; } if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) { // apply friction // let dead monsters who aren't completely onground slide if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY))) if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) { vel = ent->velocity; speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); if (speed) { friction = sv_friction; control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; newspeed = speed - FRAMETIME*control*friction; if (newspeed < 0) newspeed = 0; newspeed /= speed; vel[0] *= newspeed; vel[1] *= newspeed; } } if (ent->svflags & SVF_MONSTER) mask = MASK_MONSTERSOLID; else mask = MASK_SOLID; SV_FlyMove (ent, FRAMETIME, mask); gi.linkentity (ent); // ======== // PGM - reset this every time they move. // G_touchtriggers will set it back if appropriate ent->gravity = 1.0; // ======== G_TouchTriggers (ent); if (!ent->inuse) return; if (ent->groundentity) if (!wasonground) if (hitsound) gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); } if(!ent->inuse) // PGM g_touchtrigger free problem return; // regular thinking SV_RunThink (ent); }
/* ============= SV_Physics_NewToss Toss, bounce, and fly movement. When on ground and no velocity, do nothing. With velocity, slide. ============= */ void SV_Physics_NewToss (edict_t *ent) { trace_t trace; vec3_t move; // float backoff; edict_t *slave; qboolean wasinwater; qboolean isinwater; qboolean wasonground; float speed, newspeed; vec3_t old_origin; // float firstmove; // int mask; // regular thinking SV_RunThink (ent); // if not a team captain, so movement will be handled elsewhere if ( ent->flags & FL_TEAMSLAVE) return; if (ent->groundentity) wasonground = true; else wasonground = false; wasinwater = ent->waterlevel; // find out what we're sitting on. VectorCopy (ent->s.origin, move); move[2] -= 0.25; trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, move, ent, ent->clipmask); if(ent->groundentity && ent->groundentity->inuse) ent->groundentity = trace.ent; else ent->groundentity = NULL; // if we're sitting on something flat and have no velocity of our own, return. if (ent->groundentity && (trace.plane.normal[2] == 1.0) && !ent->velocity[0] && !ent->velocity[1] && !ent->velocity[2]) { return; } // store the old origin VectorCopy (ent->s.origin, old_origin); SV_CheckVelocity (ent); // add gravity SV_AddGravity (ent); if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) SV_AddRotationalFriction (ent); // add friction speed = VectorLength(ent->velocity); if(ent->waterlevel) // friction for water movement { newspeed = speed - (sv_waterfriction * 6 * ent->waterlevel); if (newspeed < 0) newspeed = 0; newspeed /= speed; VectorScale (ent->velocity, newspeed, ent->velocity); } else if (!ent->groundentity) // friction for air movement { newspeed = speed - ((sv_friction)); if (newspeed < 0) newspeed = 0; newspeed /= speed; VectorScale (ent->velocity, newspeed, ent->velocity); } else // use ground friction { newspeed = speed - (sv_friction * 6); if (newspeed < 0) newspeed = 0; newspeed /= speed; VectorScale (ent->velocity, newspeed, ent->velocity); } SV_FlyMove (ent, FRAMETIME, ent->clipmask); gi.linkentity (ent); G_TouchTriggers (ent); // 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); } }
void SV_Physics_Step (edict_t *ent) { bool wasonground; bool hitsound = false; float *vel; float speed, newspeed, control; float friction; edict_t *groundentity; int mask; // airborn monsters should always check for ground if (!ent->groundentity) M_CheckGround (ent); groundentity = ent->groundentity; SV_CheckVelocity (ent); if (groundentity) wasonground = true; else wasonground = false; if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) SV_AddRotationalFriction (ent); // add gravity except: // flying monsters // swimming monsters who are in the water if (! wasonground) if (!(ent->flags & FL_FLY)) if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) { if (ent->velocity[2] < level.gravity*-0.1) hitsound = true; if (ent->waterlevel == 0) SV_AddGravity (ent); } // friction for flying monsters that have been given vertical velocity if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; friction = sv_friction/3; newspeed = speed - (FRAMETIME * control * friction); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent->velocity[2] *= newspeed; } // friction for flying monsters that have been given vertical velocity if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent->velocity[2] *= newspeed; } if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) { // apply friction // let dead monsters who aren't completely onground slide if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY))) if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) { vel = ent->velocity; speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); if (speed) { friction = sv_friction; control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - FRAMETIME*control*friction; if (newspeed < 0) newspeed = 0; newspeed /= speed; vel[0] *= newspeed; vel[1] *= newspeed; } } if (ent->r.svflags & SVF_MONSTER) mask = MASK_MONSTERSOLID; else mask = MASK_SOLID; SV_FlyMove (ent, FRAMETIME, mask); GClip_LinkEntity (ent); GClip_TouchTriggers (ent); if (ent->groundentity) if (!wasonground) if (hitsound) G_Sound (ent, 0, trap_SoundIndex( S_LAND ), ATTN_NORM); } }
void SV_Physics_Step (edict_t *ent) { qboolean wasonground; qboolean hitsound = false; float *vel; float speed, newspeed, control; float friction; edict_t *groundentity; int mask; int retval; vec3_t oldpos; // BEGIN: Xatrix/Ridah vec3_t old_vel; // END: Xatrix/Ridah // Joseph if (ent->fallerflag) { // Fix if sitting off center think_checkedges(ent); } // airborn monsters should always check for ground if (!ent->groundentity) M_CheckGround (ent); groundentity = ent->groundentity; SV_CheckVelocity (ent); if (groundentity) wasonground = true; else wasonground = false; if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) SV_AddRotationalFriction (ent); // add gravity except: // flying monsters // swimming monsters who are in the water if (! wasonground) if (!(ent->flags & FL_FLY)) if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) { if (ent->velocity[2] < sv_gravity->value*-0.1) hitsound = true; // Ridah, 1-may-99, disabled this to prevent guys getting stuck in water // if (ent->waterlevel == 0) SV_AddGravity (ent); } /* // friction for flying monsters that have been given vertical velocity if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; friction = sv_friction/3; newspeed = speed - (FRAMETIME * control * friction); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent->velocity[2] *= newspeed; } */ // friction for flying monsters that have been given vertical velocity if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel); if (newspeed < 0) newspeed = 0; newspeed /= speed; ent->velocity[2] *= newspeed; } if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) { // apply friction // let dead monsters who aren't completely onground slide if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY))) if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) { vel = ent->velocity; speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); if (speed) { friction = sv_friction; control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - FRAMETIME*control*friction; if (newspeed < 0) newspeed = 0; newspeed /= speed; vel[0] *= newspeed; vel[1] *= newspeed; } } // BEGIN: Xatrix/Ridah // JOSEPH 26-APR-99 if ((ent->svflags & SVF_MONSTER) || (ent->monsterprop)) // END JOSEPH { // if (ent->cast_info.aiflags & AI_PLAYERCLIP) mask = MASK_PLAYERSOLID | CONTENTS_MONSTERCLIP; // else // mask = MASK_MONSTERSOLID; } else mask = MASK_SOLID; VectorCopy (ent->velocity, old_vel); // END: Xatrix/Ridah VectorCopy (ent->s.origin, oldpos ); retval = SV_FlyMove (ent, FRAMETIME, mask); #if 0 // leave this here for now. // Ridah, HACK... sometimes they get stuck, we should debug this properly when we get the time if (!ValidBoxAtLoc( ent->s.origin, ent->mins, ent->maxs, ent, MASK_SOLID )) { // move back to old position and clear velocity int iter=0; VectorCopy (oldpos, ent->s.origin); VectorClear (ent->velocity); // find a good position while (!ValidBoxAtLoc( ent->s.origin, ent->mins, ent->maxs, ent, MASK_SOLID )) { VectorAdd( ent->s.origin, tv((random()-0.5) * 64, (random()-0.5) * 64, (random()-0.5) * 64), ent->s.origin ); if (++iter > 10) break; } // if (iter <= 4) // { // make sure they're on the ground // M_droptofloor( ent ); // } goto exit_vel_check; // get out of here? } #endif // BEGIN: Xatrix/Ridah if (!ent->groundentity || (ent->flags & FL_FLY)) { node_t *land_node; // Ridah, prevent guys getting stuck trying to jump if (VectorDistance( ent->s.origin, oldpos ) < 1 && !ent->groundentity && (ent->last_onground < (level.time - 2))) { ent->velocity[0] = crandom() * 300; ent->velocity[1] = crandom() * 300; if (ent->velocity[2] < -200) ent->velocity[2] = -200; ent->velocity[2] += random() * 350; ent->nav_data.goal_index = 0; ent->last_onground = level.time; } if (ent->velocity[2] > 80 && retval != 20) { // while rising, maintain XY velocity ent->velocity[0] = old_vel[0]; ent->velocity[1] = old_vel[1]; } // see if we've gone passed the landing position if ( !(ent->flags & FL_FLY) && (retval == -1) && (ent->nav_data.goal_index) && (land_node = level.node_data->nodes[ent->nav_data.goal_index-1])) // && (land_node->node_type & NODE_LANDING)) { vec3_t unit_vel, goal_dir, goal_vec; float vel_scale, dist; VectorSubtract( land_node->origin, ent->s.origin, goal_vec ); goal_vec[2] = 0; dist = VectorNormalize2( goal_vec, goal_dir ); if (dist > 16) { VectorCopy( ent->velocity, unit_vel ); unit_vel[2] = 0; vel_scale = VectorNormalize( unit_vel ); if (DotProduct( unit_vel, goal_dir ) < 0.8) { // we've either gone passed, or need some correction vec3_t new_pos; float old_z; if (VectorLength( goal_vec ) < 40) { new_pos[0] = land_node->origin[0]; new_pos[1] = land_node->origin[1]; new_pos[2] = ent->s.origin[2]; if (ValidBoxAtLoc( new_pos, ent->mins, ent->maxs, ent, MASK_PLAYERSOLID | MASK_MONSTERSOLID )) { // move there, it's safe, and clear velocity VectorCopy( new_pos, ent->s.origin ); ent->velocity[0] = ent->velocity[1] = 0; goto exit_vel_check; } } // we need to adjust our velocity if (land_node->origin[2] < (ent->s.origin[2] - 64)) { old_z = ent->velocity[2]; VectorScale( goal_dir, vel_scale, ent->velocity ); ent->velocity[2] = old_z; } } } } if ( (ent->flags & FL_FLY) && ((land_node = level.node_data->nodes[ent->nav_data.goal_index-1]) || ((ent->flags &= ~FL_FLY) && false)) /*&& (land_node->node_type & NODE_LANDING)*/) { // if climbing ladder, and we're reached the landing position, stop // Ridah, 8-jun-99, make sure dog's don't climb ladders if (!ent->gender) { goto abort_climb; } if (ent->s.origin[2] > land_node->origin[2]) { //gi.dprintf( "-> end of climb\n" ); // VectorSubtract( land_node->origin, ent->s.origin, ent->velocity ); AngleVectors( ent->s.angles, ent->velocity, NULL, NULL ); ent->velocity[2] = 0; VectorNormalize( ent->velocity ); VectorScale( ent->velocity, 96, ent->velocity ); ent->velocity[2] = 200; ent->flags &= ~FL_FLY; ent->nav_data.goal_index = 0; // look for a new node ent->nav_data.cache_node = -1; if (ent->cast_info.move_end_climb) ent->cast_info.currentmove = ent->cast_info.move_end_climb; } else { trace_t tr; vec3_t end, goal_vec; VectorSubtract( land_node->origin, ent->s.origin, goal_vec ); ent->velocity[0] = goal_vec[0]; ent->velocity[1] = goal_vec[1]; ent->velocity[2] = 120; // if another character is above us, abort VectorCopy( ent->s.origin, end ); end[2] += 128; tr = gi.trace( ent->s.origin, ent->mins, ent->maxs, end, ent, MASK_PLAYERSOLID | MASK_MONSTERSOLID ); if ((tr.fraction < 1) && (tr.ent->svflags & SVF_MONSTER)) { abort_climb: AngleVectors( ent->s.angles, goal_vec, NULL, NULL ); VectorScale( goal_vec, -64, ent->velocity ); ent->flags &= ~FL_FLY; ent->nav_data.goal_index = 0; if (ent->cast_info.move_end_climb) { ent->cast_info.currentmove = ent->cast_info.move_end_climb; } else if (ent->cast_info.move_jump) { ent->cast_info.currentmove = ent->cast_info.move_jump; } } else if (ent->s.origin[2] > (land_node->origin[2] - 48)) { // we're near the top, stopping climbing anim //gi.dprintf( "near end of climb\n" ); if (ent->cast_info.move_end_climb) ent->cast_info.currentmove = ent->cast_info.move_end_climb; // add some forward momentum AngleVectors( ent->s.angles, goal_vec, NULL, NULL ); VectorMA( ent->velocity, 64, goal_vec, ent->velocity ); } } } } exit_vel_check: // END: Xatrix/Ridah gi.linkentity (ent); G_TouchTriggers (ent); // Note to Ryan: we can't use this because we are playing specific sounds elsewhere /* if (ent->groundentity) if (!wasonground) if (hitsound) // BEGIN: Xatrix/Ridah/Navigator/03-apr-1998 if (!(ent->cast_info.move_run)) // END: Xatrix/Ridah/Navigator/03-apr-1998 gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); */ } // regular thinking SV_RunThink (ent); }
void SV_Physics_Step (edict_t *ent) { qboolean wasonground; qboolean hitsound = false; float *vel; float speed, newspeed, control; float friction; edict_t *groundentity; int mask; if (!ent) { return; } /* airborn monsters should always check for ground */ if (!ent->groundentity) { M_CheckGround(ent); } groundentity = ent->groundentity; SV_CheckVelocity(ent); if (groundentity) { wasonground = true; } else { wasonground = false; } if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) { SV_AddRotationalFriction(ent); } /* add gravity except: - flying monsters - swimming monsters who are in the water */ if (!wasonground) { if (!(ent->flags & FL_FLY)) { if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) { if (ent->velocity[2] < sv_gravity->value * -0.1) { hitsound = true; } if (ent->waterlevel == 0) { SV_AddGravity(ent); } } } } /* friction for flying monsters that have been given vertical velocity */ if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; friction = sv_friction / 3; newspeed = speed - (FRAMETIME * control * friction); if (newspeed < 0) { newspeed = 0; } newspeed /= speed; ent->velocity[2] *= newspeed; } /* friction for flying monsters that have been given vertical velocity */ if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel); if (newspeed < 0) { newspeed = 0; } newspeed /= speed; ent->velocity[2] *= newspeed; } if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) { /* let dead monsters who aren't completely onground slide */ if ((wasonground) || (ent->flags & (FL_SWIM | FL_FLY))) { if (!((ent->health <= 0.0) && !M_CheckBottom(ent))) { vel = ent->velocity; speed = sqrt(vel[0] * vel[0] + vel[1] * vel[1]); if (speed) { friction = sv_friction; control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - FRAMETIME * control * friction; if (newspeed < 0) { newspeed = 0; } newspeed /= speed; vel[0] *= newspeed; vel[1] *= newspeed; } } } if (ent->svflags & SVF_MONSTER) { mask = MASK_MONSTERSOLID; } else { mask = MASK_SOLID; } SV_FlyMove(ent, FRAMETIME, mask); gi.linkentity(ent); G_TouchTriggers(ent); if (!ent->inuse) { return; } if (ent->groundentity) { if (!wasonground) { if (hitsound) { gi.sound(ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); } } } } /* regular thinking */ SV_RunThink(ent); }