//TODO: When transition to 0 grav, push away from surface you were resting on //TODO: When free-floating in air, apply some friction to your trDelta (based on mass?) void G_RunObject( gentity_t *ent ) { vector3 origin, oldOrg; trace_t tr; gentity_t *traceEnt = NULL; //FIXME: floaters need to stop floating up after a while, even if gravity stays negative? if ( ent->s.pos.trType == TR_STATIONARY )//g_gravity.value <= 0 && { ent->s.pos.trType = TR_GRAVITY; VectorCopy( &ent->r.currentOrigin, &ent->s.pos.trBase ); ent->s.pos.trTime = level.previousTime;//?necc? if ( !g_gravity.value ) { ent->s.pos.trDelta.z += 100; } } ent->nextthink = level.time + FRAMETIME; VectorCopy( &ent->r.currentOrigin, &oldOrg ); // get current position BG_EvaluateTrajectory( &ent->s.pos, level.time, &origin ); //Get current angles? BG_EvaluateTrajectory( &ent->s.apos, level.time, &ent->r.currentAngles ); if ( VectorCompare( &ent->r.currentOrigin, &origin ) ) {//error - didn't move at all! return; } // trace a line from the previous position to the current position, // ignoring interactions with the missile owner trap->Trace( &tr, &ent->r.currentOrigin, &ent->r.mins, &ent->r.maxs, &origin, ent->parent ? ent->parent->s.number : ent->s.number, ent->clipmask, qfalse, 0, 0 ); if ( !tr.startsolid && !tr.allsolid && tr.fraction ) { VectorCopy( &tr.endpos, &ent->r.currentOrigin ); trap->LinkEntity( (sharedEntity_t *)ent ); } else //if ( tr.startsolid ) { tr.fraction = 0; } G_MoverTouchPushTriggers( ent, &oldOrg ); /* if ( !(ent->s.eFlags & EF_TELEPORT_BIT) && !(ent->svFlags & SVF_NO_TELEPORT) ) { G_MoverTouchTeleportTriggers( ent, oldOrg ); if ( ent->s.eFlags & EF_TELEPORT_BIT ) {//was teleported return; } } else { ent->s.eFlags &= ~EF_TELEPORT_BIT; } */ if ( tr.fraction == 1 ) { if ( g_gravity.value <= 0 ) { if ( ent->s.apos.trType == TR_STATIONARY ) { VectorCopy( &ent->r.currentAngles, &ent->s.apos.trBase ); ent->s.apos.trType = TR_LINEAR; ent->s.apos.trDelta.y = flrand( -300, 300 ); ent->s.apos.trDelta.x = flrand( -10, 10 ); ent->s.apos.trDelta.z = flrand( -10, 10 ); ent->s.apos.trTime = level.time; } } //friction in zero-G if ( !g_gravity.value ) { float friction = 0.975f; //friction -= ent->mass/1000.0f; if ( friction < 0.1f ) { friction = 0.1f; } VectorScale( &ent->s.pos.trDelta, friction, &ent->s.pos.trDelta ); VectorCopy( &ent->r.currentOrigin, &ent->s.pos.trBase ); ent->s.pos.trTime = level.time; } return; } //hit something //Do impact damage traceEnt = &g_entities[tr.entityNum]; if ( tr.fraction || (traceEnt && traceEnt->takedamage) ) { if ( !VectorCompare( &ent->r.currentOrigin, &oldOrg ) ) {//moved and impacted if ( (traceEnt && traceEnt->takedamage) ) {//hurt someone // G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHurt.wav" ) ); } // G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHit.wav" ) ); } if ( ent->s.weapon != WP_SABER ) { DoImpact( ent, traceEnt, qtrue ); } } if ( !ent || (ent->takedamage&&ent->health <= 0) ) {//been destroyed by impact //chunks? // G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectBreak.wav" ) ); return; } //do impact physics if ( ent->s.pos.trType == TR_GRAVITY )//tr.fraction < 1.0f && {//FIXME: only do this if no trDelta if ( g_gravity.value <= 0 || tr.plane.normal.z < 0.7f ) { if ( ent->flags&(FL_BOUNCE | FL_BOUNCE_HALF) ) { if ( tr.fraction <= 0.0f ) { VectorCopy( &tr.endpos, &ent->r.currentOrigin ); VectorCopy( &tr.endpos, &ent->s.pos.trBase ); VectorClear( &ent->s.pos.trDelta ); ent->s.pos.trTime = level.time; } else { G_BounceObject( ent, &tr ); } } else {//slide down? //FIXME: slide off the slope } } else { ent->s.apos.trType = TR_STATIONARY; pitch_roll_for_slope( ent, &tr.plane.normal ); //ent->r.currentAngles[0] = 0;//FIXME: match to slope //ent->r.currentAngles[2] = 0;//FIXME: match to slope VectorCopy( &ent->r.currentAngles, &ent->s.apos.trBase ); //okay, we hit the floor, might as well stop or prediction will //make us go through the floor! //FIXME: this means we can't fall if something is pulled out from under us... G_StopObjectMoving( ent ); } } else if ( ent->s.weapon != WP_SABER ) { ent->s.apos.trType = TR_STATIONARY; pitch_roll_for_slope( ent, &tr.plane.normal ); //ent->r.currentAngles[0] = 0;//FIXME: match to slope //ent->r.currentAngles[2] = 0;//FIXME: match to slope VectorCopy( &ent->r.currentAngles, &ent->s.apos.trBase ); } //call touch func ent->touch( ent, &g_entities[tr.entityNum], &tr ); }
void G_RunObject( gentity_t *ent ) { vec3_t origin, oldOrg; trace_t tr; gentity_t *traceEnt = NULL; //FIXME: floaters need to stop floating up after a while, even if gravity stays negative? if ( ent->s.pos.trType == TR_STATIONARY )//g_gravity->value <= 0 && { ent->s.pos.trType = TR_GRAVITY; VectorCopy( ent->currentOrigin, ent->s.pos.trBase ); ent->s.pos.trTime = level.previousTime;//?necc? if ( !g_gravity->value ) { ent->s.pos.trDelta[2] += 100; } } ent->nextthink = level.time + FRAMETIME; VectorCopy( ent->currentOrigin, oldOrg ); // get current position EvaluateTrajectory( &ent->s.pos, level.time, origin ); //Get current angles? EvaluateTrajectory( &ent->s.apos, level.time, ent->currentAngles ); if ( VectorCompare( ent->currentOrigin, origin ) ) {//error - didn't move at all! return; } // trace a line from the previous position to the current position, // ignoring interactions with the missile owner gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, ent->owner ? ent->owner->s.number : ent->s.number, ent->clipmask, (EG2_Collision)0, 0 ); if ( !tr.startsolid && !tr.allsolid && tr.fraction ) { VectorCopy( tr.endpos, ent->currentOrigin ); gi.linkentity( ent ); } else //if ( tr.startsolid ) { tr.fraction = 0; } G_MoverTouchPushTriggers( ent, oldOrg ); /* if ( !(ent->s.eFlags & EF_TELEPORT_BIT) && !(ent->svFlags & SVF_NO_TELEPORT) ) { G_MoverTouchTeleportTriggers( ent, oldOrg ); if ( ent->s.eFlags & EF_TELEPORT_BIT ) {//was teleported return; } } else { ent->s.eFlags &= ~EF_TELEPORT_BIT; } */ if ( tr.fraction == 1 ) { if ( g_gravity->value <= 0 ) { if ( ent->s.apos.trType == TR_STATIONARY ) { VectorCopy( ent->currentAngles, ent->s.apos.trBase ); ent->s.apos.trType = TR_LINEAR; ent->s.apos.trDelta[1] = Q_flrand( -300, 300 ); ent->s.apos.trDelta[0] = Q_flrand( -10, 10 ); ent->s.apos.trDelta[2] = Q_flrand( -10, 10 ); ent->s.apos.trTime = level.time; } } //friction in zero-G if ( !g_gravity->value ) { float friction = 0.975f; /*friction -= ent->mass/1000.0f; if ( friction < 0.1 ) { friction = 0.1f; } */ VectorScale( ent->s.pos.trDelta, friction, ent->s.pos.trDelta ); VectorCopy( ent->currentOrigin, ent->s.pos.trBase ); ent->s.pos.trTime = level.time; } return; } //hit something //Do impact damage traceEnt = &g_entities[tr.entityNum]; if ( tr.fraction || (traceEnt && traceEnt->takedamage) ) { if ( !VectorCompare( ent->currentOrigin, oldOrg ) ) {//moved and impacted if ( (traceEnt && traceEnt->takedamage) ) {//hurt someone vec3_t fxDir; VectorNormalize2( ent->s.pos.trDelta, fxDir ); VectorScale( fxDir, -1, fxDir ); G_PlayEffect( G_EffectIndex( "melee/kick_impact" ), tr.endpos, fxDir ); //G_Sound( ent, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) ); } else { G_PlayEffect( G_EffectIndex( "melee/kick_impact_silent" ), tr.endpos, tr.plane.normal ); } if ( ent->mass > 100 ) { G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHitHeavy.wav" ) ); } else { G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHit.wav" ) ); } } DoImpact( ent, traceEnt, !(tr.surfaceFlags&SURF_NODAMAGE), &tr ); } if ( !ent || (ent->takedamage&&ent->health <= 0) ) {//been destroyed by impact //chunks? G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectBreak.wav" ) ); return; } //do impact physics if ( ent->s.pos.trType == TR_GRAVITY )//tr.fraction < 1.0 && {//FIXME: only do this if no trDelta if ( g_gravity->value <= 0 || tr.plane.normal[2] < 0.7 ) { if ( ent->s.eFlags&(EF_BOUNCE|EF_BOUNCE_HALF) ) { if ( tr.fraction <= 0.0f ) { VectorCopy( tr.endpos, ent->currentOrigin ); VectorCopy( tr.endpos, ent->s.pos.trBase ); VectorClear( ent->s.pos.trDelta ); ent->s.pos.trTime = level.time; } else { G_BounceObject( ent, &tr ); } } else {//slide down? //FIXME: slide off the slope } } else { ent->s.apos.trType = TR_STATIONARY; pitch_roll_for_slope( ent, tr.plane.normal ); //ent->currentAngles[0] = 0;//FIXME: match to slope //ent->currentAngles[2] = 0;//FIXME: match to slope VectorCopy( ent->currentAngles, ent->s.apos.trBase ); //okay, we hit the floor, might as well stop or prediction will //make us go through the floor! //FIXME: this means we can't fall if something is pulled out from under us... G_StopObjectMoving( ent ); } } else { ent->s.apos.trType = TR_STATIONARY; pitch_roll_for_slope( ent, tr.plane.normal ); //ent->currentAngles[0] = 0;//FIXME: match to slope //ent->currentAngles[2] = 0;//FIXME: match to slope VectorCopy( ent->currentAngles, ent->s.apos.trBase ); } //call touch func GEntity_TouchFunc( ent, &g_entities[tr.entityNum], &tr ); }