codemp/game/g_combat.c File Reference

#include "b_local.h"
#include "bg_saga.h"
#include "../namespace_begin.h"
#include "../namespace_end.h"

Go to the source code of this file.

Defines

#define DEATH_ALERT_RADIUS   512
#define DEATH_ALERT_SOUND_RADIUS   512

Functions

int G_ShipSurfaceForSurfName (const char *surfaceName)
qboolean G_FlyVehicleDestroySurface (gentity_t *veh, int surface)
void G_VehicleSetDamageLocFlags (gentity_t *veh, int impactDir, int deathPoint)
void G_VehUpdateShields (gentity_t *targ)
void G_LetGoOfWall (gentity_t *ent)
void BG_ClearRocketLock (playerState_t *ps)
void BotDamageNotification (gclient_t *bot, gentity_t *attacker)
void ThrowSaberToAttacker (gentity_t *self, gentity_t *attacker)
void ObjectDie (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath)
qboolean G_HeavyMelee (gentity_t *attacker)
int G_GetHitLocation (gentity_t *target, vec3_t ppoint)
void ExplodeDeath (gentity_t *self)
void ScorePlum (gentity_t *ent, vec3_t origin, int score)
void AddScore (gentity_t *ent, vec3_t origin, int score)
void TossClientWeapon (gentity_t *self, vec3_t direction, float speed)
void TossClientItems (gentity_t *self)
void LookAtKiller (gentity_t *self, gentity_t *inflictor, gentity_t *attacker)
void GibEntity (gentity_t *self, int killer)
void BodyRid (gentity_t *ent)
void body_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath)
void CheckAlmostCapture (gentity_t *self, gentity_t *attacker)
qboolean G_InKnockDown (playerState_t *ps)
int G_PickDeathAnim (gentity_t *self, vec3_t point, int damage, int mod, int hitLoc)
gentity_tG_GetJediMaster (void)
void G_AlertTeam (gentity_t *victim, gentity_t *attacker, float radius, float soundDist)
void G_DeathAlert (gentity_t *victim, gentity_t *attacker)
void DeathFX (gentity_t *ent)
void G_CheckVictoryScript (gentity_t *self)
void G_AddPowerDuelScore (int team, int score)
void G_AddPowerDuelLoserScore (int team, int score)
void AI_DeleteSelfFromGroup (gentity_t *self)
void AI_GroupMemberKilled (gentity_t *self)
void Boba_FlyStop (gentity_t *self)
qboolean Jedi_WaitingAmbush (gentity_t *self)
void CheckExitRules (void)
void Rancor_DropVictim (gentity_t *self)
void player_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath)
int CheckArmor (gentity_t *ent, int damage, int dflags)
void G_ApplyKnockback (gentity_t *targ, vec3_t newDir, float knockback)
int RaySphereIntersections (vec3_t origin, float radius, vec3_t point, vec3_t dir, vec3_t intersections[2])
void G_GetDismemberLoc (gentity_t *self, vec3_t boltPoint, int limbType)
void G_GetDismemberBolt (gentity_t *self, vec3_t boltPoint, int limbType)
void LimbTouch (gentity_t *self, gentity_t *other, trace_t *trace)
void LimbThink (gentity_t *ent)
qboolean BG_GetRootSurfNameWithVariant (void *ghoul2, const char *rootSurfName, char *returnSurfName, int returnSize)
void G_Dismember (gentity_t *ent, gentity_t *enemy, vec3_t point, int limbType, float limbRollBase, float limbPitchBase, int deathAnim, qboolean postDeath)
void DismembermentTest (gentity_t *self)
void DismembermentByNum (gentity_t *self, int num)
int G_GetHitQuad (gentity_t *self, vec3_t hitloc)
void UpdateClientRenderBolts (gentity_t *self, vec3_t renderOrigin, vec3_t renderAngles)
qboolean G_GetHitLocFromSurfName (gentity_t *ent, const char *surfName, int *hitLoc, vec3_t point, vec3_t dir, vec3_t bladeDir, int mod)
void G_CheckForDismemberment (gentity_t *ent, gentity_t *enemy, vec3_t point, int damage, int deathAnim, qboolean postDeath)
void G_LocationBasedDamageModifier (gentity_t *ent, vec3_t point, int mod, int dflags, int *damage)
qboolean G_ThereIsAMaster (void)
void G_Knockdown (gentity_t *victim)
void G_Damage (gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, vec3_t dir, vec3_t point, int damage, int dflags, int mod)
qboolean CanDamage (gentity_t *targ, vec3_t origin)
qboolean G_RadiusDamage (vec3_t origin, gentity_t *attacker, float damage, float radius, gentity_t *ignore, gentity_t *missile, int mod)

Variables

qboolean g_dontPenalizeTeam
char * modNames [MOD_MAX]
stringID_table_t animTable [MAX_ANIMATIONS+1]
qboolean g_dontFrickinCheck
qboolean g_endPDuel
qboolean g_noPDuelCheck
char * hitLocName [HL_MAX]
int gGAvoidDismember = 0
qboolean gSiegeRoundBegun
int gPainMOD = 0
int gPainHitLoc = -1
vec3_t gPainPoint


Define Documentation

#define DEATH_ALERT_RADIUS   512
 

Definition at line 1865 of file g_combat.c.

Referenced by G_DeathAlert().

#define DEATH_ALERT_SOUND_RADIUS   512
 

Definition at line 1866 of file g_combat.c.

Referenced by G_DeathAlert().


Function Documentation

void AddScore gentity_t ent,
vec3_t  origin,
int  score
 

Definition at line 436 of file g_combat.c.

References CalculateRanks(), gentity_s::client, g_dontPenalizeTeam, g_gametype, gentity_t, GT_TEAM, vmCvar_t::integer, level, PERS_SCORE, PERS_TEAM, playerState_s::persistant, gclient_s::ps, level_locals_t::teamScores, vec3_t, and level_locals_t::warmupTime.

Referenced by AddSiegeWinningTeamPoints(), BroadcastObjectiveCompletion(), player_die(), Team_FragBonuses(), Team_TouchEnemyFlag(), Team_TouchOurFlag(), Use_Target_Escapetrig(), and Use_Target_Score().

00437 {
00438         /*
00439         if (g_gametype.integer == GT_SIEGE)
00440         { //no scoring in this gametype at all.
00441                 return;
00442         }
00443         */
00444 
00445         if ( !ent->client ) {
00446                 return;
00447         }
00448         // no scoring during pre-match warmup
00449         if ( level.warmupTime ) {
00450                 return;
00451         }
00452         // show score plum
00453         //ScorePlum(ent, origin, score);
00454         //
00455         ent->client->ps.persistant[PERS_SCORE] += score;
00456         if ( g_gametype.integer == GT_TEAM && !g_dontPenalizeTeam )
00457                 level.teamScores[ ent->client->ps.persistant[PERS_TEAM] ] += score;
00458         CalculateRanks();
00459 }

void AI_DeleteSelfFromGroup gentity_t self  ) 
 

Definition at line 602 of file NPC_AI_Utils.c.

References AI_DeleteGroupMember(), gentity_t, gNPC_t::group, AIGroupInfo_s::member, gentity_s::NPC, AIGroupMember_s::number, entityState_s::number, AIGroupInfo_s::numGroup, and gentity_s::s.

Referenced by player_die().

00603 {
00604         int i;
00605 
00606         //FIXME: if killed, keep track of how many in group killed?  To affect morale?
00607         for ( i = 0; i < self->NPC->group->numGroup; i++ )
00608         {
00609                 if ( self->NPC->group->member[i].number == self->s.number )
00610                 {
00611                         AI_DeleteGroupMember( self->NPC->group, i );
00612                         return;
00613                 }
00614         }
00615 }

void AI_GroupMemberKilled gentity_t self  ) 
 

Definition at line 620 of file NPC_AI_Utils.c.

References AEL_DANGER_GREAT, AIGroupInfo_t, AIGroupInfo_s::commander, gNPC_t::currentAim, entityShared_t::currentOrigin, AIGroupInfo_s::enemy, g_entities, gentity_t, gNPC_t::group, AIGroupInfo_s::member, AIGroupInfo_s::moraleAdjust, gentity_s::NPC, AIGroupMember_s::number, AIGroupInfo_s::numGroup, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, gNPC_t::rank, RANK_ENSIGN, AIGroupInfo_s::speechDebounceTime, ST_AggressionAdjust(), ST_MarkToCover(), and ST_StartFlee().

Referenced by player_die().

00621 {
00622         AIGroupInfo_t *group = self->NPC->group;
00623         gentity_t       *member;
00624         qboolean        noflee = qfalse;
00625         int                     i;
00626 
00627         if ( !group )
00628         {//what group?
00629                 return;
00630         }
00631         if ( !self || !self->NPC || self->NPC->rank < RANK_ENSIGN )
00632         {//I'm not an officer, let's not really care for now
00633                 return;
00634         }
00635         //temporarily drop group morale for a few seconds
00636         group->moraleAdjust -= self->NPC->rank;
00637         //go through and drop aggression on my teammates (more cover, worse aim)
00638         for ( i = 0; i < group->numGroup; i++ )
00639         {
00640                 member = &g_entities[group->member[i].number];
00641                 if ( member == self )
00642                 {
00643                         continue;
00644                 }
00645                 if ( member->NPC->rank > RANK_ENSIGN )
00646                 {//officers do not panic
00647                         noflee = qtrue;
00648                 }
00649                 else
00650                 {
00651                         ST_AggressionAdjust( member, -1 );
00652                         member->NPC->currentAim -= Q_irand( 0, 10 );//Q_irand( 0, 2);//drop their aim accuracy
00653                 }
00654         }
00655         //okay, if I'm the group commander, make everyone else flee
00656         if ( group->commander != self )
00657         {//I'm not the commander... hmm, should maybe a couple flee... maybe those near me?
00658                 return;
00659         }
00660         //now see if there is another of sufficient rank to keep them from fleeing
00661         if ( !noflee )
00662         {
00663                 self->NPC->group->speechDebounceTime = 0;
00664                 for ( i = 0; i < group->numGroup; i++ )
00665                 {
00666                         member = &g_entities[group->member[i].number];
00667                         if ( member == self )
00668                         {
00669                                 continue;
00670                         }
00671                         if ( member->NPC->rank < RANK_ENSIGN )
00672                         {//grunt
00673                                 if ( group->enemy && DistanceSquared( member->r.currentOrigin, group->enemy->r.currentOrigin ) < 65536/*256*256*/ )
00674                                 {//those close to enemy run away!
00675                                         ST_StartFlee( member, group->enemy, member->r.currentOrigin, AEL_DANGER_GREAT, 3000, 5000 );
00676                                 }
00677                                 else if ( DistanceSquared( member->r.currentOrigin, self->r.currentOrigin ) < 65536/*256*256*/ )
00678                                 {//those close to me run away!
00679                                         ST_StartFlee( member, group->enemy, member->r.currentOrigin, AEL_DANGER_GREAT, 3000, 5000 );
00680                                 }
00681                                 else
00682                                 {//else, maybe just a random chance
00683                                         if ( Q_irand( 0, self->NPC->rank ) > member->NPC->rank )
00684                                         {//lower rank they are, higher rank I am, more likely they are to flee
00685                                                 ST_StartFlee( member, group->enemy, member->r.currentOrigin, AEL_DANGER_GREAT, 3000, 5000 );
00686                                         }
00687                                         else
00688                                         {
00689                                                 ST_MarkToCover( member );
00690                                         }
00691                                 }
00692                                 member->NPC->currentAim -= Q_irand( 1, 15 ); //Q_irand( 1, 3 );//drop their aim accuracy even more
00693                         }
00694                         member->NPC->currentAim -= Q_irand( 1, 15 ); //Q_irand( 1, 3 );//drop their aim accuracy even more
00695                 }
00696         }
00697 }

void BG_ClearRocketLock playerState_t ps  ) 
 

Definition at line 5751 of file bg_pmove.c.

References ENTITYNUM_NONE, playerState_t, playerState_s::rocketLastValidTime, playerState_s::rocketLockIndex, playerState_s::rocketLockTime, and playerState_s::rocketTargetTime.

Referenced by player_die(), and PM_BeginWeaponChange().

05752 {
05753         if ( ps )
05754         {
05755                 ps->rocketLockIndex = ENTITYNUM_NONE;
05756                 ps->rocketLastValidTime = 0;
05757                 ps->rocketLockTime = -1;
05758                 ps->rocketTargetTime = 0;
05759         }
05760 }

qboolean BG_GetRootSurfNameWithVariant void *  ghoul2,
const char *  rootSurfName,
char *  returnSurfName,
int  returnSize
 

Definition at line 101 of file bg_g2_utils.c.

References Com_sprintf(), MAX_VARIANTS, Q_strncpyz(), qboolean, qfalse, qtrue, and trap_G2API_GetSurfaceRenderStatus().

Referenced by G_Dismember().

00102 {
00103         if ( !ghoul2 || !trap_G2API_GetSurfaceRenderStatus( ghoul2, 0, rootSurfName ) )
00104         {//see if the basic name without variants is on
00105                 Q_strncpyz( returnSurfName, rootSurfName, returnSize );
00106                 return qtrue;
00107         }
00108         else
00109         {//check variants
00110                 int i;
00111                 for ( i = 0; i < MAX_VARIANTS; i++ )
00112                 {
00113                         Com_sprintf( returnSurfName, returnSize, "%s%c", rootSurfName, 'a'+i );
00114                         if ( !trap_G2API_GetSurfaceRenderStatus( ghoul2, 0, returnSurfName ) )
00115                         {
00116                                 return qtrue;
00117                         }
00118                 }
00119         }
00120         Q_strncpyz( returnSurfName, rootSurfName, returnSize );
00121         return qfalse;
00122 }

void Boba_FlyStop gentity_t self  ) 
 

Definition at line 367 of file NPC_AI_Jedi.c.

00368 {
00369         self->client->ps.gravity = g_gravity.value;
00370         if ( self->NPC )
00371         {
00372                 self->NPC->aiFlags &= ~NPCAI_CUSTOM_GRAVITY;
00373         }
00374         self->client->ps.eFlags2 &= ~EF2_FLYING;
00375         self->client->jetPackTime = 0;
00376         //stop jet loop sound
00377         self->s.loopSound = 0;
00378         if ( self->NPC )
00379         {
00380                 self->count = 0; // SEEKER shot ammo count
00381                 TIMER_Set( self, "jetRecharge", Q_irand( 1000, 5000 ) );
00382                 TIMER_Set( self, "jumpChaseDebounce", Q_irand( 500, 2000 ) );
00383         }
00384 }

void body_die gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  meansOfDeath
 

Definition at line 685 of file g_combat.c.

References BodyRid(), gentity_s::client, entityShared_t::currentOrigin, EF_DISINTEGRATION, playerState_s::eFlags, entityState_s::eFlags, ET_NPC, entityState_s::eType, G_FreeEntity(), gentity_t, GIB_HEALTH, gentity_s::health, playerState_s::lastHitLoc, level, MOD_CRUSH, MOD_FALLING, MOD_LAVA, MOD_SLIME, MOD_SUICIDE, MOD_TARGET_LASER, MOD_TELEFRAG, MOD_TRIGGER_HURT, MOD_UNKNOWN, MOD_WATER, gentity_s::nextthink, playerState_s::origin, entityState_s::origin2, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::r, gclient_s::respawnTime, gentity_s::s, gentity_s::think, level_locals_t::time, playerState_s::torsoTimer, and VectorCopy.

Referenced by player_die().

00685                                                                                                           {
00686         // NOTENOTE No gibbing right now, this is star wars.
00687         qboolean doDisint = qfalse;
00688 
00689         if (self->s.eType == ET_NPC)
00690         { //well, just rem it then, so long as it's done with its death anim and it's not a standard weapon.
00691                 if ( self->client && self->client->ps.torsoTimer <= 0 &&
00692                          (meansOfDeath == MOD_UNKNOWN ||
00693                           meansOfDeath == MOD_WATER ||
00694                           meansOfDeath == MOD_SLIME ||
00695                           meansOfDeath == MOD_LAVA ||
00696                           meansOfDeath == MOD_CRUSH ||
00697                           meansOfDeath == MOD_TELEFRAG ||
00698                           meansOfDeath == MOD_FALLING ||
00699                           meansOfDeath == MOD_SUICIDE ||
00700                           meansOfDeath == MOD_TARGET_LASER ||
00701                           meansOfDeath == MOD_TRIGGER_HURT) )
00702                 {
00703                         self->think = G_FreeEntity;
00704                         self->nextthink = level.time;
00705                 }
00706                 return;
00707         }
00708 
00709         if (self->health < (GIB_HEALTH+1))
00710         {
00711                 self->health = GIB_HEALTH+1;
00712 
00713                 if (self->client && (level.time - self->client->respawnTime) < 2000)
00714                 {
00715                         doDisint = qfalse;
00716                 }
00717                 else
00718                 {
00719                         doDisint = qtrue;
00720                 }
00721         }
00722 
00723         if (self->client && (self->client->ps.eFlags & EF_DISINTEGRATION))
00724         {
00725                 return;
00726         }
00727         else if (self->s.eFlags & EF_DISINTEGRATION)
00728         {
00729                 return;
00730         }
00731 
00732         if (doDisint)
00733         {
00734                 if (self->client)
00735                 {
00736                         self->client->ps.eFlags |= EF_DISINTEGRATION;
00737                         VectorCopy(self->client->ps.origin, self->client->ps.lastHitLoc);
00738                 }
00739                 else
00740                 {
00741                         self->s.eFlags |= EF_DISINTEGRATION;
00742                         VectorCopy(self->r.currentOrigin, self->s.origin2);
00743 
00744                         //since it's the corpse entity, tell it to "remove" itself
00745                         self->think = BodyRid;
00746                         self->nextthink = level.time + 1000;
00747                 }
00748                 return;
00749         }
00750 }

void BodyRid gentity_t ent  ) 
 

Definition at line 674 of file g_combat.c.

References gentity_t, gentity_s::physicsObject, qfalse, and trap_UnlinkEntity().

Referenced by body_die().

00675 {
00676         trap_UnlinkEntity( ent );
00677         ent->physicsObject = qfalse;
00678 }

void BotDamageNotification gclient_t bot,
gentity_t attacker
 

Definition at line 1861 of file ai_main.c.

References bot_state_t, botstates, bot_state_s::client, gentity_s::client, playerState_s::clientNum, bot_state_s::currentEnemy, ENEMY_FORGET_MS, bot_state_s::enemySeenTime, g_entities, gclient_t, gentity_t, bot_state_s::lastAttacked, bot_state_s::lastHurt, level, MAX_CLIENTS, NULL, entityState_s::number, PassLovedOneCheck(), PassStandardEnemyChecks(), gclient_s::ps, gentity_s::s, and level_locals_t::time.

Referenced by G_Damage().

01862 {
01863         bot_state_t *bs;
01864         bot_state_t *bs_a;
01865         int i;
01866 
01867         if (!bot || !attacker || !attacker->client)
01868         {
01869                 return;
01870         }
01871 
01872         if (bot->ps.clientNum >= MAX_CLIENTS)
01873         { //an NPC.. do nothing for them.
01874                 return;
01875         }
01876 
01877         if (attacker->s.number >= MAX_CLIENTS)
01878         { //if attacker is an npc also don't care I suppose.
01879                 return;
01880         }
01881 
01882         bs_a = botstates[attacker->s.number];
01883 
01884         if (bs_a)
01885         { //if the client attacking us is a bot as well
01886                 bs_a->lastAttacked = &g_entities[bot->ps.clientNum];
01887                 i = 0;
01888 
01889                 while (i < MAX_CLIENTS)
01890                 {
01891                         if (botstates[i] &&
01892                                 i != bs_a->client &&
01893                                 botstates[i]->lastAttacked == &g_entities[bot->ps.clientNum])
01894                         {
01895                                 botstates[i]->lastAttacked = NULL;
01896                         }
01897 
01898                         i++;
01899                 }
01900         }
01901         else //got attacked by a real client, so no one gets rights to lastAttacked
01902         {
01903                 i = 0;
01904 
01905                 while (i < MAX_CLIENTS)
01906                 {
01907                         if (botstates[i] &&
01908                                 botstates[i]->lastAttacked == &g_entities[bot->ps.clientNum])
01909                         {
01910                                 botstates[i]->lastAttacked = NULL;
01911                         }
01912 
01913                         i++;
01914                 }
01915         }
01916 
01917         bs = botstates[bot->ps.clientNum];
01918 
01919         if (!bs)
01920         {
01921                 return;
01922         }
01923 
01924         bs->lastHurt = attacker;
01925 
01926         if (bs->currentEnemy)
01927         { //we don't care about the guy attacking us if we have an enemy already
01928                 return;
01929         }
01930 
01931         if (!PassStandardEnemyChecks(bs, attacker))
01932         { //the person that hurt us is not a valid enemy
01933                 return;
01934         }
01935 
01936         if (PassLovedOneCheck(bs, attacker))
01937         { //the person that hurt us is the one we love!
01938                 bs->currentEnemy = attacker;
01939                 bs->enemySeenTime = level.time + ENEMY_FORGET_MS;
01940         }
01941 }

qboolean CanDamage gentity_t targ,
vec3_t  origin
 

Definition at line 5510 of file g_combat.c.

References entityShared_t::absmax, entityShared_t::absmin, trace_t::entityNum, ENTITYNUM_NONE, trace_t::fraction, gentity_t, MASK_SOLID, entityState_s::number, qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, trap_Trace(), vec3_origin, vec3_t, VectorAdd, VectorCopy, and VectorScale.

Referenced by G_RadiusDamage().

05510                                                     {
05511         vec3_t  dest;
05512         trace_t tr;
05513         vec3_t  midpoint;
05514 
05515         // use the midpoint of the bounds instead of the origin, because
05516         // bmodels may have their origin is 0,0,0
05517         VectorAdd (targ->r.absmin, targ->r.absmax, midpoint);
05518         VectorScale (midpoint, 0.5, midpoint);
05519 
05520         VectorCopy (midpoint, dest);
05521         trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
05522         if (tr.fraction == 1.0 || tr.entityNum == targ->s.number)
05523                 return qtrue;
05524 
05525         // this should probably check in the plane of projection, 
05526         // rather than in world coordinate, and also include Z
05527         VectorCopy (midpoint, dest);
05528         dest[0] += 15.0;
05529         dest[1] += 15.0;
05530         trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
05531         if (tr.fraction == 1.0)
05532                 return qtrue;
05533 
05534         VectorCopy (midpoint, dest);
05535         dest[0] += 15.0;
05536         dest[1] -= 15.0;
05537         trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
05538         if (tr.fraction == 1.0)
05539                 return qtrue;
05540 
05541         VectorCopy (midpoint, dest);
05542         dest[0] -= 15.0;
05543         dest[1] += 15.0;
05544         trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
05545         if (tr.fraction == 1.0)
05546                 return qtrue;
05547 
05548         VectorCopy (midpoint, dest);
05549         dest[0] -= 15.0;
05550         dest[1] -= 15.0;
05551         trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
05552         if (tr.fraction == 1.0)
05553                 return qtrue;
05554 
05555 
05556         return qfalse;
05557 }

void CheckAlmostCapture gentity_t self,
gentity_t attacker
 

Definition at line 805 of file g_combat.c.

References gentity_s::client, FL_DROPPED_ITEM, gentity_s::flags, FOFS, G_Find(), g_gametype, gentity_t, GT_CTF, GT_CTY, vmCvar_t::integer, NULL, entityState_s::origin, playerState_s::origin, PERS_PLAYEREVENTS, playerState_s::persistant, playerState_s::powerups, gclient_s::ps, PW_BLUEFLAG, PW_NEUTRALFLAG, PW_REDFLAG, gentity_s::r, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, SVF_NOCLIENT, entityShared_t::svFlags, TEAM_BLUE, vec3_t, and VectorSubtract.

Referenced by player_die().

00805                                                                 {
00806 #if 0
00807         gentity_t       *ent;
00808         vec3_t          dir;
00809         char            *classname;
00810 
00811         // if this player was carrying a flag
00812         if ( self->client->ps.powerups[PW_REDFLAG] ||
00813                 self->client->ps.powerups[PW_BLUEFLAG] ||
00814                 self->client->ps.powerups[PW_NEUTRALFLAG] ) {
00815                 // get the goal flag this player should have been going for
00816                 if ( g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY ) {
00817                         if ( self->client->sess.sessionTeam == TEAM_BLUE ) {
00818                                 classname = "team_CTF_blueflag";
00819                         }
00820                         else {
00821                                 classname = "team_CTF_redflag";
00822                         }
00823                 }
00824                 else {
00825                         if ( self->client->sess.sessionTeam == TEAM_BLUE ) {
00826                                 classname = "team_CTF_redflag";
00827                         }
00828                         else {
00829                                 classname = "team_CTF_blueflag";
00830                         }
00831                 }
00832                 ent = NULL;
00833                 do
00834                 {
00835                         ent = G_Find(ent, FOFS(classname), classname);
00836                 } while (ent && (ent->flags & FL_DROPPED_ITEM));
00837                 // if we found the destination flag and it's not picked up
00838                 if (ent && !(ent->r.svFlags & SVF_NOCLIENT) ) {
00839                         // if the player was *very* close
00840                         VectorSubtract( self->client->ps.origin, ent->s.origin, dir );
00841                         if ( VectorLength(dir) < 200 ) {
00842                                 self->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_HOLYSHIT;
00843                                 if ( attacker->client ) {
00844                                         attacker->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_HOLYSHIT;
00845                                 }
00846                         }
00847                 }
00848         }
00849 #endif
00850 }

int CheckArmor gentity_t ent,
int  damage,
int  dflags
 

Definition at line 2894 of file g_combat.c.

References ARMOR_PROTECTION, ARMOR_REDUCTION_FACTOR, ceil(), CLASS_VEHICLE, gentity_s::client, client, DAMAGE_HALF_ABSORB, DAMAGE_HALF_ARMOR_REDUCTION, DAMAGE_NO_ARMOR, playerState_s::electrifyTime, gclient_t, gentity_t, level, gentity_s::m_pVehicle, gclient_s::NPC_class, gclient_s::ps, STAT_ARMOR, playerState_s::stats, and level_locals_t::time.

Referenced by G_Damage().

02895 {
02896         gclient_t       *client;
02897         int                     save;
02898         int                     count;
02899 
02900         if (!damage)
02901                 return 0;
02902 
02903         client = ent->client;
02904 
02905         if (!client)
02906                 return 0;
02907 
02908         if (dflags & DAMAGE_NO_ARMOR)
02909                 return 0;
02910 
02911         if ( client->NPC_class == CLASS_VEHICLE
02912                 && ent->m_pVehicle
02913                 && ent->client->ps.electrifyTime > level.time )
02914         {//ion-cannon has disabled this ship's shields, take damage on hull!
02915                 return 0;
02916         }
02917         // armor
02918         count = client->ps.stats[STAT_ARMOR];
02919 
02920         if (dflags & DAMAGE_HALF_ABSORB)
02921         {       // Half the damage gets absorbed by the shields, rather than 100%
02922                 save = ceil( damage * ARMOR_PROTECTION );
02923         }
02924         else
02925         {       // All the damage gets absorbed by the shields.
02926                 save = damage;
02927         }
02928 
02929         // save is the most damage that the armor is elibigle to protect, of course, but it's limited by the total armor.
02930         if (save >= count)
02931                 save = count;
02932 
02933         if (!save)
02934                 return 0;
02935 
02936         if (dflags & DAMAGE_HALF_ARMOR_REDUCTION)               // Armor isn't whittled so easily by sniper shots.
02937         {
02938                 client->ps.stats[STAT_ARMOR] -= (int)(save*ARMOR_REDUCTION_FACTOR);
02939         }
02940         else
02941         {
02942                 client->ps.stats[STAT_ARMOR] -= save;
02943         }
02944 
02945         return save;
02946 }

void CheckExitRules void   ) 
 

Definition at line 2572 of file g_main.c.

References BeginIntermission(), CheckIntermissionExit(), gentity_s::client, level_locals_t::clients, Com_Printf(), CON_CONNECTED, clientPersistant_t::connected, d_powerDuelPrint, g_capturelimit, g_duel_fraglimit, g_endPDuel, g_entities, g_fraglimit, g_gametype, G_GetStringEdString(), g_maxclients, g_timelimit, gclient_t, gDoSlowMoDuel, gDuelExit, gEscapeTime, gEscaping, GT_CTF, GT_DUEL, GT_POWERDUEL, GT_SIEGE, gentity_s::health, vmCvar_t::integer, INTERMISSION_DELAY_TIME, level_locals_t::intermissionQueued, level_locals_t::intermissiontime, gentity_s::inuse, level, LogExit(), MAX_CLIENTS, clientPersistant_t::netname, level_locals_t::numPlayingClients, gclient_s::pers, PERS_SCORE, playerState_s::persistant, playerState_s::pm_flags, PMF_FOLLOW, gclient_s::ps, qboolean, qfalse, qtrue, S_COLOR_WHITE, ScoreIsTied(), gclient_s::sess, clientSession_t::sessionTeam, level_locals_t::startTime, TEAM_BLUE, TEAM_FREE, TEAM_RED, TEAM_SPECTATOR, level_locals_t::teamScores, level_locals_t::time, trap_SendServerCommand(), va(), level_locals_t::warmupTime, and clientSession_t::wins.

Referenced by CalculateRanks(), G_RunFrame(), and player_die().

02572                             {
02573         int                     i;
02574         gclient_t       *cl;
02575         char *sKillLimit;
02576         qboolean printLimit = qtrue;
02577         // if at the intermission, wait for all non-bots to
02578         // signal ready, then go to next level
02579         if ( level.intermissiontime ) {
02580                 CheckIntermissionExit ();
02581                 return;
02582         }
02583 
02584         if (gDoSlowMoDuel)
02585         { //don't go to intermission while in slow motion
02586                 return;
02587         }
02588 
02589         if (gEscaping)
02590         {
02591                 int i = 0;
02592                 int numLiveClients = 0;
02593 
02594                 while (i < MAX_CLIENTS)
02595                 {
02596                         if (g_entities[i].inuse && g_entities[i].client && g_entities[i].health > 0)
02597                         {
02598                                 if (g_entities[i].client->sess.sessionTeam != TEAM_SPECTATOR &&
02599                                         !(g_entities[i].client->ps.pm_flags & PMF_FOLLOW))
02600                                 {
02601                                         numLiveClients++;
02602                                 }
02603                         }
02604 
02605                         i++;
02606                 }
02607                 if (gEscapeTime < level.time)
02608                 {
02609                         gEscaping = qfalse;
02610                         LogExit( "Escape time ended." );
02611                         return;
02612                 }
02613                 if (!numLiveClients)
02614                 {
02615                         gEscaping = qfalse;
02616                         LogExit( "Everyone failed to escape." );
02617                         return;
02618                 }
02619         }
02620 
02621         if ( level.intermissionQueued ) {
02622                 //int time = (g_singlePlayer.integer) ? SP_INTERMISSION_DELAY_TIME : INTERMISSION_DELAY_TIME;
02623                 int time = INTERMISSION_DELAY_TIME;
02624                 if ( level.time - level.intermissionQueued >= time ) {
02625                         level.intermissionQueued = 0;
02626                         BeginIntermission();
02627                 }
02628                 return;
02629         }
02630 
02631         /*
02632         if (g_gametype.integer == GT_POWERDUEL)
02633         {
02634                 if (level.numPlayingClients < 3)
02635                 {
02636                         if (!level.intermissiontime)
02637                         {
02638                                 if (d_powerDuelPrint.integer)
02639                                 {
02640                                         Com_Printf("POWERDUEL WIN CONDITION: Duel forfeit (1)\n");
02641                                 }
02642                                 LogExit("Duel forfeit.");
02643                                 return;
02644                         }
02645                 }
02646         }
02647         */
02648 
02649         // check for sudden death
02650         if (g_gametype.integer != GT_SIEGE)
02651         {
02652                 if ( ScoreIsTied() ) {
02653                         // always wait for sudden death
02654                         if ((g_gametype.integer != GT_DUEL) || !g_timelimit.integer)
02655                         {
02656                                 if (g_gametype.integer != GT_POWERDUEL)
02657                                 {
02658                                         return;
02659                                 }
02660                         }
02661                 }
02662         }
02663 
02664         if (g_gametype.integer != GT_SIEGE)
02665         {
02666                 if ( g_timelimit.integer && !level.warmupTime ) {
02667                         if ( level.time - level.startTime >= g_timelimit.integer*60000 ) {
02668 //                              trap_SendServerCommand( -1, "print \"Timelimit hit.\n\"");
02669                                 trap_SendServerCommand( -1, va("print \"%s.\n\"",G_GetStringEdString("MP_SVGAME", "TIMELIMIT_HIT")));
02670                                 if (d_powerDuelPrint.integer)
02671                                 {
02672                                         Com_Printf("POWERDUEL WIN CONDITION: Timelimit hit (1)\n");
02673                                 }
02674                                 LogExit( "Timelimit hit." );
02675                                 return;
02676                         }
02677                 }
02678         }
02679 
02680         if (g_gametype.integer == GT_POWERDUEL && level.numPlayingClients >= 3)
02681         {
02682                 if (g_endPDuel)
02683                 {
02684                         g_endPDuel = qfalse;
02685                         LogExit("Powerduel ended.");
02686                 }
02687 
02688                 //yeah, this stuff was completely insane.
02689                 /*
02690                 int duelists[3];
02691                 duelists[0] = level.sortedClients[0];
02692                 duelists[1] = level.sortedClients[1];
02693                 duelists[2] = level.sortedClients[2];
02694 
02695                 if (duelists[0] != -1 &&
02696                         duelists[1] != -1 &&
02697                         duelists[2] != -1)
02698                 {
02699                         if (!g_entities[duelists[0]].inuse ||
02700                                 !g_entities[duelists[0]].client ||
02701                                 g_entities[duelists[0]].client->ps.stats[STAT_HEALTH] <= 0 ||
02702                                 g_entities[duelists[0]].client->sess.sessionTeam != TEAM_FREE)
02703                         { //The lone duelist lost, give the other two wins (if applicable) and him a loss
02704                                 if (g_entities[duelists[0]].inuse &&
02705                                         g_entities[duelists[0]].client)
02706                                 {
02707                                         g_entities[duelists[0]].client->sess.losses++;
02708                                         ClientUserinfoChanged(duelists[0]);
02709                                 }
02710                                 if (g_entities[duelists[1]].inuse &&
02711                                         g_entities[duelists[1]].client)
02712                                 {
02713                                         if (g_entities[duelists[1]].client->ps.stats[STAT_HEALTH] > 0 &&
02714                                                 g_entities[duelists[1]].client->sess.sessionTeam == TEAM_FREE)
02715                                         {
02716                                                 g_entities[duelists[1]].client->sess.wins++;
02717                                         }
02718                                         else
02719                                         {
02720                                                 g_entities[duelists[1]].client->sess.losses++;
02721                                         }
02722                                         ClientUserinfoChanged(duelists[1]);
02723                                 }
02724                                 if (g_entities[duelists[2]].inuse &&
02725                                         g_entities[duelists[2]].client)
02726                                 {
02727                                         if (g_entities[duelists[2]].client->ps.stats[STAT_HEALTH] > 0 &&
02728                                                 g_entities[duelists[2]].client->sess.sessionTeam == TEAM_FREE)
02729                                         {
02730                                                 g_entities[duelists[2]].client->sess.wins++;
02731                                         }
02732                                         else
02733                                         {
02734                                                 g_entities[duelists[2]].client->sess.losses++;
02735                                         }
02736                                         ClientUserinfoChanged(duelists[2]);
02737                                 }
02738 
02739                                 //Will want to parse indecies for two out at some point probably
02740                                 trap_SetConfigstring ( CS_CLIENT_DUELWINNER, va("%i", duelists[1] ) );
02741 
02742                                 if (d_powerDuelPrint.integer)
02743                                 {
02744                                         Com_Printf("POWERDUEL WIN CONDITION: Coupled duelists won (1)\n");
02745                                 }
02746                                 LogExit( "Coupled duelists won." );
02747                                 gDuelExit = qfalse;
02748                         }
02749                         else if ((!g_entities[duelists[1]].inuse ||
02750                                 !g_entities[duelists[1]].client ||
02751                                 g_entities[duelists[1]].client->sess.sessionTeam != TEAM_FREE ||
02752                                 g_entities[duelists[1]].client->ps.stats[STAT_HEALTH] <= 0) &&
02753                                 (!g_entities[duelists[2]].inuse ||
02754                                 !g_entities[duelists[2]].client ||
02755                                 g_entities[duelists[2]].client->sess.sessionTeam != TEAM_FREE ||
02756                                 g_entities[duelists[2]].client->ps.stats[STAT_HEALTH] <= 0))
02757                         { //the coupled duelists lost, give the lone duelist a win (if applicable) and the couple both losses
02758                                 if (g_entities[duelists[1]].inuse &&
02759                                         g_entities[duelists[1]].client)
02760                                 {
02761                                         g_entities[duelists[1]].client->sess.losses++;
02762                                         ClientUserinfoChanged(duelists[1]);
02763                                 }
02764                                 if (g_entities[duelists[2]].inuse &&
02765                                         g_entities[duelists[2]].client)
02766                                 {
02767                                         g_entities[duelists[2]].client->sess.losses++;
02768                                         ClientUserinfoChanged(duelists[2]);
02769                                 }
02770 
02771                                 if (g_entities[duelists[0]].inuse &&
02772                                         g_entities[duelists[0]].client &&
02773                                         g_entities[duelists[0]].client->ps.stats[STAT_HEALTH] > 0 &&
02774                                         g_entities[duelists[0]].client->sess.sessionTeam == TEAM_FREE)
02775                                 {
02776                                         g_entities[duelists[0]].client->sess.wins++;
02777                                         ClientUserinfoChanged(duelists[0]);
02778                                 }
02779 
02780                                 trap_SetConfigstring ( CS_CLIENT_DUELWINNER, va("%i", duelists[0] ) );
02781 
02782                                 if (d_powerDuelPrint.integer)
02783                                 {
02784                                         Com_Printf("POWERDUEL WIN CONDITION: Lone duelist won (1)\n");
02785                                 }
02786                                 LogExit( "Lone duelist won." );
02787                                 gDuelExit = qfalse;
02788                         }
02789                 }
02790                 */
02791                 return;
02792         }
02793 
02794         if ( level.numPlayingClients < 2 ) {
02795                 return;
02796         }
02797 
02798         if (g_gametype.integer == GT_DUEL ||
02799                 g_gametype.integer == GT_POWERDUEL)
02800         {
02801                 if (g_fraglimit.integer > 1)
02802                 {
02803                         sKillLimit = "Kill limit hit.";
02804                 }
02805                 else
02806                 {
02807                         sKillLimit = "";
02808                         printLimit = qfalse;
02809                 }
02810         }
02811         else
02812         {
02813                 sKillLimit = "Kill limit hit.";
02814         }
02815         if ( g_gametype.integer < GT_SIEGE && g_fraglimit.integer ) {
02816                 if ( level.teamScores[TEAM_RED] >= g_fraglimit.integer ) {
02817                         trap_SendServerCommand( -1, va("print \"Red %s\n\"", G_GetStringEdString("MP_SVGAME", "HIT_THE_KILL_LIMIT")) );
02818                         if (d_powerDuelPrint.integer)
02819                         {
02820                                 Com_Printf("POWERDUEL WIN CONDITION: Kill limit (1)\n");
02821                         }
02822                         LogExit( sKillLimit );
02823                         return;
02824                 }
02825 
02826                 if ( level.teamScores[TEAM_BLUE] >= g_fraglimit.integer ) {
02827                         trap_SendServerCommand( -1, va("print \"Blue %s\n\"", G_GetStringEdString("MP_SVGAME", "HIT_THE_KILL_LIMIT")) );
02828                         if (d_powerDuelPrint.integer)
02829                         {
02830                                 Com_Printf("POWERDUEL WIN CONDITION: Kill limit (2)\n");
02831                         }
02832                         LogExit( sKillLimit );
02833                         return;
02834                 }
02835 
02836                 for ( i=0 ; i< g_maxclients.integer ; i++ ) {
02837                         cl = level.clients + i;
02838                         if ( cl->pers.connected != CON_CONNECTED ) {
02839                                 continue;
02840                         }
02841                         if ( cl->sess.sessionTeam != TEAM_FREE ) {
02842                                 continue;
02843                         }
02844 
02845                         if ( (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) && g_duel_fraglimit.integer && cl->sess.wins >= g_duel_fraglimit.integer )
02846                         {
02847                                 if (d_powerDuelPrint.integer)
02848                                 {
02849                                         Com_Printf("POWERDUEL WIN CONDITION: Duel limit hit (1)\n");
02850                                 }
02851                                 LogExit( "Duel limit hit." );
02852                                 gDuelExit = qtrue;
02853                                 trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " hit the win limit.\n\"",
02854                                         cl->pers.netname ) );
02855                                 return;
02856                         }
02857 
02858                         if ( cl->ps.persistant[PERS_SCORE] >= g_fraglimit.integer ) {
02859                                 if (d_powerDuelPrint.integer)
02860                                 {
02861                                         Com_Printf("POWERDUEL WIN CONDITION: Kill limit (3)\n");
02862                                 }
02863                                 LogExit( sKillLimit );
02864                                 gDuelExit = qfalse;
02865                                 if (printLimit)
02866                                 {
02867                                         trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " %s.\n\"",
02868                                                                                                         cl->pers.netname,
02869                                                                                                         G_GetStringEdString("MP_SVGAME", "HIT_THE_KILL_LIMIT")
02870                                                                                                         ) 
02871                                                                                         );
02872                                 }
02873                                 return;
02874                         }
02875                 }
02876         }
02877 
02878         if ( g_gametype.integer >= GT_CTF && g_capturelimit.integer ) {
02879 
02880                 if ( level.teamScores[TEAM_RED] >= g_capturelimit.integer ) 
02881                 {
02882                         trap_SendServerCommand( -1,  va("print \"%s \"", G_GetStringEdString("MP_SVGAME", "PRINTREDTEAM")));
02883                         trap_SendServerCommand( -1,  va("print \"%s.\n\"", G_GetStringEdString("MP_SVGAME", "HIT_CAPTURE_LIMIT")));
02884                         LogExit( "Capturelimit hit." );
02885                         return;
02886                 }
02887 
02888                 if ( level.teamScores[TEAM_BLUE] >= g_capturelimit.integer ) {
02889                         trap_SendServerCommand( -1,  va("print \"%s \"", G_GetStringEdString("MP_SVGAME", "PRINTBLUETEAM")));
02890                         trap_SendServerCommand( -1,  va("print \"%s.\n\"", G_GetStringEdString("MP_SVGAME", "HIT_CAPTURE_LIMIT")));
02891                         LogExit( "Capturelimit hit." );
02892                         return;
02893                 }
02894         }
02895 }

void DeathFX gentity_t ent  ) 
 

Definition at line 1882 of file g_combat.c.

References AngleVectors(), CHAN_AUTO, CLASS_ATST, CLASS_GONK, CLASS_INTERROGATOR, CLASS_MARK1, CLASS_MARK2, CLASS_MOUSE, CLASS_PROBE, CLASS_PROTOCOL, CLASS_R2D2, CLASS_R5D2, CLASS_REMOTE, CLASS_SEEKER, CLASS_SENTRY, gentity_s::client, entityShared_t::currentAngles, entityShared_t::currentOrigin, G_EffectIndex(), G_PlayEffectID(), G_Sound(), G_SoundIndex(), gentity_t, gclient_s::NPC_class, NULL, Q_irand(), gentity_s::r, va(), vec3_t, VectorCopy, VectorMA, and VectorSet.

Referenced by player_die().

01883 {
01884         vec3_t          effectPos, right;
01885         vec3_t          defaultDir;
01886 
01887         if ( !ent || !ent->client )
01888                 return;
01889 
01890         VectorSet(defaultDir, 0, 0, 1);
01891 
01892         // team no longer indicates species/race.  NPC_class should be used to identify certain npc types
01893         switch(ent->client->NPC_class)
01894         {
01895         case CLASS_MOUSE:
01896                 VectorCopy( ent->r.currentOrigin, effectPos );
01897                 effectPos[2] -= 20;
01898                 G_PlayEffectID( G_EffectIndex("env/small_explode"), effectPos, defaultDir );
01899                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mouse/misc/death1") );
01900                 break;
01901 
01902         case CLASS_PROBE:
01903                 VectorCopy( ent->r.currentOrigin, effectPos );
01904                 effectPos[2] += 50;
01905                 G_PlayEffectID( G_EffectIndex("explosions/probeexplosion1"), effectPos, defaultDir );
01906                 break;
01907                 
01908         case CLASS_ATST: 
01909                 AngleVectors( ent->r.currentAngles, NULL, right, NULL );
01910                 VectorMA( ent->r.currentOrigin, 20, right, effectPos );
01911                 effectPos[2] += 180;
01912                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01913                 VectorMA( effectPos, -40, right, effectPos );
01914                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01915                 break;
01916 
01917         case CLASS_SEEKER:
01918         case CLASS_REMOTE:
01919                 G_PlayEffectID( G_EffectIndex("env/small_explode"), ent->r.currentOrigin, defaultDir );
01920                 break;
01921 
01922         case CLASS_GONK:
01923                 VectorCopy( ent->r.currentOrigin, effectPos );
01924                 effectPos[2] -= 5;
01925 //              statusTextIndex = Q_irand( IGT_RESISTANCEISFUTILE, IGT_NAMEIS8OF12 );
01926                 G_Sound( ent, CHAN_AUTO, G_SoundIndex(va("sound/chars/gonk/misc/death%d.wav",Q_irand( 1, 3 ))) );
01927                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01928                 break;
01929 
01930         // should list all remaining droids here, hope I didn't miss any
01931         case CLASS_R2D2:
01932                 VectorCopy( ent->r.currentOrigin, effectPos );
01933                 effectPos[2] -= 10;
01934                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01935                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_explo") );
01936                 break;
01937 
01938         case CLASS_PROTOCOL: //c3p0
01939         case CLASS_R5D2:
01940                 VectorCopy( ent->r.currentOrigin, effectPos );
01941                 effectPos[2] -= 10;
01942                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01943                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_explo") );
01944                 break;
01945 
01946         case CLASS_MARK2:
01947                 VectorCopy( ent->r.currentOrigin, effectPos );
01948                 effectPos[2] -= 15;
01949                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01950                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_explo") );
01951                 break;
01952 
01953         case CLASS_INTERROGATOR:
01954                 VectorCopy( ent->r.currentOrigin, effectPos );
01955                 effectPos[2] -= 15;
01956                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01957                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/interrogator/misc/int_droid_explo") );
01958                 break;
01959 
01960         case CLASS_MARK1:
01961                 AngleVectors( ent->r.currentAngles, NULL, right, NULL );
01962                 VectorMA( ent->r.currentOrigin, 10, right, effectPos );
01963                 effectPos[2] -= 15;
01964                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01965                 VectorMA( effectPos, -20, right, effectPos );
01966                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01967                 VectorMA( effectPos, -20, right, effectPos );
01968                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01969                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark1/misc/mark1_explo") );
01970                 break;
01971 
01972         case CLASS_SENTRY:
01973                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/sentry/misc/sentry_explo") );
01974                 VectorCopy( ent->r.currentOrigin, effectPos );
01975                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01976                 break;
01977 
01978         default:
01979                 break;
01980 
01981         }
01982 
01983 }

void DismembermentByNum gentity_t self,
int  num
 

Definition at line 3510 of file g_combat.c.

References BOTH_DEATH1, G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RHAND, G2_MODELPART_RLEG, G2_MODELPART_WAIST, G_Dismember(), G_GetDismemberBolt(), gentity_t, qfalse, and vec3_t.

Referenced by ClientCommand().

03511 {
03512         int sect = G2_MODELPART_HEAD;
03513         vec3_t boltPoint;
03514 
03515         switch (num)
03516         {
03517         case 0:
03518                 sect = G2_MODELPART_HEAD;
03519                 break;
03520         case 1:
03521                 sect = G2_MODELPART_WAIST;
03522                 break;
03523         case 2:
03524                 sect = G2_MODELPART_LARM;
03525                 break;
03526         case 3:
03527                 sect = G2_MODELPART_RARM;
03528                 break;
03529         case 4:
03530                 sect = G2_MODELPART_RHAND;
03531                 break;
03532         case 5:
03533                 sect = G2_MODELPART_LLEG;
03534                 break;
03535         case 6:
03536                 sect = G2_MODELPART_RLEG;
03537                 break;
03538         default:
03539                 break;
03540         }
03541 
03542         G_GetDismemberBolt(self, boltPoint, sect);
03543         G_Dismember( self, self, boltPoint, sect, 90, 0, BOTH_DEATH1, qfalse );
03544 }

void DismembermentTest gentity_t self  ) 
 

Definition at line 3497 of file g_combat.c.

References BOTH_DEATH1, G2_MODELPART_HEAD, G2_MODELPART_RLEG, G_Dismember(), G_GetDismemberBolt(), gentity_t, qfalse, and vec3_t.

Referenced by ClientCommand().

03498 {
03499         int sect = G2_MODELPART_HEAD;
03500         vec3_t boltPoint;
03501 
03502         while (sect <= G2_MODELPART_RLEG)
03503         {
03504                 G_GetDismemberBolt(self, boltPoint, sect);
03505                 G_Dismember( self, self, boltPoint, sect, 90, 0, BOTH_DEATH1, qfalse );
03506                 sect++;
03507         }
03508 }

void ExplodeDeath gentity_t self  ) 
 

Definition at line 368 of file g_combat.c.

References entityState_s::angles, AngleVectors(), entityShared_t::currentOrigin, G_RadiusDamage(), gentity_t, entityState_s::loopIsSoundset, entityState_s::loopSound, MOD_UNKNOWN, NULL, ObjectDie(), gentity_s::parent, entityState_s::pos, qfalse, gentity_s::r, gentity_s::s, gentity_s::splashDamage, gentity_s::splashRadius, gentity_s::takedamage, trajectory_t::trBase, vec3_t, and VectorCopy.

00369 {
00370 //      gentity_t       *tent;
00371         vec3_t          forward;
00372 
00373         self->takedamage = qfalse;//stop chain reaction runaway loops
00374 
00375         self->s.loopSound = 0;
00376         self->s.loopIsSoundset = qfalse;
00377 
00378         VectorCopy( self->r.currentOrigin, self->s.pos.trBase );
00379 
00380 //      tent = G_TempEntity( self->s.origin, EV_FX_EXPLOSION );
00381         AngleVectors(self->s.angles, forward, NULL, NULL);
00382 
00383 /*      
00384         if ( self->fxID > 0 )
00385         {
00386                 G_PlayEffect( self->fxID, self->r.currentOrigin, forward );
00387         }
00388         else
00389         */
00390 
00391         {
00392 //              CG_SurfaceExplosion( self->r.currentOrigin, forward, 20.0f, 12.0f, ((self->spawnflags&4)==qfalse) );    //FIXME: This needs to be consistent to all exploders!
00393 //              G_Sound(self, self->sounds );
00394         }
00395         
00396         if(self->splashDamage > 0 && self->splashRadius > 0)
00397         {
00398                 gentity_t *attacker = self;
00399                 if ( self->parent )
00400                 {
00401                         attacker = self->parent;
00402                 }
00403                 G_RadiusDamage( self->r.currentOrigin, attacker, self->splashDamage, self->splashRadius, 
00404                                 attacker, NULL, MOD_UNKNOWN );
00405         }
00406 
00407         ObjectDie( self, self, self, 20, 0 );
00408 }

void G_AddPowerDuelLoserScore int  team,
int  score
 

Definition at line 2036 of file g_combat.c.

References gentity_s::client, ClientUserinfoChanged(), CON_CONNECTED, clientPersistant_t::connected, clientSession_t::duelTeam, g_entities, gentity_t, gclient_s::iAmALoser, gentity_s::inuse, clientSession_t::losses, MAX_CLIENTS, entityState_s::number, gclient_s::pers, gclient_s::ps, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, STAT_HEALTH, playerState_s::stats, and TEAM_SPECTATOR.

Referenced by player_die().

02037 {
02038         int i = 0;
02039         gentity_t *check;
02040 
02041         while (i < MAX_CLIENTS)
02042         {
02043                 check = &g_entities[i];
02044                 if (check->inuse && check->client &&
02045                         check->client->pers.connected == CON_CONNECTED &&
02046                         (check->client->iAmALoser || (check->client->ps.stats[STAT_HEALTH] <= 0 && check->client->sess.sessionTeam != TEAM_SPECTATOR)) &&
02047                         check->client->sess.duelTeam == team)
02048                 { //found a living client on the specified team
02049                         check->client->sess.losses += score;
02050                         ClientUserinfoChanged(check->s.number);
02051                 }
02052                 i++;
02053         }
02054 }

void G_AddPowerDuelScore int  team,
int  score
 

Definition at line 2015 of file g_combat.c.

References gentity_s::client, ClientUserinfoChanged(), CON_CONNECTED, clientPersistant_t::connected, clientSession_t::duelTeam, g_entities, gentity_t, gclient_s::iAmALoser, gentity_s::inuse, MAX_CLIENTS, entityState_s::number, gclient_s::pers, gclient_s::ps, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, STAT_HEALTH, playerState_s::stats, TEAM_SPECTATOR, and clientSession_t::wins.

Referenced by player_die().

02016 {
02017         int i = 0;
02018         gentity_t *check;
02019 
02020         while (i < MAX_CLIENTS)
02021         {
02022                 check = &g_entities[i];
02023                 if (check->inuse && check->client &&
02024                         check->client->pers.connected == CON_CONNECTED && !check->client->iAmALoser &&
02025                         check->client->ps.stats[STAT_HEALTH] > 0 &&
02026                         check->client->sess.sessionTeam != TEAM_SPECTATOR &&
02027                         check->client->sess.duelTeam == team)
02028                 { //found a living client on the specified team
02029                         check->client->sess.wins += score;
02030                         ClientUserinfoChanged(check->s.number);
02031                 }
02032                 i++;
02033         }
02034 }

void G_AlertTeam gentity_t victim,
gentity_t attacker,
float  radius,
float  soundDist
 

Definition at line 1769 of file g_combat.c.

References gentity_s::client, entityShared_t::currentOrigin, gentity_s::enemy, g_entities, G_SetEnemy(), gentity_t, gentity_s::health, gNPCstats_e::hfov, InFOV(), gentity_s::NPC, NPC_ClearLOS2(), NULL, gclient_s::playerTeam, gentity_s::r, SCF_IGNORE_ALERTS, SCF_LOOK_FOR_ENEMIES, SCF_NO_GROUPS, gNPC_t::scriptFlags, gNPC_t::stats, trap_EntitiesInBox(), trap_InPVS(), vec3_t, and gNPCstats_e::vfov.

Referenced by G_AngerAlert(), and G_DeathAlert().

01770 {
01771         int                     radiusEnts[ 128 ];
01772         gentity_t       *check;
01773         vec3_t          mins, maxs;
01774         int                     numEnts;
01775         int                     i;
01776         float           distSq, sndDistSq = (soundDist*soundDist);
01777 
01778         if ( attacker == NULL || attacker->client == NULL )
01779                 return;
01780 
01781         //Setup the bbox to search in
01782         for ( i = 0; i < 3; i++ )
01783         {
01784                 mins[i] = victim->r.currentOrigin[i] - radius;
01785                 maxs[i] = victim->r.currentOrigin[i] + radius;
01786         }
01787 
01788         //Get the number of entities in a given space
01789         numEnts = trap_EntitiesInBox( mins, maxs, radiusEnts, 128 );
01790 
01791         //Cull this list
01792         for ( i = 0; i < numEnts; i++ )
01793         {
01794                 check = &g_entities[radiusEnts[i]];
01795 
01796                 //Validate clients
01797                 if ( check->client == NULL )
01798                         continue;
01799 
01800                 //only want NPCs
01801                 if ( check->NPC == NULL )
01802                         continue;
01803 
01804                 //Don't bother if they're ignoring enemies
01805 //              if ( check->svFlags & SVF_IGNORE_ENEMIES )
01806 //                      continue;
01807 
01808                 //This NPC specifically flagged to ignore alerts
01809                 if ( check->NPC->scriptFlags & SCF_IGNORE_ALERTS )
01810                         continue;
01811 
01812                 //This NPC specifically flagged to ignore alerts
01813                 if ( !(check->NPC->scriptFlags&SCF_LOOK_FOR_ENEMIES) )
01814                         continue;
01815 
01816                 //this ent does not participate in group AI
01817                 if ( (check->NPC->scriptFlags&SCF_NO_GROUPS) )
01818                         continue;
01819 
01820                 //Skip the requested avoid check if present
01821                 if ( check == victim )
01822                         continue;
01823 
01824                 //Skip the attacker
01825                 if ( check == attacker )
01826                         continue;
01827 
01828                 //Must be on the same team
01829                 if ( check->client->playerTeam != victim->client->playerTeam )
01830                         continue;
01831 
01832                 //Must be alive
01833                 if ( check->health <= 0 )
01834                         continue;
01835 
01836                 if ( check->enemy == NULL )
01837                 {//only do this if they're not already mad at someone
01838                         distSq = DistanceSquared( check->r.currentOrigin, victim->r.currentOrigin );
01839                         if ( distSq > 16384 /*128 squared*/ && !trap_InPVS( victim->r.currentOrigin, check->r.currentOrigin ) )
01840                         {//not even potentially visible/hearable
01841                                 continue;
01842                         }
01843                         //NOTE: this allows sound alerts to still go through doors/PVS if the teammate is within 128 of the victim...
01844                         if ( soundDist <= 0 || distSq > sndDistSq )
01845                         {//out of sound range
01846                                 if ( !InFOV( victim, check, check->NPC->stats.hfov, check->NPC->stats.vfov ) 
01847                                         ||  !NPC_ClearLOS2( check, victim->r.currentOrigin ) )
01848                                 {//out of FOV or no LOS
01849                                         continue;
01850                                 }
01851                         }
01852 
01853                         //FIXME: This can have a nasty cascading effect if setup wrong...
01854                         G_SetEnemy( check, attacker );
01855                 }
01856         }
01857 }

void G_ApplyKnockback gentity_t targ,
vec3_t  newDir,
float  knockback
 

Definition at line 2949 of file g_combat.c.

References gentity_s::client, entityShared_t::currentOrigin, g_gravity, g_knockback, gentity_t, level, gentity_s::physicsBounce, playerState_s::pm_flags, playerState_s::pm_time, PMF_TIME_KNOCKBACK, entityState_s::pos, gclient_s::ps, gentity_s::r, gentity_s::s, level_locals_t::time, TR_LINEAR_STOP, TR_NONLINEAR_STOP, TR_STATIONARY, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, vmCvar_t::value, vec3_t, VectorAdd, VectorCopy, VectorScale, and playerState_s::velocity.

Referenced by DoImpact().

02950 {
02951         vec3_t  kvel;
02952         float   mass;
02953 
02954         if ( targ->physicsBounce > 0 )  //overide the mass
02955                 mass = targ->physicsBounce;
02956         else
02957                 mass = 200;
02958 
02959         if ( g_gravity.value > 0 )
02960         {
02961                 VectorScale( newDir, g_knockback.value * (float)knockback / mass * 0.8, kvel );
02962                 kvel[2] = newDir[2] * g_knockback.value * (float)knockback / mass * 1.5;
02963         }
02964         else
02965         {
02966                 VectorScale( newDir, g_knockback.value * (float)knockback / mass, kvel );
02967         }
02968 
02969         if ( targ->client )
02970         {
02971                 VectorAdd( targ->client->ps.velocity, kvel, targ->client->ps.velocity );
02972         }
02973         else if ( targ->s.pos.trType != TR_STATIONARY && targ->s.pos.trType != TR_LINEAR_STOP && targ->s.pos.trType != TR_NONLINEAR_STOP )
02974         {
02975                 VectorAdd( targ->s.pos.trDelta, kvel, targ->s.pos.trDelta );
02976                 VectorCopy( targ->r.currentOrigin, targ->s.pos.trBase );
02977                 targ->s.pos.trTime = level.time;
02978         }
02979 
02980         // set the timer so that the other client can't cancel
02981         // out the movement immediately
02982         if ( targ->client && !targ->client->ps.pm_time ) 
02983         {
02984                 int             t;
02985 
02986                 t = knockback * 2;
02987                 if ( t < 50 ) {
02988                         t = 50;
02989                 }
02990                 if ( t > 200 ) {
02991                         t = 200;
02992                 }
02993                 targ->client->ps.pm_time = t;
02994                 targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
02995         }
02996 }

void G_CheckForDismemberment gentity_t ent,
gentity_t enemy,
vec3_t  point,
int  damage,
int  deathAnim,
qboolean  postDeath
 

Definition at line 4093 of file g_combat.c.

References CLASS_PROTOCOL, gentity_s::client, d_saberGhoul2Collision, G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RHAND, G2_MODELPART_RLEG, G2_MODELPART_WAIST, gclient_s::g2LastSurfaceHit, gclient_s::g2LastSurfaceTime, g_austrian, g_dismember, G_Dismember(), g_gametype, G_GetDismemberBolt(), G_GetDismemberLoc(), G_GetHitLocation(), G_GetHitLocFromSurfName(), G_GetHitQuad(), G_LogPrintf(), gentity_t, gGAvoidDismember, gentity_s::ghoul2, GT_DUEL, GT_POWERDUEL, hitLocName, HL_ARM_LT, HL_ARM_RT, HL_FOOT_LT, HL_FOOT_RT, HL_HAND_LT, HL_HAND_RT, HL_HEAD, HL_LEG_LT, HL_LEG_RT, HL_WAIST, vmCvar_t::integer, level, gentity_s::localAnimIndex, MAX_QPATH, MOD_UNKNOWN, clientPersistant_t::netname, gentity_s::NPC, gclient_s::NPC_class, gclient_s::pers, Q_irand(), level_locals_t::time, trap_G2API_GetSurfaceName(), vec3_origin, and vec3_t.

Referenced by ClientCommand(), ClientThink_real(), G_Damage(), and player_die().

04094 {
04095         int hitLoc = -1, hitLocUse = -1;
04096         vec3_t boltPoint;
04097         int dismember = g_dismember.integer;
04098 
04099         if (ent->localAnimIndex > 1)
04100         {
04101                 if (!ent->NPC)
04102                 {
04103                         return;
04104                 }
04105 
04106                 if (ent->client->NPC_class != CLASS_PROTOCOL)
04107                 { //this is the only non-humanoid allowed to do dismemberment.
04108                         return;
04109                 }
04110         }
04111 
04112         if (!dismember)
04113         {
04114                 return;
04115         }
04116 
04117         if (gGAvoidDismember == 1)
04118         {
04119                 return;
04120         }
04121 
04122         if (gGAvoidDismember != 2)
04123         { //this means do the dismemberment regardless of randomness and damage
04124                 if (Q_irand(0, 100) > dismember)
04125                 {
04126                         return;
04127                 }
04128 
04129                 if (damage < 5)
04130                 {
04131                         return;
04132                 }
04133         }
04134 
04135         if (gGAvoidDismember == 2)
04136         {
04137                 hitLoc = HL_HAND_RT;
04138         }
04139         else
04140         {
04141                 if (d_saberGhoul2Collision.integer && ent->client && ent->client->g2LastSurfaceTime == level.time)
04142                 {
04143                         char hitSurface[MAX_QPATH];
04144 
04145                         trap_G2API_GetSurfaceName(ent->ghoul2, ent->client->g2LastSurfaceHit, 0, hitSurface);
04146 
04147                         if (hitSurface[0])
04148                         {
04149                                 G_GetHitLocFromSurfName(ent, hitSurface, &hitLoc, point, vec3_origin, vec3_origin, MOD_UNKNOWN);
04150                         }
04151                 }
04152 
04153                 if (hitLoc == -1)
04154                 {
04155                         hitLoc = G_GetHitLocation( ent, point );
04156                 }
04157         }
04158 
04159         switch(hitLoc)
04160         {
04161         case HL_FOOT_RT:
04162         case HL_LEG_RT:
04163                 hitLocUse = G2_MODELPART_RLEG;
04164                 break;
04165         case HL_FOOT_LT:
04166         case HL_LEG_LT:
04167                 hitLocUse = G2_MODELPART_LLEG;
04168                 break;
04169                 
04170         case HL_WAIST:
04171                 hitLocUse = G2_MODELPART_WAIST;
04172                 break;
04173                 /*
04174         case HL_BACK_RT:
04175         case HL_BACK_LT:
04176         case HL_BACK:
04177         case HL_CHEST_RT:
04178         case HL_CHEST_LT:
04179         case HL_CHEST:
04180                 break;
04181                 */
04182         case HL_ARM_RT:
04183                 hitLocUse = G2_MODELPART_RARM;
04184                 break;
04185         case HL_HAND_RT:
04186                 hitLocUse = G2_MODELPART_RHAND;
04187                 break;
04188         case HL_ARM_LT:
04189         case HL_HAND_LT:
04190                 hitLocUse = G2_MODELPART_LARM;
04191                 break;
04192         case HL_HEAD:
04193                 hitLocUse = G2_MODELPART_HEAD;
04194                 break;
04195         default:
04196                 hitLocUse = G_GetHitQuad(ent, point);
04197                 break;
04198         }
04199 
04200         if (hitLocUse == -1)
04201         {
04202                 return;
04203         }
04204 
04205         if (ent->client)
04206         {
04207                 G_GetDismemberBolt(ent, boltPoint, hitLocUse);
04208                 if ( g_austrian.integer 
04209                         && (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) )
04210                 {
04211                         G_LogPrintf( "Duel Dismemberment: %s dismembered at %s\n", ent->client->pers.netname, hitLocName[hitLoc] );
04212                 }
04213         }
04214         else
04215         {
04216                 G_GetDismemberLoc(ent, boltPoint, hitLocUse);
04217         }
04218         G_Dismember(ent, enemy, boltPoint, hitLocUse, 90, 0, deathAnim, postDeath);
04219 }

void G_CheckVictoryScript gentity_t self  ) 
 

Definition at line 1985 of file g_combat.c.

References gNPC_t::blockedSpeechDebounceTime, BSET_VICTORY, CLASS_GALAKMECH, gentity_s::client, AIGroupInfo_s::commander, G_ActivateBehavior(), gentity_t, gNPC_t::greetingDebounceTime, gNPC_t::group, level, gentity_s::NPC, gclient_s::NPC_class, Q_irand(), gNPC_t::rank, gentity_s::s, level_locals_t::time, TIMER_Set(), gentity_s::wait, entityState_s::weapon, and WP_SABER.

Referenced by player_die().

01986 {
01987         if ( !G_ActivateBehavior( self, BSET_VICTORY ) )
01988         {
01989                 if ( self->NPC && self->s.weapon == WP_SABER )
01990                 {//Jedi taunt from within their AI
01991                         self->NPC->blockedSpeechDebounceTime = 0;//get them ready to taunt
01992                         return;
01993                 }
01994                 if ( self->client && self->client->NPC_class == CLASS_GALAKMECH )
01995                 {
01996                         self->wait = 1;
01997                         TIMER_Set( self, "gloatTime", Q_irand( 5000, 8000 ) );
01998                         self->NPC->blockedSpeechDebounceTime = 0;//get him ready to taunt
01999                         return;
02000                 }
02001                 //FIXME: any way to not say this *right away*?  Wait for victim's death anim/scream to finish?
02002                 if ( self->NPC && self->NPC->group && self->NPC->group->commander && self->NPC->group->commander->NPC && self->NPC->group->commander->NPC->rank > self->NPC->rank && !Q_irand( 0, 2 ) )
02003                 {//sometimes have the group commander speak instead
02004                         self->NPC->group->commander->NPC->greetingDebounceTime = level.time + Q_irand( 2000, 5000 );
02005                         //G_AddVoiceEvent( self->NPC->group->commander, Q_irand(EV_VICTORY1, EV_VICTORY3), 2000 );
02006                 }
02007                 else if ( self->NPC )
02008                 {
02009                         self->NPC->greetingDebounceTime = level.time + Q_irand( 2000, 5000 );
02010                         //G_AddVoiceEvent( self, Q_irand(EV_VICTORY1, EV_VICTORY3), 2000 );
02011                 }
02012         }
02013 }

void G_Damage gentity_t targ,
gentity_t inflictor,
gentity_t attacker,
vec3_t  dir,
vec3_t  point,
int  damage,
int  dflags,
int  mod
 

Definition at line 4369 of file g_combat.c.

References gentity_s::activator, gentity_s::alliedTeam, AngleVectors(), bgSiegeClasses, BotDamageNotification(), BROKENLIMB_LARM, BROKENLIMB_RARM, playerState_s::brokenLimbs, BSET_DEATH, CFL_STRONGAGAINSTPHYSICAL, CheckArmor(), CLASS_ATST, CLASS_GONK, CLASS_INTERROGATOR, CLASS_MARK1, CLASS_MARK2, CLASS_MOUSE, CLASS_PROBE, CLASS_PROTOCOL, CLASS_R2D2, CLASS_R5D2, CLASS_RANCOR, CLASS_SEEKER, CLASS_SENTRY, CLASS_VEHICLE, client, gentity_s::client, playerState_s::clientNum, entityShared_t::currentOrigin, gclient_s::damage_armor, gclient_s::damage_blood, gclient_s::damage_from, gclient_s::damage_fromWorld, gclient_s::damage_knockback, DAMAGE_NO_DISMEMBER, DAMAGE_NO_HIT_LOC, DAMAGE_NO_KNOCKBACK, DAMAGE_NO_PROTECTION, DAMAGE_NO_SELF_PROTECTION, DAMAGE_RADIUS, DAMAGE_SABER_KNOCKBACK1, DAMAGE_SABER_KNOCKBACK1_B2, DAMAGE_SABER_KNOCKBACK2, DAMAGE_SABER_KNOCKBACK2_B2, gentity_s::damageRedirect, gentity_s::damageRedirectTo, gentity_s::die, DirToByte(), DotProduct, playerState_s::duelIndex, playerState_s::duelInProgress, EF_DEAD, EF_INVULNERABLE, playerState_s::eFlags, entityState_s::eFlags, playerState_s::electrifyTime, gentity_s::enemy, ENTITYNUM_WORLD, ET_GENERAL, ET_MISSILE, ET_MOVER, ET_NPC, ET_PLAYER, entityState_s::eType, EV_POWERUP_BATTLESUIT, EV_SHIELD_HIT, entityState_s::eventParm, playerState_s::fd, FL_BBRUSH, FL_DMG_BY_HEAVY_WEAP_ONLY, FL_DMG_BY_SABER_ONLY, FL_GODMODE, FL_NO_KNOCKBACK, FL_SHIELDED, FL_UNDYING, gentity_s::flags, FORCE_LEVEL_1, FORCE_LEVEL_2, FORCE_LEVEL_3, forcedata_s::forcePower, forcedata_s::forcePowerLevel, forcedata_s::forcePowersActive, gclient_s::forcePowerSoundDebounce, FP_PROTECT, FP_RAGE, trace_t::fraction, gclient_s::g2LastSurfaceHit, gclient_s::g2LastSurfaceTime, G_ActivateBehavior(), G_AddEvent(), g_armBreakage, G_BreakArm(), G_CheckForDismemberment(), g_debugDamage, g_debugMelee, g_entities, g_ff_objectives, G_FlyVehicleDestroySurface(), g_friendlyFire, g_gametype, G_GetHitLocFromSurfName(), G_HeavyMelee(), g_knockback, G_LetGoOfWall(), G_LocationBasedDamageModifier(), G_LogWeaponDamage(), G_PreDefSound(), G_Printf(), g_saberDmgVelocityScale, G_ScaleNetHealth(), G_ShipSurfaceForSurfName(), G_TempEntity(), G_ThereIsAMaster(), g_trueJedi, G_VehicleSetDamageLocFlags(), G_VehUpdateShields(), gclient_t, gentity_s::genericValue4, gentity_t, gentity_s::ghoul2, GlobalUse(), gPainHitLoc, gPainMOD, gPainPoint, gSiegeRoundBegun, GT_CTF, GT_CTY, GT_JEDIMASTER, GT_SIEGE, GT_TEAM, gentity_s::health, vehicleInfo_t::health_back, vehicleInfo_t::health_front, vehicleInfo_t::health_left, vehicleInfo_t::health_right, HL_ARM_LT, HL_ARM_RT, HL_HAND_LT, HL_HAND_RT, vmCvar_t::integer, level_locals_t::intermissionQueued, gentity_s::inuse, gclient_s::invulnerableTimer, playerState_s::isJediMaster, Jetpack_Off(), gclient_s::jetPackOn, gclient_s::jetPackToggleTime, saberInfo_t::knockbackScale, saberInfo_t::knockbackScale2, gclient_s::lasthurt_client, gclient_s::lasthurt_mod, level, gentity_s::locationDamage, Vehicle_s::m_iArmor, Vehicle_s::m_iShields, playerState_s::m_iVehicleNum, Vehicle_s::m_LandTrace, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, Vehicle_s::m_vOrientation, MAX_CLIENTS, MAX_QPATH, gentity_s::maxHealth, MOD_BRYAR_PISTOL, MOD_BRYAR_PISTOL_ALT, MOD_CONC, MOD_CONC_ALT, MOD_CRUSH, MOD_DEMP2, MOD_DEMP2_ALT, MOD_DET_PACK_SPLASH, MOD_FALLING, MOD_FLECHETTE_ALT_SPLASH, MOD_MELEE, MOD_REPEATER_ALT, MOD_REPEATER_ALT_SPLASH, MOD_ROCKET, MOD_ROCKET_HOMING, MOD_ROCKET_HOMING_SPLASH, MOD_ROCKET_SPLASH, MOD_SABER, MOD_SUICIDE, MOD_TELEFRAG, MOD_THERMAL, MOD_THERMAL_SPLASH, MOD_TIMED_MINE_SPLASH, MOD_TRIGGER_HURT, MOD_TRIP_MINE_SPLASH, MOD_TURBLAST, MOD_VEHICLE, MOVER_POS1, gentity_s::moverState, gclient_s::noclip, entityState_s::NPC_class, gclient_s::NPC_class, NULL, entityState_s::number, OnSameTeam(), playerState_s::origin, entityState_s::otherEntityNum, playerState_s::otherKiller, playerState_s::otherKillerDebounceTime, playerState_s::otherKillerTime, entityState_s::owner, gentity_s::pain, PDSOUND_PROTECTHIT, PERS_ATTACKEE_ARMOR, PERS_ATTACKER, PERS_HITS, playerState_s::persistant, PITCH, playerState_s::pm_flags, playerState_s::pm_time, PMF_STUCK_TO_WALL, PMF_TIME_KNOCKBACK, gentity_s::pos1, gentity_s::pos2, playerState_s::powerups, gclient_s::ps, PW_BATTLESUIT, PW_FORCE_BOON, Q3_INFINITE, Q_irand(), qfalse, qtrue, gentity_s::r, ROLL, gentity_s::s, gclient_s::saber, gclient_s::sess, clientSession_t::sessionTeam, SHIPSURF_BACK, SHIPSURF_FRONT, SHIPSURF_LEFT, SHIPSURF_RIGHT, entityState_s::shouldtarget, gclient_s::siegeClass, STAT_ARMOR, STAT_HEALTH, STAT_MAX_HEALTH, playerState_s::stats, SVF_GLASS_BRUSH, entityShared_t::svFlags, gentity_s::takedamage, Team_CheckHurtCarrier(), gentity_s::teamnodmg, entityState_s::teamowner, level_locals_t::time, entityState_s::time2, playerState_s::torsoAnim, trap_G2API_GetSurfaceName(), playerState_s::trueJedi, playerState_s::trueNonJedi, vehicleInfo_t::type, gentity_s::use, vmCvar_t::value, vec3_origin, vec3_t, VectorAdd, VectorClear, VectorCopy, VectorNormalize(), VectorScale, VectorSubtract, playerState_s::velocity, VH_ANIMAL, VH_FIGHTER, VH_SPEEDER, VH_WALKER, playerState_s::weapon, WEAPON_CHARGING, WEAPON_CHARGING_ALT, WEAPON_READY, playerState_s::weaponstate, playerState_s::weaponTime, and WP_SABER.

Referenced by AnimateRiders(), Blocked_Door(), Blocked_Mover(), Boba_FireFlameThrower(), ClientEvents(), ClientThink_real(), Cmd_DuelTeam_f(), DEMP2_AltRadiusDamage(), DetPackBlow(), Do_Strike(), DoGripAction(), DoImpact(), EjectAll(), ForceLightningDamage(), funcBBrushDieGo(), G_EjectDroidUnit(), G_KillBox(), G_MissileImpact(), G_MoverPush(), G_RadiusDamage(), G_RunFrame(), G_RunStuckMissile(), G_TryPushingEntity(), Howler_TryDamage(), hurt_touch(), hyperspace_touch(), ImperialProbe_Wait(), Interrogator_Melee(), MineMonster_TryDamage(), NPC_BSGM_Attack(), NPC_BSSeeker_Default(), NPC_Mark1_Pain(), NPC_Mark2_Pain(), NPC_Seeker_Pain(), P_WorldEffects(), player_die(), PM_VehicleImpact(), Rancor_Attack(), Rancor_Bite(), Rancor_Crush(), Rancor_Smash(), Rancor_Swing(), Seeker_Ranged(), shipboundary_touch(), target_kill_use(), target_laser_think(), Wampa_Slash(), WP_DisruptorAltFire(), WP_FireMelee(), WP_FireStunBaton(), WP_SaberApplyDamage(), WP_SaberPositionUpdate(), and WP_SaberRadiusDamage().

04370                                                                                        {
04371         gclient_t       *client;
04372         int                     take;
04373         int                     save;
04374         int                     asave;
04375         int                     knockback;
04376         int                     max;
04377         int                     subamt = 0;
04378         float           famt = 0;
04379         float           hamt = 0;
04380         float           shieldAbsorbed = 0;
04381 
04382         if (targ && targ->damageRedirect)
04383         {
04384                 G_Damage(&g_entities[targ->damageRedirectTo], inflictor, attacker, dir, point, damage, dflags, mod);
04385                 return;
04386         }
04387 
04388         if (mod == MOD_DEMP2 && targ && targ->inuse && targ->client)
04389         {
04390                 if ( targ->client->ps.electrifyTime < level.time )
04391                 {//electrocution effect
04392                         if (targ->s.eType == ET_NPC && targ->s.NPC_class == CLASS_VEHICLE &&
04393                                 targ->m_pVehicle && (targ->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER || targ->m_pVehicle->m_pVehicleInfo->type == VH_WALKER))
04394                         { //do some extra stuff to speeders/walkers
04395                                 targ->client->ps.electrifyTime = level.time + Q_irand( 3000, 4000 );
04396                         }
04397                         else if ( targ->s.NPC_class != CLASS_VEHICLE 
04398                                 || (targ->m_pVehicle && targ->m_pVehicle->m_pVehicleInfo->type != VH_FIGHTER) )
04399                         {//don't do this to fighters
04400                                 targ->client->ps.electrifyTime = level.time + Q_irand( 300, 800 );
04401                         }
04402                 }
04403         }
04404 
04405         if (g_gametype.integer == GT_SIEGE &&
04406                 !gSiegeRoundBegun)
04407         { //nothing can be damaged til the round starts.
04408                 return;
04409         }
04410 
04411         if (!targ->takedamage) {
04412                 return;
04413         }
04414 
04415         if ( (targ->flags&FL_SHIELDED) && mod != MOD_SABER  && !targ->client)
04416         {//magnetically protected, this thing can only be damaged by lightsabers
04417                 return;
04418         }
04419 
04420         if ((targ->flags & FL_DMG_BY_SABER_ONLY) && mod != MOD_SABER)
04421         { //saber-only damage
04422                 return;
04423         }
04424 
04425         if ( targ->client )
04426         {//don't take damage when in a walker, or fighter
04427                 //unless the walker/fighter is dead!!! -rww
04428                 if ( targ->client->ps.clientNum < MAX_CLIENTS && targ->client->ps.m_iVehicleNum )
04429                 {
04430                         gentity_t *veh = &g_entities[targ->client->ps.m_iVehicleNum];
04431                         if ( veh->m_pVehicle && veh->health > 0 )
04432                         {
04433                                 if ( veh->m_pVehicle->m_pVehicleInfo->type == VH_WALKER ||
04434                                          veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER)
04435                                 {
04436                                         if (!(dflags & DAMAGE_NO_PROTECTION))
04437                                         {
04438                                                 return;
04439                                         }
04440                                 }
04441                         }
04442                 }
04443         }
04444 
04445         if ((targ->flags & FL_DMG_BY_HEAVY_WEAP_ONLY))
04446         { //only take damage from explosives and such
04447                 if (mod != MOD_REPEATER_ALT &&
04448                         mod != MOD_ROCKET &&
04449                         mod != MOD_FLECHETTE_ALT_SPLASH &&
04450                         mod != MOD_ROCKET_HOMING &&
04451                         mod != MOD_THERMAL &&
04452                         mod != MOD_THERMAL_SPLASH &&
04453                         mod != MOD_TRIP_MINE_SPLASH &&
04454                         mod != MOD_TIMED_MINE_SPLASH &&
04455                         mod != MOD_DET_PACK_SPLASH &&
04456                         mod != MOD_VEHICLE &&
04457                         mod != MOD_CONC &&
04458                         mod != MOD_CONC_ALT &&
04459                         mod != MOD_SABER &&
04460                         mod != MOD_TURBLAST &&
04461                         mod != MOD_SUICIDE &&
04462                         mod != MOD_FALLING &&
04463                         mod != MOD_CRUSH &&
04464                         mod != MOD_TELEFRAG &&
04465                         mod != MOD_TRIGGER_HURT)
04466                 {
04467                         if ( mod != MOD_MELEE || !G_HeavyMelee( attacker ) )
04468                         { //let classes with heavy melee ability damage heavy wpn dmg doors with fists
04469                                 return;
04470                         }
04471                 }
04472         }
04473 
04474         if (targ->flags & FL_BBRUSH)
04475         {
04476                 if (mod == MOD_DEMP2 ||
04477                         mod == MOD_DEMP2_ALT ||
04478                         mod == MOD_BRYAR_PISTOL ||
04479                         mod == MOD_BRYAR_PISTOL_ALT ||
04480                         mod == MOD_MELEE)
04481                 { //these don't damage bbrushes.. ever
04482                         if ( mod != MOD_MELEE || !G_HeavyMelee( attacker ) )
04483                         { //let classes with heavy melee ability damage breakable brushes with fists
04484                                 return;
04485                         }
04486                 }
04487         }
04488 
04489         if (targ && targ->client && targ->client->ps.duelInProgress)
04490         {
04491                 if (attacker && attacker->client && attacker->s.number != targ->client->ps.duelIndex)
04492                 {
04493                         return;
04494                 }
04495                 else if (attacker && attacker->client && mod != MOD_SABER)
04496                 {
04497                         return;
04498                 }
04499         }
04500         if (attacker && attacker->client && attacker->client->ps.duelInProgress)
04501         {
04502                 if (targ && targ->client && targ->s.number != attacker->client->ps.duelIndex)
04503                 {
04504                         return;
04505                 }
04506                 else if (targ && targ->client && mod != MOD_SABER)
04507                 {
04508                         return;
04509                 }
04510         }
04511 
04512         if ( !(dflags & DAMAGE_NO_PROTECTION) ) 
04513         {//rage overridden by no_protection
04514                 if (targ && targ->client && (targ->client->ps.fd.forcePowersActive & (1 << FP_RAGE)))
04515                 {
04516                         damage *= 0.5;
04517                 }
04518         }
04519 
04520         // the intermission has allready been qualified for, so don't
04521         // allow any extra scoring
04522         if ( level.intermissionQueued ) {
04523                 return;
04524         }
04525         if ( !inflictor ) {
04526                 inflictor = &g_entities[ENTITYNUM_WORLD];
04527         }
04528         if ( !attacker ) {
04529                 attacker = &g_entities[ENTITYNUM_WORLD];
04530         }
04531 
04532         // shootable doors / buttons don't actually have any health
04533 
04534         //if genericValue4 == 1 then it's glass or a breakable and those do have health
04535         if ( targ->s.eType == ET_MOVER && targ->genericValue4 != 1 ) {
04536                 if ( targ->use && targ->moverState == MOVER_POS1 ) {
04537                         GlobalUse( targ, inflictor, attacker );
04538                 }
04539                 return;
04540         }
04541         // reduce damage by the attacker's handicap value
04542         // unless they are rocket jumping
04543         if ( attacker->client 
04544                 && attacker != targ 
04545                 && attacker->s.eType == ET_PLAYER 
04546                 && g_gametype.integer != GT_SIEGE ) 
04547         {
04548                 max = attacker->client->ps.stats[STAT_MAX_HEALTH];
04549                 damage = damage * max / 100;
04550         }
04551 
04552         if ( !(dflags&DAMAGE_NO_HIT_LOC) )
04553         {//see if we should modify it by damage location
04554                 if (targ->inuse && (targ->client || targ->s.eType == ET_NPC) &&
04555                         attacker->inuse && (attacker->client || attacker->s.eType == ET_NPC))
04556                 { //check for location based damage stuff.
04557                         G_LocationBasedDamageModifier(targ, point, mod, dflags, &damage);
04558                 }
04559         }
04560 
04561         if ( targ->client 
04562                 && targ->client->NPC_class == CLASS_RANCOR 
04563                 && (!attacker||!attacker->client||attacker->client->NPC_class!=CLASS_RANCOR) )
04564         {
04565                 // I guess always do 10 points of damage...feel free to tweak as needed
04566                 if ( damage < 10 )
04567                 {//ignore piddly little damage
04568                         damage = 0;
04569                 }
04570                 else if ( damage >= 10 )
04571                 {
04572                         damage = 10;
04573                 }
04574         }
04575 
04576         client = targ->client;
04577 
04578         if ( client ) {
04579                 if ( client->noclip ) {
04580                         return;
04581                 }
04582         }
04583 
04584         if ( !dir ) {
04585                 dflags |= DAMAGE_NO_KNOCKBACK;
04586         } else {
04587                 VectorNormalize(dir);
04588         }
04589 
04590         knockback = damage;
04591         if ( knockback > 200 ) {
04592                 knockback = 200;
04593         }
04594         if ( targ->flags & FL_NO_KNOCKBACK ) {
04595                 knockback = 0;
04596         }
04597         if ( dflags & DAMAGE_NO_KNOCKBACK ) {
04598                 knockback = 0;
04599         }
04600 
04601         // figure momentum add, even if the damage won't be taken
04602         if ( knockback && targ->client ) {
04603                 vec3_t  kvel;
04604                 float   mass;
04605 
04606                 mass = 200;
04607 
04608                 if (mod == MOD_SABER)
04609                 {
04610                         float saberKnockbackScale = g_saberDmgVelocityScale.value;
04611                         if ( (dflags&DAMAGE_SABER_KNOCKBACK1)
04612                                 || (dflags&DAMAGE_SABER_KNOCKBACK2) )
04613                         {//saber does knockback, scale it by the right number
04614                                 if ( !saberKnockbackScale )
04615                                 {
04616                                         saberKnockbackScale = 1.0f;
04617                                 }
04618                                 if ( attacker
04619                                         && attacker->client )
04620                                 {
04621                                         if ( (dflags&DAMAGE_SABER_KNOCKBACK1) )
04622                                         {
04623                                                 if ( attacker && attacker->client )
04624                                                 {
04625                                                         saberKnockbackScale *= attacker->client->saber[0].knockbackScale;
04626                                                 }
04627                                         }
04628                                         if ( (dflags&DAMAGE_SABER_KNOCKBACK1_B2) )
04629                                         {
04630                                                 if ( attacker && attacker->client )
04631                                                 {
04632                                                         saberKnockbackScale *= attacker->client->saber[0].knockbackScale2;
04633                                                 }
04634                                         }
04635                                         if ( (dflags&DAMAGE_SABER_KNOCKBACK2) )
04636                                         {
04637                                                 if ( attacker && attacker->client )
04638                                                 {
04639                                                         saberKnockbackScale *= attacker->client->saber[1].knockbackScale;
04640                                                 }
04641                                         }
04642                                         if ( (dflags&DAMAGE_SABER_KNOCKBACK2_B2) )
04643                                         {
04644                                                 if ( attacker && attacker->client )
04645                                                 {
04646                                                         saberKnockbackScale *= attacker->client->saber[1].knockbackScale2;
04647                                                 }
04648                                         }
04649                                 }
04650                         }
04651                         VectorScale (dir, (g_knockback.value * (float)knockback / mass)*saberKnockbackScale, kvel);
04652                 }
04653                 else
04654                 {
04655                         VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel);
04656                 }
04657                 VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity);
04658 
04659                 if (attacker && attacker->client && attacker != targ)
04660                 {
04661                         float dur = 5000;
04662                         float dur2 = 100;
04663                         if (targ->client && targ->s.eType == ET_NPC && targ->s.NPC_class == CLASS_VEHICLE)
04664                         {
04665                                 dur = 25000;
04666                                 dur2 = 25000;
04667                         }
04668                         targ->client->ps.otherKiller = attacker->s.number;
04669                         targ->client->ps.otherKillerTime = level.time + dur;
04670                         targ->client->ps.otherKillerDebounceTime = level.time + dur2;
04671                 }
04672                 // set the timer so that the other client can't cancel
04673                 // out the movement immediately
04674                 if ( !targ->client->ps.pm_time && (g_saberDmgVelocityScale.integer || mod != MOD_SABER || (dflags&DAMAGE_SABER_KNOCKBACK1) || (dflags&DAMAGE_SABER_KNOCKBACK2) || (dflags&DAMAGE_SABER_KNOCKBACK1_B2) || (dflags&DAMAGE_SABER_KNOCKBACK2_B2) ) ) {
04675                         int             t;
04676 
04677                         t = knockback * 2;
04678                         if ( t < 50 ) {
04679                                 t = 50;
04680                         }
04681                         if ( t > 200 ) {
04682                                 t = 200;
04683                         }
04684                         targ->client->ps.pm_time = t;
04685                         targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
04686                 }
04687         }
04688         else if (targ->client && targ->s.eType == ET_NPC && targ->s.NPC_class == CLASS_VEHICLE && attacker != targ)
04689         {
04690                 targ->client->ps.otherKiller = attacker->s.number;
04691                 targ->client->ps.otherKillerTime = level.time + 25000;
04692                 targ->client->ps.otherKillerDebounceTime = level.time + 25000;
04693         }
04694 
04695         
04696         if ( (g_trueJedi.integer || g_gametype.integer == GT_SIEGE)
04697                 && client )
04698         {//less explosive damage for jedi, more saber damage for non-jedi
04699                 if ( client->ps.trueJedi 
04700                         || (g_gametype.integer == GT_SIEGE&&client->ps.weapon == WP_SABER))
04701                 {//if the target is a trueJedi, reduce splash and explosive damage to 1/2
04702                         switch ( mod )
04703                         {
04704                         case MOD_REPEATER_ALT:
04705                         case MOD_REPEATER_ALT_SPLASH:
04706                         case MOD_DEMP2_ALT:
04707                         case MOD_FLECHETTE_ALT_SPLASH:
04708                         case MOD_ROCKET:
04709                         case MOD_ROCKET_SPLASH:
04710                         case MOD_ROCKET_HOMING:
04711                         case MOD_ROCKET_HOMING_SPLASH:
04712                         case MOD_THERMAL:
04713                         case MOD_THERMAL_SPLASH:
04714                         case MOD_TRIP_MINE_SPLASH:
04715                         case MOD_TIMED_MINE_SPLASH:
04716                         case MOD_DET_PACK_SPLASH:
04717                                 damage *= 0.75;
04718                                 break;
04719                         }
04720                 }
04721                 else if ( (client->ps.trueNonJedi || (g_gametype.integer == GT_SIEGE&&client->ps.weapon != WP_SABER))
04722                         && mod == MOD_SABER )
04723                 {//if the target is a trueNonJedi, take more saber damage... combined with the 1.5 in the w_saber stuff, this is 6 times damage!
04724                         if ( damage < 100 )
04725                         {
04726                                 damage *= 4;
04727                                 if ( damage > 100 )
04728                                 {
04729                                         damage = 100;
04730                                 }
04731                         }
04732                 }
04733         }
04734 
04735         if (attacker->client && targ->client && g_gametype.integer == GT_SIEGE &&
04736                 targ->client->siegeClass != -1 && (bgSiegeClasses[targ->client->siegeClass].classflags & (1<<CFL_STRONGAGAINSTPHYSICAL)))
04737         { //this class is flagged to take less damage from physical attacks.
04738                 //For now I'm just decreasing against any client-based attack, this can be changed later I guess.
04739                 damage *= 0.5;
04740         }
04741 
04742         // check for completely getting out of the damage
04743         if ( !(dflags & DAMAGE_NO_PROTECTION) ) {
04744 
04745                 // if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target
04746                 // if the attacker was on the same team
04747                 if ( targ != attacker)
04748                 {
04749                         if (OnSameTeam (targ, attacker))
04750                         {
04751                                 if ( !g_friendlyFire.integer )
04752                                 {
04753                                         return;
04754                                 }
04755                         }
04756                         else if (attacker && attacker->inuse &&
04757                                 !attacker->client && attacker->activator &&
04758                                 targ != attacker->activator &&
04759                                 attacker->activator->inuse && attacker->activator->client)
04760                         { //emplaced guns don't hurt teammates of user
04761                                 if (OnSameTeam (targ, attacker->activator))
04762                                 {
04763                                         if ( !g_friendlyFire.integer )
04764                                         {
04765                                                 return;
04766                                         }
04767                                 }
04768                         }
04769                         else if (targ->inuse && targ->client &&
04770                                 g_gametype.integer >= GT_TEAM &&
04771                                 attacker->s.number >= MAX_CLIENTS &&
04772                                 attacker->alliedTeam &&
04773                                 targ->client->sess.sessionTeam == attacker->alliedTeam &&
04774                                 !g_friendlyFire.integer)
04775                         { //things allied with my team should't hurt me.. I guess
04776                                 return;
04777                         }
04778                 }
04779 
04780                 if (g_gametype.integer == GT_JEDIMASTER && !g_friendlyFire.integer &&
04781                         targ && targ->client && attacker && attacker->client &&
04782                         targ != attacker && !targ->client->ps.isJediMaster && !attacker->client->ps.isJediMaster &&
04783                         G_ThereIsAMaster())
04784                 {
04785                         return;
04786                 }
04787 
04788                 if (targ->s.number >= MAX_CLIENTS && targ->client 
04789                         && targ->s.shouldtarget && targ->s.teamowner &&
04790                         attacker && attacker->inuse && attacker->client && targ->s.owner >= 0 && targ->s.owner < MAX_CLIENTS)
04791                 {
04792                         gentity_t *targown = &g_entities[targ->s.owner];
04793 
04794                         if (targown && targown->inuse && targown->client && OnSameTeam(targown, attacker))
04795                         {
04796                                 if (!g_friendlyFire.integer)
04797                                 {
04798                                         return;
04799                                 }
04800                         }
04801                 }
04802 
04803                 // check for godmode
04804                 if ( (targ->flags & FL_GODMODE) && targ->s.eType != ET_NPC ) {
04805                         return;
04806                 }
04807 
04808                 if (targ && targ->client && (targ->client->ps.eFlags & EF_INVULNERABLE) &&
04809                         attacker && attacker->client && targ != attacker)
04810                 {
04811                         if (targ->client->invulnerableTimer <= level.time)
04812                         {
04813                                 targ->client->ps.eFlags &= ~EF_INVULNERABLE;
04814                         }
04815                         else
04816                         {
04817                                 return;
04818                         }
04819                 }
04820         }
04821 
04822         //check for teamnodmg
04823         //NOTE: non-client objects hitting clients (and clients hitting clients) purposely doesn't obey this teamnodmg (for emplaced guns)
04824         if ( attacker && !targ->client )
04825         {//attacker hit a non-client
04826                 if ( g_gametype.integer == GT_SIEGE &&
04827                         !g_ff_objectives.integer )
04828                 {//in siege mode (and...?)
04829                         if ( targ->teamnodmg )
04830                         {//targ shouldn't take damage from a certain team
04831                                 if ( attacker->client )
04832                                 {//a client hit a non-client object
04833                                         if ( targ->teamnodmg == attacker->client->sess.sessionTeam )
04834                                         {
04835                                                 return;
04836                                         }
04837                                 }
04838                                 else if ( attacker->teamnodmg )
04839                                 {//a non-client hit a non-client object
04840                                         //FIXME: maybe check alliedTeam instead?
04841                                         if ( targ->teamnodmg == attacker->teamnodmg )
04842                                         {
04843                                                 if (attacker->activator &&
04844                                                         attacker->activator->inuse &&
04845                                                         attacker->activator->s.number < MAX_CLIENTS &&
04846                                                         attacker->activator->client &&
04847                                                         attacker->activator->client->sess.sessionTeam != targ->teamnodmg)
04848                                                 { //uh, let them damage it I guess.
04849                                                 }
04850                                                 else
04851                                                 {
04852                                                         return;
04853                                                 }
04854                                         }
04855                                 }
04856                         }
04857                 }
04858         }
04859 
04860         // battlesuit protects from all radius damage (but takes knockback)
04861         // and protects 50% against all damage
04862         if ( client && client->ps.powerups[PW_BATTLESUIT] ) {
04863                 G_AddEvent( targ, EV_POWERUP_BATTLESUIT, 0 );
04864                 if ( ( dflags & DAMAGE_RADIUS ) || ( mod == MOD_FALLING ) ) {
04865                         return;
04866                 }
04867                 damage *= 0.5;
04868         }
04869 
04870         // add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
04871         if ( attacker->client && targ != attacker && targ->health > 0
04872                         && targ->s.eType != ET_MISSILE
04873                         && targ->s.eType != ET_GENERAL
04874                         && client) {
04875                 if ( OnSameTeam( targ, attacker ) ) {
04876                         attacker->client->ps.persistant[PERS_HITS]--;
04877                 } else {
04878                         attacker->client->ps.persistant[PERS_HITS]++;
04879                 }
04880                 attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health<<8)|(client->ps.stats[STAT_ARMOR]);
04881         }
04882 
04883         // always give half damage if hurting self... but not in siege.  Heavy weapons need a counter.
04884         // calculated after knockback, so rocket jumping works
04885         if ( targ == attacker && !(dflags & DAMAGE_NO_SELF_PROTECTION)) {
04886                 if ( g_gametype.integer == GT_SIEGE )
04887                 {
04888                         damage *= 1.5;
04889                 }
04890                 else
04891                 {
04892                         damage *= 0.5;
04893                 }
04894         }
04895 
04896         if ( damage < 1 ) {
04897                 damage = 1;
04898         }
04899         take = damage;
04900         save = 0;
04901 
04902         // save some from armor
04903         asave = CheckArmor (targ, take, dflags);
04904 
04905         if (asave)
04906         {
04907                 shieldAbsorbed = asave;
04908         }
04909 
04910         take -= asave;
04911         if ( targ->client )
04912         {//update vehicle shields and armor, check for explode 
04913                 if ( targ->client->NPC_class == CLASS_VEHICLE &&
04914                         targ->m_pVehicle )
04915                 {//FIXME: should be in its own function in g_vehicles.c now, too big to be here
04916                         int surface = -1;
04917                         if ( attacker )
04918                         {//so we know the last guy who shot at us
04919                                 targ->enemy = attacker;
04920                         }
04921 
04922                         if ( ( targ->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL ) )
04923                         {
04924                                 //((CVehicleNPC *)targ->NPC)->m_ulFlags |= CVehicleNPC::VEH_BUCKING;
04925                         }
04926 
04927                         targ->m_pVehicle->m_iShields = targ->client->ps.stats[STAT_ARMOR];
04928                         G_VehUpdateShields( targ );
04929                         targ->m_pVehicle->m_iArmor -= take;
04930                         if ( targ->m_pVehicle->m_iArmor <= 0 ) 
04931                         {
04932                                 targ->s.eFlags |= EF_DEAD;
04933                                 targ->client->ps.eFlags |= EF_DEAD;
04934                                 targ->m_pVehicle->m_iArmor = 0;
04935                         }
04936                         if ( targ->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
04937                         {//get the last surf that was hit
04938                                 if ( targ->client && targ->client->g2LastSurfaceTime == level.time)
04939                                 {
04940                                         char hitSurface[MAX_QPATH];
04941 
04942                                         trap_G2API_GetSurfaceName(targ->ghoul2, targ->client->g2LastSurfaceHit, 0, hitSurface);
04943 
04944                                         if (hitSurface[0])
04945                                         {
04946                                                 surface = G_ShipSurfaceForSurfName( &hitSurface[0] );
04947 
04948                                                 if ( take && surface > 0 )
04949                                                 {//hit a certain part of the ship
04950                                                         int deathPoint = 0;
04951 
04952                                                         targ->locationDamage[surface] += take;
04953 
04954                                                         switch(surface)
04955                                                         {
04956                                                         case SHIPSURF_FRONT:
04957                                                                 deathPoint = targ->m_pVehicle->m_pVehicleInfo->health_front;
04958                                                                 break;
04959                                                         case SHIPSURF_BACK:
04960                                                                 deathPoint = targ->m_pVehicle->m_pVehicleInfo->health_back;
04961                                                                 break;
04962                                                         case SHIPSURF_RIGHT:
04963                                                                 deathPoint = targ->m_pVehicle->m_pVehicleInfo->health_right;
04964                                                                 break;
04965                                                         case SHIPSURF_LEFT:
04966                                                                 deathPoint = targ->m_pVehicle->m_pVehicleInfo->health_left;
04967                                                                 break;
04968                                                         default:
04969                                                                 break;
04970                                                         }
04971 
04972                                                         //presume 0 means it wasn't set and so it should never die.
04973                                                         if ( deathPoint )
04974                                                         {
04975                                                                 if ( targ->locationDamage[surface] >= deathPoint)
04976                                                                 { //this area of the ship is now dead
04977                                                                         if ( G_FlyVehicleDestroySurface( targ, surface ) )
04978                                                                         {//actually took off a surface
04979                                                                                 G_VehicleSetDamageLocFlags( targ, surface, deathPoint );
04980                                                                         }
04981                                                                 }
04982                                                                 else
04983                                                                 {
04984                                                                         G_VehicleSetDamageLocFlags( targ, surface, deathPoint );
04985                                                                 }
04986                                                         }
04987                                                 }
04988                                         }
04989                                 }
04990                         }
04991                         if ( targ->m_pVehicle->m_pVehicleInfo->type != VH_ANIMAL )
04992                         {
04993                                 /*
04994                                 if ( targ->m_pVehicle->m_iArmor <= 0 ) 
04995                                 {//vehicle all out of armor
04996                                         Vehicle_t *pVeh = targ->m_pVehicle;
04997                                         if ( pVeh->m_iDieTime == 0 )
04998                                         {//just start the flaming effect and explosion delay, if it's not going already...
04999                                                 pVeh->m_pVehicleInfo->StartDeathDelay( pVeh, 0 );
05000                                         }
05001                                 }
05002                                 else*/
05003                                 if ( attacker 
05004                                                 //&& attacker->client 
05005                                                 && targ != attacker
05006                                                 && point 
05007                                                 && !VectorCompare( targ->client->ps.origin, point )
05008                                                 && targ->m_pVehicle->m_LandTrace.fraction >= 1.0f)
05009                                 {//just took a hit, knock us around
05010                                         vec3_t  vUp, impactDir;
05011                                         float   impactStrength = (damage/200.0f)*10.0f;
05012                                         float   dot = 0.0f;
05013                                         if ( impactStrength > 10.0f )
05014                                         {
05015                                                 impactStrength = 10.0f;
05016                                         }
05017                                         //pitch or roll us based on where we were hit
05018                                         AngleVectors( targ->m_pVehicle->m_vOrientation, NULL, NULL, vUp );
05019                                         VectorSubtract( point, targ->r.currentOrigin, impactDir );
05020                                         VectorNormalize( impactDir );
05021                                         if ( surface <= 0 )
05022                                         {//no surf guess where we were hit, then
05023                                                 vec3_t  vFwd, vRight;
05024                                                 AngleVectors( targ->m_pVehicle->m_vOrientation, vFwd, vRight, vUp );
05025                                                 dot = DotProduct( vRight, impactDir );
05026                                                 if ( dot > 0.4f )
05027                                                 {
05028                                                         surface = SHIPSURF_RIGHT;
05029                                                 }
05030                                                 else if ( dot < -0.4f )
05031                                                 {
05032                                                         surface = SHIPSURF_LEFT;
05033                                                 }
05034                                                 else
05035                                                 {
05036                                                         dot = DotProduct( vFwd, impactDir );
05037                                                         if ( dot > 0.0f )
05038                                                         {
05039                                                                 surface = SHIPSURF_FRONT;
05040                                                         }
05041                                                         else
05042                                                         {
05043                                                                 surface = SHIPSURF_BACK;
05044                                                         }
05045                                                 }
05046                                         }
05047                                         switch ( surface )
05048                                         {
05049                                         case SHIPSURF_FRONT:
05050                                                 dot = DotProduct( vUp, impactDir );
05051                                                 if ( dot > 0 )
05052                                                 {
05053                                                         targ->m_pVehicle->m_vOrientation[PITCH] += impactStrength;
05054                                                 }
05055                                                 else
05056                                                 {
05057                                                         targ->m_pVehicle->m_vOrientation[PITCH] -= impactStrength;
05058                                                 }
05059                                                 break;
05060                                         case SHIPSURF_BACK:
05061                                                 dot = DotProduct( vUp, impactDir );
05062                                                 if ( dot > 0 )
05063                                                 {
05064                                                         targ->m_pVehicle->m_vOrientation[PITCH] -= impactStrength;
05065                                                 }
05066                                                 else
05067                                                 {
05068                                                         targ->m_pVehicle->m_vOrientation[PITCH] += impactStrength;
05069                                                 }
05070                                                 break;
05071                                         case SHIPSURF_RIGHT:
05072                                                 dot = DotProduct( vUp, impactDir );
05073                                                 if ( dot > 0 )
05074                                                 {
05075                                                         targ->m_pVehicle->m_vOrientation[ROLL] -= impactStrength;
05076                                                 }
05077                                                 else
05078                                                 {
05079                                                         targ->m_pVehicle->m_vOrientation[ROLL] += impactStrength;
05080                                                 }
05081                                                 break;
05082                                         case SHIPSURF_LEFT:
05083                                                 dot = DotProduct( vUp, impactDir );
05084                                                 if ( dot > 0 )
05085                                                 {
05086                                                         targ->m_pVehicle->m_vOrientation[ROLL] += impactStrength;
05087                                                 }
05088                                                 else
05089                                                 {
05090                                                         targ->m_pVehicle->m_vOrientation[ROLL] -= impactStrength;
05091                                                 }
05092                                                 break;
05093                                         }
05094 
05095                                 }
05096                         }
05097                 }
05098         }
05099 
05100         if ( mod == MOD_DEMP2 || mod == MOD_DEMP2_ALT )
05101         {//FIXME: screw with non-animal vehicles, too?
05102                 if ( client )
05103                 {
05104                         if ( client->NPC_class == CLASS_VEHICLE 
05105                                 && targ->m_pVehicle
05106                                 && targ->m_pVehicle->m_pVehicleInfo
05107                                 && targ->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
05108                         {//all damage goes into the disruption of shields and systems
05109                                 take = 0;
05110                         }
05111                         else
05112                         {
05113 
05114                                 if (client->jetPackOn)
05115                                 { //disable jetpack temporarily
05116                                         Jetpack_Off(targ);
05117                                         client->jetPackToggleTime = level.time + Q_irand(3000, 10000);
05118                                 }
05119 
05120                                 if ( client->NPC_class == CLASS_PROTOCOL || client->NPC_class == CLASS_SEEKER ||
05121                                         client->NPC_class == CLASS_R2D2 || client->NPC_class == CLASS_R5D2 ||
05122                                         client->NPC_class == CLASS_MOUSE || client->NPC_class == CLASS_GONK )
05123                                 {
05124                                         // DEMP2 does more damage to these guys.
05125                                         take *= 2;
05126                                 }
05127                                 else if ( client->NPC_class == CLASS_PROBE || client->NPC_class == CLASS_INTERROGATOR ||
05128                                                         client->NPC_class == CLASS_MARK1 || client->NPC_class == CLASS_MARK2 || client->NPC_class == CLASS_SENTRY ||
05129                                                         client->NPC_class == CLASS_ATST )
05130                                 {
05131                                         // DEMP2 does way more damage to these guys.
05132                                         take *= 5;
05133                                 }
05134                                 else
05135                                 {
05136                                         if (take > 0)
05137                                         {
05138                                                 take /= 3;
05139                                                 if (take < 1)
05140                                                 {
05141                                                         take = 1;
05142                                                 }
05143                                         }
05144                                 }
05145                         }
05146                 }
05147         }
05148 
05149 #ifndef FINAL_BUILD
05150         if ( g_debugDamage.integer ) {
05151                 G_Printf( "%i: client:%i health:%i damage:%i armor:%i\n", level.time, targ->s.number,
05152                         targ->health, take, asave );
05153         }
05154 #endif
05155 
05156         // add to the damage inflicted on a player this frame
05157         // the total will be turned into screen blends and view angle kicks
05158         // at the end of the frame
05159         if ( client ) {
05160                 if ( attacker ) {
05161                         client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
05162                 } else {
05163                         client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD;
05164                 }
05165                 client->damage_armor += asave;
05166                 client->damage_blood += take;
05167                 client->damage_knockback += knockback;
05168                 if ( dir ) {
05169                         VectorCopy ( dir, client->damage_from );
05170                         client->damage_fromWorld = qfalse;
05171                 } else {
05172                         VectorCopy ( targ->r.currentOrigin, client->damage_from );
05173                         client->damage_fromWorld = qtrue;
05174                 }
05175 
05176                 if (attacker && attacker->client)
05177                 {
05178                         BotDamageNotification(client, attacker);
05179                 }
05180                 else if (inflictor && inflictor->client)
05181                 {
05182                         BotDamageNotification(client, inflictor);
05183                 }
05184         }
05185 
05186         // See if it's the player hurting the emeny flag carrier
05187         if( g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY) {
05188                 Team_CheckHurtCarrier(targ, attacker);
05189         }
05190 
05191         if (targ->client) {
05192                 // set the last client who damaged the target
05193                 targ->client->lasthurt_client = attacker->s.number;
05194                 targ->client->lasthurt_mod = mod;
05195         }
05196 
05197         if ( !(dflags & DAMAGE_NO_PROTECTION) ) 
05198         {//protect overridden by no_protection
05199                 if (take && targ->client && (targ->client->ps.fd.forcePowersActive & (1 << FP_PROTECT)))
05200                 {
05201                         if (targ->client->ps.fd.forcePower)
05202                         {
05203                                 int maxtake = take;
05204 
05205                                 //G_Sound(targ, CHAN_AUTO, protectHitSound);
05206                                 if (targ->client->forcePowerSoundDebounce < level.time)
05207                                 {
05208                                         G_PreDefSound(targ->client->ps.origin, PDSOUND_PROTECTHIT);
05209                                         targ->client->forcePowerSoundDebounce = level.time + 400;
05210                                 }
05211 
05212                                 if (targ->client->ps.fd.forcePowerLevel[FP_PROTECT] == FORCE_LEVEL_1)
05213                                 {
05214                                         famt = 1;
05215                                         hamt = 0.40;
05216 
05217                                         if (maxtake > 100)
05218                                         {
05219                                                 maxtake = 100;
05220                                         }
05221                                 }
05222                                 else if (targ->client->ps.fd.forcePowerLevel[FP_PROTECT] == FORCE_LEVEL_2)
05223                                 {
05224                                         famt = 0.5;
05225                                         hamt = 0.60;
05226 
05227                                         if (maxtake > 200)
05228                                         {
05229                                                 maxtake = 200;
05230                                         }
05231                                 }
05232                                 else if (targ->client->ps.fd.forcePowerLevel[FP_PROTECT] == FORCE_LEVEL_3)
05233                                 {
05234                                         famt = 0.25;
05235                                         hamt = 0.80;
05236 
05237                                         if (maxtake > 400)
05238                                         {
05239                                                 maxtake = 400;
05240                                         }
05241                                 }
05242 
05243                                 if (!targ->client->ps.powerups[PW_FORCE_BOON])
05244                                 {
05245                                         targ->client->ps.fd.forcePower -= maxtake*famt;
05246                                 }
05247                                 else
05248                                 {
05249                                         targ->client->ps.fd.forcePower -= (maxtake*famt)/2;
05250                                 }
05251                                 subamt = (maxtake*hamt)+(take-maxtake);
05252                                 if (targ->client->ps.fd.forcePower < 0)
05253                                 {
05254                                         subamt += targ->client->ps.fd.forcePower;
05255                                         targ->client->ps.fd.forcePower = 0;
05256                                 }
05257                                 if (subamt)
05258                                 {
05259                                         take -= subamt;
05260 
05261                                         if (take < 0)
05262                                         {
05263                                                 take = 0;
05264                                         }
05265                                 }
05266                         }
05267                 }
05268         }
05269 
05270         if (shieldAbsorbed)
05271         {
05272                 /*
05273                 if ( targ->client->NPC_class == CLASS_VEHICLE )
05274                 {
05275                         targ->client->ps.electrifyTime = level.time + Q_irand( 500, 1000 );
05276                 }
05277                 else
05278                 */
05279                 {
05280                         gentity_t       *evEnt;
05281 
05282                         // Send off an event to show a shield shell on the player, pointing in the right direction.
05283                         //evEnt = G_TempEntity(vec3_origin, EV_SHIELD_HIT);
05284                         //rww - er.. what the? This isn't broadcast, why is it being set on vec3_origin?!
05285                         evEnt = G_TempEntity(targ->r.currentOrigin, EV_SHIELD_HIT);
05286                         evEnt->s.otherEntityNum = targ->s.number;
05287                         evEnt->s.eventParm = DirToByte(dir);
05288                         evEnt->s.time2=shieldAbsorbed;
05289         /*
05290                         shieldAbsorbed *= 20;
05291 
05292                         if (shieldAbsorbed > 1500)
05293                         {
05294                                 shieldAbsorbed = 1500;
05295                         }
05296                         if (shieldAbsorbed < 200)
05297                         {
05298                                 shieldAbsorbed = 200;
05299                         }
05300 
05301                         if (targ->client->ps.powerups[PW_SHIELDHIT] < (level.time + shieldAbsorbed))
05302                         {
05303                                 targ->client->ps.powerups[PW_SHIELDHIT] = level.time + shieldAbsorbed;
05304                         }
05305                         //flicker for as many ms as damage was absorbed (*20)
05306                         //therefore 10 damage causes 1/5 of a seond of flickering, whereas
05307                         //a full 100 causes 2 seconds (but is reduced to 1.5 seconds due to the max)
05308 
05309         */
05310                 }
05311         }
05312 
05313         // do the damage
05314         if (take) 
05315         {
05316                 if (targ->client && targ->s.number < MAX_CLIENTS &&
05317                         (mod == MOD_DEMP2 || mod == MOD_DEMP2_ALT))
05318                 { //uh.. shock them or something. what the hell, I don't know.
05319             if (targ->client->ps.weaponTime <= 0)
05320                         { //yeah, we were supposed to be beta a week ago, I don't feel like
05321                                 //breaking the game so I'm gonna be safe and only do this only
05322                                 //if your weapon is not busy
05323                                 targ->client->ps.weaponTime = 2000;
05324                                 targ->client->ps.electrifyTime = level.time + 2000;
05325                                 if (targ->client->ps.weaponstate == WEAPON_CHARGING ||
05326                                         targ->client->ps.weaponstate == WEAPON_CHARGING_ALT)
05327                                 {
05328                                         targ->client->ps.weaponstate = WEAPON_READY;
05329                                 }
05330                         }
05331                 }
05332 
05333                 if ( !(dflags & DAMAGE_NO_PROTECTION) ) 
05334                 {//rage overridden by no_protection
05335                         if (targ->client && (targ->client->ps.fd.forcePowersActive & (1 << FP_RAGE)) && (inflictor->client || attacker->client))
05336                         {
05337                                 take /= (targ->client->ps.fd.forcePowerLevel[FP_RAGE]+1);
05338                         }
05339                 }
05340                 targ->health = targ->health - take;
05341 
05342                 if ( (targ->flags&FL_UNDYING) )
05343                 {//take damage down to 1, but never die
05344                         if ( targ->health < 1 )
05345                         {
05346                                 targ->health = 1;
05347                         }
05348                 }
05349 
05350                 if ( targ->client ) {
05351                         targ->client->ps.stats[STAT_HEALTH] = targ->health;
05352                 }
05353 
05354                 if ( !(dflags & DAMAGE_NO_PROTECTION) ) 
05355                 {//rage overridden by no_protection
05356                         if (targ->client && (targ->client->ps.fd.forcePowersActive & (1 << FP_RAGE)) && (inflictor->client || attacker->client))
05357                         {
05358                                 if (targ->health <= 0)
05359                                 {
05360                                         targ->health = 1;
05361                                 }
05362                                 if (targ->client->ps.stats[STAT_HEALTH] <= 0)
05363                                 {
05364                                         targ->client->ps.stats[STAT_HEALTH] = 1;
05365                                 }
05366                         }
05367                 }
05368 
05369                 //We want to go ahead and set gPainHitLoc regardless of if we have a pain func,
05370                 //so we can adjust the location damage too.
05371                 if (targ->client && targ->ghoul2 && targ->client->g2LastSurfaceTime == level.time)
05372                 { //We updated the hit surface this frame, so it's valid.
05373                         char hitSurface[MAX_QPATH];
05374 
05375                         trap_G2API_GetSurfaceName(targ->ghoul2, targ->client->g2LastSurfaceHit, 0, hitSurface);
05376 
05377                         if (hitSurface[0])
05378                         {
05379                                 G_GetHitLocFromSurfName(targ, hitSurface, &gPainHitLoc, point, dir, vec3_origin, mod);
05380                         }
05381                         else
05382                         {
05383                                 gPainHitLoc = -1;
05384                         }
05385 
05386                         if (gPainHitLoc < HL_MAX && gPainHitLoc >= 0 && targ->locationDamage[gPainHitLoc] < Q3_INFINITE &&
05387                                 (targ->s.eType == ET_PLAYER || targ->s.NPC_class != CLASS_VEHICLE))
05388                         {
05389                                 targ->locationDamage[gPainHitLoc] += take;
05390 
05391                                 if (g_armBreakage.integer && !targ->client->ps.brokenLimbs &&
05392                                         targ->client->ps.stats[STAT_HEALTH] > 0 && targ->health > 0 &&
05393                                         !(targ->s.eFlags & EF_DEAD))
05394                                 { //check for breakage
05395                                         if (targ->locationDamage[HL_ARM_RT]+targ->locationDamage[HL_HAND_RT] >= 80)
05396                                         {
05397                                                 G_BreakArm(targ, BROKENLIMB_RARM);
05398                                         }
05399                                         else if (targ->locationDamage[HL_ARM_LT]+targ->locationDamage[HL_HAND_LT] >= 80)
05400                                         {
05401                                                 G_BreakArm(targ, BROKENLIMB_LARM);
05402                                         }
05403                                 }
05404                         }
05405                 }
05406                 else
05407                 {
05408                         gPainHitLoc = -1;
05409                 }
05410 
05411                 if (targ->maxHealth)
05412                 { //if this is non-zero this guy should be updated his s.health to send to the client
05413                         G_ScaleNetHealth(targ);
05414                 }
05415 
05416                 if ( targ->health <= 0 ) {
05417                         if ( client )
05418                         {
05419                                 targ->flags |= FL_NO_KNOCKBACK;
05420 
05421                                 if (point)
05422                                 {
05423                                         VectorCopy( point, targ->pos1 );
05424                                 }
05425                                 else
05426                                 {
05427                                         VectorCopy(targ->client->ps.origin, targ->pos1);
05428                                 }
05429                         }
05430                         else if (targ->s.eType == ET_NPC)
05431                         { //g2animent
05432                                 VectorCopy(point, targ->pos1);
05433                         }
05434 
05435                         if (targ->health < -999)
05436                                 targ->health = -999;
05437 
05438                         // If we are a breaking glass brush, store the damage point so we can do cool things with it.
05439                         if ( targ->r.svFlags & SVF_GLASS_BRUSH )
05440                         {
05441                                 VectorCopy( point, targ->pos1 );
05442                                 if (dir)
05443                                 {
05444                                         VectorCopy( dir, targ->pos2 );
05445                                 }
05446                                 else
05447                                 {
05448                                         VectorClear(targ->pos2);
05449                                 }
05450                         }
05451 
05452                         if (targ->s.eType == ET_NPC &&
05453                                 targ->client &&
05454                                 (targ->s.eFlags & EF_DEAD))
05455                         { //an NPC that's already dead. Maybe we can cut some more limbs off!
05456                                 if ( (mod == MOD_SABER || (mod == MOD_MELEE && G_HeavyMelee( attacker )) )//saber or heavy melee (claws)
05457                                         && take > 2
05458                                         && !(dflags&DAMAGE_NO_DISMEMBER) )
05459                                 {
05460                                         G_CheckForDismemberment(targ, attacker, targ->pos1, take, targ->client->ps.torsoAnim, qtrue);
05461                                 }
05462                         }
05463 
05464                         targ->enemy = attacker;
05465                         targ->die (targ, inflictor, attacker, take, mod);
05466                         G_ActivateBehavior( targ, BSET_DEATH );
05467                         return;
05468                 } 
05469                 else 
05470                 {
05471                         if ( g_debugMelee.integer )
05472                         {//getting hurt makes you let go of the wall
05473                                 if ( targ->client && (targ->client->ps.pm_flags&PMF_STUCK_TO_WALL) )
05474                                 {
05475                                         G_LetGoOfWall( targ );
05476                                 }
05477                         }
05478                         if ( targ->pain ) 
05479                         {
05480                                 if (targ->s.eType != ET_NPC || mod != MOD_SABER || take > 1)
05481                                 { //don't even notify NPCs of pain if it's just idle saber damage
05482                                         gPainMOD = mod;
05483                                         if (point)
05484                                         {
05485                                                 VectorCopy(point, gPainPoint);
05486                                         }
05487                                         else
05488                                         {
05489                                                 VectorCopy(targ->r.currentOrigin, gPainPoint);
05490                                         }
05491                                         targ->pain (targ, attacker, take);
05492                                 }
05493                         }
05494                 }
05495 
05496                 G_LogWeaponDamage(attacker->s.number, mod, take);
05497         }
05498 
05499 }

void G_DeathAlert gentity_t victim,
gentity_t attacker
 

Definition at line 1868 of file g_combat.c.

References DEATH_ALERT_RADIUS, DEATH_ALERT_SOUND_RADIUS, G_AlertTeam(), and gentity_t.

Referenced by player_die().

01869 {//FIXME: with all the other alert stuff, do we really need this?
01870         G_AlertTeam( victim, attacker, DEATH_ALERT_RADIUS, DEATH_ALERT_SOUND_RADIUS );
01871 }

void G_Dismember gentity_t ent,
gentity_t enemy,
vec3_t  point,
int  limbType,
float  limbRollBase,
float  limbPitchBase,
int  deathAnim,
qboolean  postDeath
 

Definition at line 3311 of file g_combat.c.

References entityState_s::apos, BG_GetRootSurfNameWithVariant(), BG_InDeathAnim(), gentity_s::classname, gentity_s::client, gentity_s::clipmask, Com_sprintf(), entityShared_t::contents, CONTENTS_TRIGGER, entityShared_t::currentAngles, entityShared_t::currentOrigin, entityState_s::customRGBA, gentity_s::epGravFactor, gentity_s::epVelocity, ET_GENERAL, ET_NPC, entityState_s::eType, FRAMETIME, G2_MODEL_PART, G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RHAND, G2_MODELPART_RLEG, G2_MODELPART_WAIST, entityState_s::g2radius, G_SetOrigin(), G_Spawn(), gentity_t, gentity_s::ghoul2, gclient_s::lastSaberBase_Always, gclient_s::lastSaberStorageTime, level, LimbThink(), LimbTouch(), MASK_SOLID, MAX_QPATH, entityShared_t::maxs, entityShared_t::mins, entityState_s::modelGhoul2, entityState_s::modelindex, gentity_s::nextthink, entityState_s::number, gclient_s::olderIsValid, gclient_s::olderSaberBase, entityState_s::otherEntityNum2, gentity_s::physicsObject, entityState_s::pos, gclient_s::ps, Q_irand(), Q_strncpyz(), qtrue, gentity_s::r, gentity_s::s, gentity_s::speed, SVF_USE_CURRENT_ORIGIN, entityShared_t::svFlags, gentity_s::think, level_locals_t::time, playerState_s::torsoAnim, playerState_s::torsoTimer, gentity_s::touch, trap_G2API_GetSurfaceRenderStatus(), trap_G2API_SetSurfaceOnOff(), trap_LinkEntity(), trajectory_t::trBase, trajectory_t::trDelta, vec3_t, VectorAdd, VectorClear, VectorCopy, VectorMA, VectorNormalize(), VectorScale, VectorSet, VectorSubtract, playerState_s::velocity, playerState_s::viewangles, entityState_s::weapon, playerState_s::weapon, and WP_SABER.

Referenced by DismembermentByNum(), DismembermentTest(), G_CheckForDismemberment(), Rancor_Attack(), Rancor_Bite(), and Wampa_Slash().

03312 {
03313         vec3_t  newPoint, dir, vel;
03314         gentity_t *limb;
03315         char    limbName[MAX_QPATH];
03316         char    stubName[MAX_QPATH];
03317         char    stubCapName[MAX_QPATH];
03318 
03319         if (limbType == G2_MODELPART_HEAD)
03320         {
03321                 Q_strncpyz( limbName , "head", sizeof( limbName  ) );
03322                 Q_strncpyz( stubCapName, "torso_cap_head", sizeof( stubCapName ) );
03323         }
03324         else if (limbType == G2_MODELPART_WAIST)
03325         {
03326                 Q_strncpyz( limbName, "torso", sizeof( limbName ) );
03327                 Q_strncpyz( stubCapName, "hips_cap_torso", sizeof( stubCapName ) );
03328         }
03329         else if (limbType == G2_MODELPART_LARM)
03330         {
03331                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "l_arm", limbName, sizeof(limbName) );
03332                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "torso", stubName, sizeof(stubName) );
03333                 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_l_arm", stubName );
03334         }
03335         else if (limbType == G2_MODELPART_RARM)
03336         {
03337                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_arm", limbName, sizeof(limbName) );
03338                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "torso", stubName, sizeof(stubName) );
03339                 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_arm", stubName );
03340         }
03341         else if (limbType == G2_MODELPART_RHAND)
03342         {
03343                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_hand", limbName, sizeof(limbName) );
03344                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_arm", stubName, sizeof(stubName) );
03345                 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_hand", stubName );
03346         }
03347         else if (limbType == G2_MODELPART_LLEG)
03348         {
03349                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "l_leg", limbName, sizeof(limbName) );
03350                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "hips", stubName, sizeof(stubName) );
03351                 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_l_leg", stubName );
03352         }
03353         else if (limbType == G2_MODELPART_RLEG)
03354         {
03355                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_leg", limbName, sizeof(limbName) );
03356                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "hips", stubName, sizeof(stubName) );
03357                 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_leg", stubName );
03358         }
03359         else
03360         {//umm... just default to the right leg, I guess (same as on client)
03361                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "r_leg", limbName, sizeof(limbName) );
03362                 BG_GetRootSurfNameWithVariant( ent->ghoul2, "hips", stubName, sizeof(stubName) );
03363                 Com_sprintf( stubCapName, sizeof( stubCapName), "%s_cap_r_leg", stubName );
03364         }
03365 
03366         if (ent->ghoul2 && limbName && trap_G2API_GetSurfaceRenderStatus(ent->ghoul2, 0, limbName))
03367         { //is it already off? If so there's no reason to be doing it again, so get out of here.
03368                 return;
03369         }
03370 
03371         VectorCopy( point, newPoint );
03372         limb = G_Spawn();
03373         limb->classname = "playerlimb";
03374 
03375         /*
03376         if (limbType == G2_MODELPART_WAIST)
03377         { //slight hack
03378                 newPoint[2] += 1;
03379         }
03380         */
03381 
03382         G_SetOrigin( limb, newPoint );
03383         VectorCopy( newPoint, limb->s.pos.trBase );
03384         limb->think = LimbThink;
03385         limb->touch = LimbTouch;
03386         limb->speed = level.time + Q_irand(8000, 16000);
03387         limb->nextthink = level.time + FRAMETIME;
03388 
03389         limb->r.svFlags = SVF_USE_CURRENT_ORIGIN;
03390         limb->clipmask = MASK_SOLID;
03391         limb->r.contents = CONTENTS_TRIGGER;
03392         limb->physicsObject = qtrue;
03393         VectorSet( limb->r.mins, -6.0f, -6.0f, -3.0f );
03394         VectorSet( limb->r.maxs, 6.0f, 6.0f, 6.0f );
03395 
03396         limb->s.g2radius = 200;
03397 
03398         limb->s.eType = ET_GENERAL;
03399         limb->s.weapon = G2_MODEL_PART;
03400         limb->s.modelGhoul2 = limbType;
03401         limb->s.modelindex = ent->s.number;
03402         if (!ent->client)
03403         {
03404                 limb->s.modelindex = -1;
03405                 limb->s.otherEntityNum2 = ent->s.number;
03406         }
03407 
03408         VectorClear(limb->s.apos.trDelta);
03409 
03410         if (ent->client)
03411         {
03412                 VectorCopy(ent->client->ps.viewangles, limb->r.currentAngles);
03413                 VectorCopy(ent->client->ps.viewangles, limb->s.apos.trBase);
03414         }
03415         else
03416         {
03417                 VectorCopy(ent->r.currentAngles, limb->r.currentAngles);
03418                 VectorCopy(ent->r.currentAngles, limb->s.apos.trBase);
03419         }
03420 
03421         //Set up the ExPhys values for the entity.
03422         limb->epGravFactor = 0;
03423         VectorClear(limb->epVelocity);
03424         VectorSubtract( point, ent->r.currentOrigin, dir );
03425         VectorNormalize( dir );
03426         if (ent->client)
03427         {
03428                 VectorCopy(ent->client->ps.velocity, vel);
03429         }
03430         else
03431         {
03432                 VectorCopy(ent->s.pos.trDelta, vel);
03433         }
03434         VectorMA( vel, 80, dir, limb->epVelocity );
03435 
03436         //add some vertical velocity
03437         if (limbType == G2_MODELPART_HEAD ||
03438                 limbType == G2_MODELPART_WAIST)
03439         {
03440                 limb->epVelocity[2] += 10;
03441         }
03442 
03443         if (enemy && enemy->client && ent && ent != enemy && ent->s.number != enemy->s.number &&
03444                 enemy->client->ps.weapon == WP_SABER && enemy->client->olderIsValid &&
03445                 (level.time - enemy->client->lastSaberStorageTime) < 200)
03446         { //The enemy has valid saber positions between this and last frame. Use them to factor in direction of the limb.
03447                 vec3_t dif;
03448                 float totalDistance;
03449                 const float distScale = 1.2f;
03450 
03451                 //scale down the initial velocity first, which is based on the speed of the limb owner.
03452                 //ExPhys object velocity operates on a slightly different scale than Q3-based physics velocity.
03453                 VectorScale(limb->epVelocity, 0.4f, limb->epVelocity);
03454 
03455                 VectorSubtract(enemy->client->lastSaberBase_Always, enemy->client->olderSaberBase, dif);
03456                 totalDistance = VectorNormalize(dif);
03457 
03458                 VectorScale(dif, totalDistance*distScale, dif);
03459                 VectorAdd(limb->epVelocity, dif, limb->epVelocity);
03460 
03461                 if (ent->client && (ent->client->ps.torsoTimer > 0 || !BG_InDeathAnim(ent->client->ps.torsoAnim)))
03462                 { //if he's done with his death anim we don't actually want the limbs going far
03463                         vec3_t preVel;
03464 
03465                         VectorCopy(limb->epVelocity, preVel);
03466                         preVel[2] = 0;
03467                         totalDistance = VectorNormalize(preVel);
03468 
03469                         if (totalDistance < 40.0f)
03470                         {
03471                                 float mAmt = 40.0f;//60.0f/totalDistance;
03472 
03473                                 limb->epVelocity[0] = preVel[0]*mAmt;
03474                                 limb->epVelocity[1] = preVel[1]*mAmt;
03475                         }
03476                 }
03477                 else if (ent->client)
03478                 {
03479                         VectorScale(limb->epVelocity, 0.3f, limb->epVelocity);
03480                 }
03481         }
03482 
03483         if (ent->s.eType == ET_NPC && ent->ghoul2 && limbName && stubCapName)
03484         { //if it's an npc remove these surfs on the server too. For players we don't even care cause there's no further dismemberment after death.
03485                 trap_G2API_SetSurfaceOnOff(ent->ghoul2, limbName, 0x00000100);
03486                 trap_G2API_SetSurfaceOnOff(ent->ghoul2, stubCapName, 0);
03487         }
03488 
03489         limb->s.customRGBA[0] = ent->s.customRGBA[0];
03490         limb->s.customRGBA[1] = ent->s.customRGBA[1];
03491         limb->s.customRGBA[2] = ent->s.customRGBA[2];
03492         limb->s.customRGBA[3] = ent->s.customRGBA[3];
03493 
03494         trap_LinkEntity( limb );
03495 }

qboolean G_FlyVehicleDestroySurface gentity_t veh,
int  surface
 

Referenced by G_Damage().

void G_GetDismemberBolt gentity_t self,
vec3_t  boltPoint,
int  limbType
 

Definition at line 3139 of file g_combat.c.

References entityState_s::angles, gentity_s::client, ENTITYNUM_NONE, EV_SABER_HIT, entityState_s::eventParm, G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RHAND, G2_MODELPART_RLEG, G2_MODELPART_WAIST, G_TempEntity(), gentity_s::genericValue5, gentity_t, gentity_s::ghoul2, entityState_s::legsAnim, level, gentity_s::localAnimIndex, mdxaBone_t::matrix, gentity_s::modelScale, NULL, entityState_s::number, entityState_s::origin, playerState_s::origin, entityState_s::otherEntityNum, entityState_s::otherEntityNum2, gclient_s::ps, gentity_s::s, level_locals_t::time, trap_G2API_AddBolt(), trap_G2API_GetBoltMatrix(), vec3_t, VectorCopy, VectorNormalize(), playerState_s::velocity, playerState_s::viewangles, entityState_s::weapon, and YAW.

Referenced by DismembermentByNum(), DismembermentTest(), and G_CheckForDismemberment().

03140 {
03141         int useBolt = self->genericValue5;
03142         vec3_t properOrigin, properAngles, addVel;
03143         //vec3_t legAxis[3];
03144         mdxaBone_t      boltMatrix;
03145         float fVSpeed = 0;
03146         char *rotateBone = NULL;
03147 
03148         switch (limbType)
03149         {
03150         case G2_MODELPART_HEAD:
03151                 rotateBone = "cranium";
03152                 break;
03153         case G2_MODELPART_WAIST:
03154                 if (self->localAnimIndex <= 1)
03155                 { //humanoid
03156                         rotateBone = "thoracic";
03157                 }
03158                 else
03159                 {
03160                         rotateBone = "pelvis";
03161                 }
03162                 break;
03163         case G2_MODELPART_LARM:
03164                 rotateBone = "lradius";
03165                 break;
03166         case G2_MODELPART_RARM:
03167                 rotateBone = "rradius";
03168                 break;
03169         case G2_MODELPART_RHAND:
03170                 rotateBone = "rhand";
03171                 break;
03172         case G2_MODELPART_LLEG:
03173                 rotateBone = "ltibia";
03174                 break;
03175         case G2_MODELPART_RLEG:
03176                 rotateBone = "rtibia";
03177                 break;
03178         default:
03179                 rotateBone = "rtibia";
03180                 break;
03181         }
03182 
03183         useBolt = trap_G2API_AddBolt(self->ghoul2, 0, rotateBone);
03184 
03185         VectorCopy(self->client->ps.origin, properOrigin);
03186         VectorCopy(self->client->ps.viewangles, properAngles);
03187 
03188         //try to predict the origin based on velocity so it's more like what the client is seeing
03189         VectorCopy(self->client->ps.velocity, addVel);
03190         VectorNormalize(addVel);
03191 
03192         if (self->client->ps.velocity[0] < 0)
03193         {
03194                 fVSpeed += (-self->client->ps.velocity[0]);
03195         }
03196         else
03197         {
03198                 fVSpeed += self->client->ps.velocity[0];
03199         }
03200         if (self->client->ps.velocity[1] < 0)
03201         {
03202                 fVSpeed += (-self->client->ps.velocity[1]);
03203         }
03204         else
03205         {
03206                 fVSpeed += self->client->ps.velocity[1];
03207         }
03208         if (self->client->ps.velocity[2] < 0)
03209         {
03210                 fVSpeed += (-self->client->ps.velocity[2]);
03211         }
03212         else
03213         {
03214                 fVSpeed += self->client->ps.velocity[2];
03215         }
03216 
03217         fVSpeed *= 0.08;
03218 
03219         properOrigin[0] += addVel[0]*fVSpeed;
03220         properOrigin[1] += addVel[1]*fVSpeed;
03221         properOrigin[2] += addVel[2]*fVSpeed;
03222 
03223         properAngles[0] = 0;
03224         properAngles[1] = self->client->ps.viewangles[YAW];
03225         properAngles[2] = 0;
03226 
03227         trap_G2API_GetBoltMatrix(self->ghoul2, 0, useBolt, &boltMatrix, properAngles, properOrigin, level.time, NULL, self->modelScale);
03228 
03229         boltPoint[0] = boltMatrix.matrix[0][3];
03230         boltPoint[1] = boltMatrix.matrix[1][3];
03231         boltPoint[2] = boltMatrix.matrix[2][3];
03232 
03233         trap_G2API_GetBoltMatrix(self->ghoul2, 1, 0, &boltMatrix, properAngles, properOrigin, level.time, NULL, self->modelScale);
03234 
03235         if (self->client && limbType == G2_MODELPART_RHAND)
03236         { //Make some saber hit sparks over the severed wrist area
03237                 vec3_t boltAngles;
03238                 gentity_t *te;
03239 
03240                 boltAngles[0] = -boltMatrix.matrix[0][1];
03241                 boltAngles[1] = -boltMatrix.matrix[1][1];
03242                 boltAngles[2] = -boltMatrix.matrix[2][1];
03243 
03244                 te = G_TempEntity( boltPoint, EV_SABER_HIT );
03245                 te->s.otherEntityNum = self->s.number;
03246                 te->s.otherEntityNum2 = ENTITYNUM_NONE;
03247                 te->s.weapon = 0;//saberNum
03248                 te->s.legsAnim = 0;//bladeNum
03249 
03250                 VectorCopy(boltPoint, te->s.origin);
03251                 VectorCopy(boltAngles, te->s.angles);
03252                 
03253                 if (!te->s.angles[0] && !te->s.angles[1] && !te->s.angles[2])
03254                 { //don't let it play with no direction
03255                         te->s.angles[1] = 1;
03256                 }
03257 
03258                 te->s.eventParm = 16; //lots of sparks
03259         }
03260 }

void G_GetDismemberLoc gentity_t self,
vec3_t  boltPoint,
int  limbType
 

Definition at line 3067 of file g_combat.c.

References AngleVectors(), entityShared_t::currentAngles, entityShared_t::currentOrigin, G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RHAND, G2_MODELPART_RLEG, G2_MODELPART_WAIST, gentity_t, gentity_s::r, vec3_t, and VectorCopy.

Referenced by G_CheckForDismemberment().

03068 { //Just get the general area without using server-side ghoul2
03069         vec3_t fwd, right, up;
03070 
03071         AngleVectors(self->r.currentAngles, fwd, right, up);
03072 
03073         VectorCopy(self->r.currentOrigin, boltPoint);
03074 
03075         switch (limbType)
03076         {
03077         case G2_MODELPART_HEAD:
03078                 boltPoint[0] += up[0]*24;
03079                 boltPoint[1] += up[1]*24;
03080                 boltPoint[2] += up[2]*24;
03081                 break;
03082         case G2_MODELPART_WAIST:
03083                 boltPoint[0] += up[0]*4;
03084                 boltPoint[1] += up[1]*4;
03085                 boltPoint[2] += up[2]*4;
03086                 break;
03087         case G2_MODELPART_LARM:
03088                 boltPoint[0] += up[0]*18;
03089                 boltPoint[1] += up[1]*18;
03090                 boltPoint[2] += up[2]*18;
03091 
03092                 boltPoint[0] -= right[0]*10;
03093                 boltPoint[1] -= right[1]*10;
03094                 boltPoint[2] -= right[2]*10;
03095                 break;
03096         case G2_MODELPART_RARM:
03097                 boltPoint[0] += up[0]*18;
03098                 boltPoint[1] += up[1]*18;
03099                 boltPoint[2] += up[2]*18;
03100 
03101                 boltPoint[0] += right[0]*10;
03102                 boltPoint[1] += right[1]*10;
03103                 boltPoint[2] += right[2]*10;
03104                 break;
03105         case G2_MODELPART_RHAND:
03106                 boltPoint[0] += up[0]*8;
03107                 boltPoint[1] += up[1]*8;
03108                 boltPoint[2] += up[2]*8;
03109 
03110                 boltPoint[0] += right[0]*10;
03111                 boltPoint[1] += right[1]*10;
03112                 boltPoint[2] += right[2]*10;
03113                 break;
03114         case G2_MODELPART_LLEG:
03115                 boltPoint[0] -= up[0]*4;
03116                 boltPoint[1] -= up[1]*4;
03117                 boltPoint[2] -= up[2]*4;
03118 
03119                 boltPoint[0] -= right[0]*10;
03120                 boltPoint[1] -= right[1]*10;
03121                 boltPoint[2] -= right[2]*10;
03122                 break;
03123         case G2_MODELPART_RLEG:
03124                 boltPoint[0] -= up[0]*4;
03125                 boltPoint[1] -= up[1]*4;
03126                 boltPoint[2] -= up[2]*4;
03127 
03128                 boltPoint[0] += right[0]*10;
03129                 boltPoint[1] += right[1]*10;
03130                 boltPoint[2] += right[2]*10;
03131                 break;
03132         default:
03133                 break;
03134         }
03135 
03136         return;
03137 }

int G_GetHitLocation gentity_t target,
vec3_t  ppoint
 

Definition at line 45 of file g_combat.c.

References entityShared_t::absmax, entityShared_t::absmin, AngleVectors(), gentity_s::client, entityShared_t::currentAngles, DotProduct, fabs(), gentity_t, HL_ARM_LT, HL_ARM_RT, HL_BACK, HL_BACK_LT, HL_BACK_RT, HL_CHEST, HL_CHEST_LT, HL_CHEST_RT, HL_FOOT_LT, HL_FOOT_RT, HL_HAND_LT, HL_HAND_RT, HL_HEAD, HL_LEG_LT, HL_LEG_RT, HL_NONE, HL_WAIST, entityShared_t::maxs, entityShared_t::mins, gentity_s::r, vec3_origin, vec3_t, VectorAdd, VectorCopy, VectorNormalize(), VectorScale, VectorSet, VectorSubtract, and YAW.

Referenced by G_CheckForDismemberment(), G_LocationBasedDamageModifier(), G_PickDeathAnim(), and WP_DisruptorAltFire().

00046 {
00047         vec3_t                  point, point_dir;
00048         vec3_t                  forward, right, up;
00049         vec3_t                  tangles, tcenter;
00050         float                   tradius;
00051         float                   udot, fdot, rdot;
00052         int                             Vertical, Forward, Lateral;
00053         int                             HitLoc;
00054 
00055         // Get target forward, right and up.
00056         if(target->client)
00057         {
00058                 // Ignore player's pitch and roll.
00059                 VectorSet(tangles, 0, target->r.currentAngles[YAW], 0);
00060         }
00061 
00062         AngleVectors(tangles, forward, right, up);
00063 
00064         // Get center of target.
00065         VectorAdd(target->r.absmin, target->r.absmax, tcenter);
00066         VectorScale(tcenter, 0.5, tcenter);
00067 
00068         // Get radius width of target.
00069         tradius = (fabs(target->r.maxs[0]) + fabs(target->r.maxs[1]) + fabs(target->r.mins[0]) + fabs(target->r.mins[1]))/4;
00070 
00071         // Get impact point.
00072         if(ppoint && !VectorCompare(ppoint, vec3_origin))
00073         {
00074                 VectorCopy(ppoint, point);
00075         }
00076         else
00077         {
00078                 return HL_NONE;
00079         }
00080 
00081 /*
00082 //get impact dir
00083         if(pdir && !VectorCompare(pdir, vec3_origin))
00084         {
00085                 VectorCopy(pdir, dir);
00086         }
00087         else
00088         {
00089                 return;
00090         }
00091 
00092 //put point at controlled distance from center
00093         VectorSubtract(point, tcenter, tempvec);
00094         tempvec[2] = 0;
00095         hdist = VectorLength(tempvec);
00096 
00097         VectorMA(point, hdist - tradius, dir, point);
00098         //now a point on the surface of a cylinder with a radius of tradius
00099 */      
00100         VectorSubtract(point, tcenter, point_dir);
00101         VectorNormalize(point_dir);
00102 
00103         // Get bottom to top (vertical) position index
00104         udot = DotProduct(up, point_dir);
00105         if(udot>.800)
00106         {
00107                 Vertical = 4;
00108         }
00109         else if(udot>.400)
00110         {
00111                 Vertical = 3;
00112         }
00113         else if(udot>-.333)
00114         {
00115                 Vertical = 2;
00116         }
00117         else if(udot>-.666)
00118         {
00119                 Vertical = 1;
00120         }
00121         else
00122         {
00123                 Vertical = 0;
00124         }
00125 
00126         // Get back to front (forward) position index.
00127         fdot = DotProduct(forward, point_dir);
00128         if(fdot>.666)
00129         {
00130                 Forward = 4;
00131         }
00132         else if(fdot>.333)
00133         {
00134                 Forward = 3;
00135         }
00136         else if(fdot>-.333)
00137         {
00138                 Forward = 2;
00139         }
00140         else if(fdot>-.666)
00141         {
00142                 Forward = 1;
00143         }
00144         else
00145         {
00146                 Forward = 0;
00147         }
00148 
00149         // Get left to right (lateral) position index.
00150         rdot = DotProduct(right, point_dir);
00151         if(rdot>.666)
00152         {
00153                 Lateral = 4;
00154         }
00155         else if(rdot>.333)
00156         {
00157                 Lateral = 3;
00158         }
00159         else if(rdot>-.333)
00160         {
00161                 Lateral = 2;
00162         }
00163         else if(rdot>-.666)
00164         {
00165                 Lateral = 1;
00166         }
00167         else
00168         {
00169                 Lateral = 0;
00170         }
00171 
00172         HitLoc = Vertical * 25 + Forward * 5 + Lateral;
00173 
00174         if(HitLoc <= 10)
00175         {
00176                 // Feet.
00177                 if ( rdot > 0 )
00178                 {
00179                         return HL_FOOT_RT;
00180                 }
00181                 else
00182                 {
00183                         return HL_FOOT_LT;
00184                 }
00185         }
00186         else if(HitLoc <= 50)
00187         {
00188                 // Legs.
00189                 if ( rdot > 0 )
00190                 {
00191                         return HL_LEG_RT;
00192                 }
00193                 else
00194                 {
00195                         return HL_LEG_LT;
00196                 }
00197         }
00198         else if(HitLoc == 56||HitLoc == 60||HitLoc == 61||HitLoc == 65||HitLoc == 66||HitLoc == 70)
00199         {
00200                 // Hands.
00201                 if ( rdot > 0 )
00202                 {
00203                         return HL_HAND_RT;
00204                 }
00205                 else
00206                 {
00207                         return HL_HAND_LT;
00208                 }
00209         }
00210         else if(HitLoc == 83||HitLoc == 87||HitLoc == 88||HitLoc == 92||HitLoc == 93||HitLoc == 97)
00211         {
00212                 // Arms.
00213                 if ( rdot > 0 )
00214                 {
00215                         return HL_ARM_RT;
00216                 }
00217                 else
00218                 {
00219                         return HL_ARM_LT;
00220                 }
00221         }
00222         else if((HitLoc >= 107 && HitLoc <= 109)||(HitLoc >= 112 && HitLoc <= 114)||(HitLoc >= 117 && HitLoc <= 119))
00223         {
00224                 // Head.
00225                 return HL_HEAD;
00226         }
00227         else
00228         {
00229                 if(udot < 0.3)
00230                 {
00231                         return HL_WAIST;
00232                 }
00233                 else if(fdot < 0)
00234                 {
00235                         if(rdot > 0.4)
00236                         {
00237                                 return HL_BACK_RT;
00238                         }
00239                         else if(rdot < -0.4)
00240                         {
00241                                 return HL_BACK_LT;
00242                         }
00243                         else if(fdot < 0)
00244                         {
00245                                 return HL_BACK;
00246                         }
00247                 }
00248                 else
00249                 {
00250                         if(rdot > 0.3)
00251                         {
00252                                 return HL_CHEST_RT;
00253                         }
00254                         else if(rdot < -0.3)
00255                         {
00256                                 return HL_CHEST_LT;
00257                         }
00258                         else if(fdot < 0)
00259                         {
00260                                 return HL_CHEST;
00261                         }
00262                 }
00263         }
00264         return HL_NONE;
00265 }

qboolean G_GetHitLocFromSurfName gentity_t ent,
const char *  surfName,
int *  hitLoc,
vec3_t  point,
vec3_t  dir,
vec3_t  bladeDir,
int  mod
 

Definition at line 3632 of file g_combat.c.

References AngleVectors(), renderInfo_s::boltValidityTime, CLASS_ATST, CLASS_GALAKMECH, CLASS_GONK, CLASS_INTERROGATOR, CLASS_MARK1, CLASS_MARK2, CLASS_MOUSE, CLASS_PROBE, CLASS_PROTOCOL, CLASS_R2D2, CLASS_SENTRY, gentity_s::client, entityShared_t::currentAngles, entityShared_t::currentOrigin, DotProduct, g_dismember, gentity_t, gentity_s::ghoul2, HL_ARM_LT, HL_ARM_RT, HL_BACK, HL_BACK_LT, HL_BACK_RT, HL_CHEST, HL_CHEST_LT, HL_CHEST_RT, HL_FOOT_LT, HL_FOOT_RT, HL_GENERIC1, HL_GENERIC2, HL_GENERIC3, HL_GENERIC4, HL_GENERIC5, HL_GENERIC6, HL_HAND_LT, HL_HAND_RT, HL_HEAD, HL_LEG_LT, HL_LEG_RT, HL_NONE, HL_WAIST, vmCvar_t::integer, level, gentity_s::localAnimIndex, MOD_SABER, gentity_s::modelScale, NEGATIVE_Y, gclient_s::NPC_class, NULL, ORIGIN, playerState_s::origin, gclient_s::ps, Q_stricmp(), Q_strncmp(), qboolean, qfalse, qtrue, gentity_s::r, gclient_s::renderInfo, level_locals_t::time, renderInfo_s::torsoAngles, renderInfo_s::torsoPoint, trap_G2API_AddBolt(), trap_G2API_GetBoltMatrix(), UpdateClientRenderBolts(), vec3_t, VectorSet, VectorSubtract, playerState_s::viewangles, and YAW.

Referenced by G_CheckForDismemberment(), G_Damage(), and G_LocationBasedDamageModifier().

03633 {
03634         qboolean dismember = qfalse;
03635         int actualTime;
03636         int kneeLBolt = -1;
03637         int kneeRBolt = -1;
03638         int handRBolt = -1;
03639         int handLBolt = -1;
03640         int footRBolt = -1;
03641         int footLBolt = -1;
03642 
03643         *hitLoc = HL_NONE;
03644 
03645         if ( !surfName || !surfName[0] )
03646         {
03647                 return qfalse;
03648         }
03649 
03650         if( !ent->client )
03651         {
03652                 return qfalse;
03653         }
03654 
03655         if (!point)
03656         {
03657                 return qfalse;
03658         }
03659 
03660         if ( ent->client 
03661                 && ( ent->client->NPC_class == CLASS_R2D2 
03662                         || ent->client->NPC_class == CLASS_R2D2 
03663                         || ent->client->NPC_class == CLASS_GONK
03664                         || ent->client->NPC_class == CLASS_MOUSE
03665                         || ent->client->NPC_class == CLASS_SENTRY
03666                         || ent->client->NPC_class == CLASS_INTERROGATOR
03667                         || ent->client->NPC_class == CLASS_SENTRY
03668                         || ent->client->NPC_class == CLASS_PROBE ) )
03669         {//we don't care about per-surface hit-locations or dismemberment for these guys 
03670                 return qfalse;
03671         }
03672 
03673         if (ent->localAnimIndex <= 1)
03674         { //humanoid
03675                 handLBolt = trap_G2API_AddBolt(ent->ghoul2, 0, "*l_hand");
03676                 handRBolt = trap_G2API_AddBolt(ent->ghoul2, 0, "*r_hand");
03677                 kneeLBolt = trap_G2API_AddBolt(ent->ghoul2, 0, "*hips_l_knee");
03678                 kneeRBolt = trap_G2API_AddBolt(ent->ghoul2, 0, "*hips_r_knee");
03679                 footLBolt = trap_G2API_AddBolt(ent->ghoul2, 0, "*l_leg_foot");
03680                 footRBolt = trap_G2API_AddBolt(ent->ghoul2, 0, "*r_leg_foot");
03681         }
03682 
03683         if ( ent->client && (ent->client->NPC_class == CLASS_ATST) )
03684         {
03685                 //FIXME: almost impossible to hit these... perhaps we should
03686                 //              check for splashDamage and do radius damage to these parts?
03687                 //              Or, if we ever get bbox G2 traces, that may fix it, too
03688                 if (!Q_stricmp("head_light_blaster_cann",surfName))
03689                 {
03690                         *hitLoc = HL_ARM_LT;
03691                 }
03692                 else if (!Q_stricmp("head_concussion_charger",surfName))
03693                 {
03694                         *hitLoc = HL_ARM_RT;
03695                 }
03696                 return(qfalse);
03697         }
03698         else if ( ent->client && (ent->client->NPC_class == CLASS_MARK1) )
03699         {
03700                 if (!Q_stricmp("l_arm",surfName))
03701                 {
03702                         *hitLoc = HL_ARM_LT;
03703                 }
03704                 else if (!Q_stricmp("r_arm",surfName))
03705                 {
03706                         *hitLoc = HL_ARM_RT;
03707                 }
03708                 else if (!Q_stricmp("torso_front",surfName))
03709                 {
03710                         *hitLoc = HL_CHEST;
03711                 }
03712                 else if (!Q_stricmp("torso_tube1",surfName))
03713                 {
03714                         *hitLoc = HL_GENERIC1;
03715                 }
03716                 else if (!Q_stricmp("torso_tube2",surfName))
03717                 {
03718                         *hitLoc = HL_GENERIC2;
03719                 }
03720                 else if (!Q_stricmp("torso_tube3",surfName))
03721                 {
03722                         *hitLoc = HL_GENERIC3;
03723                 }
03724                 else if (!Q_stricmp("torso_tube4",surfName))
03725                 {
03726                         *hitLoc = HL_GENERIC4;
03727                 }
03728                 else if (!Q_stricmp("torso_tube5",surfName))
03729                 {
03730                         *hitLoc = HL_GENERIC5;
03731                 }
03732                 else if (!Q_stricmp("torso_tube6",surfName))
03733                 {
03734                         *hitLoc = HL_GENERIC6;
03735                 }
03736                 return(qfalse);
03737         }
03738         else if ( ent->client && (ent->client->NPC_class == CLASS_MARK2) )
03739         {
03740                 if (!Q_stricmp("torso_canister1",surfName))
03741                 {
03742                         *hitLoc = HL_GENERIC1;
03743                 }
03744                 else if (!Q_stricmp("torso_canister2",surfName))
03745                 {
03746                         *hitLoc = HL_GENERIC2;
03747                 }
03748                 else if (!Q_stricmp("torso_canister3",surfName))
03749                 {
03750                         *hitLoc = HL_GENERIC3;
03751                 }
03752                 return(qfalse);
03753         }
03754         else if ( ent->client && (ent->client->NPC_class == CLASS_GALAKMECH) )
03755         {
03756                 if (!Q_stricmp("torso_antenna",surfName)||!Q_stricmp("torso_antenna_base",surfName))
03757                 {
03758                         *hitLoc = HL_GENERIC1;
03759                 }
03760                 else if (!Q_stricmp("torso_shield",surfName))
03761                 {
03762                         *hitLoc = HL_GENERIC2;
03763                 }
03764                 else
03765                 {
03766                         *hitLoc = HL_CHEST;
03767                 }
03768                 return(qfalse);
03769         }
03770 
03771         //FIXME: check the hitLoc and hitDir against the cap tag for the place 
03772         //where the split will be- if the hit dir is roughly perpendicular to 
03773         //the direction of the cap, then the split is allowed, otherwise we
03774         //hit it at the wrong angle and should not dismember...
03775         actualTime = level.time;
03776         if ( !Q_strncmp( "hips", surfName, 4 ) )
03777         {//FIXME: test properly for legs
03778                 *hitLoc = HL_WAIST;
03779                 if ( ent->client != NULL && ent->ghoul2 )
03780                 {
03781                         mdxaBone_t      boltMatrix;
03782                         vec3_t  tagOrg, angles;
03783 
03784                         VectorSet( angles, 0, ent->r.currentAngles[YAW], 0 );
03785                         if (kneeLBolt>=0)
03786                         {
03787                                 trap_G2API_GetBoltMatrix( ent->ghoul2, 0, kneeLBolt, 
03788                                                                 &boltMatrix, angles, ent->r.currentOrigin,
03789                                                                 actualTime, NULL, ent->modelScale );
03790                                 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, tagOrg );
03791                                 if ( DistanceSquared( point, tagOrg ) < 100 )
03792                                 {//actually hit the knee
03793                                         *hitLoc = HL_LEG_LT;
03794                                 }
03795                         }
03796                         if (*hitLoc == HL_WAIST)
03797                         {
03798                                 if (kneeRBolt>=0)
03799                                 {
03800                                         trap_G2API_GetBoltMatrix( ent->ghoul2, 0, kneeRBolt, 
03801                                                                         &boltMatrix, angles, ent->r.currentOrigin,
03802                                                                         actualTime, NULL, ent->modelScale );
03803                                         BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, tagOrg );
03804                                         if ( DistanceSquared( point, tagOrg ) < 100 )
03805                                         {//actually hit the knee
03806                                                 *hitLoc = HL_LEG_RT;
03807                                         }
03808                                 }
03809                         }
03810                 }
03811         }
03812         else if ( !Q_strncmp( "torso", surfName, 5 ) )
03813         {
03814                 if ( !ent->client )
03815                 {
03816                         *hitLoc = HL_CHEST;
03817                 }
03818                 else
03819                 {
03820                         vec3_t  t_fwd, t_rt, t_up, dirToImpact;
03821                         float frontSide, rightSide, upSide;
03822                         AngleVectors( ent->client->renderInfo.torsoAngles, t_fwd, t_rt, t_up );
03823 
03824                         if (ent->client->renderInfo.boltValidityTime != level.time)
03825                         {
03826                                 vec3_t renderAng;
03827 
03828                                 renderAng[0] = 0;
03829                                 renderAng[1] = ent->client->ps.viewangles[YAW];
03830                                 renderAng[2] = 0;
03831 
03832                                 UpdateClientRenderBolts(ent, ent->client->ps.origin, renderAng);
03833                         }
03834 
03835                         VectorSubtract( point, ent->client->renderInfo.torsoPoint, dirToImpact );
03836                         frontSide = DotProduct( t_fwd, dirToImpact );
03837                         rightSide = DotProduct( t_rt, dirToImpact );
03838                         upSide = DotProduct( t_up, dirToImpact );
03839                         if ( upSide < -10 )
03840                         {//hit at waist
03841                                 *hitLoc = HL_WAIST;
03842                         }
03843                         else
03844                         {//hit on upper torso
03845                                 if ( rightSide > 4 )
03846                                 {
03847                                         *hitLoc = HL_ARM_RT;
03848                                 }
03849                                 else if ( rightSide < -4 )
03850                                 {
03851                                         *hitLoc = HL_ARM_LT;
03852                                 }
03853                                 else if ( rightSide > 2 )
03854                                 {
03855                                         if ( frontSide > 0 )
03856                                         {
03857                                                 *hitLoc = HL_CHEST_RT;
03858                                         }
03859                                         else
03860                                         {
03861                                                 *hitLoc = HL_BACK_RT;
03862                                         }
03863                                 }
03864                                 else if ( rightSide < -2 )
03865                                 {
03866                                         if ( frontSide > 0 )
03867                                         {
03868                                                 *hitLoc = HL_CHEST_LT;
03869                                         }
03870                                         else
03871                                         {
03872                                                 *hitLoc = HL_BACK_LT;
03873                                         }
03874                                 }
03875                                 else if ( upSide > -3 && mod == MOD_SABER )
03876                                 {
03877                                         *hitLoc = HL_HEAD;
03878                                 }
03879                                 else if ( frontSide > 0 )
03880                                 {
03881                                         *hitLoc = HL_CHEST;
03882                                 }
03883                                 else
03884                                 {
03885                                         *hitLoc = HL_BACK;
03886                                 }
03887                         }
03888                 }
03889         }
03890         else if ( !Q_strncmp( "head", surfName, 4 ) )
03891         {
03892                 *hitLoc = HL_HEAD;
03893         }
03894         else if ( !Q_strncmp( "r_arm", surfName, 5 ) )
03895         {
03896                 *hitLoc = HL_ARM_RT;
03897                 if ( ent->client != NULL && ent->ghoul2 )
03898                 {
03899                         mdxaBone_t      boltMatrix;
03900                         vec3_t  tagOrg, angles;
03901 
03902                         VectorSet( angles, 0, ent->r.currentAngles[YAW], 0 );
03903                         if (handRBolt>=0)
03904                         {
03905                                 trap_G2API_GetBoltMatrix( ent->ghoul2, 0, handRBolt, 
03906                                                                 &boltMatrix, angles, ent->r.currentOrigin,
03907                                                                 actualTime, NULL, ent->modelScale );
03908                                 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, tagOrg );
03909                                 if ( DistanceSquared( point, tagOrg ) < 256 )
03910                                 {//actually hit the hand
03911                                         *hitLoc = HL_HAND_RT;
03912                                 }
03913                         }
03914                 }
03915         }
03916         else if ( !Q_strncmp( "l_arm", surfName, 5 ) )
03917         {
03918                 *hitLoc = HL_ARM_LT;
03919                 if ( ent->client != NULL && ent->ghoul2 )
03920                 {
03921                         mdxaBone_t      boltMatrix;
03922                         vec3_t  tagOrg, angles;
03923 
03924                         VectorSet( angles, 0, ent->r.currentAngles[YAW], 0 );
03925                         if (handLBolt>=0)
03926                         {
03927                                 trap_G2API_GetBoltMatrix( ent->ghoul2, 0, handLBolt, 
03928                                                                 &boltMatrix, angles, ent->r.currentOrigin,
03929                                                                 actualTime, NULL, ent->modelScale );
03930                                 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, tagOrg );
03931                                 if ( DistanceSquared( point, tagOrg ) < 256 )
03932                                 {//actually hit the hand
03933                                         *hitLoc = HL_HAND_LT;
03934                                 }
03935                         }
03936                 }
03937         }
03938         else if ( !Q_strncmp( "r_leg", surfName, 5 ) )
03939         {
03940                 *hitLoc = HL_LEG_RT;
03941                 if ( ent->client != NULL && ent->ghoul2 )
03942                 {
03943                         mdxaBone_t      boltMatrix;
03944                         vec3_t  tagOrg, angles;
03945 
03946                         VectorSet( angles, 0, ent->r.currentAngles[YAW], 0 );
03947                         if (footRBolt>=0)
03948                         {
03949                                 trap_G2API_GetBoltMatrix( ent->ghoul2, 0, footRBolt, 
03950                                                                 &boltMatrix, angles, ent->r.currentOrigin,
03951                                                                 actualTime, NULL, ent->modelScale );
03952                                 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, tagOrg );
03953                                 if ( DistanceSquared( point, tagOrg ) < 100 )
03954                                 {//actually hit the foot
03955                                         *hitLoc = HL_FOOT_RT;
03956                                 }
03957                         }
03958                 }
03959         }
03960         else if ( !Q_strncmp( "l_leg", surfName, 5 ) )
03961         {
03962                 *hitLoc = HL_LEG_LT;
03963                 if ( ent->client != NULL && ent->ghoul2 )
03964                 {
03965                         mdxaBone_t      boltMatrix;
03966                         vec3_t  tagOrg, angles;
03967 
03968                         VectorSet( angles, 0, ent->r.currentAngles[YAW], 0 );
03969                         if (footLBolt>=0)
03970                         {
03971                                 trap_G2API_GetBoltMatrix( ent->ghoul2, 0, footLBolt, 
03972                                                                 &boltMatrix, angles, ent->r.currentOrigin,
03973                                                                 actualTime, NULL, ent->modelScale );
03974                                 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, tagOrg );
03975                                 if ( DistanceSquared( point, tagOrg ) < 100 )
03976                                 {//actually hit the foot
03977                                         *hitLoc = HL_FOOT_LT;
03978                                 }
03979                         }
03980                 }
03981         }
03982         else if ( !Q_strncmp( "r_hand", surfName, 6 ) || !Q_strncmp( "w_", surfName, 2 ) )
03983         {//right hand or weapon
03984                 *hitLoc = HL_HAND_RT;
03985         }
03986         else if ( !Q_strncmp( "l_hand", surfName, 6 ) )
03987         {
03988                 *hitLoc = HL_HAND_LT;
03989         }
03990         /*
03991 #ifdef _DEBUG
03992         else
03993         {
03994                 Com_Printf( "ERROR: surface %s does not belong to any hitLocation!!!\n", surfName );
03995         }
03996 #endif //_DEBUG
03997         */
03998 
03999         //if ( g_dismemberment->integer >= 11381138 || !ent->client->dismembered )
04000         if (g_dismember.integer == 100)
04001         { //full probability...
04002                 if ( ent->client && ent->client->NPC_class == CLASS_PROTOCOL )
04003                 {
04004                         dismember = qtrue;
04005                 }
04006                 else if ( dir && (dir[0] || dir[1] || dir[2]) &&
04007                         bladeDir && (bladeDir[0] || bladeDir[1] || bladeDir[2]) )
04008                 {//we care about direction (presumably for dismemberment)
04009                         //if ( g_dismemberProbabilities->value<=0.0f||G_Dismemberable( ent, *hitLoc ) )
04010                         if (1) //Fix me?
04011                         {//either we don't care about probabilties or the probability let us continue
04012                                 char *tagName = NULL;
04013                                 float   aoa = 0.5f;
04014                                 //dir must be roughly perpendicular to the hitLoc's cap bolt
04015                                 switch ( *hitLoc )
04016                                 {
04017                                         case HL_LEG_RT:
04018                                                 tagName = "*hips_cap_r_leg";
04019                                                 break;
04020                                         case HL_LEG_LT:
04021                                                 tagName = "*hips_cap_l_leg";
04022                                                 break;
04023                                         case HL_WAIST:
04024                                                 tagName = "*hips_cap_torso";
04025                                                 aoa = 0.25f;
04026                                                 break;
04027                                         case HL_CHEST_RT:
04028                                         case HL_ARM_RT:
04029                                         case HL_BACK_LT:
04030                                                 tagName = "*torso_cap_r_arm";
04031                                                 break;
04032                                         case HL_CHEST_LT:
04033                                         case HL_ARM_LT:
04034                                         case HL_BACK_RT:
04035                                                 tagName = "*torso_cap_l_arm";
04036                                                 break;
04037                                         case HL_HAND_RT:
04038                                                 tagName = "*r_arm_cap_r_hand";
04039                                                 break;
04040                                         case HL_HAND_LT:
04041                                                 tagName = "*l_arm_cap_l_hand";
04042                                                 break;
04043                                         case HL_HEAD:
04044                                                 tagName = "*torso_cap_head";
04045                                                 aoa = 0.25f;
04046                                                 break;
04047                                         case HL_CHEST:
04048                                         case HL_BACK:
04049                                         case HL_FOOT_RT:
04050                                         case HL_FOOT_LT:
04051                                         default:
04052                                                 //no dismemberment possible with these, so no checks needed
04053                                                 break;
04054                                 }
04055                                 if ( tagName )
04056                                 {
04057                                         int tagBolt = trap_G2API_AddBolt( ent->ghoul2, 0, tagName );
04058                                         if ( tagBolt != -1 )
04059                                         {
04060                                                 mdxaBone_t      boltMatrix;
04061                                                 vec3_t  tagOrg, tagDir, angles;
04062 
04063                                                 VectorSet( angles, 0, ent->r.currentAngles[YAW], 0 );
04064                                                 trap_G2API_GetBoltMatrix( ent->ghoul2, 0, tagBolt, 
04065                                                                                 &boltMatrix, angles, ent->r.currentOrigin,
04066                                                                                 actualTime, NULL, ent->modelScale );
04067                                                 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, tagOrg );
04068                                                 BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, tagDir );
04069                                                 if ( DistanceSquared( point, tagOrg ) < 256 )
04070                                                 {//hit close
04071                                                         float dot = DotProduct( dir, tagDir );
04072                                                         if ( dot < aoa && dot > -aoa )
04073                                                         {//hit roughly perpendicular
04074                                                                 dot = DotProduct( bladeDir, tagDir );
04075                                                                 if ( dot < aoa && dot > -aoa )
04076                                                                 {//blade was roughly perpendicular
04077                                                                         dismember = qtrue;
04078                                                                 }
04079                                                         }
04080                                                 }
04081                                         }
04082                                 }
04083                         }
04084                 }
04085                 else
04086                 { //hmm, no direction supplied.
04087                         dismember = qtrue;
04088                 }
04089         }
04090         return dismember;
04091 }

int G_GetHitQuad gentity_t self,
vec3_t  hitloc
 

Definition at line 3546 of file g_combat.c.

References AngleVectors(), entityState_s::apos, gentity_s::client, DotProduct, G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RLEG, gentity_t, gPainHitLoc, NULL, playerState_s::origin, entityState_s::pos, gclient_s::ps, gentity_s::s, trajectory_t::trBase, vec3_t, VectorCopy, VectorNormalize(), VectorSubtract, playerState_s::viewangles, and playerState_s::viewheight.

Referenced by G_CheckForDismemberment().

03547 {
03548         vec3_t diff, fwdangles={0,0,0}, right;
03549         vec3_t clEye;
03550         float rightdot;
03551         float zdiff;
03552         int hitLoc = gPainHitLoc;
03553 
03554         if (self->client)
03555         {
03556                 VectorCopy(self->client->ps.origin, clEye);
03557                 clEye[2] += self->client->ps.viewheight;
03558         }
03559         else
03560         {
03561                 VectorCopy(self->s.pos.trBase, clEye);
03562                 clEye[2] += 16;
03563         }
03564 
03565         VectorSubtract( hitloc, clEye, diff );
03566         diff[2] = 0;
03567         VectorNormalize( diff );
03568 
03569         if (self->client)
03570         {
03571                 fwdangles[1] = self->client->ps.viewangles[1];
03572         }
03573         else
03574         {
03575                 fwdangles[1] = self->s.apos.trBase[1];
03576         }
03577         // Ultimately we might care if the shot was ahead or behind, but for now, just quadrant is fine.
03578         AngleVectors( fwdangles, NULL, right, NULL );
03579 
03580         rightdot = DotProduct(right, diff);
03581         zdiff = hitloc[2] - clEye[2];
03582         
03583         if ( zdiff > 0 )
03584         {
03585                 if ( rightdot > 0.3 )
03586                 {
03587                         hitLoc = G2_MODELPART_RARM;
03588                 }
03589                 else if ( rightdot < -0.3 )
03590                 {
03591                         hitLoc = G2_MODELPART_LARM;
03592                 }
03593                 else
03594                 {
03595                         hitLoc = G2_MODELPART_HEAD;
03596                 }
03597         }
03598         else if ( zdiff > -20 )
03599         {
03600                 if ( rightdot > 0.1 )
03601                 {
03602                         hitLoc = G2_MODELPART_RARM;
03603                 }
03604                 else if ( rightdot < -0.1 )
03605                 {
03606                         hitLoc = G2_MODELPART_LARM;
03607                 }
03608                 else
03609                 {
03610                         hitLoc = G2_MODELPART_HEAD;
03611                 }
03612         }
03613         else
03614         {
03615                 if ( rightdot >= 0 )
03616                 {
03617                         hitLoc = G2_MODELPART_RLEG;
03618                 }
03619                 else
03620                 {
03621                         hitLoc = G2_MODELPART_LLEG;
03622                 }
03623         }
03624 
03625         return hitLoc;
03626 }

gentity_t* G_GetJediMaster void   ) 
 

Definition at line 1743 of file g_combat.c.

References gentity_s::client, g_entities, gentity_t, gentity_s::inuse, playerState_s::isJediMaster, MAX_CLIENTS, NULL, and gclient_s::ps.

Referenced by player_die().

01744 {
01745         int i = 0;
01746         gentity_t *ent;
01747 
01748         while (i < MAX_CLIENTS)
01749         {
01750                 ent = &g_entities[i];
01751 
01752                 if (ent && ent->inuse && ent->client && ent->client->ps.isJediMaster)
01753                 {
01754                         return ent;
01755                 }
01756 
01757                 i++;
01758         }
01759 
01760         return NULL;
01761 }

qboolean G_HeavyMelee gentity_t attacker  ) 
 

Definition at line 32 of file g_combat.c.

References bgSiegeClasses, CFL_HEAVYMELEE, gentity_s::client, g_gametype, gentity_t, GT_SIEGE, vmCvar_t::integer, qboolean, qfalse, qtrue, and gclient_s::siegeClass.

Referenced by G_Damage(), player_die(), and WP_FireMelee().

00033 {
00034         if (g_gametype.integer == GT_SIEGE 
00035                 && attacker 
00036                 && attacker->client
00037                 && attacker->client->siegeClass != -1 
00038                 && (bgSiegeClasses[attacker->client->siegeClass].classflags & (1<<CFL_HEAVYMELEE)) )
00039         {
00040                 return qtrue;
00041         }
00042         return qfalse;
00043 }

qboolean G_InKnockDown playerState_t ps  ) 
 

Definition at line 852 of file g_combat.c.

References BOTH_FORCE_GETUP_B1, BOTH_FORCE_GETUP_B2, BOTH_FORCE_GETUP_B3, BOTH_FORCE_GETUP_B4, BOTH_FORCE_GETUP_B5, BOTH_FORCE_GETUP_F1, BOTH_FORCE_GETUP_F2, BOTH_GETUP1, BOTH_GETUP2, BOTH_GETUP3, BOTH_GETUP4, BOTH_GETUP5, BOTH_KNOCKDOWN1, BOTH_KNOCKDOWN2, BOTH_KNOCKDOWN3, BOTH_KNOCKDOWN4, BOTH_KNOCKDOWN5, playerState_s::legsAnim, playerState_t, qboolean, qfalse, and qtrue.

00853 {
00854         switch ( (ps->legsAnim) )
00855         {
00856         case BOTH_KNOCKDOWN1:
00857         case BOTH_KNOCKDOWN2:
00858         case BOTH_KNOCKDOWN3:
00859         case BOTH_KNOCKDOWN4:
00860         case BOTH_KNOCKDOWN5:
00861                 return qtrue;
00862                 break;
00863         case BOTH_GETUP1:
00864         case BOTH_GETUP2:
00865         case BOTH_GETUP3:
00866         case BOTH_GETUP4:
00867         case BOTH_GETUP5:
00868         case BOTH_FORCE_GETUP_F1:
00869         case BOTH_FORCE_GETUP_F2:
00870         case BOTH_FORCE_GETUP_B1:
00871         case BOTH_FORCE_GETUP_B2:
00872         case BOTH_FORCE_GETUP_B3:
00873         case BOTH_FORCE_GETUP_B4:
00874         case BOTH_FORCE_GETUP_B5:
00875                 return qtrue;
00876                 break;
00877         }
00878         return qfalse;
00879 }

void G_Knockdown gentity_t victim  ) 
 

Definition at line 4327 of file g_combat.c.

04328 {
04329         if ( victim && victim->client && BG_KnockDownable(&victim->client->ps) )
04330         {
04331                 victim->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
04332                 victim->client->ps.forceDodgeAnim = 0;
04333                 victim->client->ps.forceHandExtendTime = level.time + 1100;
04334                 victim->client->ps.quickerGetup = qfalse;
04335         }
04336 }

void G_LetGoOfWall gentity_t ent  ) 
 

Definition at line 3025 of file w_force.c.

References BG_InReboundHold(), BG_InReboundJump(), gentity_s::client, gentity_t, playerState_s::legsAnim, playerState_s::legsTimer, playerState_s::pm_flags, PMF_STUCK_TO_WALL, gclient_s::ps, playerState_s::torsoAnim, and playerState_s::torsoTimer.

Referenced by ForceThrow(), and G_Damage().

03026 {
03027         if ( !ent || !ent->client )
03028         {
03029                 return;
03030         }
03031         ent->client->ps.pm_flags &= ~PMF_STUCK_TO_WALL;
03032         if ( BG_InReboundJump( ent->client->ps.legsAnim ) 
03033                 || BG_InReboundHold( ent->client->ps.legsAnim ) )
03034         {
03035                 ent->client->ps.legsTimer = 0;
03036         }
03037         if ( BG_InReboundJump( ent->client->ps.torsoAnim ) 
03038                 || BG_InReboundHold( ent->client->ps.torsoAnim ) )
03039         {
03040                 ent->client->ps.torsoTimer = 0;
03041         }
03042 }

void G_LocationBasedDamageModifier gentity_t ent,
vec3_t  point,
int  mod,
int  dflags,
int *  damage
 

Definition at line 4221 of file g_combat.c.

References CLASS_VEHICLE, gentity_s::client, d_projectileGhoul2Collision, d_saberGhoul2Collision, DAMAGE_NO_HIT_LOC, gclient_s::g2LastSurfaceHit, gclient_s::g2LastSurfaceTime, G_GetHitLocation(), G_GetHitLocFromSurfName(), g_locationBasedDamage, gentity_t, gentity_s::ghoul2, HL_ARM_LT, HL_ARM_RT, HL_BACK, HL_BACK_LT, HL_BACK_RT, HL_CHEST, HL_CHEST_LT, HL_CHEST_RT, HL_FOOT_LT, HL_FOOT_RT, HL_HAND_LT, HL_HAND_RT, HL_HEAD, HL_LEG_LT, HL_LEG_RT, HL_WAIST, vmCvar_t::integer, level, MAX_QPATH, MOD_SABER, MOD_UNKNOWN, gclient_s::NPC_class, level_locals_t::time, trap_G2API_GetSurfaceName(), vec3_origin, and vec3_t.

Referenced by G_Damage().

04222 {
04223         int hitLoc = -1;
04224 
04225         if (!g_locationBasedDamage.integer)
04226         { //then leave it alone
04227                 return;
04228         }
04229 
04230         if ( (dflags&DAMAGE_NO_HIT_LOC) )
04231         { //then leave it alone
04232                 return;
04233         }
04234 
04235         if (mod == MOD_SABER && *damage <= 1)
04236         { //don't bother for idle damage
04237                 return;
04238         }
04239 
04240         if (!point)
04241         {
04242                 return;
04243         }
04244 
04245         if ( ent->client && ent->client->NPC_class == CLASS_VEHICLE )
04246         {//no location-based damage on vehicles
04247                 return;
04248         }
04249 
04250         if ((d_saberGhoul2Collision.integer && ent->client && ent->client->g2LastSurfaceTime == level.time && mod == MOD_SABER) || //using ghoul2 collision? Then if the mod is a saber we should have surface data from the last hit (unless thrown).
04251                 (d_projectileGhoul2Collision.integer && ent->client && ent->client->g2LastSurfaceTime == level.time)) //It's safe to assume we died from the projectile that just set our surface index. So, go ahead and use that as the surf I guess.
04252         {
04253                 char hitSurface[MAX_QPATH];
04254 
04255                 trap_G2API_GetSurfaceName(ent->ghoul2, ent->client->g2LastSurfaceHit, 0, hitSurface);
04256 
04257                 if (hitSurface[0])
04258                 {
04259                         G_GetHitLocFromSurfName(ent, hitSurface, &hitLoc, point, vec3_origin, vec3_origin, MOD_UNKNOWN);
04260                 }
04261         }
04262 
04263         if (hitLoc == -1)
04264         {
04265                 hitLoc = G_GetHitLocation( ent, point );
04266         }
04267 
04268         switch (hitLoc)
04269         {
04270         case HL_FOOT_RT:
04271         case HL_FOOT_LT:
04272                 *damage *= 0.5;
04273                 break;
04274         case HL_LEG_RT:
04275         case HL_LEG_LT:
04276                 *damage *= 0.7;
04277                 break;
04278         case HL_WAIST:
04279         case HL_BACK_RT:
04280         case HL_BACK_LT:
04281         case HL_BACK:
04282         case HL_CHEST_RT:
04283         case HL_CHEST_LT:
04284         case HL_CHEST:
04285                 break; //normal damage
04286         case HL_ARM_RT:
04287         case HL_ARM_LT:
04288                 *damage *= 0.85;
04289                 break;
04290         case HL_HAND_RT:
04291         case HL_HAND_LT:
04292                 *damage *= 0.6;
04293                 break;
04294         case HL_HEAD:
04295                 *damage *= 1.3;
04296                 break;
04297         default:
04298                 break; //do nothing then
04299         }
04300 }

int G_PickDeathAnim gentity_t self,
vec3_t  point,
int  damage,
int  mod,
int  hitLoc
 

Definition at line 1373 of file g_combat.c.

References BG_HasAnimation(), BG_PickAnim(), BOTH_CHOKE3, BOTH_DEAD1, BOTH_DEAD10, BOTH_DEAD11, BOTH_DEAD12, BOTH_DEAD13, BOTH_DEAD14, BOTH_DEAD15, BOTH_DEAD16, BOTH_DEAD17, BOTH_DEAD18, BOTH_DEAD19, BOTH_DEAD2, BOTH_DEAD3, BOTH_DEAD4, BOTH_DEAD5, BOTH_DEAD6, BOTH_DEAD7, BOTH_DEAD8, BOTH_DEAD9, BOTH_DEADBACKWARD1, BOTH_DEADBACKWARD2, BOTH_DEADFLOP1, BOTH_DEADFORWARD1, BOTH_DEADFORWARD2, BOTH_DEATH1, BOTH_DEATH10, BOTH_DEATH11, BOTH_DEATH12, BOTH_DEATH13, BOTH_DEATH14, BOTH_DEATH15, BOTH_DEATH16, BOTH_DEATH17, BOTH_DEATH18, BOTH_DEATH19, BOTH_DEATH1IDLE, BOTH_DEATH2, BOTH_DEATH25, BOTH_DEATH3, BOTH_DEATH4, BOTH_DEATH5, BOTH_DEATH6, BOTH_DEATH7, BOTH_DEATH8, BOTH_DEATH9, BOTH_DEATHBACKWARD1, BOTH_DEATHBACKWARD2, BOTH_DEATHFORWARD1, BOTH_DEATHFORWARD2, BOTH_FALLDEAD1LAND, BOTH_FALLDEATH1, BOTH_FALLDEATH1INAIR, BOTH_FALLDEATH1LAND, BOTH_LYINGDEAD1, BOTH_LYINGDEATH1, BOTH_RIGHTHANDCHOPPEDOFF, BOTH_STUMBLEDEAD1, BOTH_STUMBLEDEATH1, gentity_s::client, ENTITYNUM_NONE, ET_NPC, entityState_s::eType, G_GetHitLocation(), gentity_t, gGAvoidDismember, HL_ARM_LT, HL_ARM_RT, HL_BACK, HL_BACK_LT, HL_BACK_RT, HL_CHEST, HL_CHEST_LT, HL_CHEST_RT, HL_FOOT_LT, HL_FOOT_RT, HL_HAND_LT, HL_HAND_RT, HL_HEAD, HL_LEG_LT, HL_LEG_RT, HL_NONE, HL_WAIST, gclient_s::inSpaceIndex, entityState_s::legsAnim, playerState_s::legsAnim, gentity_s::localAnimIndex, MOD_SABER, entityState_s::pos, gclient_s::ps, Q_irand(), gentity_s::s, STAT_MAX_HEALTH, playerState_s::stats, trajectory_t::trDelta, vec3_t, VectorCopy, and playerState_s::velocity.

Referenced by player_die().

01374 {//FIXME: play dead flop anims on body if in an appropriate _DEAD anim when this func is called
01375         int deathAnim = -1;
01376         int max_health;
01377         int legAnim = 0;
01378         vec3_t objVelocity;
01379 
01380         if (!self || !self->client)
01381         {
01382                 if (!self || self->s.eType != ET_NPC)
01383                 { //g2animent
01384                         return 0;
01385                 }
01386         }
01387 
01388         if (self->client)
01389         {
01390                 max_health = self->client->ps.stats[STAT_MAX_HEALTH];
01391 
01392                 if (self->client->inSpaceIndex && self->client->inSpaceIndex != ENTITYNUM_NONE)
01393                 {
01394                         return BOTH_CHOKE3;
01395                 }
01396         }
01397         else
01398         {
01399                 max_health = 60;
01400         }
01401 
01402         if (self->client)
01403         {
01404                 VectorCopy(self->client->ps.velocity, objVelocity);
01405         }
01406         else
01407         {
01408                 VectorCopy(self->s.pos.trDelta, objVelocity);
01409         }
01410 
01411         if ( hitLoc == HL_NONE )
01412         {
01413                 hitLoc = G_GetHitLocation( self, point );//self->hitLoc
01414         }
01415 
01416         if (self->client)
01417         {
01418                 legAnim = self->client->ps.legsAnim;
01419         }
01420         else
01421         {
01422                 legAnim = self->s.legsAnim;
01423         }
01424 
01425         if (gGAvoidDismember)
01426         {
01427                 return BOTH_RIGHTHANDCHOPPEDOFF;
01428         }
01429 
01430         //dead flops
01431         switch( legAnim )
01432         {
01433         case BOTH_DEATH1:               //# First Death anim
01434         case BOTH_DEAD1:
01435         case BOTH_DEATH2:                       //# Second Death anim
01436         case BOTH_DEAD2:
01437         case BOTH_DEATH8:                       //# 
01438         case BOTH_DEAD8:
01439         case BOTH_DEATH13:                      //# 
01440         case BOTH_DEAD13:
01441         case BOTH_DEATH14:                      //# 
01442         case BOTH_DEAD14:
01443         case BOTH_DEATH16:                      //# 
01444         case BOTH_DEAD16:
01445         case BOTH_DEADBACKWARD1:                //# First thrown backward death finished pose
01446         case BOTH_DEADBACKWARD2:                //# Second thrown backward death finished pose
01447                 deathAnim = -2;
01448                 /*
01449                 if ( PM_FinishedCurrentLegsAnim( self ) )
01450                 {//done with the anim
01451                         deathAnim = BOTH_DEADFLOP2;
01452                 }
01453                 else
01454                 {
01455                         deathAnim = -2;
01456                 }
01457                 break;
01458         case BOTH_DEADFLOP2:
01459                 deathAnim = BOTH_DEADFLOP2;
01460                 break;
01461                 */
01462         case BOTH_DEATH10:                      //# 
01463         case BOTH_DEAD10:
01464         case BOTH_DEATH15:                      //# 
01465         case BOTH_DEAD15:
01466         case BOTH_DEADFORWARD1:         //# First thrown forward death finished pose
01467         case BOTH_DEADFORWARD2:         //# Second thrown forward death finished pose
01468                 deathAnim = -2;
01469                 /*
01470                 if ( PM_FinishedCurrentLegsAnim( self ) )
01471                 {//done with the anim
01472                         deathAnim = BOTH_DEADFLOP1;
01473                 }
01474                 else
01475                 {
01476                         deathAnim = -2;
01477                 }
01478                 break;
01479                 */
01480         case BOTH_DEADFLOP1:
01481                 deathAnim = -2;
01482                 //deathAnim = BOTH_DEADFLOP1;
01483                 break;
01484         case BOTH_DEAD3:                                //# Third Death finished pose
01485         case BOTH_DEAD4:                                //# Fourth Death finished pose
01486         case BOTH_DEAD5:                                //# Fifth Death finished pose
01487         case BOTH_DEAD6:                                //# Sixth Death finished pose
01488         case BOTH_DEAD7:                                //# Seventh Death finished pose
01489         case BOTH_DEAD9:                                //# 
01490         case BOTH_DEAD11:                       //#
01491         case BOTH_DEAD12:                       //# 
01492         case BOTH_DEAD17:                       //# 
01493         case BOTH_DEAD18:                       //# 
01494         case BOTH_DEAD19:                       //# 
01495         case BOTH_LYINGDEAD1:           //# Killed lying down death finished pose
01496         case BOTH_STUMBLEDEAD1:         //# Stumble forward death finished pose
01497         case BOTH_FALLDEAD1LAND:                //# Fall forward and splat death finished pose
01498         case BOTH_DEATH3:                       //# Third Death anim
01499         case BOTH_DEATH4:                       //# Fourth Death anim
01500         case BOTH_DEATH5:                       //# Fifth Death anim
01501         case BOTH_DEATH6:                       //# Sixth Death anim
01502         case BOTH_DEATH7:                       //# Seventh Death anim
01503         case BOTH_DEATH9:                       //# 
01504         case BOTH_DEATH11:                      //#
01505         case BOTH_DEATH12:                      //# 
01506         case BOTH_DEATH17:                      //# 
01507         case BOTH_DEATH18:                      //# 
01508         case BOTH_DEATH19:                      //# 
01509         case BOTH_DEATHFORWARD1:                //# First Death in which they get thrown forward
01510         case BOTH_DEATHFORWARD2:                //# Second Death in which they get thrown forward
01511         case BOTH_DEATHBACKWARD1:       //# First Death in which they get thrown backward
01512         case BOTH_DEATHBACKWARD2:       //# Second Death in which they get thrown backward
01513         case BOTH_DEATH1IDLE:           //# Idle while close to death
01514         case BOTH_LYINGDEATH1:          //# Death to play when killed lying down
01515         case BOTH_STUMBLEDEATH1:                //# Stumble forward and fall face first death
01516         case BOTH_FALLDEATH1:           //# Fall forward off a high cliff and splat death - start
01517         case BOTH_FALLDEATH1INAIR:      //# Fall forward off a high cliff and splat death - loop
01518         case BOTH_FALLDEATH1LAND:       //# Fall forward off a high cliff and splat death - hit bottom
01519                 deathAnim = -2;
01520                 break;
01521         }
01522         if ( deathAnim == -1 )
01523         {
01524                 if (self->client)
01525                 {
01526                         deathAnim = G_CheckSpecialDeathAnim( self, point, damage, mod, hitLoc );
01527                 }
01528 
01529                 if (deathAnim == -1)
01530                 {
01531                         //death anims
01532                         switch( hitLoc )
01533                         {
01534                         case HL_FOOT_RT:
01535                         case HL_FOOT_LT:
01536                                 if ( mod == MOD_SABER && !Q_irand( 0, 2 ) )
01537                                 {
01538                                         return BOTH_DEATH10;//chest: back flip
01539                                 }
01540                                 else if ( !Q_irand( 0, 2 ) )
01541                                 {
01542                                         deathAnim = BOTH_DEATH4;//back: forward
01543                                 }
01544                                 else if ( !Q_irand( 0, 1 ) )
01545                                 {
01546                                         deathAnim = BOTH_DEATH5;//same as 4
01547                                 }
01548                                 else
01549                                 {
01550                                         deathAnim = BOTH_DEATH15;//back: forward
01551                                 }
01552                                 break;
01553                         case HL_LEG_RT:
01554                                 if ( !Q_irand( 0, 2 ) )
01555                                 {
01556                                         deathAnim = BOTH_DEATH4;//back: forward
01557                                 }
01558                                 else if ( !Q_irand( 0, 1 ) )
01559                                 {
01560                                         deathAnim = BOTH_DEATH5;//same as 4
01561                                 }
01562                                 else
01563                                 {
01564                                         deathAnim = BOTH_DEATH15;//back: forward
01565                                 }
01566                                 break;
01567                         case HL_LEG_LT:
01568                                 if ( !Q_irand( 0, 2 ) )
01569                                 {
01570                                         deathAnim = BOTH_DEATH4;//back: forward
01571                                 }
01572                                 else if ( !Q_irand( 0, 1 ) )
01573                                 {
01574                                         deathAnim = BOTH_DEATH5;//same as 4
01575                                 }
01576                                 else
01577                                 {
01578                                         deathAnim = BOTH_DEATH15;//back: forward
01579                                 }
01580                                 break;
01581                         case HL_BACK:
01582                                 if ( !VectorLengthSquared( objVelocity ) )
01583                                 {
01584                                         deathAnim = BOTH_DEATH17;//head/back: croak
01585                                 }
01586                                 else
01587                                 {
01588                                         if ( !Q_irand( 0, 2 ) )
01589                                         {
01590                                                 deathAnim = BOTH_DEATH4;//back: forward
01591                                         }
01592                                         else if ( !Q_irand( 0, 1 ) )
01593                                         {
01594                                                 deathAnim = BOTH_DEATH5;//same as 4
01595                                         }
01596                                         else
01597                                         {
01598                                                 deathAnim = BOTH_DEATH15;//back: forward
01599                                         }
01600                                 }
01601                                 break;
01602                         case HL_CHEST_RT:
01603                         case HL_ARM_RT:
01604                         case HL_HAND_RT:
01605                         case HL_BACK_RT:
01606                                 if ( damage <= max_health*0.25 )
01607                                 {
01608                                         deathAnim = BOTH_DEATH9;//chest right: snap, fall forward
01609                                 }
01610                                 else if ( damage <= max_health*0.5 )
01611                                 {
01612                                         deathAnim = BOTH_DEATH3;//chest right: back
01613                                 }
01614                                 else if ( damage <= max_health*0.75 )
01615                                 {
01616                                         deathAnim = BOTH_DEATH6;//chest right: spin
01617                                 }
01618                                 else 
01619                                 {
01620                                         //TEMP HACK: play spinny deaths less often
01621                                         if ( Q_irand( 0, 1 ) )
01622                                         {
01623                                                 deathAnim = BOTH_DEATH8;//chest right: spin high
01624                                         }
01625                                         else
01626                                         {
01627                                                 switch ( Q_irand( 0, 2 ) )
01628                                                 {
01629                                                 default:
01630                                                 case 0:
01631                                                         deathAnim = BOTH_DEATH9;//chest right: snap, fall forward
01632                                                         break;
01633                                                 case 1:
01634                                                         deathAnim = BOTH_DEATH3;//chest right: back
01635                                                         break;
01636                                                 case 2:
01637                                                         deathAnim = BOTH_DEATH6;//chest right: spin
01638                                                         break;
01639                                                 }
01640                                         }
01641                                 }
01642                                 break;
01643                         case HL_CHEST_LT:
01644                         case HL_ARM_LT:
01645                         case HL_HAND_LT:
01646                         case HL_BACK_LT:
01647                                 if ( damage <= max_health*0.25 )
01648                                 {
01649                                         deathAnim = BOTH_DEATH11;//chest left: snap, fall forward
01650                                 }
01651                                 else if ( damage <= max_health*0.5 )
01652                                 {
01653                                         deathAnim = BOTH_DEATH7;//chest left: back
01654                                 }
01655                                 else if ( damage <= max_health*0.75 )
01656                                 {
01657                                         deathAnim = BOTH_DEATH12;//chest left: spin
01658                                 }
01659                                 else
01660                                 {
01661                                         //TEMP HACK: play spinny deaths less often
01662                                         if ( Q_irand( 0, 1 ) )
01663                                         {
01664                                                 deathAnim = BOTH_DEATH14;//chest left: spin high
01665                                         }
01666                                         else
01667                                         {
01668                                                 switch ( Q_irand( 0, 2 ) )
01669                                                 {
01670                                                 default:
01671                                                 case 0:
01672                                                         deathAnim = BOTH_DEATH11;//chest left: snap, fall forward
01673                                                         break;
01674                                                 case 1:
01675                                                         deathAnim = BOTH_DEATH7;//chest left: back
01676                                                         break;
01677                                                 case 2:
01678                                                         deathAnim = BOTH_DEATH12;//chest left: spin
01679                                                         break;
01680                                                 }
01681                                         }
01682                                 }
01683                                 break;
01684                         case HL_CHEST:
01685                         case HL_WAIST:
01686                                 if ( damage <= max_health*0.25 || !VectorLengthSquared( objVelocity ) )
01687                                 {
01688                                         if ( !Q_irand( 0, 1 ) )
01689                                         {
01690                                                 deathAnim = BOTH_DEATH18;//gut: fall right
01691                                         }
01692                                         else
01693                                         {
01694                                                 deathAnim = BOTH_DEATH19;//gut: fall left
01695                                         }
01696                                 }
01697                                 else if ( damage <= max_health*0.5 )
01698                                 {
01699                                         deathAnim = BOTH_DEATH2;//chest: backward short
01700                                 }
01701                                 else if ( damage <= max_health*0.75 )
01702                                 {
01703                                         if ( !Q_irand( 0, 1 ) )
01704                                         {
01705                                                 deathAnim = BOTH_DEATH1;//chest: backward med
01706                                         }
01707                                         else
01708                                         {
01709                                                 deathAnim = BOTH_DEATH16;//same as 1
01710                                         }
01711                                 }
01712                                 else
01713                                 {
01714                                         deathAnim = BOTH_DEATH10;//chest: back flip
01715                                 }
01716                                 break;
01717                         case HL_HEAD:
01718                                 if ( damage <= max_health*0.5 )
01719                                 {
01720                                         deathAnim = BOTH_DEATH17;//head/back: croak
01721                                 }
01722                                 else
01723                                 {
01724                                         deathAnim = BOTH_DEATH13;//head: stumble, fall back
01725                                 }
01726                                 break;
01727                         default:
01728                                 break;
01729                         }
01730                 }
01731         }
01732 
01733         // Validate.....
01734         if ( deathAnim == -1 || !BG_HasAnimation( self->localAnimIndex, deathAnim ))
01735         {
01736                 // I guess we'll take what we can get.....
01737                 deathAnim = BG_PickAnim( self->localAnimIndex, BOTH_DEATH1, BOTH_DEATH25 );
01738         }
01739 
01740         return deathAnim;
01741 }

qboolean G_RadiusDamage vec3_t  origin,
gentity_t attacker,
float  damage,
float  radius,
gentity_t ignore,
gentity_t missile,
int  mod
 

Definition at line 5565 of file g_combat.c.

References entityShared_t::absmax, entityShared_t::absmin, CanDamage(), CLASS_VEHICLE, gentity_s::client, entityShared_t::currentOrigin, DAMAGE_RADIUS, ET_NPC, entityState_s::eType, EV_GHOUL2_MARK, entityState_s::eventParm, G_Damage(), g_entities, G_TempEntity(), gentity_t, gentity_s::inuse, LogAccuracyHit(), Vehicle_s::m_pPilot, gentity_s::m_pVehicle, MAX_GENTITIES, entityState_s::NPC_class, NULL, entityState_s::number, entityState_s::origin, entityState_s::origin2, entityState_s::otherEntityNum, qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, gentity_s::takedamage, trap_EntitiesInBox(), vec3_t, VectorCopy, VectorSubtract, entityState_s::weapon, and WP_ROCKET_LAUNCHER.

Referenced by auto_turret_die(), charge_stick(), DetPackBlow(), Do_Strike(), emplaced_gun_update(), EWebDie(), ExplodeDeath(), funcBBrushDieGo(), fx_runner_think(), G_ExplodeMissile(), G_MissileImpact(), laserTrapExplode(), thermalDetonatorExplode(), turret_die(), and turretG2_die().

05566                                                                                          {
05567         float           points, dist;
05568         gentity_t       *ent;
05569         int                     entityList[MAX_GENTITIES];
05570         int                     numListedEntities;
05571         vec3_t          mins, maxs;
05572         vec3_t          v;
05573         vec3_t          dir;
05574         int                     i, e;
05575         qboolean        hitClient = qfalse;
05576         qboolean        roastPeople = qfalse;
05577 
05578         /*
05579         if (missile && !missile->client && missile->s.weapon > WP_NONE &&
05580                 missile->s.weapon < WP_NUM_WEAPONS && missile->r.ownerNum >= 0 &&
05581                 (missile->r.ownerNum < MAX_CLIENTS || g_entities[missile->r.ownerNum].s.eType == ET_NPC))
05582         { //sounds like it's a valid weapon projectile.. is it a valid explosive to create marks from?
05583                 switch(missile->s.weapon)
05584                 {
05585                 case WP_FLECHETTE: //flechette issuing this will be alt-fire
05586                 case WP_ROCKET_LAUNCHER:
05587                 case WP_THERMAL:
05588                 case WP_TRIP_MINE:
05589                 case WP_DET_PACK:
05590                         roastPeople = qtrue; //Then create explosive marks
05591                         break;
05592                 default:
05593                         break;
05594                 }
05595         }
05596         */
05597         //oh well.. maybe sometime? I am trying to cut down on tempent use.
05598 
05599         if ( radius < 1 ) {
05600                 radius = 1;
05601         }
05602 
05603         for ( i = 0 ; i < 3 ; i++ ) {
05604                 mins[i] = origin[i] - radius;
05605                 maxs[i] = origin[i] + radius;
05606         }
05607 
05608         numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
05609 
05610         for ( e = 0 ; e < numListedEntities ; e++ ) {
05611                 ent = &g_entities[entityList[ e ]];
05612 
05613                 if (ent == ignore)
05614                         continue;
05615                 if (!ent->takedamage)
05616                         continue;
05617 
05618                 // find the distance from the edge of the bounding box
05619                 for ( i = 0 ; i < 3 ; i++ ) {
05620                         if ( origin[i] < ent->r.absmin[i] ) {
05621                                 v[i] = ent->r.absmin[i] - origin[i];
05622                         } else if ( origin[i] > ent->r.absmax[i] ) {
05623                                 v[i] = origin[i] - ent->r.absmax[i];
05624                         } else {
05625                                 v[i] = 0;
05626                         }
05627                 }
05628 
05629                 dist = VectorLength( v );
05630                 if ( dist >= radius ) {
05631                         continue;
05632                 }
05633 
05634                 points = damage * ( 1.0 - dist / radius );
05635 
05636                 if( CanDamage (ent, origin) ) {
05637                         if( LogAccuracyHit( ent, attacker ) ) {
05638                                 hitClient = qtrue;
05639                         }
05640                         VectorSubtract (ent->r.currentOrigin, origin, dir);
05641                         // push the center of mass higher than the origin so players
05642                         // get knocked into the air more
05643                         dir[2] += 24;
05644                         if (attacker && attacker->inuse && attacker->client &&
05645                                 attacker->s.eType == ET_NPC && attacker->s.NPC_class == CLASS_VEHICLE &&
05646                                 attacker->m_pVehicle && attacker->m_pVehicle->m_pPilot)
05647                         { //say my pilot did it.
05648                                 G_Damage (ent, NULL, (gentity_t *)attacker->m_pVehicle->m_pPilot, dir, origin, (int)points, DAMAGE_RADIUS, mod);
05649                         }
05650                         else
05651                         {
05652                                 G_Damage (ent, NULL, attacker, dir, origin, (int)points, DAMAGE_RADIUS, mod);
05653                         }
05654 
05655                         if (ent && ent->client && roastPeople && missile &&
05656                                 !VectorCompare(ent->r.currentOrigin, missile->r.currentOrigin))
05657                         { //the thing calling this function can create burn marks on people, so create an event to do so
05658                                 gentity_t *evEnt = G_TempEntity(ent->r.currentOrigin, EV_GHOUL2_MARK);
05659 
05660                                 evEnt->s.otherEntityNum = ent->s.number; //the entity the mark should be placed on
05661                                 evEnt->s.weapon = WP_ROCKET_LAUNCHER; //always say it's rocket so we make the right mark
05662 
05663                                 //Try to place the decal by going from the missile location to the location of the person that was hit
05664                                 VectorCopy(missile->r.currentOrigin, evEnt->s.origin);
05665                                 VectorCopy(ent->r.currentOrigin, evEnt->s.origin2);
05666 
05667                                 //it's hacky, but we want to move it up so it's more likely to hit
05668                                 //the torso.
05669                                 if (missile->r.currentOrigin[2] < ent->r.currentOrigin[2])
05670                                 { //move it up less so the decal is placed lower on the model then
05671                                         evEnt->s.origin2[2] += 8;
05672                                 }
05673                                 else
05674                                 {
05675                                         evEnt->s.origin2[2] += 24;
05676                                 }
05677 
05678                                 //Special col check
05679                                 evEnt->s.eventParm = 1;
05680                         }
05681                 }
05682         }
05683 
05684         return hitClient;
05685 }

int G_ShipSurfaceForSurfName const char *  surfaceName  ) 
 

Referenced by G_Damage().

qboolean G_ThereIsAMaster void   ) 
 

Definition at line 4307 of file g_combat.c.

References gentity_s::client, g_entities, gentity_t, playerState_s::isJediMaster, MAX_CLIENTS, gclient_s::ps, qboolean, qfalse, and qtrue.

Referenced by G_Damage(), and ScanForEnemies().

04308 {
04309         int i = 0;
04310         gentity_t *ent;
04311 
04312         while (i < MAX_CLIENTS)
04313         {
04314                 ent = &g_entities[i];
04315 
04316                 if (ent && ent->client && ent->client->ps.isJediMaster)
04317                 {
04318                         return qtrue;
04319                 }
04320 
04321                 i++;
04322         }
04323 
04324         return qfalse;
04325 }

void G_VehicleSetDamageLocFlags gentity_t veh,
int  impactDir,
int  deathPoint
 

Referenced by G_Damage().

void G_VehUpdateShields gentity_t targ  ) 
 

Referenced by G_Damage(), and Initialize().

void GibEntity gentity_t self,
int  killer
 

Definition at line 667 of file g_combat.c.

References entityShared_t::contents, ET_INVISIBLE, entityState_s::eType, EV_GIB_PLAYER, G_AddEvent(), gentity_t, qfalse, gentity_s::r, gentity_s::s, and gentity_s::takedamage.

00667                                               {
00668         G_AddEvent( self, EV_GIB_PLAYER, killer );
00669         self->takedamage = qfalse;
00670         self->s.eType = ET_INVISIBLE;
00671         self->r.contents = 0;
00672 }

qboolean Jedi_WaitingAmbush gentity_t self  ) 
 

Definition at line 5561 of file NPC_AI_Jedi.c.

References gentity_s::client, gentity_t, JSF_AMBUSH, gclient_s::noclip, qboolean, qfalse, qtrue, and gentity_s::spawnflags.

05562 {
05563         if ( (self->spawnflags&JSF_AMBUSH) && self->client->noclip )
05564         {
05565                 return qtrue;
05566         }
05567         return qfalse;
05568 }

void LimbThink gentity_t ent  ) 
 

Definition at line 3266 of file g_combat.c.

References G2_MODELPART_HEAD, G2_MODELPART_LARM, G2_MODELPART_LLEG, G2_MODELPART_RARM, G2_MODELPART_RHAND, G2_MODELPART_RLEG, G2_MODELPART_WAIST, G_FreeEntity(), G_RunExPhys(), gentity_s::genericValue5, gentity_t, level, entityState_s::modelGhoul2, gentity_s::nextthink, NULL, qtrue, gentity_s::s, gentity_s::speed, gentity_s::think, and level_locals_t::time.

Referenced by G_Dismember().

03267 {
03268         float gravity = 3.0f;
03269         float mass = 0.09f;
03270         float bounce = 1.3f;
03271 
03272         switch (ent->s.modelGhoul2)
03273         {
03274         case G2_MODELPART_HEAD:
03275                 mass = 0.08f;
03276                 bounce = 1.4f;
03277                 break;
03278         case G2_MODELPART_WAIST:
03279                 mass = 0.1f;
03280                 bounce = 1.2f;
03281                 break;
03282         case G2_MODELPART_LARM:
03283         case G2_MODELPART_RARM:
03284         case G2_MODELPART_RHAND:
03285         case G2_MODELPART_LLEG:
03286         case G2_MODELPART_RLEG:
03287         default:
03288                 break;
03289         }
03290 
03291         if (ent->speed < level.time)
03292         {
03293                 ent->think = G_FreeEntity;
03294                 ent->nextthink = level.time;
03295                 return;
03296         }
03297 
03298         if (ent->genericValue5 <= level.time)
03299         { //this will be every frame by standard, but we want to compensate in case sv_fps is not 20.
03300                 G_RunExPhys(ent, gravity, mass, bounce, qtrue, NULL, 0);
03301                 ent->genericValue5 = level.time + 50;
03302         }
03303 
03304         ent->nextthink = level.time;
03305 }

void LimbTouch gentity_t self,
gentity_t other,
trace_t trace
 

Definition at line 3262 of file g_combat.c.

References gentity_t.

Referenced by G_Dismember().

03263 {
03264 }

void LookAtKiller gentity_t self,
gentity_t inflictor,
gentity_t attacker
 

Definition at line 642 of file g_combat.c.

References entityState_s::angles, gentity_s::client, gentity_t, PITCH, entityState_s::pos, gclient_s::ps, ROLL, gentity_s::s, STAT_DEAD_YAW, playerState_s::stats, trajectory_t::trBase, vec3_t, VectorSubtract, vectoyaw(), and YAW.

00642                                                                                 {
00643         vec3_t          dir;
00644         vec3_t          angles;
00645 
00646         if ( attacker && attacker != self ) {
00647                 VectorSubtract (attacker->s.pos.trBase, self->s.pos.trBase, dir);
00648         } else if ( inflictor && inflictor != self ) {
00649                 VectorSubtract (inflictor->s.pos.trBase, self->s.pos.trBase, dir);
00650         } else {
00651                 self->client->ps.stats[STAT_DEAD_YAW] = self->s.angles[YAW];
00652                 return;
00653         }
00654 
00655         self->client->ps.stats[STAT_DEAD_YAW] = vectoyaw ( dir );
00656 
00657         angles[YAW] = vectoyaw ( dir );
00658         angles[PITCH] = 0; 
00659         angles[ROLL] = 0;
00660 }

void ObjectDie gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  meansOfDeath
 

Definition at line 21 of file g_combat.c.

References G_FreeEntity(), G_UseTargets(), gentity_t, and gentity_s::target.

Referenced by auto_turret_die(), ExplodeDeath(), and turretG2_die().

00022 {
00023         if(self->target)
00024         {
00025                 G_UseTargets(self, attacker);
00026         }
00027 
00028         //remove my script_targetname
00029         G_FreeEntity( self );
00030 }

void player_die gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  meansOfDeath
 

Definition at line 2073 of file g_combat.c.

References gentity_s::activator, AddScore(), AI_DeleteSelfFromGroup(), AI_GroupMemberKilled(), AngleVectors(), animTable, gclient_s::beingThrown, BG_ClearRocketLock(), bgEntity_t, BlowDetpacks(), Boba_FlyStop(), body_die(), gclient_s::bodyGrabIndex, gclient_s::bodyGrabTime, BSET_DEATH, BSET_FFDEATH, CARNAGE_REWARD_TIME, CHAN_AUTO, CHAN_WEAPON, CheckAlmostCapture(), CheckExitRules(), CLASS_MARK1, CLASS_R2D2, CLASS_R5D2, CLASS_RANCOR, CLASS_VEHICLE, gentity_s::client, client, level_locals_t::clients, Cmd_Score_f(), gNPC_t::combatPoint, CON_CONNECTED, clientPersistant_t::connected, entityShared_t::contents, CONTENTS_CORPSE, CONTENTS_NODROP, entityShared_t::currentAngles, entityShared_t::currentOrigin, DAMAGE_NO_PROTECTION, DeathFX(), gentity_s::die, gclient_s::doingThrow, clientSession_t::duelTeam, DUELTEAM_DOUBLE, DUELTEAM_LONE, EF2_SHIP_DEATH, playerState_s::eFlags2, vehicleInfo_t::Eject, playerState_s::emplacedIndex, AIGroupInfo_s::enemy, gentity_s::enemy, ENTITYNUM_NONE, ENTITYNUM_WORLD, ET_NPC, entityState_s::eType, EV_DEATH1, EV_OBITUARY, entityState_s::eventParm, vehicleInfo_t::explosionDelay, playerState_s::fallingToDeath, playerState_s::fd, FL_UNDYING, gentity_s::flags, forcedata_s::forceDeactivateAll, G_ActivateBehavior(), G_AddEvent(), G_AddPowerDuelLoserScore(), G_AddPowerDuelScore(), g_austrian, G_BreakArm(), G_CheckForDismemberment(), G_CheckVictoryScript(), G_Damage(), G_DeathAlert(), g_dontFrickinCheck, G_EffectIndex(), g_endPDuel, g_entities, G_FreeEntity(), g_gametype, G_GetJediMaster(), G_HeavyMelee(), G_LogPrintf(), G_LogWeaponDeath(), G_LogWeaponFrag(), G_LogWeaponKill(), G_MuteSound(), g_noPDuelCheck, G_PickDeathAnim(), G_PlayEffectID(), G_SetAnim(), G_SetOrigin(), g_slowmoDuelEnd, G_Sound(), G_TempEntity(), G_UpdateClientAnims(), G_UseTargets(), G_UseTargets2(), gclient_t, gDoSlowMoDuel, gentity_t, gentity_s::ghoul2, GIB_HEALTH, gNPC_t::group, gSlowMoDuelTime, GT_DUEL, GT_JEDIMASTER, GT_POWERDUEL, playerState_s::hackingTime, gentity_s::health, playerState_s::heldByClient, vehicleInfo_t::hideRider, HL_NONE, gclient_s::holdingObjectiveItem, gclient_s::iAmALoser, gclient_s::inSpaceIndex, vmCvar_t::integer, level_locals_t::intermissiontime, gentity_s::inuse, gclient_s::isHacking, playerState_s::isJediMaster, entityState_s::isJediMaster, Jedi_WaitingAmbush(), Jetpack_Off(), gclient_s::lastkilled_client, gclient_s::lastKillTime, level, entityState_s::loopIsSoundset, entityState_s::loopSound, Vehicle_s::m_iNumPassengers, playerState_s::m_iVehicleNum, Vehicle_s::m_pDroidUnit, Vehicle_s::m_pPilot, Vehicle_s::m_ppPassengers, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, MAX_CLIENTS, level_locals_t::maxclients, entityShared_t::maxs, memset(), MOD_BLASTER, MOD_CRUSH, MOD_FALLING, MOD_MELEE, MOD_SABER, MOD_STUN_BATON, MOD_SUICIDE, MOD_TEAM_CHANGE, MOD_TRIGGER_HURT, MOD_UNKNOWN, saberInfo_t::model, modNames, stringID_table_s::name, clientPersistant_t::netname, gNPC_t::nextBStateThink, gentity_s::nextthink, gclient_s::noclip, gclient_s::noCorpse, gentity_s::NPC, entityState_s::NPC_class, gclient_s::NPC_class, NPC_FreeCombatPoint(), NULL, entityState_s::number, level_locals_t::numPlayingClients, OnSameTeam(), playerState_s::origin, entityState_s::otherEntityNum, entityState_s::otherEntityNum2, playerState_s::otherKiller, playerState_s::otherKillerTime, gclient_s::pers, PERS_EXCELLENT_COUNT, PERS_GAUNTLET_FRAG_COUNT, PERS_HITS, PERS_KILLED, PERS_PLAYEREVENTS, playerState_s::persistant, PLAYEREVENT_GAUNTLETREWARD, PM_DEAD, playerState_s::pm_flags, PM_NORMAL, playerState_s::pm_type, PMF_STUCK_TO_WALL, gentity_s::pos1, playerState_s::powerups, entityState_s::powerups, gclient_s::ps, PW_BLUEFLAG, PW_NEUTRALFLAG, PW_REDFLAG, qboolean, qfalse, qtrue, gentity_s::r, Rancor_DropVictim(), gclient_s::respawnTime, REWARD_SPRITE_TIME, gclient_s::rewardTime, gentity_s::s, bgEntity_s::s, gclient_s::saber, forcedata_s::saberAnimLevel, playerState_s::saberEntityNum, playerState_s::saberHolstered, playerState_s::saberInFlight, gclient_s::saberStoredIndex, SCF_FFDEATH, gNPC_t::scriptFlags, gclient_s::sess, clientSession_t::sessionTeam, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, SETANIM_FLAG_RESTART, level_locals_t::sortedClients, saberInfo_t::soundOff, clientSession_t::spectatorClient, STAT_HEALTH, playerState_s::stats, forcedata_s::suicides, SVF_BROADCAST, entityShared_t::svFlags, gentity_s::takedamage, gentity_s::target4, TEAM_BLUE, Team_FragBonuses(), TEAM_FREE, TEAM_RED, Team_ReturnFlag(), TEAM_SPECTATOR, gNPC_t::tempGoal, gentity_s::think, ThrowSaberToAttacker(), level_locals_t::time, gNPC_t::timeOfDeath, TIMER_Clear2(), playerState_s::torsoAnim, TossClientItems(), trap_G2API_GetSurfaceRenderStatus(), trap_LinkEntity(), trap_PointContents(), vehicleInfo_t::type, vec3_t, VectorCopy, VH_FIGHTER, playerState_s::weapon, entityState_s::weapon, WP_NONE, WP_SABER, WP_TURRET, and playerState_s::zoomMode.

Referenced by ClientCommand(), ClientSpawn(), Cmd_Kill_f(), Cmd_SiegeClass_f(), G_ResetDuelists(), NPC_Begin(), and SetTeam().

02073                                                                                                             {
02074         gentity_t       *ent;
02075         int                     anim;
02076         int                     contents;
02077         int                     killer;
02078         int                     i;
02079         char            *killerName, *obit;
02080         qboolean        wasJediMaster = qfalse;
02081         int                     sPMType = 0;
02082 
02083         if ( self->client->ps.pm_type == PM_DEAD ) {
02084                 return;
02085         }
02086 
02087         if ( level.intermissiontime ) {
02088                 return;
02089         }
02090 
02091         //check player stuff
02092         g_dontFrickinCheck = qfalse;
02093 
02094         if (g_gametype.integer == GT_POWERDUEL)
02095         { //don't want to wait til later in the frame if this is the case
02096                 CheckExitRules();
02097 
02098                 if ( level.intermissiontime )
02099                 {
02100                         return;
02101                 }
02102         }
02103 
02104         if (self->s.eType == ET_NPC &&
02105                 self->s.NPC_class == CLASS_VEHICLE &&
02106                 self->m_pVehicle &&
02107                 !self->m_pVehicle->m_pVehicleInfo->explosionDelay &&
02108                 (self->m_pVehicle->m_pPilot || self->m_pVehicle->m_iNumPassengers > 0 || self->m_pVehicle->m_pDroidUnit))
02109         { //kill everyone on board in the name of the attacker... if the vehicle has no death delay
02110                 gentity_t *murderer = NULL;
02111                 gentity_t *killEnt;
02112                 int i = 0;
02113 
02114                 if (self->client->ps.otherKillerTime >= level.time)
02115                 { //use the last attacker
02116                         murderer = &g_entities[self->client->ps.otherKiller];
02117                         if (!murderer->inuse || !murderer->client)
02118                         {
02119                                 murderer = NULL;
02120                         }
02121                         else
02122                         {
02123                                 if (murderer->s.number >= MAX_CLIENTS &&
02124                                         murderer->s.eType == ET_NPC &&
02125                                         murderer->s.NPC_class == CLASS_VEHICLE &&
02126                                         murderer->m_pVehicle &&
02127                                         murderer->m_pVehicle->m_pPilot)
02128                                 {
02129                                         gentity_t *murderPilot = &g_entities[murderer->m_pVehicle->m_pPilot->s.number];
02130                                         if (murderPilot->inuse && murderPilot->client)
02131                                         { //give the pilot of the offending vehicle credit for the kill
02132                                                 murderer = murderPilot;
02133                                         }
02134                                 }
02135                         }
02136                 }
02137                 else if (attacker && attacker->inuse && attacker->client)
02138                 {
02139                         if (attacker->s.number >= MAX_CLIENTS &&
02140                                 attacker->s.eType == ET_NPC &&
02141                                 attacker->s.NPC_class == CLASS_VEHICLE &&
02142                                 attacker->m_pVehicle &&
02143                                 attacker->m_pVehicle->m_pPilot)
02144                         { //set vehicles pilot's killer as murderer
02145                                 murderer = &g_entities[attacker->m_pVehicle->m_pPilot->s.number];
02146                                 if (murderer->inuse && murderer->client &&murderer->client->ps.otherKillerTime >= level.time)
02147                                 {
02148                                         murderer = &g_entities[murderer->client->ps.otherKiller];
02149                                         if (!murderer->inuse || !murderer->client)
02150                                         {
02151                                                 murderer = NULL;
02152                                         }
02153                                 }
02154                                 else
02155                                 {
02156                                         murderer = NULL;
02157                                 }
02158                         }
02159                         else
02160                         {
02161                                 murderer = &g_entities[attacker->s.number];
02162                         }
02163                 }
02164                 else if (self->m_pVehicle->m_pPilot)
02165                 {
02166                         murderer = (gentity_t *)self->m_pVehicle->m_pPilot;
02167                         if (!murderer->inuse || !murderer->client)
02168                         {
02169                                 murderer = NULL;
02170                         }
02171                 }
02172 
02173                 //no valid murderer.. just use self I guess
02174                 if (!murderer)
02175                 {
02176                         murderer = self;
02177                 }
02178 
02179                 if ( self->m_pVehicle->m_pVehicleInfo->hideRider )
02180                 {//pilot is *inside* me, so kill him, too
02181                         killEnt = (gentity_t *)self->m_pVehicle->m_pPilot;
02182                         if (killEnt && killEnt->inuse && killEnt->client)
02183                         {
02184                                 G_Damage(killEnt, murderer, murderer, NULL, killEnt->client->ps.origin, 99999, DAMAGE_NO_PROTECTION, MOD_BLASTER);
02185                         }
02186                         if ( self->m_pVehicle->m_pVehicleInfo )
02187                         {//FIXME: this wile got stuck in an endless loop, that's BAD!!  This method SUCKS (not initting "i", not incrementing it or using it directly, all sorts of badness), so I'm rewriting it
02188                                 //while (i < self->m_pVehicle->m_iNumPassengers)
02189                                 int numPass = self->m_pVehicle->m_iNumPassengers;
02190                                 for ( i = 0; i < numPass && self->m_pVehicle->m_iNumPassengers; i++ )
02191                                 {//go through and eject the last passenger
02192                                         killEnt = (gentity_t *)self->m_pVehicle->m_ppPassengers[self->m_pVehicle->m_iNumPassengers-1];
02193                                         if ( killEnt )
02194                                         {
02195                                                 self->m_pVehicle->m_pVehicleInfo->Eject(self->m_pVehicle, (bgEntity_t *)killEnt, qtrue);
02196                                                 if ( killEnt->inuse && killEnt->client )
02197                                                 {
02198                                                         G_Damage(killEnt, murderer, murderer, NULL, killEnt->client->ps.origin, 99999, DAMAGE_NO_PROTECTION, MOD_BLASTER);
02199                                                 }
02200                                         }
02201                                 }
02202                         }
02203                 }
02204                 killEnt = (gentity_t *)self->m_pVehicle->m_pDroidUnit;
02205                 if (killEnt && killEnt->inuse && killEnt->client)
02206                 {
02207                         killEnt->flags &= ~FL_UNDYING;
02208                         G_Damage(killEnt, murderer, murderer, NULL, killEnt->client->ps.origin, 99999, DAMAGE_NO_PROTECTION, MOD_BLASTER);
02209                 }
02210         }
02211 
02212         self->client->ps.emplacedIndex = 0;
02213 
02214         G_BreakArm(self, 0); //unbreak anything we have broken
02215         self->client->ps.saberEntityNum = self->client->saberStoredIndex; //in case we died while our saber was knocked away.
02216 
02217         self->client->bodyGrabIndex = ENTITYNUM_NONE;
02218         self->client->bodyGrabTime = 0;
02219 
02220         if (self->client->holdingObjectiveItem > 0)
02221         { //carrying a siege objective item - make sure it updates and removes itself from us now in case this is an instant death-respawn situation
02222                 gentity_t *objectiveItem = &g_entities[self->client->holdingObjectiveItem];
02223 
02224                 if (objectiveItem->inuse && objectiveItem->think)
02225                 {
02226             objectiveItem->think(objectiveItem);
02227                 }
02228         }
02229 
02230         if ( (self->client->inSpaceIndex && self->client->inSpaceIndex != ENTITYNUM_NONE) ||
02231                  (self->client->ps.eFlags2 & EF2_SHIP_DEATH) )
02232         {
02233                 self->client->noCorpse = qtrue;
02234         }
02235 
02236         if ( self->client->NPC_class != CLASS_VEHICLE
02237                 && self->client->ps.m_iVehicleNum )
02238         { //I'm riding a vehicle
02239                 //tell it I'm getting off
02240                 gentity_t *veh = &g_entities[self->client->ps.m_iVehicleNum];
02241 
02242                 if (veh->inuse && veh->client && veh->m_pVehicle)
02243                 {
02244                         veh->m_pVehicle->m_pVehicleInfo->Eject(veh->m_pVehicle, (bgEntity_t *)self, qtrue);
02245 
02246                         if (veh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER)
02247                         { //go into "die in ship" mode with flag
02248                                 self->client->ps.eFlags2 |= EF2_SHIP_DEATH;
02249 
02250                                 //put me over where my vehicle exploded
02251                                 G_SetOrigin(self, veh->client->ps.origin);
02252                                 VectorCopy(veh->client->ps.origin, self->client->ps.origin);
02253                         }
02254                 }
02255                 //droids throw heads if they haven't yet
02256                 switch(self->client->NPC_class)
02257                 {
02258                 case CLASS_R2D2:
02259                         if ( !trap_G2API_GetSurfaceRenderStatus( self->ghoul2, 0, "head" ) )
02260                         {
02261                                 vec3_t  up;
02262                                 AngleVectors( self->r.currentAngles, NULL, NULL, up );
02263                                 G_PlayEffectID( G_EffectIndex("chunks/r2d2head_veh"), self->r.currentOrigin, up );
02264                         }
02265                         break;
02266 
02267                 case CLASS_R5D2:
02268                         if ( !trap_G2API_GetSurfaceRenderStatus( self->ghoul2, 0, "head" ) )
02269                         {
02270                                 vec3_t  up;
02271                                 AngleVectors( self->r.currentAngles, NULL, NULL, up );
02272                                 G_PlayEffectID( G_EffectIndex("chunks/r5d2head_veh"), self->r.currentOrigin, up );
02273                         }
02274                         break;
02275                 }
02276         }
02277 
02278         if ( self->NPC )
02279         {
02280                 if ( self->client && Jedi_WaitingAmbush( self ) )
02281                 {//ambushing trooper
02282                         self->client->noclip = qfalse;
02283                 }
02284                 NPC_FreeCombatPoint( self->NPC->combatPoint, qfalse );
02285                 if ( self->NPC->group )
02286                 {
02287                         //lastInGroup = (self->NPC->group->numGroup < 2);
02288                         AI_GroupMemberKilled( self );
02289                         AI_DeleteSelfFromGroup( self );
02290                 }
02291 
02292                 if ( self->NPC->tempGoal )
02293                 {
02294                         G_FreeEntity( self->NPC->tempGoal );
02295                         self->NPC->tempGoal = NULL;
02296                 }
02297                 /*
02298                 if ( self->s.eFlags & EF_LOCKED_TO_WEAPON )
02299                 {
02300                         // dumb, just get the NPC out of the chair
02301 extern void RunEmplacedWeapon( gentity_t *ent, usercmd_t **ucmd );
02302 
02303                         usercmd_t cmd, *ad_cmd;
02304 
02305                         memset( &cmd, 0, sizeof( usercmd_t ));
02306 
02307                         //gentity_t *old = self->owner;
02308 
02309                         if ( self->owner )
02310                         {
02311                                 self->owner->s.frame = self->owner->startFrame = self->owner->endFrame = 0;
02312                                 self->owner->svFlags &= ~SVF_ANIMATING;
02313                         }
02314 
02315                         cmd.buttons |= BUTTON_USE;
02316                         ad_cmd = &cmd;
02317                         RunEmplacedWeapon( self, &ad_cmd );
02318                         //self->owner = old;
02319                 }
02320                 */
02321                 //if ( self->client->NPC_class == CLASS_BOBAFETT && self->client->moveType == MT_FLYSWIM )
02322                 if (0)
02323                 {
02324                         Boba_FlyStop( self );
02325                 }
02326                 if ( self->s.NPC_class == CLASS_RANCOR )
02327                 {
02328                         Rancor_DropVictim( self );
02329                 }
02330         }
02331         if ( attacker && attacker->NPC && attacker->NPC->group && attacker->NPC->group->enemy == self )
02332         {
02333                 attacker->NPC->group->enemy = NULL;
02334         }
02335 
02336         //Cheap method until/if I decide to put fancier stuff in (e.g. sabers falling out of hand and slowly
02337         //holstering on death like sp)
02338         if (self->client->ps.weapon == WP_SABER &&
02339                 !self->client->ps.saberHolstered &&
02340                 self->client->ps.saberEntityNum)
02341         {
02342                 if (!self->client->ps.saberInFlight &&
02343                         self->client->saber[0].soundOff)
02344                 {
02345                         G_Sound(self, CHAN_AUTO, self->client->saber[0].soundOff);
02346                 }
02347                 if (self->client->saber[1].soundOff &&
02348                         self->client->saber[1].model[0])
02349                 {
02350                         G_Sound(self, CHAN_AUTO, self->client->saber[1].soundOff);
02351                 }
02352         }
02353 
02354         //Use any target we had
02355         G_UseTargets( self, self );
02356 
02357         if (g_slowmoDuelEnd.integer && (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) && attacker && attacker->inuse && attacker->client)
02358         {
02359                 if (!gDoSlowMoDuel)
02360                 {
02361                         gDoSlowMoDuel = qtrue;
02362                         gSlowMoDuelTime = level.time;
02363                 }
02364         }
02365         /*
02366         else if (self->NPC && attacker && attacker->client && attacker->s.number < MAX_CLIENTS && !gDoSlowMoDuel)
02367         {
02368                 gDoSlowMoDuel = qtrue;
02369                 gSlowMoDuelTime = level.time;
02370         }
02371         */
02372 
02373         //Make sure the jetpack is turned off.
02374         Jetpack_Off(self);
02375 
02376         self->client->ps.heldByClient = 0;
02377         self->client->beingThrown = 0;
02378         self->client->doingThrow = 0;
02379         BG_ClearRocketLock( &self->client->ps );
02380         self->client->isHacking = 0;
02381         self->client->ps.hackingTime = 0;
02382 
02383         if (inflictor && inflictor->activator && !inflictor->client && !attacker->client &&
02384                 inflictor->activator->client && inflictor->activator->inuse &&
02385                 inflictor->s.weapon == WP_TURRET)
02386         {
02387                 attacker = inflictor->activator;
02388         }
02389 
02390         if (self->client && self->client->ps.isJediMaster)
02391         {
02392                 wasJediMaster = qtrue;
02393         }
02394 
02395         //if he was charging or anything else, kill the sound
02396         G_MuteSound(self->s.number, CHAN_WEAPON);
02397 
02398         BlowDetpacks(self); //blow detpacks if they're planted
02399 
02400         self->client->ps.fd.forceDeactivateAll = 1;
02401 
02402         if ((self == attacker || !attacker->client) &&
02403                 (meansOfDeath == MOD_CRUSH || meansOfDeath == MOD_FALLING || meansOfDeath == MOD_TRIGGER_HURT || meansOfDeath == MOD_UNKNOWN) &&
02404                 self->client->ps.otherKillerTime > level.time)
02405         {
02406                 attacker = &g_entities[self->client->ps.otherKiller];
02407         }
02408 
02409         // check for an almost capture
02410         CheckAlmostCapture( self, attacker );
02411 
02412         self->client->ps.pm_type = PM_DEAD;
02413         self->client->ps.pm_flags &= ~PMF_STUCK_TO_WALL;
02414 
02415         if ( attacker ) {
02416                 killer = attacker->s.number;
02417                 if ( attacker->client ) {
02418                         killerName = attacker->client->pers.netname;
02419                 } else {
02420                         killerName = "<non-client>";
02421                 }
02422         } else {
02423                 killer = ENTITYNUM_WORLD;
02424                 killerName = "<world>";
02425         }
02426 
02427         if ( killer < 0 || killer >= MAX_CLIENTS ) {
02428                 killer = ENTITYNUM_WORLD;
02429                 killerName = "<world>";
02430         }
02431 
02432         if ( meansOfDeath < 0 || meansOfDeath >= sizeof( modNames ) / sizeof( modNames[0] ) ) {
02433                 obit = "<bad obituary>";
02434         } else {
02435                 obit = modNames[ meansOfDeath ];
02436         }
02437 
02438         G_LogPrintf("Kill: %i %i %i: %s killed %s by %s\n", 
02439                 killer, self->s.number, meansOfDeath, killerName, 
02440                 self->client->pers.netname, obit );
02441 
02442         if ( g_austrian.integer 
02443                 && (g_gametype.integer == GT_DUEL) 
02444                 && level.numPlayingClients >= 2 )
02445         {
02446                 int spawnTime = (level.clients[level.sortedClients[0]].respawnTime > level.clients[level.sortedClients[1]].respawnTime) ? level.clients[level.sortedClients[0]].respawnTime : level.clients[level.sortedClients[1]].respawnTime;
02447                 G_LogPrintf("Duel Kill Details:\n");
02448                 G_LogPrintf("Kill Time: %d\n", level.time-spawnTime );
02449                 G_LogPrintf("victim: %s, hits on enemy %d\n", self->client->pers.netname, self->client->ps.persistant[PERS_HITS] );
02450                 if ( attacker && attacker->client )
02451                 {
02452                         G_LogPrintf("killer: %s, hits on enemy %d, health: %d\n", attacker->client->pers.netname, attacker->client->ps.persistant[PERS_HITS], attacker->health );
02453                         //also - if MOD_SABER, list the animation and saber style
02454                         if ( meansOfDeath == MOD_SABER )
02455                         {
02456                                 G_LogPrintf("killer saber style: %d, killer saber anim %s\n", attacker->client->ps.fd.saberAnimLevel, animTable[(attacker->client->ps.torsoAnim)].name );
02457                         }
02458                 }
02459         }
02460 
02461         G_LogWeaponKill(killer, meansOfDeath);
02462         G_LogWeaponDeath(self->s.number, self->s.weapon);
02463         if (attacker && attacker->client && attacker->inuse)
02464         {
02465                 G_LogWeaponFrag(killer, self->s.number);
02466         }
02467 
02468         // broadcast the death event to everyone
02469         if (self->s.eType != ET_NPC && !g_noPDuelCheck)
02470         {
02471                 ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY );
02472                 ent->s.eventParm = meansOfDeath;
02473                 ent->s.otherEntityNum = self->s.number;
02474                 ent->s.otherEntityNum2 = killer;
02475                 ent->r.svFlags = SVF_BROADCAST; // send to everyone
02476                 ent->s.isJediMaster = wasJediMaster;
02477         }
02478 
02479         self->enemy = attacker;
02480 
02481         self->client->ps.persistant[PERS_KILLED]++;
02482 
02483         if (self == attacker)
02484         {
02485                 self->client->ps.fd.suicides++;
02486         }
02487 
02488         if (attacker && attacker->client) {
02489                 attacker->client->lastkilled_client = self->s.number;
02490 
02491                 G_CheckVictoryScript(attacker);
02492 
02493                 if ( attacker == self || OnSameTeam (self, attacker ) ) {
02494                         if (g_gametype.integer == GT_DUEL)
02495                         { //in duel, if you kill yourself, the person you are dueling against gets a kill for it
02496                                 int otherClNum = -1;
02497                                 if (level.sortedClients[0] == self->s.number)
02498                                 {
02499                                         otherClNum = level.sortedClients[1];
02500                                 }
02501                                 else if (level.sortedClients[1] == self->s.number)
02502                                 {
02503                                         otherClNum = level.sortedClients[0];
02504                                 }
02505 
02506                                 if (otherClNum >= 0 && otherClNum < MAX_CLIENTS &&
02507                                         g_entities[otherClNum].inuse && g_entities[otherClNum].client &&
02508                                         otherClNum != attacker->s.number)
02509                                 {
02510                                         AddScore( &g_entities[otherClNum], self->r.currentOrigin, 1 );
02511                                 }
02512                                 else
02513                                 {
02514                                         AddScore( attacker, self->r.currentOrigin, -1 );
02515                                 }
02516                         }
02517                         else
02518                         {
02519                                 AddScore( attacker, self->r.currentOrigin, -1 );
02520                         }
02521                         if (g_gametype.integer == GT_JEDIMASTER)
02522                         {
02523                                 if (self->client && self->client->ps.isJediMaster)
02524                                 { //killed ourself so return the saber to the original position
02525                                   //(to avoid people jumping off ledges and making the saber
02526                                   //unreachable for 60 seconds)
02527                                         ThrowSaberToAttacker(self, NULL);
02528                                         self->client->ps.isJediMaster = qfalse;
02529                                 }
02530                         }
02531                 } else {
02532                         if (g_gametype.integer == GT_JEDIMASTER)
02533                         {
02534                                 if ((attacker->client && attacker->client->ps.isJediMaster) ||
02535                                         (self->client && self->client->ps.isJediMaster))
02536                                 {
02537                                         AddScore( attacker, self->r.currentOrigin, 1 );
02538                                         
02539                                         if (self->client && self->client->ps.isJediMaster)
02540                                         {
02541                                                 ThrowSaberToAttacker(self, attacker);
02542                                                 self->client->ps.isJediMaster = qfalse;
02543                                         }
02544                                 }
02545                                 else
02546                                 {
02547                                         gentity_t *jmEnt = G_GetJediMaster();
02548 
02549                                         if (jmEnt && jmEnt->client)
02550                                         {
02551                                                 AddScore( jmEnt, self->r.currentOrigin, 1 );
02552                                         }
02553                                 }
02554                         }
02555                         else
02556                         {
02557                                 AddScore( attacker, self->r.currentOrigin, 1 );
02558                         }
02559 
02560                         if( meansOfDeath == MOD_STUN_BATON ) {
02561                                 
02562                                 // play humiliation on player
02563                                 attacker->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT]++;
02564 
02565                                 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
02566 
02567                                 // also play humiliation on target
02568                                 self->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_GAUNTLETREWARD;
02569                         }
02570 
02571                         // check for two kills in a short amount of time
02572                         // if this is close enough to the last kill, give a reward sound
02573                         if ( level.time - attacker->client->lastKillTime < CARNAGE_REWARD_TIME ) {
02574                                 // play excellent on player
02575                                 attacker->client->ps.persistant[PERS_EXCELLENT_COUNT]++;
02576 
02577                                 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
02578                         }
02579                         attacker->client->lastKillTime = level.time;
02580 
02581                 }
02582         } else {
02583                 if (self->client && self->client->ps.isJediMaster)
02584                 { //killed ourself so return the saber to the original position
02585                   //(to avoid people jumping off ledges and making the saber
02586                   //unreachable for 60 seconds)
02587                         ThrowSaberToAttacker(self, NULL);
02588                         self->client->ps.isJediMaster = qfalse;
02589                 }
02590 
02591                 if (g_gametype.integer == GT_DUEL)
02592                 { //in duel, if you kill yourself, the person you are dueling against gets a kill for it
02593                         int otherClNum = -1;
02594                         if (level.sortedClients[0] == self->s.number)
02595                         {
02596                                 otherClNum = level.sortedClients[1];
02597                         }
02598                         else if (level.sortedClients[1] == self->s.number)
02599                         {
02600                                 otherClNum = level.sortedClients[0];
02601                         }
02602 
02603                         if (otherClNum >= 0 && otherClNum < MAX_CLIENTS &&
02604                                 g_entities[otherClNum].inuse && g_entities[otherClNum].client &&
02605                                 otherClNum != self->s.number)
02606                         {
02607                                 AddScore( &g_entities[otherClNum], self->r.currentOrigin, 1 );
02608                         }
02609                         else
02610                         {
02611                                 AddScore( self, self->r.currentOrigin, -1 );
02612                         }
02613                 }
02614                 else
02615                 {
02616                         AddScore( self, self->r.currentOrigin, -1 );
02617                 }
02618         }
02619 
02620         // Add team bonuses
02621         Team_FragBonuses(self, inflictor, attacker);
02622 
02623         // if I committed suicide, the flag does not fall, it returns.
02624         if (meansOfDeath == MOD_SUICIDE) {
02625                 if ( self->client->ps.powerups[PW_NEUTRALFLAG] ) {              // only happens in One Flag CTF
02626                         Team_ReturnFlag( TEAM_FREE );
02627                         self->client->ps.powerups[PW_NEUTRALFLAG] = 0;
02628                 }
02629                 else if ( self->client->ps.powerups[PW_REDFLAG] ) {             // only happens in standard CTF
02630                         Team_ReturnFlag( TEAM_RED );
02631                         self->client->ps.powerups[PW_REDFLAG] = 0;
02632                 }
02633                 else if ( self->client->ps.powerups[PW_BLUEFLAG] ) {    // only happens in standard CTF
02634                         Team_ReturnFlag( TEAM_BLUE );
02635                         self->client->ps.powerups[PW_BLUEFLAG] = 0;
02636                 }
02637         }
02638 
02639         // if client is in a nodrop area, don't drop anything (but return CTF flags!)
02640         contents = trap_PointContents( self->r.currentOrigin, -1 );
02641         if ( !( contents & CONTENTS_NODROP ) && !self->client->ps.fallingToDeath) {
02642                 if (self->s.eType != ET_NPC)
02643                 {
02644                         TossClientItems( self );
02645                 }
02646         }
02647         else {
02648                 if ( self->client->ps.powerups[PW_NEUTRALFLAG] ) {              // only happens in One Flag CTF
02649                         Team_ReturnFlag( TEAM_FREE );
02650                 }
02651                 else if ( self->client->ps.powerups[PW_REDFLAG] ) {             // only happens in standard CTF
02652                         Team_ReturnFlag( TEAM_RED );
02653                 }
02654                 else if ( self->client->ps.powerups[PW_BLUEFLAG] ) {    // only happens in standard CTF
02655                         Team_ReturnFlag( TEAM_BLUE );
02656                 }
02657         }
02658 
02659         if ( MOD_TEAM_CHANGE == meansOfDeath )
02660         {
02661                 // Give them back a point since they didn't really die.
02662                 AddScore( self, self->r.currentOrigin, 1 );
02663         }
02664         else
02665         {
02666                 Cmd_Score_f( self );            // show scores
02667         }
02668 
02669         // send updated scores to any clients that are following this one,
02670         // or they would get stale scoreboards
02671         for ( i = 0 ; i < level.maxclients ; i++ ) {
02672                 gclient_t       *client;
02673 
02674                 client = &level.clients[i];
02675                 if ( client->pers.connected != CON_CONNECTED ) {
02676                         continue;
02677                 }
02678                 if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
02679                         continue;
02680                 }
02681                 if ( client->sess.spectatorClient == self->s.number ) {
02682                         Cmd_Score_f( g_entities + i );
02683                 }
02684         }
02685 
02686         self->takedamage = qtrue;       // can still be gibbed
02687 
02688         self->s.weapon = WP_NONE;
02689         self->s.powerups = 0;
02690         if (self->s.eType != ET_NPC)
02691         { //handled differently for NPCs
02692                 self->r.contents = CONTENTS_CORPSE;
02693         }
02694         self->client->ps.zoomMode = 0;  // Turn off zooming when we die
02695 
02696         //rww - 07/19/02 - I removed this because it isn't working and it's ugly (for people on the outside)
02697         /*
02698         self->s.angles[0] = 0;
02699         self->s.angles[2] = 0;
02700         LookAtKiller (self, inflictor, attacker);
02701 
02702         VectorCopy( self->s.angles, self->client->ps.viewangles );
02703         */
02704 
02705         self->s.loopSound = 0;
02706         self->s.loopIsSoundset = qfalse;
02707 
02708         if (self->s.eType != ET_NPC)
02709         { //handled differently for NPCs
02710                 self->r.maxs[2] = -8;
02711         }
02712 
02713         // don't allow respawn until the death anim is done
02714         // g_forcerespawn may force spawning at some later time
02715         self->client->respawnTime = level.time + 1700;
02716 
02717         // remove powerups
02718         memset( self->client->ps.powerups, 0, sizeof(self->client->ps.powerups) );
02719 
02720         // NOTENOTE No gib deaths right now, this is star wars.
02721         /*
02722         // never gib in a nodrop
02723         if ( (self->health <= GIB_HEALTH && !(contents & CONTENTS_NODROP) && g_blood.integer) || meansOfDeath == MOD_SUICIDE) 
02724         {
02725                 // gib death
02726                 GibEntity( self, killer );
02727         } 
02728         else 
02729         */
02730         {
02731                 // normal death
02732                 
02733                 static int i;
02734 
02735                 anim = G_PickDeathAnim(self, self->pos1, damage, meansOfDeath, HL_NONE);
02736 
02737                 if (anim >= 1)
02738                 { //Some droids don't have death anims
02739                         // for the no-blood option, we need to prevent the health
02740                         // from going to gib level
02741                         if ( self->health <= GIB_HEALTH ) {
02742                                 self->health = GIB_HEALTH+1;
02743                         }
02744 
02745                         self->client->respawnTime = level.time + 1000;//((self->client->animations[anim].numFrames*40)/(50.0f / self->client->animations[anim].frameLerp))+300;
02746 
02747                         sPMType = self->client->ps.pm_type;
02748                         self->client->ps.pm_type = PM_NORMAL; //don't want pm type interfering with our setanim calls.
02749 
02750                         if (self->inuse)
02751                         { //not disconnecting
02752                                 G_SetAnim(self, NULL, SETANIM_BOTH, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART, 0);
02753                         }
02754 
02755                         self->client->ps.pm_type = sPMType;
02756 
02757                         if (meansOfDeath == MOD_SABER || (meansOfDeath == MOD_MELEE && G_HeavyMelee( attacker )) )//saber or heavy melee (claws)
02758                         { //update the anim on the actual skeleton (so bolt point will reflect the correct position) and then check for dismem
02759                                 G_UpdateClientAnims(self, 1.0f);
02760                                 G_CheckForDismemberment(self, attacker, self->pos1, damage, anim, qfalse);
02761                         }
02762                 }
02763                 else if (self->NPC && self->client && self->client->NPC_class != CLASS_MARK1 &&
02764                         self->client->NPC_class != CLASS_VEHICLE)
02765                 { //in this case if we're an NPC it's my guess that we want to get removed straight away.
02766                         self->think = G_FreeEntity;
02767                         self->nextthink = level.time;
02768                 }
02769 
02770                 //self->client->ps.legsAnim = anim;
02771                 //self->client->ps.torsoAnim = anim;
02772 //              self->client->ps.pm_flags |= PMF_UPDATE_ANIM;           // Make sure the pmove sets up the GHOUL2 anims.
02773 
02774                 //rww - do this on respawn, not death
02775                 //CopyToBodyQue (self);
02776 
02777                 //G_AddEvent( self, EV_DEATH1 + i, killer );
02778                 if (wasJediMaster)
02779                 {
02780                         G_AddEvent( self, EV_DEATH1 + i, 1 );
02781                 }
02782                 else
02783                 {
02784                         G_AddEvent( self, EV_DEATH1 + i, 0 );
02785                 }
02786 
02787                 if (self != attacker)
02788                 { //don't make NPCs want to murder you on respawn for killing yourself!
02789                         G_DeathAlert( self, attacker );
02790                 }
02791 
02792                 // the body can still be gibbed
02793                 if (!self->NPC)
02794                 { //don't remove NPCs like this!
02795                         self->die = body_die;
02796                 }
02797 
02798                 //It won't gib, it will disintegrate (because this is Star Wars).
02799                 self->takedamage = qtrue;
02800 
02801                 // globally cycle through the different death animations
02802                 i = ( i + 1 ) % 3;
02803         }
02804 
02805         if ( self->NPC )
02806         {//If an NPC, make sure we start running our scripts again- this gets set to infinite while we fall to our deaths
02807                 self->NPC->nextBStateThink = level.time;
02808         }
02809 
02810         if ( G_ActivateBehavior( self, BSET_DEATH ) )
02811         {
02812                 //deathScript = qtrue;
02813         }
02814         
02815         if ( self->NPC && (self->NPC->scriptFlags&SCF_FFDEATH) )
02816         {
02817                 if ( G_ActivateBehavior( self, BSET_FFDEATH ) )  
02818                 {//FIXME: should running this preclude running the normal deathscript?
02819                         //deathScript = qtrue;
02820                 }
02821                 G_UseTargets2( self, self, self->target4 );
02822         }
02823         
02824         /*
02825         if ( !deathScript && !(self->svFlags&SVF_KILLED_SELF) )
02826         {
02827                 //Should no longer run scripts
02828                 //WARNING!!! DO NOT DO THIS WHILE RUNNING A SCRIPT, ICARUS WILL CRASH!!!
02829                 //FIXME: shouldn't ICARUS handle this internally?
02830                 ICARUS_FreeEnt(self);
02831         }
02832         */
02833         //rwwFIXMEFIXME: Do this too?
02834 
02835         // Free up any timers we may have on us.
02836         TIMER_Clear2( self );
02837 
02838         trap_LinkEntity (self);
02839 
02840         if ( self->NPC )
02841         {
02842                 self->NPC->timeOfDeath = level.time;//this will change - used for debouncing post-death events
02843         }
02844 
02845         // Start any necessary death fx for this entity
02846         DeathFX( self );
02847 
02848 
02849         if (g_gametype.integer == GT_POWERDUEL && !g_noPDuelCheck)
02850         { //powerduel checks
02851                 if (self->client->sess.duelTeam == DUELTEAM_LONE)
02852                 { //automatically means a win as there is only one
02853                         G_AddPowerDuelScore(DUELTEAM_DOUBLE, 1);
02854                         G_AddPowerDuelLoserScore(DUELTEAM_LONE, 1);
02855                         g_endPDuel = qtrue;
02856                 }
02857                 else if (self->client->sess.duelTeam == DUELTEAM_DOUBLE)
02858                 {
02859                         int i = 0;
02860                         gentity_t *check;
02861                         qboolean heLives = qfalse;
02862 
02863                         while (i < MAX_CLIENTS)
02864                         {
02865                                 check = &g_entities[i];
02866                                 if (check->inuse && check->client && check->s.number != self->s.number &&
02867                                         check->client->pers.connected == CON_CONNECTED && !check->client->iAmALoser &&
02868                                         check->client->ps.stats[STAT_HEALTH] > 0 &&
02869                                         check->client->sess.sessionTeam != TEAM_SPECTATOR &&
02870                                         check->client->sess.duelTeam == DUELTEAM_DOUBLE)
02871                                 { //still an active living paired duelist so it's not over yet.
02872                                         heLives = qtrue;
02873                                         break;
02874                                 }
02875                                 i++;
02876                         }
02877 
02878                         if (!heLives)
02879                         { //they're all dead, give the lone duelist the win.
02880                                 G_AddPowerDuelScore(DUELTEAM_LONE, 1);
02881                                 G_AddPowerDuelLoserScore(DUELTEAM_DOUBLE, 1);
02882                                 g_endPDuel = qtrue;
02883                         }
02884                 }
02885         }
02886 }

void Rancor_DropVictim gentity_t self  ) 
 

Definition at line 140 of file NPC_AI_Rancor.c.

References gentity_s::activator, gentity_s::client, gentity_s::count, entityShared_t::currentAngles, EF2_HELD_BY_MONSTER, EF_NODRAW, playerState_s::eFlags, playerState_s::eFlags2, gentity_s::enemy, ENTITYNUM_NONE, G_SetAngles(), gentity_t, playerState_s::hasLookTarget, gentity_s::health, playerState_s::legsTimer, level, playerState_s::lookTarget, gNPC_t::nextBStateThink, gentity_s::NPC, NULL, PITCH, gclient_s::ps, qfalse, gentity_s::r, ROLL, SetClientViewAngle(), level_locals_t::time, playerState_s::torsoTimer, and playerState_s::viewangles.

Referenced by NPC_BSRancor_Default(), player_die(), Rancor_CheckDropVictim(), and Rancor_Swing().

00141 {
00142         //FIXME: if Rancor dies, it should drop its victim.
00143         //FIXME: if Rancor is removed, it must remove its victim.
00144         if ( self->activator )
00145         {
00146                 if ( self->activator->client )
00147                 {
00148                         self->activator->client->ps.eFlags2 &= ~EF2_HELD_BY_MONSTER;
00149                         self->activator->client->ps.hasLookTarget = qfalse;
00150                         self->activator->client->ps.lookTarget = ENTITYNUM_NONE;
00151                         self->activator->client->ps.viewangles[ROLL] = 0;
00152                         SetClientViewAngle( self->activator, self->activator->client->ps.viewangles );
00153                         self->activator->r.currentAngles[PITCH] = self->activator->r.currentAngles[ROLL] = 0;
00154                         G_SetAngles( self->activator, self->activator->r.currentAngles );
00155                 }
00156                 if ( self->activator->health <= 0 )
00157                 {
00158                         //if ( self->activator->s.number )
00159                         {//never free player
00160                                 if ( self->count == 1 )
00161                                 {//in my hand, just drop them
00162                                         if ( self->activator->client )
00163                                         {
00164                                                 self->activator->client->ps.legsTimer = self->activator->client->ps.torsoTimer = 0;
00165                                                 //FIXME: ragdoll?
00166                                         }
00167                                 }
00168                                 else
00169                                 {
00170                                         if ( self->activator->client )
00171                                         {
00172                                                 self->activator->client->ps.eFlags |= EF_NODRAW;//so his corpse doesn't drop out of me...
00173                                         }
00174                                         //G_FreeEntity( self->activator );
00175                                 }
00176                         }
00177                 }
00178                 else
00179                 {
00180                         if ( self->activator->NPC )
00181                         {//start thinking again
00182                                 self->activator->NPC->nextBStateThink = level.time;
00183                         }
00184                         //clear their anim and let them fall
00185                         self->activator->client->ps.legsTimer = self->activator->client->ps.torsoTimer = 0;
00186                 }
00187                 if ( self->enemy == self->activator )
00188                 {
00189                         self->enemy = NULL;
00190                 }
00191                 self->activator = NULL;
00192         }
00193         self->count = 0;//drop him
00194 }

int RaySphereIntersections vec3_t  origin,
float  radius,
vec3_t  point,
vec3_t  dir,
vec3_t  intersections[2]
 

Definition at line 3003 of file g_combat.c.

References sqrt(), vec3_t, VectorMA, and VectorNormalize().

03003                                                                                                              {
03004         float b, c, d, t;
03005 
03006         //      | origin - (point + t * dir) | = radius
03007         //      a = dir[0]^2 + dir[1]^2 + dir[2]^2;
03008         //      b = 2 * (dir[0] * (point[0] - origin[0]) + dir[1] * (point[1] - origin[1]) + dir[2] * (point[2] - origin[2]));
03009         //      c = (point[0] - origin[0])^2 + (point[1] - origin[1])^2 + (point[2] - origin[2])^2 - radius^2;
03010 
03011         // normalize dir so a = 1
03012         VectorNormalize(dir);
03013         b = 2 * (dir[0] * (point[0] - origin[0]) + dir[1] * (point[1] - origin[1]) + dir[2] * (point[2] - origin[2]));
03014         c = (point[0] - origin[0]) * (point[0] - origin[0]) +
03015                 (point[1] - origin[1]) * (point[1] - origin[1]) +
03016                 (point[2] - origin[2]) * (point[2] - origin[2]) -
03017                 radius * radius;
03018 
03019         d = b * b - 4 * c;
03020         if (d > 0) {
03021                 t = (- b + sqrt(d)) / 2;
03022                 VectorMA(point, t, dir, intersections[0]);
03023                 t = (- b - sqrt(d)) / 2;
03024                 VectorMA(point, t, dir, intersections[1]);
03025                 return 2;
03026         }
03027         else if (d == 0) {
03028                 t = (- b ) / 2;
03029                 VectorMA(point, t, dir, intersections[0]);
03030                 return 1;
03031         }
03032         return 0;
03033 }

void ScorePlum gentity_t ent,
vec3_t  origin,
int  score
 

Definition at line 416 of file g_combat.c.

References EV_SCOREPLUM, G_TempEntity(), gentity_t, entityState_s::number, entityState_s::otherEntityNum, gentity_s::r, gentity_s::s, entityShared_t::singleClient, SVF_SINGLECLIENT, entityShared_t::svFlags, entityState_s::time, and vec3_t.

00416                                                            {
00417         gentity_t *plum;
00418 
00419         plum = G_TempEntity( origin, EV_SCOREPLUM );
00420         // only send this temp entity to a single client
00421         plum->r.svFlags |= SVF_SINGLECLIENT;
00422         plum->r.singleClient = ent->s.number;
00423         //
00424         plum->s.otherEntityNum = ent->s.number;
00425         plum->s.time = score;
00426 }

void ThrowSaberToAttacker gentity_t self,
gentity_t attacker
 

Definition at line 258 of file g_client.c.

References entityState_s::apos, gentity_s::client, Com_Printf(), CS_CLIENT_JEDIMASTER, entityShared_t::currentAngles, entityShared_t::currentOrigin, EF_NODRAW, entityState_s::eFlags, gentity_s::enemy, ET_MISSILE, entityState_s::eType, g_entities, gentity_t, gJMSaberEnt, gentity_s::inuse, saberInfo_t::model, entityState_s::modelGhoul2, NULL, entityState_s::number, playerState_s::origin, entityState_s::origin, entityState_s::origin2, entityState_s::pos, gentity_s::pos2, gclient_s::ps, qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, playerState_s::saberEntityNum, playerState_s::saberIndex, playerState_s::saberInFlight, saberInfo_t::skin, trap_LinkEntity(), trap_SetConfigstring(), trajectory_t::trBase, trajectory_t::trDelta, vec3_t, VectorCopy, VectorNormalize(), VectorSubtract, and WP_SaberAddG2Model().

Referenced by player_die().

00259 {
00260         gentity_t *ent = &g_entities[self->client->ps.saberIndex];
00261         vec3_t a;
00262         int altVelocity = 0;
00263 
00264         if (!ent || ent->enemy != self)
00265         { //something has gone very wrong (this should never happen)
00266                 //but in case it does.. find the saber manually
00267 #ifdef _DEBUG
00268                 Com_Printf("Lost the saber! Attempting to use global pointer..\n");
00269 #endif
00270                 ent = gJMSaberEnt;
00271 
00272                 if (!ent)
00273                 {
00274 #ifdef _DEBUG
00275                         Com_Printf("The global pointer was NULL. This is a bad thing.\n");
00276 #endif
00277                         return;
00278                 }
00279 
00280 #ifdef _DEBUG
00281                 Com_Printf("Got it (%i). Setting enemy to client %i.\n", ent->s.number, self->s.number);
00282 #endif
00283 
00284                 ent->enemy = self;
00285                 self->client->ps.saberIndex = ent->s.number;
00286         }
00287 
00288         trap_SetConfigstring ( CS_CLIENT_JEDIMASTER, "-1" );
00289 
00290         if (attacker && attacker->client && self->client->ps.saberInFlight)
00291         { //someone killed us and we had the saber thrown, so actually move this saber to the saber location
00292           //if we killed ourselves with saber thrown, however, same suicide rules of respawning at spawn spot still
00293           //apply.
00294                 gentity_t *flyingsaber = &g_entities[self->client->ps.saberEntityNum];
00295 
00296                 if (flyingsaber && flyingsaber->inuse)
00297                 {
00298                         VectorCopy(flyingsaber->s.pos.trBase, ent->s.pos.trBase);
00299                         VectorCopy(flyingsaber->s.pos.trDelta, ent->s.pos.trDelta);
00300                         VectorCopy(flyingsaber->s.apos.trBase, ent->s.apos.trBase);
00301                         VectorCopy(flyingsaber->s.apos.trDelta, ent->s.apos.trDelta);
00302 
00303                         VectorCopy(flyingsaber->r.currentOrigin, ent->r.currentOrigin);
00304                         VectorCopy(flyingsaber->r.currentAngles, ent->r.currentAngles);
00305                         altVelocity = 1;
00306                 }
00307         }
00308 
00309         self->client->ps.saberInFlight = qtrue; //say he threw it anyway in order to properly remove from dead body
00310 
00311         WP_SaberAddG2Model( ent, self->client->saber[0].model, self->client->saber[0].skin );
00312 
00313         ent->s.eFlags &= ~(EF_NODRAW);
00314         ent->s.modelGhoul2 = 1;
00315         ent->s.eType = ET_MISSILE;
00316         ent->enemy = NULL;
00317 
00318         if (!attacker || !attacker->client)
00319         {
00320                 VectorCopy(ent->s.origin2, ent->s.pos.trBase);
00321                 VectorCopy(ent->s.origin2, ent->s.origin);
00322                 VectorCopy(ent->s.origin2, ent->r.currentOrigin);
00323                 ent->pos2[0] = 0;
00324                 trap_LinkEntity(ent);
00325                 return;
00326         }
00327 
00328         if (!altVelocity)
00329         {
00330                 VectorCopy(self->s.pos.trBase, ent->s.pos.trBase);
00331                 VectorCopy(self->s.pos.trBase, ent->s.origin);
00332                 VectorCopy(self->s.pos.trBase, ent->r.currentOrigin);
00333 
00334                 VectorSubtract(attacker->client->ps.origin, ent->s.pos.trBase, a);
00335 
00336                 VectorNormalize(a);
00337 
00338                 ent->s.pos.trDelta[0] = a[0]*256;
00339                 ent->s.pos.trDelta[1] = a[1]*256;
00340                 ent->s.pos.trDelta[2] = 256;
00341         }
00342 
00343         trap_LinkEntity(ent);
00344 }

void TossClientItems gentity_t self  ) 
 

Definition at line 567 of file g_combat.c.

References playerState_s::ammo, weaponData_s::ammoIndex, BG_FindItemForPowerup(), BG_FindItemForWeapon(), entityState_s::bolt2, gentity_s::client, clientPersistant_t::cmd, gentity_s::count, Drop_Item(), EV_DESTROY_WEAPON_MODEL, entityState_s::eventParm, g_gametype, G_TempEntity(), gentity_t, gitem_t, GT_SIEGE, GT_TEAM, vmCvar_t::integer, level, entityState_s::number, gclient_s::pers, playerState_s::powerups, gclient_s::ps, PW_NUM_POWERUPS, gentity_s::r, gentity_s::s, STAT_WEAPONS, playerState_s::stats, SVF_BROADCAST, entityShared_t::svFlags, level_locals_t::time, vec3_origin, entityState_s::weapon, usercmd_s::weapon, WEAPON_DROPPING, weaponData, playerState_s::weaponstate, WP_BRYAR_PISTOL, WP_EMPLACED_GUN, WP_NONE, and WP_TURRET.

Referenced by ClientDisconnect(), player_die(), and Rancor_Attack().

00567                                         {
00568         gitem_t         *item;
00569         int                     weapon;
00570         float           angle;
00571         int                     i;
00572         gentity_t       *drop;
00573 
00574         if (g_gametype.integer == GT_SIEGE)
00575         { //just don't drop anything then
00576                 return;
00577         }
00578 
00579         // drop the weapon if not a gauntlet or machinegun
00580         weapon = self->s.weapon;
00581 
00582         // make a special check to see if they are changing to a new
00583         // weapon that isn't the mg or gauntlet.  Without this, a client
00584         // can pick up a weapon, be killed, and not drop the weapon because
00585         // their weapon change hasn't completed yet and they are still holding the MG.
00586         if ( weapon == WP_BRYAR_PISTOL) {
00587                 if ( self->client->ps.weaponstate == WEAPON_DROPPING ) {
00588                         weapon = self->client->pers.cmd.weapon;
00589                 }
00590                 if ( !( self->client->ps.stats[STAT_WEAPONS] & ( 1 << weapon ) ) ) {
00591                         weapon = WP_NONE;
00592                 }
00593         }
00594 
00595         self->s.bolt2 = weapon;
00596 
00597         if ( weapon > WP_BRYAR_PISTOL && 
00598                 weapon != WP_EMPLACED_GUN &&
00599                 weapon != WP_TURRET &&
00600                 self->client->ps.ammo[ weaponData[weapon].ammoIndex ] ) {
00601                 gentity_t *te;
00602 
00603                 // find the item type for this weapon
00604                 item = BG_FindItemForWeapon( weapon );
00605 
00606                 // tell all clients to remove the weapon model on this guy until he respawns
00607                 te = G_TempEntity( vec3_origin, EV_DESTROY_WEAPON_MODEL );
00608                 te->r.svFlags |= SVF_BROADCAST;
00609                 te->s.eventParm = self->s.number;
00610 
00611                 // spawn the item
00612                 Drop_Item( self, item, 0 );
00613         }
00614 
00615         // drop all the powerups if not in teamplay
00616         if ( g_gametype.integer != GT_TEAM && g_gametype.integer != GT_SIEGE ) {
00617                 angle = 45;
00618                 for ( i = 1 ; i < PW_NUM_POWERUPS ; i++ ) {
00619                         if ( self->client->ps.powerups[ i ] > level.time ) {
00620                                 item = BG_FindItemForPowerup( i );
00621                                 if ( !item ) {
00622                                         continue;
00623                                 }
00624                                 drop = Drop_Item( self, item, angle );
00625                                 // decide how many seconds it has left
00626                                 drop->count = ( self->client->ps.powerups[ i ] - level.time ) / 1000;
00627                                 if ( drop->count < 1 ) {
00628                                         drop->count = 1;
00629                                 }
00630                                 angle += 45;
00631                         }
00632                 }
00633         }
00634 }

void TossClientWeapon gentity_t self,
vec3_t  direction,
float  speed
 

Definition at line 468 of file g_combat.c.

References playerState_s::ammo, weaponData_s::ammoIndex, BG_FindItemForWeapon(), BG_GetItemIndexByTag(), bg_itemlist, gentity_s::client, gentity_s::count, EV_NOAMMO, G_AddEvent(), g_gametype, entityState_s::generic1, gentity_t, gitem_t, GT_SIEGE, vmCvar_t::integer, IT_WEAPON, LaunchItem(), level, entityState_s::number, playerState_s::origin, entityState_s::powerups, gclient_s::ps, gitem_s::quantity, gentity_s::s, STAT_WEAPONS, playerState_s::stats, level_locals_t::time, vec3_t, entityState_s::weapon, playerState_s::weapon, weaponData, WP_BRYAR_PISTOL, WP_DET_PACK, WP_EMPLACED_GUN, WP_NONE, WP_NUM_WEAPONS, WP_THERMAL, WP_TRIP_MINE, and WP_TURRET.

Referenced by ForceThrow().

00469 {
00470         vec3_t vel;
00471         gitem_t *item;
00472         gentity_t *launched;
00473         int weapon = self->s.weapon;
00474         int ammoSub;
00475 
00476         if (g_gametype.integer == GT_SIEGE)
00477         { //no dropping weaps
00478                 return;
00479         }
00480 
00481         if (weapon <= WP_BRYAR_PISTOL)
00482         { //can't have this
00483                 return;
00484         }
00485 
00486         if (weapon == WP_EMPLACED_GUN ||
00487                 weapon == WP_TURRET)
00488         {
00489                 return;
00490         }
00491 
00492         // find the item type for this weapon
00493         item = BG_FindItemForWeapon( weapon );
00494 
00495         ammoSub = (self->client->ps.ammo[weaponData[weapon].ammoIndex] - bg_itemlist[BG_GetItemIndexByTag(weapon, IT_WEAPON)].quantity);
00496 
00497         if (ammoSub < 0)
00498         {
00499                 int ammoQuan = item->quantity;
00500                 ammoQuan -= (-ammoSub);
00501 
00502                 if (ammoQuan <= 0)
00503                 { //no ammo
00504                         return;
00505                 }
00506         }
00507 
00508         vel[0] = direction[0]*speed;
00509         vel[1] = direction[1]*speed;
00510         vel[2] = direction[2]*speed;
00511 
00512         launched = LaunchItem(item, self->client->ps.origin, vel);
00513 
00514         launched->s.generic1 = self->s.number;
00515         launched->s.powerups = level.time + 1500;
00516 
00517         launched->count = bg_itemlist[BG_GetItemIndexByTag(weapon, IT_WEAPON)].quantity;
00518 
00519         self->client->ps.ammo[weaponData[weapon].ammoIndex] -= bg_itemlist[BG_GetItemIndexByTag(weapon, IT_WEAPON)].quantity;
00520 
00521         if (self->client->ps.ammo[weaponData[weapon].ammoIndex] < 0)
00522         {
00523                 launched->count -= (-self->client->ps.ammo[weaponData[weapon].ammoIndex]);
00524                 self->client->ps.ammo[weaponData[weapon].ammoIndex] = 0;
00525         }
00526 
00527         if ((self->client->ps.ammo[weaponData[weapon].ammoIndex] < 1 && weapon != WP_DET_PACK) ||
00528                 (weapon != WP_THERMAL && weapon != WP_DET_PACK && weapon != WP_TRIP_MINE))
00529         {
00530                 int i = 0;
00531                 int weap = -1;
00532 
00533                 self->client->ps.stats[STAT_WEAPONS] &= ~(1 << weapon);
00534 
00535                 while (i < WP_NUM_WEAPONS)
00536                 {
00537                         if ((self->client->ps.stats[STAT_WEAPONS] & (1 << i)) && i != WP_NONE)
00538                         { //this one's good
00539                                 weap = i;
00540                                 break;
00541                         }
00542                         i++;
00543                 }
00544 
00545                 if (weap != -1)
00546                 {
00547                         self->s.weapon = weap;
00548                         self->client->ps.weapon = weap;
00549                 }
00550                 else
00551                 {
00552                         self->s.weapon = 0;
00553                         self->client->ps.weapon = 0;
00554                 }
00555 
00556                 G_AddEvent(self, EV_NOAMMO, weapon);
00557         }
00558 }

void UpdateClientRenderBolts gentity_t self,
vec3_t  renderOrigin,
vec3_t  renderAngles
 

Definition at line 7257 of file w_saber.c.

References renderInfo_s::boltValidityTime, gentity_s::client, renderInfo_s::crotchBolt, renderInfo_s::crotchPoint, renderInfo_s::footLBolt, renderInfo_s::footLPoint, renderInfo_s::footRBolt, renderInfo_s::footRPoint, gentity_t, gentity_s::ghoul2, renderInfo_s::handLBolt, renderInfo_s::handLPoint, renderInfo_s::handRBolt, renderInfo_s::handRPoint, renderInfo_s::headBolt, renderInfo_s::headPoint, level, mdxaBone_t::matrix, gentity_s::modelScale, NULL, playerState_s::origin, gclient_s::ps, gclient_s::renderInfo, renderInfo_t, level_locals_t::time, renderInfo_s::torsoBolt, renderInfo_s::torsoPoint, trap_G2API_GetBoltMatrix(), vec3_t, and VectorCopy.

Referenced by G_GetHitLocFromSurfName().

07258 {
07259         mdxaBone_t boltMatrix;
07260         renderInfo_t *ri = &self->client->renderInfo;
07261 
07262         if (!self->ghoul2)
07263         {
07264                 VectorCopy(self->client->ps.origin, ri->headPoint);
07265                 VectorCopy(self->client->ps.origin, ri->handRPoint);
07266                 VectorCopy(self->client->ps.origin, ri->handLPoint);
07267                 VectorCopy(self->client->ps.origin, ri->torsoPoint);
07268                 VectorCopy(self->client->ps.origin, ri->crotchPoint);
07269                 VectorCopy(self->client->ps.origin, ri->footRPoint);
07270                 VectorCopy(self->client->ps.origin, ri->footLPoint);
07271         }
07272         else
07273         {
07274                 //head
07275                 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->headBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07276                 ri->headPoint[0] = boltMatrix.matrix[0][3];
07277                 ri->headPoint[1] = boltMatrix.matrix[1][3];
07278                 ri->headPoint[2] = boltMatrix.matrix[2][3];
07279 
07280                 //right hand
07281                 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->handRBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07282                 ri->handRPoint[0] = boltMatrix.matrix[0][3];
07283                 ri->handRPoint[1] = boltMatrix.matrix[1][3];
07284                 ri->handRPoint[2] = boltMatrix.matrix[2][3];
07285 
07286                 //left hand
07287                 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->handLBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07288                 ri->handLPoint[0] = boltMatrix.matrix[0][3];
07289                 ri->handLPoint[1] = boltMatrix.matrix[1][3];
07290                 ri->handLPoint[2] = boltMatrix.matrix[2][3];
07291 
07292                 //chest
07293                 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->torsoBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07294                 ri->torsoPoint[0] = boltMatrix.matrix[0][3];
07295                 ri->torsoPoint[1] = boltMatrix.matrix[1][3];
07296                 ri->torsoPoint[2] = boltMatrix.matrix[2][3];
07297 
07298                 //crotch
07299                 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->crotchBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07300                 ri->crotchPoint[0] = boltMatrix.matrix[0][3];
07301                 ri->crotchPoint[1] = boltMatrix.matrix[1][3];
07302                 ri->crotchPoint[2] = boltMatrix.matrix[2][3];
07303 
07304                 //right foot
07305                 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->footRBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07306                 ri->footRPoint[0] = boltMatrix.matrix[0][3];
07307                 ri->footRPoint[1] = boltMatrix.matrix[1][3];
07308                 ri->footRPoint[2] = boltMatrix.matrix[2][3];
07309 
07310                 //left foot
07311                 trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->footLBolt, &boltMatrix, renderAngles, renderOrigin, level.time, NULL, self->modelScale);
07312                 ri->footLPoint[0] = boltMatrix.matrix[0][3];
07313                 ri->footLPoint[1] = boltMatrix.matrix[1][3];
07314                 ri->footLPoint[2] = boltMatrix.matrix[2][3];
07315         }
07316 
07317         self->client->renderInfo.boltValidityTime = level.time;
07318 }


Variable Documentation

stringID_table_t animTable[MAX_ANIMATIONS+1]
 

Definition at line 2061 of file g_combat.c.

qboolean g_dontFrickinCheck
 

Definition at line 2070 of file g_combat.c.

Referenced by CheckTournament(), player_die(), and RemovePowerDuelLosers().

qboolean g_dontPenalizeTeam
 

Definition at line 435 of file g_combat.c.

Referenced by AddScore(), and SetTeam().

qboolean g_endPDuel
 

Definition at line 2071 of file g_combat.c.

Referenced by CheckExitRules(), and player_die().

qboolean g_noPDuelCheck
 

Definition at line 2072 of file g_combat.c.

Referenced by G_ResetDuelists(), and player_die().

int gGAvoidDismember = 0
 

Definition at line 3628 of file g_combat.c.

Referenced by ClientCommand(), ClientThink_real(), G_CheckForDismemberment(), and G_PickDeathAnim().

int gPainHitLoc = -1
 

Definition at line 4366 of file g_combat.c.

Referenced by G_Damage(), G_GetHitQuad(), NPC_Mark1_Pain(), NPC_Mark2_Pain(), and NPC_Pain().

int gPainMOD = 0
 

Definition at line 4365 of file g_combat.c.

Referenced by G_Damage(), NPC_Droid_Pain(), NPC_GM_Pain(), NPC_Pain(), NPC_Probe_Pain(), and NPC_Sentry_Pain().

vec3_t gPainPoint
 

Definition at line 4367 of file g_combat.c.

Referenced by G_Damage(), NPC_GM_Pain(), NPC_Jedi_Pain(), and NPC_Pain().

qboolean gSiegeRoundBegun
 

Definition at line 4363 of file g_combat.c.

char* hitLocName[HL_MAX]
 

Initial value:

 
{
        "none", 
        "right foot",   
        "left foot",    
        "right leg",    
        "left leg",     
        "waist",        
        "back right shoulder",  
        "back left shoulder",   
        "back", 
        "front right shouler",  
        "front left shoulder",  
        "chest",        
        "right arm",    
        "left arm",     
        "right hand",   
        "left hand",    
        "head", 
        "generic1",     
        "generic2",     
        "generic3",     
        "generic4",     
        "generic5",     
        "generic6"      
}

Definition at line 3040 of file g_combat.c.

Referenced by G_CheckForDismemberment().

char* modNames[MOD_MAX]
 

Definition at line 754 of file g_combat.c.

Referenced by G_LogWeaponOutput(), and player_die().