codemp/game/g_missile.c File Reference

#include "g_local.h"
#include "w_saber.h"
#include "q_shared.h"
#include "../namespace_begin.h"
#include "../namespace_end.h"

Go to the source code of this file.

Defines

#define MISSILE_PRESTEP_TIME   50

Functions

void laserTrapStick (gentity_t *ent, vec3_t endpos, vec3_t normal)
void Jedi_Decloak (gentity_t *self)
qboolean FighterIsLanded (Vehicle_t *pVeh, playerState_t *parentPS)
float RandFloat (float min, float max)
void G_ReflectMissile (gentity_t *ent, gentity_t *missile, vec3_t forward)
void G_DeflectMissile (gentity_t *ent, gentity_t *missile, vec3_t forward)
void G_BounceMissile (gentity_t *ent, trace_t *trace)
void G_ExplodeMissile (gentity_t *ent)
void G_RunStuckMissile (gentity_t *ent)
void G_BounceProjectile (vec3_t start, vec3_t impact, vec3_t dir, vec3_t endout)
gentity_tCreateMissile (vec3_t org, vec3_t dir, float vel, int life, gentity_t *owner, qboolean altFire)
void G_MissileBounceEffect (gentity_t *ent, vec3_t org, vec3_t dir)
void WP_SaberBlockNonRandom (gentity_t *self, vec3_t hitloc, qboolean missileBlock)
void G_MissileImpact (gentity_t *ent, trace_t *trace)
void G_RunMissile (gentity_t *ent)


Define Documentation

#define MISSILE_PRESTEP_TIME   50
 

Definition at line 7 of file g_missile.c.


Function Documentation

gentity_t* CreateMissile vec3_t  org,
vec3_t  dir,
float  vel,
int  life,
gentity_t owner,
qboolean  altFire
 

Definition at line 291 of file g_missile.c.

References entityShared_t::currentOrigin, EF_ALT_FIRING, entityState_s::eFlags, ET_MISSILE, entityState_s::eType, G_FreeEntity(), G_Spawn(), gentity_t, level, gentity_s::nextthink, NULL, entityState_s::number, entityShared_t::ownerNum, gentity_s::parent, entityState_s::pos, gentity_s::r, gentity_s::s, SVF_USE_CURRENT_ORIGIN, entityShared_t::svFlags, gentity_s::target_ent, gentity_s::think, level_locals_t::time, TR_LINEAR, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, vec3_t, VectorCopy, and VectorScale.

Referenced by EWebFire(), ImperialProbe_FireBlaster(), Mark1_FireBlaster(), Mark1_FireRocket(), Mark1Dead_FireBlaster(), Mark1Dead_FireRocket(), Mark2_FireBlaster(), Remote_Fire(), Seeker_Fire(), Sentry_Fire(), WP_FireBlasterMissile(), WP_FireEmplacedMissile(), WP_FireGenericBlasterMissile(), WP_FireTurboLaserMissile(), WP_FireTurretMissile(), and WP_FireVehicleWeapon().

00294 {
00295         gentity_t       *missile;
00296 
00297         missile = G_Spawn();
00298         
00299         missile->nextthink = level.time + life;
00300         missile->think = G_FreeEntity;
00301         missile->s.eType = ET_MISSILE;
00302         missile->r.svFlags = SVF_USE_CURRENT_ORIGIN;
00303         missile->parent = owner;
00304         missile->r.ownerNum = owner->s.number;
00305 
00306         if (altFire)
00307         {
00308                 missile->s.eFlags |= EF_ALT_FIRING;
00309         }
00310 
00311         missile->s.pos.trType = TR_LINEAR;
00312         missile->s.pos.trTime = level.time;// - MISSILE_PRESTEP_TIME;   // NOTENOTE This is a Quake 3 addition over JK2
00313         missile->target_ent = NULL;
00314 
00315         SnapVector(org);
00316         VectorCopy( org, missile->s.pos.trBase );
00317         VectorScale( dir, vel, missile->s.pos.trDelta );
00318         VectorCopy( org, missile->r.currentOrigin);
00319         SnapVector(missile->s.pos.trDelta);
00320 
00321         return missile;
00322 }

qboolean FighterIsLanded Vehicle_t pVeh,
playerState_t parentPS
 

Definition at line 297 of file FighterNPC.c.

References FighterOverValidLandingSurface(), playerState_t, qboolean, qfalse, qtrue, playerState_s::speed, and Vehicle_t.

Referenced by G_MissileImpact(), and PM_VehicleImpact().

00298 {
00299         if ( FighterOverValidLandingSurface( pVeh )
00300                 && !parentPS->speed )//stopped
00301         {
00302                 return qtrue;
00303         }
00304         return qfalse;
00305 }

void G_BounceMissile gentity_t ent,
trace_t trace
 

Definition at line 148 of file g_missile.c.

References BG_EvaluateTrajectoryDelta(), gentity_s::bounceCount, CHAN_BODY, entityShared_t::currentOrigin, DotProduct, trace_t::endpos, FL_BOUNCE_HALF, FL_BOUNCE_SHRAPNEL, gentity_s::flags, trace_t::fraction, G2_MODEL_PART, G_SetOrigin(), G_Sound(), G_SoundIndex(), gentity_t, level, gentity_s::nextthink, cplane_s::normal, trace_t::plane, entityState_s::pos, level_locals_t::previousTime, Q_irand(), gentity_s::r, gentity_s::s, level_locals_t::time, TR_GRAVITY, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, va(), vec3_t, VectorAdd, VectorCopy, VectorMA, VectorScale, entityState_s::weapon, WP_SABER, and WP_THERMAL.

Referenced by G_MissileImpact().

00148                                                        {
00149         vec3_t  velocity;
00150         float   dot;
00151         int             hitTime;
00152 
00153         // reflect the velocity on the trace plane
00154         hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
00155         BG_EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
00156         dot = DotProduct( velocity, trace->plane.normal );
00157         VectorMA( velocity, -2*dot, trace->plane.normal, ent->s.pos.trDelta );
00158 
00159 
00160         if ( ent->flags & FL_BOUNCE_SHRAPNEL ) 
00161         {
00162                 VectorScale( ent->s.pos.trDelta, 0.25f, ent->s.pos.trDelta );
00163                 ent->s.pos.trType = TR_GRAVITY;
00164 
00165                 // check for stop
00166                 if ( trace->plane.normal[2] > 0.7 && ent->s.pos.trDelta[2] < 40 ) //this can happen even on very slightly sloped walls, so changed it from > 0 to > 0.7
00167                 {
00168                         G_SetOrigin( ent, trace->endpos );
00169                         ent->nextthink = level.time + 100;
00170                         return;
00171                 }
00172         }
00173         else if ( ent->flags & FL_BOUNCE_HALF ) 
00174         {
00175                 VectorScale( ent->s.pos.trDelta, 0.65, ent->s.pos.trDelta );
00176                 // check for stop
00177                 if ( trace->plane.normal[2] > 0.2 && VectorLength( ent->s.pos.trDelta ) < 40 ) 
00178                 {
00179                         G_SetOrigin( ent, trace->endpos );
00180                         return;
00181                 }
00182         }
00183 
00184         if (ent->s.weapon == WP_THERMAL)
00185         { //slight hack for hit sound
00186                 G_Sound(ent, CHAN_BODY, G_SoundIndex(va("sound/weapons/thermal/bounce%i.wav", Q_irand(1, 2))));
00187         }
00188         else if (ent->s.weapon == WP_SABER)
00189         {
00190                 G_Sound(ent, CHAN_BODY, G_SoundIndex(va("sound/weapons/saber/bounce%i.wav", Q_irand(1, 3))));
00191         }
00192         else if (ent->s.weapon == G2_MODEL_PART)
00193         {
00194                 //Limb bounce sound?
00195         }
00196 
00197         VectorAdd( ent->r.currentOrigin, trace->plane.normal, ent->r.currentOrigin);
00198         VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
00199         ent->s.pos.trTime = level.time;
00200 
00201         if (ent->bounceCount != -5)
00202         {
00203                 ent->bounceCount--;
00204         }
00205 }

void G_BounceProjectile vec3_t  start,
vec3_t  impact,
vec3_t  dir,
vec3_t  endout
 

Definition at line 277 of file g_missile.c.

References DotProduct, vec3_t, VectorMA, VectorNormalize(), and VectorSubtract.

00277                                                                                   {
00278         vec3_t v, newv;
00279         float dot;
00280 
00281         VectorSubtract( impact, start, v );
00282         dot = DotProduct( v, dir );
00283         VectorMA( v, -2*dot, dir, newv );
00284 
00285         VectorNormalize(newv);
00286         VectorMA(impact, 8192, newv, endout);
00287 }

void G_DeflectMissile gentity_t ent,
gentity_t missile,
vec3_t  forward
 

Definition at line 91 of file g_missile.c.

References AngleVectors(), gentity_s::client, entityShared_t::currentOrigin, DotProduct, G2_MODEL_PART, gentity_t, level, gentity_s::nextthink, entityState_s::number, entityShared_t::ownerNum, entityState_s::pos, gclient_s::ps, gentity_s::r, RandFloat(), gentity_s::s, gentity_s::think, level_locals_t::time, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, vec3_t, VectorCopy, VectorNormalize(), VectorScale, playerState_s::viewangles, entityState_s::weapon, WP_ROCKET_LAUNCHER, and WP_SABER.

Referenced by G_MissileImpact().

00092 {
00093         vec3_t  bounce_dir;
00094         int             i;
00095         float   speed;
00096         int             isowner = 0;
00097         vec3_t missile_dir;
00098 
00099         if (missile->r.ownerNum == ent->s.number)
00100         { //the original owner is bouncing the missile, so don't try to bounce it back at him
00101                 isowner = 1;
00102         }
00103 
00104         //save the original speed
00105         speed = VectorNormalize( missile->s.pos.trDelta );
00106 
00107         if (ent->client)
00108         {
00109                 //VectorSubtract( ent->r.currentOrigin, missile->r.currentOrigin, missile_dir );
00110                 AngleVectors(ent->client->ps.viewangles, missile_dir, 0, 0);
00111                 VectorCopy(missile_dir, bounce_dir);
00112                 //VectorCopy( missile->s.pos.trDelta, bounce_dir );
00113                 VectorScale( bounce_dir, DotProduct( forward, missile_dir ), bounce_dir );
00114                 VectorNormalize( bounce_dir );
00115         }
00116         else
00117         {
00118                 VectorCopy(forward, bounce_dir);
00119                 VectorNormalize(bounce_dir);
00120         }
00121 
00122         for ( i = 0; i < 3; i++ )
00123         {
00124                 bounce_dir[i] += RandFloat( -1.0f, 1.0f );
00125         }
00126 
00127         VectorNormalize( bounce_dir );
00128         VectorScale( bounce_dir, speed, missile->s.pos.trDelta );
00129         missile->s.pos.trTime = level.time;             // move a bit on the very first frame
00130         VectorCopy( missile->r.currentOrigin, missile->s.pos.trBase );
00131         if ( missile->s.weapon != WP_SABER && missile->s.weapon != G2_MODEL_PART )
00132         {//you are mine, now!
00133                 missile->r.ownerNum = ent->s.number;
00134         }
00135         if ( missile->s.weapon == WP_ROCKET_LAUNCHER )
00136         {//stop homing
00137                 missile->think = 0;
00138                 missile->nextthink = 0;
00139         }
00140 }

void G_ExplodeMissile gentity_t ent  ) 
 

Definition at line 215 of file g_missile.c.

References gentity_s::activator, BG_EvaluateTrajectory(), entityShared_t::currentOrigin, DirToByte(), ET_GENERAL, entityState_s::eType, EV_MISSILE_MISS, gentity_s::freeAfterEvent, G_AddEvent(), g_entities, G_RadiusDamage(), G_SetOrigin(), gentity_t, level, entityState_s::number, gentity_s::parent, entityState_s::pos, qfalse, qtrue, gentity_s::r, gentity_s::s, gentity_s::splashDamage, gentity_s::splashMethodOfDeath, gentity_s::splashRadius, gentity_s::takedamage, level_locals_t::time, trap_LinkEntity(), and vec3_t.

Referenced by RocketDie().

00215                                         {
00216         vec3_t          dir;
00217         vec3_t          origin;
00218 
00219         BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
00220         SnapVector( origin );
00221         G_SetOrigin( ent, origin );
00222 
00223         // we don't have a valid direction, so just point straight up
00224         dir[0] = dir[1] = 0;
00225         dir[2] = 1;
00226 
00227         ent->s.eType = ET_GENERAL;
00228         G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( dir ) );
00229 
00230         ent->freeAfterEvent = qtrue;
00231 
00232         ent->takedamage = qfalse;
00233         // splash damage
00234         if ( ent->splashDamage ) {
00235                 if( G_RadiusDamage( ent->r.currentOrigin, ent->parent, ent->splashDamage, ent->splashRadius, ent, 
00236                                 ent, ent->splashMethodOfDeath ) ) 
00237                 {
00238                         if (ent->parent)
00239                         {
00240                                 g_entities[ent->parent->s.number].client->accuracy_hits++;
00241                         }
00242                         else if (ent->activator)
00243                         {
00244                                 g_entities[ent->activator->s.number].client->accuracy_hits++;
00245                         }
00246                 }
00247         }
00248 
00249         trap_LinkEntity( ent );
00250 }

void G_MissileBounceEffect gentity_t ent,
vec3_t  org,
vec3_t  dir
 

Definition at line 324 of file g_missile.c.

References entityState_s::angles, entityShared_t::currentOrigin, EV_SABER_BLOCK, entityState_s::eventParm, G_EffectIndex(), G_PlayEffectID(), G_TempEntity(), gentity_t, entityState_s::legsAnim, entityState_s::origin, gentity_s::r, gentity_s::s, vec3_t, VectorCopy, entityState_s::weapon, WP_BLASTER, WP_BOWCASTER, and WP_BRYAR_PISTOL.

Referenced by G_MissileImpact().

00325 {
00326         //FIXME: have an EV_BOUNCE_MISSILE event that checks the s.weapon and does the appropriate effect
00327         switch( ent->s.weapon )
00328         {
00329         case WP_BOWCASTER:
00330                 G_PlayEffectID( G_EffectIndex("bowcaster/deflect"), ent->r.currentOrigin, dir );
00331                 break;
00332         case WP_BLASTER:
00333         case WP_BRYAR_PISTOL:
00334                 G_PlayEffectID( G_EffectIndex("blaster/deflect"), ent->r.currentOrigin, dir );
00335                 break;
00336         default:
00337                 {
00338                         gentity_t *te = G_TempEntity( org, EV_SABER_BLOCK );
00339                         VectorCopy(org, te->s.origin);
00340                         VectorCopy(dir, te->s.angles);
00341                         te->s.eventParm = 0;
00342                         te->s.weapon = 0;//saberNum
00343                         te->s.legsAnim = 0;//bladeNum
00344                 }
00345                 break;
00346         }
00347 }

void G_MissileImpact gentity_t ent,
trace_t trace
 

Definition at line 355 of file g_missile.c.

References entityState_s::angles, AngleVectors(), BG_EvaluateTrajectoryDelta(), gentity_s::bounceCount, CLASS_ATST, CLASS_GONK, CLASS_INTERROGATOR, CLASS_MARK1, CLASS_MARK2, CLASS_MOUSE, CLASS_PROBE, CLASS_R2D2, CLASS_R5D2, CLASS_REMOTE, CLASS_SEEKER, CLASS_SENTRY, class_t, CLASS_VEHICLE, gentity_s::classname, gentity_s::client, gclient_s::cloakToggleTime, clientPersistant_t::cmd, entityShared_t::contents, CONTENTS_LIGHTSABER, entityShared_t::currentAngles, entityShared_t::currentOrigin, gentity_s::damage, DAMAGE_HALF_ABSORB, DAMAGE_HEAVY_WEAP_CLASS, gentity_s::dflags, DirToByte(), playerState_s::duelIndex, playerState_s::duelInProgress, EF_ALT_FIRING, EF_MISSILE_STICK, entityState_s::eFlags, playerState_s::electrifyTime, trace_t::endpos, trace_t::entityNum, ET_GENERAL, entityState_s::eType, EV_GRENADE_BOUNCE, EV_MISSILE_HIT, EV_MISSILE_MISS, EV_MISSILE_MISS_METAL, EV_MISSILE_STICK, EV_SABER_BLOCK, entityState_s::eventParm, playerState_s::fd, FighterIsLanded(), FL_BOUNCE, FL_BOUNCE_HALF, FL_BOUNCE_SHRAPNEL, FL_DMG_BY_HEAVY_WEAP_ONLY, FL_SHIELDED, gentity_s::flags, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forcePowerLevel, usercmd_s::forwardmove, FP_SABER_DEFENSE, gentity_s::freeAfterEvent, G2_MODEL_PART, G_AddEvent(), G_BounceMissile(), G_Damage(), G_DeflectMissile(), g_entities, G_MissileBounceEffect(), G_RadiusDamage(), G_ReflectMissile(), G_SetOrigin(), G_TempEntity(), gentity_t, Jedi_Decloak(), laserTrapStick(), entityState_s::legsAnim, level, LogAccuracyHit(), gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, gentity_s::methodOfDeath, MOD_CONC, MOD_CONC_ALT, MOD_DEMP2_ALT, MOD_DET_PACK_SPLASH, MOD_FLECHETTE_ALT_SPLASH, MOD_REPEATER_ALT, MOD_ROCKET, MOD_ROCKET_HOMING, MOD_SABER, MOD_THERMAL, MOD_THERMAL_SPLASH, MOD_TIMED_MINE_SPLASH, MOD_TRIP_MINE_SPLASH, MOD_TURBLAST, MOD_VEHICLE, gentity_s::neverFree, cplane_s::normal, gclient_s::NPC_class, NULL, entityState_s::number, entityState_s::origin, entityState_s::otherEntityNum, entityShared_t::ownerNum, gentity_s::parent, gclient_s::pers, trace_t::plane, entityState_s::pos, playerState_s::powerups, gclient_s::ps, PW_CLOAKED, Q3_INFINITE, Q_irand(), Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, playerState_s::saberBlockTime, playerState_s::saberEventFlags, SEF_DEFLECTED, SnapVectorTowards(), gentity_s::spawnflags, gentity_s::splashDamage, gentity_s::splashMethodOfDeath, gentity_s::splashRadius, SURF_FORCEFIELD, SURF_METALSTEPS, trace_t::surfaceFlags, gentity_s::takedamage, gentity_s::think, level_locals_t::time, trap_LinkEntity(), trajectory_t::trBase, vehicleInfo_t::type, vec3_t, VectorCopy, playerState_s::velocity, VH_FIGHTER, VH_SPEEDER, playerState_s::viewangles, entityState_s::weapon, playerState_s::weaponTime, WP_BOWCASTER, WP_DEMP2, WP_DET_PACK, WP_EMPLACED_GUN, WP_FLECHETTE, WP_ROCKET_LAUNCHER, WP_SABER, WP_SaberBlockNonRandom(), WP_SaberCanBlock(), WP_THERMAL, and WP_TRIP_MINE.

Referenced by G_RunMissile(), and WP_TouchVehMissile().

00355                                                        {
00356         gentity_t               *other;
00357         qboolean                hitClient = qfalse;
00358         qboolean                isKnockedSaber = qfalse;
00359 
00360         other = &g_entities[trace->entityNum];
00361 
00362         // check for bounce
00363         if ( !other->takedamage &&
00364                 (ent->bounceCount > 0 || ent->bounceCount == -5) &&
00365                 ( ent->flags & ( FL_BOUNCE | FL_BOUNCE_HALF ) ) ) {
00366                 G_BounceMissile( ent, trace );
00367                 G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
00368                 return;
00369         }
00370         else if (ent->neverFree && ent->s.weapon == WP_SABER && (ent->flags & FL_BOUNCE_HALF))
00371         { //this is a knocked-away saber
00372                 if (ent->bounceCount > 0 || ent->bounceCount == -5)
00373                 {
00374                         G_BounceMissile( ent, trace );
00375                         G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
00376                         return;
00377                 }
00378 
00379                 isKnockedSaber = qtrue;
00380         }
00381         
00382         // I would glom onto the FL_BOUNCE code section above, but don't feel like risking breaking something else
00383         if ( (!other->takedamage && (ent->bounceCount > 0 || ent->bounceCount == -5) && ( ent->flags&(FL_BOUNCE_SHRAPNEL) ) ) || ((trace->surfaceFlags&SURF_FORCEFIELD)&&!ent->splashDamage&&!ent->splashRadius&&(ent->bounceCount > 0 || ent->bounceCount == -5)) ) 
00384         {
00385                 G_BounceMissile( ent, trace );
00386 
00387                 if ( ent->bounceCount < 1 )
00388                 {
00389                         ent->flags &= ~FL_BOUNCE_SHRAPNEL;
00390                 }
00391                 return;
00392         }
00393 
00394         /*
00395         if ( !other->takedamage && ent->s.weapon == WP_THERMAL && !ent->alt_fire )
00396         {//rolling thermal det - FIXME: make this an eFlag like bounce & stick!!!
00397                 //G_BounceRollMissile( ent, trace );
00398                 if ( ent->owner && ent->owner->s.number == 0 ) 
00399                 {
00400                         G_MissileAddAlerts( ent );
00401                 }
00402                 //gi.linkentity( ent );
00403                 return;
00404         }
00405         */
00406 
00407         if ((other->r.contents & CONTENTS_LIGHTSABER) && !isKnockedSaber)
00408         { //hit this person's saber, so..
00409                 gentity_t *otherOwner = &g_entities[other->r.ownerNum];
00410 
00411                 if (otherOwner->takedamage && otherOwner->client && otherOwner->client->ps.duelInProgress &&
00412                         otherOwner->client->ps.duelIndex != ent->r.ownerNum)
00413                 {
00414                         goto killProj;
00415                 }
00416         }
00417         else if (!isKnockedSaber)
00418         {
00419                 if (other->takedamage && other->client && other->client->ps.duelInProgress &&
00420                         other->client->ps.duelIndex != ent->r.ownerNum)
00421                 {
00422                         goto killProj;
00423                 }
00424         }
00425 
00426         if (other->flags & FL_DMG_BY_HEAVY_WEAP_ONLY)
00427         {
00428                 if (ent->methodOfDeath != MOD_REPEATER_ALT &&
00429                         ent->methodOfDeath != MOD_ROCKET &&
00430                         ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH &&
00431                         ent->methodOfDeath != MOD_ROCKET_HOMING &&
00432                         ent->methodOfDeath != MOD_THERMAL &&
00433                         ent->methodOfDeath != MOD_THERMAL_SPLASH &&
00434                         ent->methodOfDeath != MOD_TRIP_MINE_SPLASH &&
00435                         ent->methodOfDeath != MOD_TIMED_MINE_SPLASH &&
00436                         ent->methodOfDeath != MOD_DET_PACK_SPLASH &&
00437                         ent->methodOfDeath != MOD_VEHICLE &&
00438                         ent->methodOfDeath != MOD_CONC &&
00439                         ent->methodOfDeath != MOD_CONC_ALT &&
00440                         ent->methodOfDeath != MOD_SABER &&
00441                         ent->methodOfDeath != MOD_TURBLAST)
00442                 {
00443                         vec3_t fwd;
00444 
00445                         if (trace)
00446                         {
00447                                 VectorCopy(trace->plane.normal, fwd);
00448                         }
00449                         else
00450                         { //oh well
00451                                 AngleVectors(other->r.currentAngles, fwd, NULL, NULL);
00452                         }
00453 
00454                         G_DeflectMissile(other, ent, fwd);
00455                         G_MissileBounceEffect(ent, ent->r.currentOrigin, fwd);
00456                         return;
00457                 }
00458         }
00459 
00460         if ((other->flags & FL_SHIELDED) &&
00461                 ent->s.weapon != WP_ROCKET_LAUNCHER &&
00462                 ent->s.weapon != WP_THERMAL &&
00463                 ent->s.weapon != WP_TRIP_MINE &&
00464                 ent->s.weapon != WP_DET_PACK &&
00465                 ent->s.weapon != WP_DEMP2 &&
00466                 ent->s.weapon != WP_EMPLACED_GUN &&
00467                 ent->methodOfDeath != MOD_REPEATER_ALT &&
00468                 ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH && 
00469                 ent->methodOfDeath != MOD_TURBLAST &&
00470                 ent->methodOfDeath != MOD_VEHICLE &&
00471                 ent->methodOfDeath != MOD_CONC &&
00472                 ent->methodOfDeath != MOD_CONC_ALT &&
00473                 !(ent->dflags&DAMAGE_HEAVY_WEAP_CLASS) )
00474         {
00475                 vec3_t fwd;
00476 
00477                 if (other->client)
00478                 {
00479                         AngleVectors(other->client->ps.viewangles, fwd, NULL, NULL);
00480                 }
00481                 else
00482                 {
00483                         AngleVectors(other->r.currentAngles, fwd, NULL, NULL);
00484                 }
00485 
00486                 G_DeflectMissile(other, ent, fwd);
00487                 G_MissileBounceEffect(ent, ent->r.currentOrigin, fwd);
00488                 return;
00489         }
00490                 
00491         if (other->takedamage && other->client &&
00492                 ent->s.weapon != WP_ROCKET_LAUNCHER &&
00493                 ent->s.weapon != WP_THERMAL &&
00494                 ent->s.weapon != WP_TRIP_MINE &&
00495                 ent->s.weapon != WP_DET_PACK &&
00496                 ent->s.weapon != WP_DEMP2 &&
00497                 ent->methodOfDeath != MOD_REPEATER_ALT &&
00498                 ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH &&
00499                 ent->methodOfDeath != MOD_CONC &&
00500                 ent->methodOfDeath != MOD_CONC_ALT &&
00501                 other->client->ps.saberBlockTime < level.time &&
00502                 !isKnockedSaber &&
00503                 WP_SaberCanBlock(other, ent->r.currentOrigin, 0, 0, qtrue, 0))
00504         { //only block one projectile per 200ms (to prevent giant swarms of projectiles being blocked)
00505                 vec3_t fwd;
00506                 gentity_t *te;
00507                 int otherDefLevel = other->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE];
00508 
00509                 te = G_TempEntity( ent->r.currentOrigin, EV_SABER_BLOCK );
00510                 VectorCopy(ent->r.currentOrigin, te->s.origin);
00511                 VectorCopy(trace->plane.normal, te->s.angles);
00512                 te->s.eventParm = 0;
00513                 te->s.weapon = 0;//saberNum
00514                 te->s.legsAnim = 0;//bladeNum
00515 
00516                 /*if (other->client->ps.velocity[2] > 0 ||
00517                         other->client->pers.cmd.forwardmove ||
00518                         other->client->pers.cmd.rightmove)
00519                         */
00520                 if (other->client->ps.velocity[2] > 0 ||
00521                         other->client->pers.cmd.forwardmove < 0) //now we only do it if jumping or running backward. Should be able to full-on charge.
00522                 {
00523                         otherDefLevel -= 1;
00524                         if (otherDefLevel < 0)
00525                         {
00526                                 otherDefLevel = 0;
00527                         }
00528                 }
00529 
00530                 AngleVectors(other->client->ps.viewangles, fwd, NULL, NULL);
00531                 if (otherDefLevel == FORCE_LEVEL_1)
00532                 {
00533                         //if def is only level 1, instead of deflecting the shot it should just die here
00534                 }
00535                 else if (otherDefLevel == FORCE_LEVEL_2)
00536                 {
00537                         G_DeflectMissile(other, ent, fwd);
00538                 }
00539                 else
00540                 {
00541                         G_ReflectMissile(other, ent, fwd);
00542                 }
00543                 other->client->ps.saberBlockTime = level.time + (350 - (otherDefLevel*100)); //200;
00544 
00545                 //For jedi AI
00546                 other->client->ps.saberEventFlags |= SEF_DEFLECTED;
00547 
00548                 if (otherDefLevel == FORCE_LEVEL_3)
00549                 {
00550                         other->client->ps.saberBlockTime = 0; //^_^
00551                 }
00552 
00553                 if (otherDefLevel == FORCE_LEVEL_1)
00554                 {
00555                         goto killProj;
00556                 }
00557                 return;
00558         }
00559         else if ((other->r.contents & CONTENTS_LIGHTSABER) && !isKnockedSaber)
00560         { //hit this person's saber, so..
00561                 gentity_t *otherOwner = &g_entities[other->r.ownerNum];
00562 
00563                 if (otherOwner->takedamage && otherOwner->client &&
00564                         ent->s.weapon != WP_ROCKET_LAUNCHER &&
00565                         ent->s.weapon != WP_THERMAL &&
00566                         ent->s.weapon != WP_TRIP_MINE &&
00567                         ent->s.weapon != WP_DET_PACK &&
00568                         ent->s.weapon != WP_DEMP2 &&
00569                         ent->methodOfDeath != MOD_REPEATER_ALT &&
00570                         ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH &&
00571                         ent->methodOfDeath != MOD_CONC &&
00572                         ent->methodOfDeath != MOD_CONC_ALT /*&&
00573                         otherOwner->client->ps.saberBlockTime < level.time*/)
00574                 { //for now still deflect even if saberBlockTime >= level.time because it hit the actual saber
00575                         vec3_t fwd;
00576                         gentity_t *te;
00577                         int otherDefLevel = otherOwner->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE];
00578 
00579                         //in this case, deflect it even if we can't actually block it because it hit our saber
00580                         //WP_SaberCanBlock(otherOwner, ent->r.currentOrigin, 0, 0, qtrue, 0);
00581                         if (otherOwner->client && otherOwner->client->ps.weaponTime <= 0)
00582                         {
00583                                 WP_SaberBlockNonRandom(otherOwner, ent->r.currentOrigin, qtrue);
00584                         }
00585 
00586                         te = G_TempEntity( ent->r.currentOrigin, EV_SABER_BLOCK );
00587                         VectorCopy(ent->r.currentOrigin, te->s.origin);
00588                         VectorCopy(trace->plane.normal, te->s.angles);
00589                         te->s.eventParm = 0;
00590                         te->s.weapon = 0;//saberNum
00591                         te->s.legsAnim = 0;//bladeNum
00592 
00593                         /*if (otherOwner->client->ps.velocity[2] > 0 ||
00594                                 otherOwner->client->pers.cmd.forwardmove ||
00595                                 otherOwner->client->pers.cmd.rightmove)*/
00596                         if (otherOwner->client->ps.velocity[2] > 0 ||
00597                                 otherOwner->client->pers.cmd.forwardmove < 0) //now we only do it if jumping or running backward. Should be able to full-on charge.
00598                         {
00599                                 otherDefLevel -= 1;
00600                                 if (otherDefLevel < 0)
00601                                 {
00602                                         otherDefLevel = 0;
00603                                 }
00604                         }
00605 
00606                         AngleVectors(otherOwner->client->ps.viewangles, fwd, NULL, NULL);
00607 
00608                         if (otherDefLevel == FORCE_LEVEL_1)
00609                         {
00610                                 //if def is only level 1, instead of deflecting the shot it should just die here
00611                         }
00612                         else if (otherDefLevel == FORCE_LEVEL_2)
00613                         {
00614                                 G_DeflectMissile(otherOwner, ent, fwd);
00615                         }
00616                         else
00617                         {
00618                                 G_ReflectMissile(otherOwner, ent, fwd);
00619                         }
00620                         otherOwner->client->ps.saberBlockTime = level.time + (350 - (otherDefLevel*100));//200;
00621 
00622                         //For jedi AI
00623                         otherOwner->client->ps.saberEventFlags |= SEF_DEFLECTED;
00624 
00625                         if (otherDefLevel == FORCE_LEVEL_3)
00626                         {
00627                                 otherOwner->client->ps.saberBlockTime = 0; //^_^
00628                         }
00629 
00630                         if (otherDefLevel == FORCE_LEVEL_1)
00631                         {
00632                                 goto killProj;
00633                         }
00634                         return;
00635                 }
00636         }
00637 
00638         // check for sticking
00639         if ( !other->takedamage && ( ent->s.eFlags & EF_MISSILE_STICK ) ) 
00640         {
00641                 laserTrapStick( ent, trace->endpos, trace->plane.normal );
00642                 G_AddEvent( ent, EV_MISSILE_STICK, 0 );
00643                 return;
00644         }
00645 
00646         // impact damage
00647         if (other->takedamage && !isKnockedSaber) {
00648                 // FIXME: wrong damage direction?
00649                 if ( ent->damage ) {
00650                         vec3_t  velocity;
00651                         qboolean didDmg = qfalse;
00652 
00653                         if( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) {
00654                                 g_entities[ent->r.ownerNum].client->accuracy_hits++;
00655                                 hitClient = qtrue;
00656                         }
00657                         BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
00658                         if ( VectorLength( velocity ) == 0 ) {
00659                                 velocity[2] = 1;        // stepped on a grenade
00660                         }
00661 
00662                         if (ent->s.weapon == WP_BOWCASTER || ent->s.weapon == WP_FLECHETTE ||
00663                                 ent->s.weapon == WP_ROCKET_LAUNCHER)
00664                         {
00665                                 if (ent->s.weapon == WP_FLECHETTE && (ent->s.eFlags & EF_ALT_FIRING))
00666                                 {
00667                                         ent->think(ent);
00668                                 }
00669                                 else
00670                                 {
00671                                         G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
00672                                                 /*ent->s.origin*/ent->r.currentOrigin, ent->damage, 
00673                                                 DAMAGE_HALF_ABSORB, ent->methodOfDeath);
00674                                         didDmg = qtrue;
00675                                 }
00676                         }
00677                         else
00678                         {
00679                                 G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
00680                                         /*ent->s.origin*/ent->r.currentOrigin, ent->damage, 
00681                                         0, ent->methodOfDeath);
00682                                 didDmg = qtrue;
00683                         }
00684 
00685                         if (didDmg && other && other->client)
00686                         { //What I'm wondering is why this isn't in the NPC pain funcs. But this is what SP does, so whatever.
00687                                 class_t npc_class = other->client->NPC_class;
00688 
00689                                 // If we are a robot and we aren't currently doing the full body electricity...
00690                                 if ( npc_class == CLASS_SEEKER || npc_class == CLASS_PROBE || npc_class == CLASS_MOUSE ||
00691                                            npc_class == CLASS_GONK || npc_class == CLASS_R2D2 || npc_class == CLASS_R5D2 || npc_class == CLASS_REMOTE ||
00692                                            npc_class == CLASS_MARK1 || npc_class == CLASS_MARK2 || //npc_class == CLASS_PROTOCOL ||//no protocol, looks odd
00693                                            npc_class == CLASS_INTERROGATOR || npc_class == CLASS_ATST || npc_class == CLASS_SENTRY )
00694                                 {
00695                                         // special droid only behaviors
00696                                         if ( other->client->ps.electrifyTime < level.time + 100 )
00697                                         {
00698                                                 // ... do the effect for a split second for some more feedback
00699                                                 other->client->ps.electrifyTime = level.time + 450;
00700                                         }
00701                                         //FIXME: throw some sparks off droids,too
00702                                 }
00703                         }
00704                 }
00705 
00706                 if ( ent->s.weapon == WP_DEMP2 )
00707                 {//a hit with demp2 decloaks people, disables ships
00708                         if ( other && other->client && other->client->NPC_class == CLASS_VEHICLE )
00709                         {//hit a vehicle
00710                                 if ( other->m_pVehicle //valid vehicle ent
00711                                         && other->m_pVehicle->m_pVehicleInfo//valid stats
00712                                         && (other->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER//always affect speeders
00713                                                 ||(other->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER && ent->classname && Q_stricmp("vehicle_proj", ent->classname ) == 0) )//only vehicle ion weapons affect a fighter in this manner
00714                                         && !FighterIsLanded( other->m_pVehicle , &other->client->ps )//not landed
00715                                         && !(other->spawnflags&2) )//and not suspended
00716                                 {//vehicles hit by "ion cannons" lose control
00717                                         if ( other->client->ps.electrifyTime > level.time )
00718                                         {//add onto it
00719                                                 //FIXME: extern the length of the "out of control" time?
00720                                                 other->client->ps.electrifyTime += Q_irand(200,500);
00721                                                 if ( other->client->ps.electrifyTime > level.time + 4000 )
00722                                                 {//cap it
00723                                                         other->client->ps.electrifyTime = level.time + 4000;
00724                                                 }
00725                                         }
00726                                         else
00727                                         {//start it
00728                                                 //FIXME: extern the length of the "out of control" time?
00729                                                 other->client->ps.electrifyTime = level.time + Q_irand(200,500);
00730                                         }
00731                                 }
00732                         }
00733                         else if ( other && other->client && other->client->ps.powerups[PW_CLOAKED] )
00734                         {
00735                                 Jedi_Decloak( other );
00736                                 if ( ent->methodOfDeath == MOD_DEMP2_ALT )
00737                                 {//direct hit with alt disables cloak forever
00738                                         //permanently disable the saboteur's cloak
00739                                         other->client->cloakToggleTime = Q3_INFINITE;
00740                                 }
00741                                 else
00742                                 {//temp disable
00743                                         other->client->cloakToggleTime = level.time + Q_irand( 3000, 10000 );
00744                                 }
00745                         }
00746                 }
00747         }
00748 killProj:
00749         // is it cheaper in bandwidth to just remove this ent and create a new
00750         // one, rather than changing the missile into the explosion?
00751 
00752         if ( other->takedamage && other->client && !isKnockedSaber ) {
00753                 G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
00754                 ent->s.otherEntityNum = other->s.number;
00755         } else if( trace->surfaceFlags & SURF_METALSTEPS ) {
00756                 G_AddEvent( ent, EV_MISSILE_MISS_METAL, DirToByte( trace->plane.normal ) );
00757         } else if (ent->s.weapon != G2_MODEL_PART && !isKnockedSaber) {
00758                 G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
00759         }
00760 
00761         if (!isKnockedSaber)
00762         {
00763                 ent->freeAfterEvent = qtrue;
00764 
00765                 // change over to a normal entity right at the point of impact
00766                 ent->s.eType = ET_GENERAL;
00767         }
00768 
00769         SnapVectorTowards( trace->endpos, ent->s.pos.trBase );  // save net bandwidth
00770 
00771         G_SetOrigin( ent, trace->endpos );
00772 
00773         ent->takedamage = qfalse;
00774         // splash damage (doesn't apply to person directly hit)
00775         if ( ent->splashDamage ) {
00776                 if( G_RadiusDamage( trace->endpos, ent->parent, ent->splashDamage, ent->splashRadius, 
00777                         other, ent, ent->splashMethodOfDeath ) ) {
00778                         if( !hitClient 
00779                                 && g_entities[ent->r.ownerNum].client ) {
00780                                 g_entities[ent->r.ownerNum].client->accuracy_hits++;
00781                         }
00782                 }
00783         }
00784 
00785         if (ent->s.weapon == G2_MODEL_PART)
00786         {
00787                 ent->freeAfterEvent = qfalse; //it will free itself
00788         }
00789 
00790         trap_LinkEntity( ent );
00791 }

void G_ReflectMissile gentity_t ent,
gentity_t missile,
vec3_t  forward
 

Definition at line 24 of file g_missile.c.

References entityShared_t::currentOrigin, DotProduct, G2_MODEL_PART, g_entities, gentity_t, level, gentity_s::nextthink, entityState_s::number, entityShared_t::ownerNum, entityState_s::pos, gentity_s::r, RandFloat(), gentity_s::s, gentity_s::think, level_locals_t::time, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, vec3_t, VectorCopy, VectorNormalize(), VectorScale, VectorSubtract, entityState_s::weapon, WP_ROCKET_LAUNCHER, and WP_SABER.

Referenced by ForceThrow(), and G_MissileImpact().

00025 {
00026         vec3_t  bounce_dir;
00027         int             i;
00028         float   speed;
00029         gentity_t       *owner = ent;
00030         int             isowner = 0;
00031 
00032         if ( ent->r.ownerNum )
00033         {
00034                 owner = &g_entities[ent->r.ownerNum];
00035         }
00036 
00037         if (missile->r.ownerNum == ent->s.number)
00038         { //the original owner is bouncing the missile, so don't try to bounce it back at him
00039                 isowner = 1;
00040         }
00041 
00042         //save the original speed
00043         speed = VectorNormalize( missile->s.pos.trDelta );
00044 
00045         //if ( ent && owner && owner->NPC && owner->enemy && Q_stricmp( "Tavion", owner->NPC_type ) == 0 && Q_irand( 0, 3 ) )
00046         if ( &g_entities[missile->r.ownerNum] && missile->s.weapon != WP_SABER && missile->s.weapon != G2_MODEL_PART && !isowner )
00047         {//bounce back at them if you can
00048                 VectorSubtract( g_entities[missile->r.ownerNum].r.currentOrigin, missile->r.currentOrigin, bounce_dir );
00049                 VectorNormalize( bounce_dir );
00050         }
00051         else if (isowner)
00052         { //in this case, actually push the missile away from me, and since we're giving boost to our own missile by pushing it, up the velocity
00053                 vec3_t missile_dir;
00054 
00055                 speed *= 1.5;
00056 
00057                 VectorSubtract( missile->r.currentOrigin, ent->r.currentOrigin, missile_dir );
00058                 VectorCopy( missile->s.pos.trDelta, bounce_dir );
00059                 VectorScale( bounce_dir, DotProduct( forward, missile_dir ), bounce_dir );
00060                 VectorNormalize( bounce_dir );
00061         }
00062         else
00063         {
00064                 vec3_t missile_dir;
00065 
00066                 VectorSubtract( ent->r.currentOrigin, missile->r.currentOrigin, missile_dir );
00067                 VectorCopy( missile->s.pos.trDelta, bounce_dir );
00068                 VectorScale( bounce_dir, DotProduct( forward, missile_dir ), bounce_dir );
00069                 VectorNormalize( bounce_dir );
00070         }
00071         for ( i = 0; i < 3; i++ )
00072         {
00073                 bounce_dir[i] += RandFloat( -0.2f, 0.2f );
00074         }
00075 
00076         VectorNormalize( bounce_dir );
00077         VectorScale( bounce_dir, speed, missile->s.pos.trDelta );
00078         missile->s.pos.trTime = level.time;             // move a bit on the very first frame
00079         VectorCopy( missile->r.currentOrigin, missile->s.pos.trBase );
00080         if ( missile->s.weapon != WP_SABER && missile->s.weapon != G2_MODEL_PART )
00081         {//you are mine, now!
00082                 missile->r.ownerNum = ent->s.number;
00083         }
00084         if ( missile->s.weapon == WP_ROCKET_LAUNCHER )
00085         {//stop homing
00086                 missile->think = 0;
00087                 missile->nextthink = 0;
00088         }
00089 }

void G_RunMissile gentity_t ent  ) 
 

Definition at line 798 of file g_missile.c.

References trace_t::allsolid, entityState_s::apos, BG_EvaluateTrajectory(), gentity_s::bounceCount, gentity_s::client, gentity_s::clipmask, entityShared_t::currentOrigin, d_projectileGhoul2Collision, EF_JETPACK_ACTIVE, EF_MISSILE_STICK, entityState_s::eFlags, trace_t::endpos, trace_t::entityNum, ENTITYNUM_NONE, ENTITYNUM_WORLD, ET_MISSILE, ET_NPC, entityState_s::eType, EV_GHOUL2_MARK, FL_BOUNCE_HALF, gentity_s::flags, trace_t::fraction, G2_MODEL_PART, gclient_s::g2LastSurfaceHit, gclient_s::g2LastSurfaceTime, G2TRFLAG_DOGHOULTRACE, G2TRFLAG_GETSURFINDEX, G2TRFLAG_HITCORPSES, G2TRFLAG_THICK, G_AddEvent(), g_entities, G_FreeEntity(), g_g2TraceLod, G_MissileImpact(), G_RunStuckMissile(), G_RunThink(), gentity_t, gentity_s::ghoul2, entityState_s::groundEntityNum, gclient_s::hook, vmCvar_t::integer, gentity_s::inuse, gentity_s::isSaberEntity, level, MAX_CLIENTS, entityShared_t::maxs, entityShared_t::mins, gentity_s::neverFree, NULL, entityState_s::number, entityState_s::origin, entityState_s::origin2, entityState_s::otherEntityNum, entityShared_t::ownerNum, gentity_s::parent, gentity_s::passThroughNum, PITCH, entityState_s::pos, qboolean, qfalse, qtrue, gentity_s::r, ROLL, gentity_s::s, trace_t::startsolid, SURF_NOIMPACT, trace_t::surfaceFlags, SVF_OWNERNOTSHARED, entityShared_t::svFlags, gentity_s::target_ent, level_locals_t::time, TR_GRAVITY, TR_LINEAR, TR_STATIONARY, trap_G2Trace(), trap_LinkEntity(), trap_Trace(), trajectory_t::trBase, trajectory_t::trDelta, entityState_s::trickedentindex, trajectory_t::trTime, trajectory_t::trType, vec3_t, VectorClear, VectorCopy, entityState_s::weapon, WP_NONE, WP_NUM_WEAPONS, and WP_SABER.

Referenced by G_RunFrame().

00798                                     {
00799         vec3_t          origin, groundSpot;
00800         trace_t         tr;
00801         int                     passent;
00802         qboolean        isKnockedSaber = qfalse;
00803 
00804         if (ent->neverFree && ent->s.weapon == WP_SABER && (ent->flags & FL_BOUNCE_HALF))
00805         {
00806                 isKnockedSaber = qtrue;
00807                 ent->s.pos.trType = TR_GRAVITY;
00808         }
00809 
00810         // get current position
00811         BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
00812 
00813         // if this missile bounced off an invulnerability sphere
00814         if ( ent->target_ent ) {
00815                 passent = ent->target_ent->s.number;
00816         }
00817         else {
00818                 // ignore interactions with the missile owner
00819                 if ( (ent->r.svFlags&SVF_OWNERNOTSHARED) 
00820                         && (ent->s.eFlags&EF_JETPACK_ACTIVE) )
00821                 {//A vehicle missile that should be solid to its owner
00822                         //I don't care about hitting my owner
00823                         passent = ent->s.number;
00824                 }
00825                 else
00826                 {
00827                         passent = ent->r.ownerNum;
00828                 }
00829         }
00830         // trace a line from the previous position to the current position
00831         if (d_projectileGhoul2Collision.integer)
00832         {
00833                 trap_G2Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask, G2TRFLAG_DOGHOULTRACE|G2TRFLAG_GETSURFINDEX|G2TRFLAG_THICK|G2TRFLAG_HITCORPSES, g_g2TraceLod.integer );
00834 
00835                 if (tr.fraction != 1.0 && tr.entityNum < ENTITYNUM_WORLD)
00836                 {
00837                         gentity_t *g2Hit = &g_entities[tr.entityNum];
00838 
00839                         if (g2Hit->inuse && g2Hit->client && g2Hit->ghoul2)
00840                         { //since we used G2TRFLAG_GETSURFINDEX, tr.surfaceFlags will actually contain the index of the surface on the ghoul2 model we collided with.
00841                                 g2Hit->client->g2LastSurfaceHit = tr.surfaceFlags;
00842                                 g2Hit->client->g2LastSurfaceTime = level.time;
00843                         }
00844 
00845                         if (g2Hit->ghoul2)
00846                         {
00847                                 tr.surfaceFlags = 0; //clear the surface flags after, since we actually care about them in here.
00848                         }
00849                 }
00850         }
00851         else
00852         {
00853                 trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask );
00854         }
00855 
00856         if ( tr.startsolid || tr.allsolid ) {
00857                 // make sure the tr.entityNum is set to the entity we're stuck in
00858                 trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask );
00859                 tr.fraction = 0;
00860         }
00861         else {
00862                 VectorCopy( tr.endpos, ent->r.currentOrigin );
00863         }
00864 
00865         if (ent->passThroughNum && tr.entityNum == (ent->passThroughNum-1))
00866         {
00867                 VectorCopy( origin, ent->r.currentOrigin );
00868                 trap_LinkEntity( ent );
00869                 goto passthrough;
00870         }
00871 
00872         trap_LinkEntity( ent );
00873 
00874         if (ent->s.weapon == G2_MODEL_PART && !ent->bounceCount)
00875         {
00876                 vec3_t lowerOrg;
00877                 trace_t trG;
00878 
00879                 VectorCopy(ent->r.currentOrigin, lowerOrg);
00880                 lowerOrg[2] -= 1;
00881                 trap_Trace( &trG, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, lowerOrg, passent, ent->clipmask );
00882 
00883                 VectorCopy(trG.endpos, groundSpot);
00884 
00885                 if (!trG.startsolid && !trG.allsolid && trG.entityNum == ENTITYNUM_WORLD)
00886                 {
00887                         ent->s.groundEntityNum = trG.entityNum;
00888                 }
00889                 else
00890                 {
00891                         ent->s.groundEntityNum = ENTITYNUM_NONE;
00892                 }
00893         }
00894 
00895         if ( tr.fraction != 1) {
00896                 // never explode or bounce on sky
00897                 if ( tr.surfaceFlags & SURF_NOIMPACT ) {
00898                         // If grapple, reset owner
00899                         if (ent->parent && ent->parent->client && ent->parent->client->hook == ent) {
00900                                 ent->parent->client->hook = NULL;
00901                         }
00902 
00903                         if ((ent->s.weapon == WP_SABER && ent->isSaberEntity) || isKnockedSaber)
00904                         {
00905                                 G_RunThink( ent );
00906                                 return;
00907                         }
00908                         else if (ent->s.weapon != G2_MODEL_PART)
00909                         {
00910                                 G_FreeEntity( ent );
00911                                 return;
00912                         }
00913                 }
00914 
00915 #if 0 //will get stomped with missile impact event...
00916                 if (ent->s.weapon > WP_NONE && ent->s.weapon < WP_NUM_WEAPONS &&
00917                         (tr.entityNum < MAX_CLIENTS || g_entities[tr.entityNum].s.eType == ET_NPC))
00918                 { //player or NPC, try making a mark on him
00919                         /*
00920                         gentity_t *evEnt = G_TempEntity(ent->r.currentOrigin, EV_GHOUL2_MARK);
00921 
00922                         evEnt->s.owner = tr.entityNum; //the entity the mark should be placed on
00923                         evEnt->s.weapon = ent->s.weapon; //the weapon used (to determine mark type)
00924                         VectorCopy(ent->r.currentOrigin, evEnt->s.origin); //the point of impact
00925 
00926                         //origin2 gets the predicted trajectory-based position.
00927                         BG_EvaluateTrajectory( &ent->s.pos, level.time, evEnt->s.origin2 );
00928 
00929                         //If they are the same, there will be problems.
00930                         if (VectorCompare(evEnt->s.origin, evEnt->s.origin2))
00931                         {
00932                                 evEnt->s.origin2[2] += 2; //whatever, at least it won't mess up.
00933                         }
00934                         */
00935                         //ok, let's try adding it to the missile ent instead (tempents bad!)
00936                         G_AddEvent(ent, EV_GHOUL2_MARK, 0);
00937 
00938                         //copy current pos to s.origin, and current projected traj to origin2
00939                         VectorCopy(ent->r.currentOrigin, ent->s.origin);
00940                         BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin2 );
00941 
00942                         //the index for whoever we are hitting
00943                         ent->s.otherEntityNum = tr.entityNum;
00944 
00945                         if (VectorCompare(ent->s.origin, ent->s.origin2))
00946                         {
00947                                 ent->s.origin2[2] += 2.0f; //whatever, at least it won't mess up.
00948                         }
00949                 }
00950 #else
00951                 if (ent->s.weapon > WP_NONE && ent->s.weapon < WP_NUM_WEAPONS &&
00952                         (tr.entityNum < MAX_CLIENTS || g_entities[tr.entityNum].s.eType == ET_NPC))
00953                 { //player or NPC, try making a mark on him
00954                         //copy current pos to s.origin, and current projected traj to origin2
00955                         VectorCopy(ent->r.currentOrigin, ent->s.origin);
00956                         BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin2 );
00957 
00958                         if (VectorCompare(ent->s.origin, ent->s.origin2))
00959                         {
00960                                 ent->s.origin2[2] += 2.0f; //whatever, at least it won't mess up.
00961                         }
00962                 }
00963 #endif
00964 
00965                 G_MissileImpact( ent, &tr );
00966 
00967                 if (tr.entityNum == ent->s.otherEntityNum)
00968                 { //if the impact event other and the trace ent match then it's ok to do the g2 mark
00969                         ent->s.trickedentindex = 1;
00970                 }
00971 
00972                 if ( ent->s.eType != ET_MISSILE && ent->s.weapon != G2_MODEL_PART )
00973                 {
00974                         return;         // exploded
00975                 }
00976         }
00977 
00978 passthrough:
00979         if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
00980         {//stuck missiles should check some special stuff
00981                 G_RunStuckMissile( ent );
00982                 return;
00983         }
00984 
00985         if (ent->s.weapon == G2_MODEL_PART)
00986         {
00987                 if (ent->s.groundEntityNum == ENTITYNUM_WORLD)
00988                 {
00989                         ent->s.pos.trType = TR_LINEAR;
00990                         VectorClear(ent->s.pos.trDelta);
00991                         ent->s.pos.trTime = level.time;
00992 
00993                         VectorCopy(groundSpot, ent->s.pos.trBase);
00994                         VectorCopy(groundSpot, ent->r.currentOrigin);
00995 
00996                         if (ent->s.apos.trType != TR_STATIONARY)
00997                         {
00998                                 ent->s.apos.trType = TR_STATIONARY;
00999                                 ent->s.apos.trTime = level.time;
01000 
01001                                 ent->s.apos.trBase[ROLL] = 0;
01002                                 ent->s.apos.trBase[PITCH] = 0;
01003                         }
01004                 }
01005         }
01006 
01007         // check think function after bouncing
01008         G_RunThink( ent );
01009 }

void G_RunStuckMissile gentity_t ent  ) 
 

Definition at line 252 of file g_missile.c.

References entityState_s::apos, ENTITYNUM_WORLD, G_Damage(), g_entities, G_RunThink(), gentity_t, entityState_s::groundEntityNum, MOD_CRUSH, NULL, entityState_s::pos, gentity_s::s, gentity_s::takedamage, TR_STATIONARY, trajectory_t::trDelta, trajectory_t::trType, and vec3_origin.

Referenced by G_RunMissile().

00253 {
00254         if ( ent->takedamage )
00255         {
00256                 if ( ent->s.groundEntityNum >= 0 && ent->s.groundEntityNum < ENTITYNUM_WORLD )
00257                 {
00258                         gentity_t *other = &g_entities[ent->s.groundEntityNum];
00259 
00260                         if ( (!VectorCompare( vec3_origin, other->s.pos.trDelta ) && other->s.pos.trType != TR_STATIONARY) || 
00261                                 (!VectorCompare( vec3_origin, other->s.apos.trDelta ) && other->s.apos.trType != TR_STATIONARY) )
00262                         {//thing I stuck to is moving or rotating now, kill me
00263                                 G_Damage( ent, other, other, NULL, NULL, 99999, 0, MOD_CRUSH );
00264                                 return;
00265                         }
00266                 }
00267         }
00268         // check think function
00269         G_RunThink( ent );
00270 }

void Jedi_Decloak gentity_t self  ) 
 

Definition at line 818 of file NPC_AI_Jedi.c.

00819 {
00820         if ( self )
00821         {
00822                 self->flags &= ~FL_NOTARGET;
00823                 if ( self->client )
00824                 {
00825                         if ( self->client->ps.powerups[PW_CLOAKED] )
00826                         {//Uncloak
00827                                 self->client->ps.powerups[PW_CLOAKED] = 0;
00828 
00829                                 G_Sound( self, CHAN_ITEM, G_SoundIndex("sound/chars/shadowtrooper/decloak.wav") );
00830                         }
00831                 }
00832         }
00833 }

void laserTrapStick gentity_t ent,
vec3_t  endpos,
vec3_t  normal
 

Definition at line 2400 of file g_weapon.c.

References entityState_s::angles, entityState_s::apos, entityState_s::bolt2, CHAN_WEAPON, gentity_s::count, entityShared_t::currentAngles, gentity_s::die, EF_FIRING, entityState_s::eFlags, G_SetOrigin(), G_Sound(), G_SoundIndex(), gentity_s::genericValue15, gentity_t, gentity_s::health, laserTrapDelayedExplode(), laserTrapThink(), level, LT_ACTIVATION_DELAY, LT_ALT_TIME, LT_SIZE, entityShared_t::maxs, entityShared_t::mins, gentity_s::movedir, gentity_s::nextthink, entityState_s::pos, gentity_s::pos1, proxMineThink(), qtrue, gentity_s::r, gentity_s::s, SVF_OWNERNOTSHARED, entityShared_t::svFlags, gentity_s::takedamage, gentity_s::think, entityState_s::time, level_locals_t::time, gentity_s::touch, touch_NULL(), touchLaserTrap(), TR_STATIONARY, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, vec3_t, vectoangles(), VectorClear, VectorCopy, and VectorSet.

02401 {
02402         G_SetOrigin( ent, endpos );
02403         VectorCopy( normal, ent->pos1 );
02404 
02405         VectorClear( ent->s.apos.trDelta );
02406         // This will orient the object to face in the direction of the normal
02407         VectorCopy( normal, ent->s.pos.trDelta );
02408         //VectorScale( normal, -1, ent->s.pos.trDelta );
02409         ent->s.pos.trTime = level.time;
02410         
02411         
02412         //This does nothing, cg_missile makes assumptions about direction of travel controlling angles
02413         vectoangles( normal, ent->s.apos.trBase );
02414         VectorClear( ent->s.apos.trDelta );
02415         ent->s.apos.trType = TR_STATIONARY;
02416         VectorCopy( ent->s.apos.trBase, ent->s.angles );
02417         VectorCopy( ent->s.angles, ent->r.currentAngles );
02418         
02419 
02420         G_Sound( ent, CHAN_WEAPON, G_SoundIndex( "sound/weapons/laser_trap/stick.wav" ) );
02421         if ( ent->count )
02422         {//a tripwire
02423                 //add draw line flag
02424                 VectorCopy( normal, ent->movedir );
02425                 ent->think = laserTrapThink;
02426                 ent->nextthink = level.time + LT_ACTIVATION_DELAY;//delay the activation
02427                 ent->touch = touch_NULL;
02428                 //make it shootable
02429                 ent->takedamage = qtrue;
02430                 ent->health = 5;
02431                 ent->die = laserTrapDelayedExplode;
02432 
02433                 //shove the box through the wall
02434                 VectorSet( ent->r.mins, -LT_SIZE*2, -LT_SIZE*2, -LT_SIZE*2 );
02435                 VectorSet( ent->r.maxs, LT_SIZE*2, LT_SIZE*2, LT_SIZE*2 );
02436 
02437                 //so that the owner can blow it up with projectiles
02438                 ent->r.svFlags |= SVF_OWNERNOTSHARED;
02439         }
02440         else
02441         {
02442                 ent->touch = touchLaserTrap;
02443                 ent->think = proxMineThink;//laserTrapExplode;
02444                 ent->genericValue15 = level.time + 30000; //auto-explode after 30 seconds.
02445                 ent->nextthink = level.time + LT_ALT_TIME; // How long 'til she blows
02446 
02447                 //make it shootable
02448                 ent->takedamage = qtrue;
02449                 ent->health = 5;
02450                 ent->die = laserTrapDelayedExplode;
02451 
02452                 //shove the box through the wall
02453                 VectorSet( ent->r.mins, -LT_SIZE*2, -LT_SIZE*2, -LT_SIZE*2 );
02454                 VectorSet( ent->r.maxs, LT_SIZE*2, LT_SIZE*2, LT_SIZE*2 );
02455 
02456                 //so that the owner can blow it up with projectiles
02457                 ent->r.svFlags |= SVF_OWNERNOTSHARED;
02458 
02459                 if ( !(ent->s.eFlags&EF_FIRING) )
02460                 {//arm me
02461                         G_Sound( ent, CHAN_WEAPON, G_SoundIndex( "sound/weapons/laser_trap/warning.wav" ) );
02462                         ent->s.eFlags |= EF_FIRING;
02463                         ent->s.time = -1;
02464                         ent->s.bolt2 = 1;
02465                 }
02466         }
02467 }

float RandFloat float  min,
float  max
 

Definition at line 39 of file w_saber.c.

References min, and rand().

Referenced by G_DeflectMissile(), G_ReflectMissile(), and WP_SaberBlock().

00039                                       {
00040         return ((rand() * (max - min)) / 32768.0F) + min;
00041 }

void WP_SaberBlockNonRandom gentity_t self,
vec3_t  hitloc,
qboolean  missileBlock
 

Definition at line 9122 of file w_saber.c.

References AngleVectors(), BLOCKED_LOWER_LEFT, BLOCKED_LOWER_RIGHT, BLOCKED_TOP, BLOCKED_UPPER_LEFT, BLOCKED_UPPER_RIGHT, gentity_s::client, DotProduct, gentity_t, NULL, playerState_s::origin, gclient_s::ps, playerState_s::saberBlocked, vec3_t, VectorCopy, VectorNormalize(), VectorSubtract, playerState_s::viewangles, playerState_s::viewheight, and WP_MissileBlockForBlock().

09123 {
09124         vec3_t diff, fwdangles={0,0,0}, right;
09125         vec3_t clEye;
09126         float rightdot;
09127         float zdiff;
09128 
09129         VectorCopy(self->client->ps.origin, clEye);
09130         clEye[2] += self->client->ps.viewheight;
09131 
09132         VectorSubtract( hitloc, clEye, diff );
09133         diff[2] = 0;
09134         VectorNormalize( diff );
09135 
09136         fwdangles[1] = self->client->ps.viewangles[1];
09137         // Ultimately we might care if the shot was ahead or behind, but for now, just quadrant is fine.
09138         AngleVectors( fwdangles, NULL, right, NULL );
09139 
09140         rightdot = DotProduct(right, diff);
09141         zdiff = hitloc[2] - clEye[2];
09142         
09143         if ( zdiff > 0 )
09144         {
09145                 if ( rightdot > 0.3 )
09146                 {
09147                         self->client->ps.saberBlocked = BLOCKED_UPPER_RIGHT;
09148                 }
09149                 else if ( rightdot < -0.3 )
09150                 {
09151                         self->client->ps.saberBlocked = BLOCKED_UPPER_LEFT;
09152                 }
09153                 else
09154                 {
09155                         self->client->ps.saberBlocked = BLOCKED_TOP;
09156                 }
09157         }
09158         else if ( zdiff > -20 )//20 )
09159         {
09160                 if ( zdiff < -10 )//30 )
09161                 {//hmm, pretty low, but not low enough to use the low block, so we need to duck
09162                         
09163                 }
09164                 if ( rightdot > 0.1 )
09165                 {
09166                         self->client->ps.saberBlocked = BLOCKED_UPPER_RIGHT;
09167                 }
09168                 else if ( rightdot < -0.1 )
09169                 {
09170                         self->client->ps.saberBlocked = BLOCKED_UPPER_LEFT;
09171                 }
09172                 else
09173                 {
09174                         self->client->ps.saberBlocked = BLOCKED_TOP;
09175                 }
09176         }
09177         else
09178         {
09179                 if ( rightdot >= 0 )
09180                 {
09181                         self->client->ps.saberBlocked = BLOCKED_LOWER_RIGHT;
09182                 }
09183                 else
09184                 {
09185                         self->client->ps.saberBlocked = BLOCKED_LOWER_LEFT;
09186                 }
09187         }
09188 
09189         if ( missileBlock )
09190         {
09191                 self->client->ps.saberBlocked = WP_MissileBlockForBlock( self->client->ps.saberBlocked );
09192         }
09193 }