codemp/game/g_object.c

Go to the documentation of this file.
00001 #include "g_local.h"
00002 
00003 extern void G_MoverTouchPushTriggers( gentity_t *ent, vec3_t oldOrg );
00004 void G_StopObjectMoving( gentity_t *object );
00005 
00006 void pitch_roll_for_slope( gentity_t *forwhom, vec3_t pass_slope );
00007 
00008 /*
00009 ================
00010 G_BounceObject
00011 
00012 ================
00013 */
00014 void G_BounceObject( gentity_t *ent, trace_t *trace ) 
00015 {
00016         vec3_t  velocity;
00017         float   dot, bounceFactor;
00018         int             hitTime;
00019 
00020         // reflect the velocity on the trace plane
00021         hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
00022         BG_EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
00023         dot = DotProduct( velocity, trace->plane.normal );
00024 //      bounceFactor = 60/ent->mass;            // NOTENOTE Mass is not yet implemented
00025         bounceFactor = 1.0f;
00026         if ( bounceFactor > 1.0f )
00027         {
00028                 bounceFactor = 1.0f;
00029         }
00030         VectorMA( velocity, -2*dot*bounceFactor, trace->plane.normal, ent->s.pos.trDelta );
00031 
00032         //FIXME: customized or material-based impact/bounce sounds
00033         if ( ent->flags & FL_BOUNCE_HALF ) 
00034         {
00035                 VectorScale( ent->s.pos.trDelta, 0.5, ent->s.pos.trDelta );
00036 
00037                 // check for stop
00038                 if ( ((trace->plane.normal[2] > 0.7&&g_gravity.value>0) || (trace->plane.normal[2]<-0.7&&g_gravity.value<0)) && ((ent->s.pos.trDelta[2]<40&&g_gravity.value>0)||(ent->s.pos.trDelta[2]>-40&&g_gravity.value<0)) ) //this can happen even on very slightly sloped walls, so changed it from > 0 to > 0.7
00039                 {
00040                         //G_SetOrigin( ent, trace->endpos );
00041                         //ent->nextthink = level.time + 500;
00042                         ent->s.apos.trType = TR_STATIONARY;
00043                         VectorCopy( ent->r.currentAngles, ent->s.apos.trBase );
00044                         VectorCopy( trace->endpos, ent->r.currentOrigin );
00045                         VectorCopy( trace->endpos, ent->s.pos.trBase );
00046                         ent->s.pos.trTime = level.time;
00047                         return;
00048                 }
00049         }
00050 
00051         // NEW--It would seem that we want to set our trBase to the trace endpos
00052         //      and set the trTime to the actual time of impact....
00053         //      FIXME: Should we still consider adding the normal though??
00054         VectorCopy( trace->endpos, ent->r.currentOrigin );
00055         ent->s.pos.trTime = hitTime;
00056 
00057         VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
00058         VectorCopy( trace->plane.normal, ent->pos1 );//???
00059 }
00060 
00061 
00062 /*
00063 ================
00064 G_RunObject
00065 
00066   TODO:  When transition to 0 grav, push away from surface you were resting on
00067   TODO:  When free-floating in air, apply some friction to your trDelta (based on mass?)
00068 ================
00069 */
00070 extern void DoImpact( gentity_t *self, gentity_t *other, qboolean damageSelf );
00071 extern void pitch_roll_for_slope( gentity_t *forwhom, vec3_t pass_slope );
00072 void G_RunObject( gentity_t *ent ) 
00073 {
00074         vec3_t          origin, oldOrg;
00075         trace_t         tr;
00076         gentity_t       *traceEnt = NULL;
00077 
00078         //FIXME: floaters need to stop floating up after a while, even if gravity stays negative?
00079         if ( ent->s.pos.trType == TR_STATIONARY )//g_gravity.value <= 0 && 
00080         {
00081                 ent->s.pos.trType = TR_GRAVITY;
00082                 VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
00083                 ent->s.pos.trTime = level.previousTime;//?necc?
00084                 if ( !g_gravity.value )
00085                 {
00086                         ent->s.pos.trDelta[2] += 100;
00087                 }
00088         }
00089 
00090         ent->nextthink = level.time + FRAMETIME;
00091 
00092         VectorCopy( ent->r.currentOrigin, oldOrg );
00093         // get current position
00094         BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
00095         //Get current angles?
00096         BG_EvaluateTrajectory( &ent->s.apos, level.time, ent->r.currentAngles );
00097 
00098         if ( VectorCompare( ent->r.currentOrigin, origin ) )
00099         {//error - didn't move at all!
00100                 return;
00101         }
00102         // trace a line from the previous position to the current position,
00103         // ignoring interactions with the missile owner
00104         trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, 
00105                 ent->parent ? ent->parent->s.number : ent->s.number, ent->clipmask );
00106 
00107         if ( !tr.startsolid && !tr.allsolid && tr.fraction ) 
00108         {
00109                 VectorCopy( tr.endpos, ent->r.currentOrigin );
00110                 trap_LinkEntity( ent );
00111         }
00112         else
00113         //if ( tr.startsolid ) 
00114         {
00115                 tr.fraction = 0;
00116         }
00117 
00118         G_MoverTouchPushTriggers( ent, oldOrg );
00119         /*
00120         if ( !(ent->s.eFlags & EF_TELEPORT_BIT) && !(ent->svFlags & SVF_NO_TELEPORT) )
00121         {
00122                 G_MoverTouchTeleportTriggers( ent, oldOrg );
00123                 if ( ent->s.eFlags & EF_TELEPORT_BIT )
00124                 {//was teleported
00125                         return;
00126                 }
00127         }
00128         else
00129         {
00130                 ent->s.eFlags &= ~EF_TELEPORT_BIT;
00131         }
00132         */
00133 
00134         if ( tr.fraction == 1 ) 
00135         {
00136                 if ( g_gravity.value <= 0 )
00137                 {
00138                         if ( ent->s.apos.trType == TR_STATIONARY )
00139                         {
00140                                 VectorCopy( ent->r.currentAngles, ent->s.apos.trBase );
00141                                 ent->s.apos.trType = TR_LINEAR;
00142                                 ent->s.apos.trDelta[1] = flrand( -300, 300 );
00143                                 ent->s.apos.trDelta[0] = flrand( -10, 10 );
00144                                 ent->s.apos.trDelta[2] = flrand( -10, 10 );
00145                                 ent->s.apos.trTime = level.time;
00146                         }
00147                 }
00148                 //friction in zero-G
00149                 if ( !g_gravity.value )
00150                 {
00151                         float friction = 0.975f;
00152                         //friction -= ent->mass/1000.0f;
00153                         if ( friction < 0.1 )
00154                         {
00155                                 friction = 0.1f;
00156                         }
00157 
00158                         VectorScale( ent->s.pos.trDelta, friction, ent->s.pos.trDelta );
00159                         VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
00160                         ent->s.pos.trTime = level.time;
00161                 }
00162                 return;
00163         }
00164 
00165         //hit something
00166 
00167         //Do impact damage
00168         traceEnt = &g_entities[tr.entityNum];
00169         if ( tr.fraction || (traceEnt && traceEnt->takedamage) )
00170         {
00171                 if ( !VectorCompare( ent->r.currentOrigin, oldOrg ) )
00172                 {//moved and impacted
00173                         if ( (traceEnt && traceEnt->takedamage) )
00174                         {//hurt someone
00175 //                              G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHurt.wav" ) );
00176                         }
00177 //                      G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHit.wav" ) );
00178                 }
00179 
00180                 if (ent->s.weapon != WP_SABER)
00181                 {
00182                         DoImpact( ent, traceEnt, qtrue );
00183                 }
00184         }
00185 
00186         if ( !ent || (ent->takedamage&&ent->health <= 0) )
00187         {//been destroyed by impact
00188                 //chunks?
00189 //              G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectBreak.wav" ) );
00190                 return;
00191         }
00192 
00193         //do impact physics
00194         if ( ent->s.pos.trType == TR_GRAVITY )//tr.fraction < 1.0 && 
00195         {//FIXME: only do this if no trDelta
00196                 if ( g_gravity.value <= 0 || tr.plane.normal[2] < 0.7 )
00197                 {
00198                         if ( ent->flags&(FL_BOUNCE|FL_BOUNCE_HALF) )
00199                         {
00200                                 if ( tr.fraction <= 0.0f )
00201                                 {
00202                                         VectorCopy( tr.endpos, ent->r.currentOrigin );
00203                                         VectorCopy( tr.endpos, ent->s.pos.trBase );
00204                                         VectorClear( ent->s.pos.trDelta );
00205                                         ent->s.pos.trTime = level.time;
00206                                 }
00207                                 else
00208                                 {
00209                                         G_BounceObject( ent, &tr );
00210                                 }
00211                         }
00212                         else
00213                         {//slide down?
00214                                 //FIXME: slide off the slope
00215                         }
00216                 }
00217                 else
00218                 {
00219                         ent->s.apos.trType = TR_STATIONARY;
00220                         pitch_roll_for_slope( ent, tr.plane.normal );
00221                         //ent->r.currentAngles[0] = 0;//FIXME: match to slope
00222                         //ent->r.currentAngles[2] = 0;//FIXME: match to slope
00223                         VectorCopy( ent->r.currentAngles, ent->s.apos.trBase );
00224                         //okay, we hit the floor, might as well stop or prediction will
00225                         //make us go through the floor!
00226                         //FIXME: this means we can't fall if something is pulled out from under us...
00227                         G_StopObjectMoving( ent );
00228                 }
00229         }
00230         else if (ent->s.weapon != WP_SABER)
00231         {
00232                 ent->s.apos.trType = TR_STATIONARY;
00233                 pitch_roll_for_slope( ent, tr.plane.normal );
00234                 //ent->r.currentAngles[0] = 0;//FIXME: match to slope
00235                 //ent->r.currentAngles[2] = 0;//FIXME: match to slope
00236                 VectorCopy( ent->r.currentAngles, ent->s.apos.trBase );
00237         }
00238 
00239         //call touch func
00240         ent->touch( ent, &g_entities[tr.entityNum], &tr );
00241 }
00242 
00243 
00244 void G_StopObjectMoving( gentity_t *object )
00245 {
00246         object->s.pos.trType = TR_STATIONARY;
00247         VectorCopy( object->r.currentOrigin, object->s.origin );
00248         VectorCopy( object->r.currentOrigin, object->s.pos.trBase );
00249         VectorClear( object->s.pos.trDelta );
00250 
00251         /*
00252         //Stop spinning
00253         VectorClear( self->s.apos.trDelta );
00254         vectoangles(trace->plane.normal, self->s.angles);
00255         VectorCopy(self->s.angles, self->r.currentAngles );
00256         VectorCopy(self->s.angles, self->s.apos.trBase);
00257         */
00258 }
00259 
00260 void G_StartObjectMoving( gentity_t *object, vec3_t dir, float speed, trType_t trType )
00261 {
00262         VectorNormalize (dir);
00263 
00264         //object->s.eType = ET_GENERAL;
00265         object->s.pos.trType = trType;
00266         VectorCopy( object->r.currentOrigin, object->s.pos.trBase );
00267         VectorScale(dir, speed, object->s.pos.trDelta );
00268         object->s.pos.trTime = level.time;
00269 
00270         /*
00271         //FIXME: incorporate spin?
00272         vectoangles(dir, object->s.angles);
00273         VectorCopy(object->s.angles, object->s.apos.trBase);
00274         VectorSet(object->s.apos.trDelta, 300, 0, 0 );
00275         object->s.apos.trTime = level.time;
00276         */
00277 
00278         //FIXME: make these objects go through G_RunObject automatically, like missiles do
00279         if ( object->think == NULL )
00280         {
00281                 object->nextthink = level.time + FRAMETIME;
00282                 object->think = G_RunObject;
00283         }
00284         else
00285         {//You're responsible for calling RunObject
00286         }
00287 }