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