#include "g_local.h"
Include dependency graph for g_combat.c:

Go to the source code of this file.
Functions | |
| void | AddScore (gentity_t *ent, vec3_t origin, int score) |
| void | body_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath) |
| qboolean | CanDamage (gentity_t *targ, vec3_t origin) |
| void | CheckAlmostCapture (gentity_t *self, gentity_t *attacker) |
| void | CheckAlmostScored (gentity_t *self, gentity_t *attacker) |
| int | CheckArmor (gentity_t *ent, int damage, int dflags) |
| 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 | G_RadiusDamage (vec3_t origin, gentity_t *attacker, float damage, float radius, gentity_t *ignore, int mod) |
| void | GibEntity (gentity_t *self, int killer) |
| void | LookAtKiller (gentity_t *self, gentity_t *inflictor, gentity_t *attacker) |
| void | player_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath) |
| int | RaySphereIntersections (vec3_t origin, float radius, vec3_t point, vec3_t dir, vec3_t intersections[2]) |
| void | ScorePlum (gentity_t *ent, vec3_t origin, int score) |
| void | TossClientItems (gentity_t *self) |
Variables | |
| char * | modNames [] |
|
||||||||||||||||
|
Definition at line 52 of file g_combat.c. References CalculateRanks(), gentity_s::client, g_gametype, gentity_t, level, playerState_s::persistant, gclient_s::ps, ScorePlum(), level_locals_t::teamScores, and level_locals_t::warmupTime. Referenced by player_die(), Team_FragBonuses(), Team_TouchEnemyFlag(), Team_TouchOurFlag(), and Use_Target_Score(). 00052 {
00053 if ( !ent->client ) {
00054 return;
00055 }
00056 // no scoring during pre-match warmup
00057 if ( level.warmupTime ) {
00058 return;
00059 }
00060 // show score plum
00061 ScorePlum(ent, origin, score);
00062 //
00063 ent->client->ps.persistant[PERS_SCORE] += score;
00064 if ( g_gametype.integer == GT_TEAM )
00065 level.teamScores[ ent->client->ps.persistant[PERS_TEAM] ] += score;
00066 CalculateRanks();
00067 }
|
Here is the call graph for this function:

|
||||||||||||||||||||||||
|
Definition at line 272 of file g_combat.c. References g_blood, gentity_t, GIB_HEALTH, GibEntity(), and vmCvar_t::integer. 00272 {
00273 if ( self->health > GIB_HEALTH ) {
00274 return;
00275 }
00276 if ( !g_blood.integer ) {
00277 self->health = GIB_HEALTH+1;
00278 return;
00279 }
00280
00281 GibEntity( self, 0 );
00282 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1078 of file g_combat.c. References entityShared_t::absmax, entityShared_t::absmin, ENTITYNUM_NONE, gentity_t, MASK_SOLID, entityState_s::number, qboolean, gentity_s::r, gentity_s::s, tr, trap_Trace(), vec3_origin, vec3_t, VectorAdd, VectorCopy, and VectorScale. Referenced by G_RadiusDamage(). 01078 {
01079 vec3_t dest;
01080 trace_t tr;
01081 vec3_t midpoint;
01082
01083 // use the midpoint of the bounds instead of the origin, because
01084 // bmodels may have their origin is 0,0,0
01085 VectorAdd (targ->r.absmin, targ->r.absmax, midpoint);
01086 VectorScale (midpoint, 0.5, midpoint);
01087
01088 VectorCopy (midpoint, dest);
01089 trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
01090 if (tr.fraction == 1.0 || tr.entityNum == targ->s.number)
01091 return qtrue;
01092
01093 // this should probably check in the plane of projection,
01094 // rather than in world coordinate, and also include Z
01095 VectorCopy (midpoint, dest);
01096 dest[0] += 15.0;
01097 dest[1] += 15.0;
01098 trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
01099 if (tr.fraction == 1.0)
01100 return qtrue;
01101
01102 VectorCopy (midpoint, dest);
01103 dest[0] += 15.0;
01104 dest[1] -= 15.0;
01105 trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
01106 if (tr.fraction == 1.0)
01107 return qtrue;
01108
01109 VectorCopy (midpoint, dest);
01110 dest[0] -= 15.0;
01111 dest[1] += 15.0;
01112 trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
01113 if (tr.fraction == 1.0)
01114 return qtrue;
01115
01116 VectorCopy (midpoint, dest);
01117 dest[0] -= 15.0;
01118 dest[1] -= 15.0;
01119 trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
01120 if (tr.fraction == 1.0)
01121 return qtrue;
01122
01123
01124 return qfalse;
01125 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 356 of file g_combat.c. References gentity_s::client, gentity_s::flags, FOFS, G_Find(), g_gametype, gentity_t, entityState_s::origin, playerState_s::origin, playerState_s::persistant, gclient_s::ps, gentity_s::r, gentity_s::s, entityShared_t::svFlags, vec3_t, VectorLength(), and VectorSubtract. Referenced by player_die(). 00356 {
00357 gentity_t *ent;
00358 vec3_t dir;
00359 char *classname;
00360
00361 // if this player was carrying a flag
00362 if ( self->client->ps.powerups[PW_REDFLAG] ||
00363 self->client->ps.powerups[PW_BLUEFLAG] ||
00364 self->client->ps.powerups[PW_NEUTRALFLAG] ) {
00365 // get the goal flag this player should have been going for
00366 if ( g_gametype.integer == GT_CTF ) {
00367 if ( self->client->sess.sessionTeam == TEAM_BLUE ) {
00368 classname = "team_CTF_blueflag";
00369 }
00370 else {
00371 classname = "team_CTF_redflag";
00372 }
00373 }
00374 else {
00375 if ( self->client->sess.sessionTeam == TEAM_BLUE ) {
00376 classname = "team_CTF_redflag";
00377 }
00378 else {
00379 classname = "team_CTF_blueflag";
00380 }
00381 }
00382 ent = NULL;
00383 do
00384 {
00385 ent = G_Find(ent, FOFS(classname), classname);
00386 } while (ent && (ent->flags & FL_DROPPED_ITEM));
00387 // if we found the destination flag and it's not picked up
00388 if (ent && !(ent->r.svFlags & SVF_NOCLIENT) ) {
00389 // if the player was *very* close
00390 VectorSubtract( self->client->ps.origin, ent->s.origin, dir );
00391 if ( VectorLength(dir) < 200 ) {
00392 self->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_HOLYSHIT;
00393 if ( attacker->client ) {
00394 attacker->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_HOLYSHIT;
00395 }
00396 }
00397 }
00398 }
00399 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 406 of file g_combat.c. References gentity_s::client, FOFS, G_Find(), gentity_t, NULL, entityState_s::origin, playerState_s::origin, playerState_s::persistant, gclient_s::ps, gentity_s::s, vec3_t, VectorLength(), and VectorSubtract. Referenced by player_die(). 00406 {
00407 gentity_t *ent;
00408 vec3_t dir;
00409 char *classname;
00410
00411 // if the player was carrying cubes
00412 if ( self->client->ps.generic1 ) {
00413 if ( self->client->sess.sessionTeam == TEAM_BLUE ) {
00414 classname = "team_redobelisk";
00415 }
00416 else {
00417 classname = "team_blueobelisk";
00418 }
00419 ent = G_Find(NULL, FOFS(classname), classname);
00420 // if we found the destination obelisk
00421 if ( ent ) {
00422 // if the player was *very* close
00423 VectorSubtract( self->client->ps.origin, ent->s.origin, dir );
00424 if ( VectorLength(dir) < 200 ) {
00425 self->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_HOLYSHIT;
00426 if ( attacker->client ) {
00427 attacker->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_HOLYSHIT;
00428 }
00429 }
00430 }
00431 }
00432 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 690 of file g_combat.c. References ARMOR_PROTECTION, ceil(), gentity_s::client, count, gclient_t, gentity_t, gclient_s::ps, and playerState_s::stats. Referenced by G_Damage(). 00691 {
00692 gclient_t *client;
00693 int save;
00694 int count;
00695
00696 if (!damage)
00697 return 0;
00698
00699 client = ent->client;
00700
00701 if (!client)
00702 return 0;
00703
00704 if (dflags & DAMAGE_NO_ARMOR)
00705 return 0;
00706
00707 // armor
00708 count = client->ps.stats[STAT_ARMOR];
00709 save = ceil( damage * ARMOR_PROTECTION );
00710 if (save >= count)
00711 save = count;
00712
00713 if (!save)
00714 return 0;
00715
00716 client->ps.stats[STAT_ARMOR] -= save;
00717
00718 return save;
00719 }
|
Here is the call graph for this function:

|
||||||||||||||||||||||||||||||||||||
|
Definition at line 821 of file g_combat.c. References bg_itemlist, CheckArmor(), CheckObeliskAttack(), gentity_s::client, entityShared_t::currentOrigin, gclient_s::damage_armor, gclient_s::damage_blood, gclient_s::damage_from, gclient_s::damage_fromWorld, gclient_s::damage_knockback, gentity_s::die, gentity_s::enemy, ET_MISSILE, entityState_s::eType, EV_POWERUP_BATTLESUIT, gentity_s::flags, G_AddEvent(), g_debugDamage, g_entities, g_friendlyFire, g_gametype, G_InvulnerabilityEffect(), g_knockback, G_Printf(), gclient_t, gentity_t, gitem_s::giTag, GT_CTF, GT_OBELISK, gentity_s::health, vmCvar_t::integer, level_locals_t::intermissionQueued, gclient_s::lasthurt_client, gclient_s::lasthurt_mod, level, max, gentity_s::moverState, gclient_s::noclip, entityState_s::number, OnSameTeam(), gentity_s::pain, gentity_s::parent, playerState_s::persistant, playerState_s::pm_flags, playerState_s::pm_time, point, playerState_s::powerups, gclient_s::ps, gentity_s::r, gentity_s::s, playerState_s::stats, t, gentity_s::takedamage, Team_CheckHurtCarrier(), level_locals_t::time, gentity_s::use, vmCvar_t::value, vec3_t, VectorAdd, VectorCopy, VectorNormalize(), VectorScale, and playerState_s::velocity. Referenced by Blocked_Door(), Bullet_Fire(), CheckGauntletAttack(), ClientEvents(), G_KillBox(), G_MissileImpact(), G_MoverPush(), G_RadiusDamage(), hurt_touch(), P_WorldEffects(), ShotgunPellet(), target_kill_use(), target_laser_think(), Weapon_LightningFire(), and weapon_railgun_fire(). 00822 {
00823 gclient_t *client;
00824 int take;
00825 int save;
00826 int asave;
00827 int knockback;
00828 int max;
00829 #ifdef MISSIONPACK
00830 vec3_t bouncedir, impactpoint;
00831 #endif
00832
00833 if (!targ->takedamage) {
00834 return;
00835 }
00836
00837 // the intermission has allready been qualified for, so don't
00838 // allow any extra scoring
00839 if ( level.intermissionQueued ) {
00840 return;
00841 }
00842 #ifdef MISSIONPACK
00843 if ( targ->client && mod != MOD_JUICED) {
00844 if ( targ->client->invulnerabilityTime > level.time) {
00845 if ( dir && point ) {
00846 G_InvulnerabilityEffect( targ, dir, point, impactpoint, bouncedir );
00847 }
00848 return;
00849 }
00850 }
00851 #endif
00852 if ( !inflictor ) {
00853 inflictor = &g_entities[ENTITYNUM_WORLD];
00854 }
00855 if ( !attacker ) {
00856 attacker = &g_entities[ENTITYNUM_WORLD];
00857 }
00858
00859 // shootable doors / buttons don't actually have any health
00860 if ( targ->s.eType == ET_MOVER ) {
00861 if ( targ->use && targ->moverState == MOVER_POS1 ) {
00862 targ->use( targ, inflictor, attacker );
00863 }
00864 return;
00865 }
00866 #ifdef MISSIONPACK
00867 if( g_gametype.integer == GT_OBELISK && CheckObeliskAttack( targ, attacker ) ) {
00868 return;
00869 }
00870 #endif
00871 // reduce damage by the attacker's handicap value
00872 // unless they are rocket jumping
00873 if ( attacker->client && attacker != targ ) {
00874 max = attacker->client->ps.stats[STAT_MAX_HEALTH];
00875 #ifdef MISSIONPACK
00876 if( bg_itemlist[attacker->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
00877 max /= 2;
00878 }
00879 #endif
00880 damage = damage * max / 100;
00881 }
00882
00883 client = targ->client;
00884
00885 if ( client ) {
00886 if ( client->noclip ) {
00887 return;
00888 }
00889 }
00890
00891 if ( !dir ) {
00892 dflags |= DAMAGE_NO_KNOCKBACK;
00893 } else {
00894 VectorNormalize(dir);
00895 }
00896
00897 knockback = damage;
00898 if ( knockback > 200 ) {
00899 knockback = 200;
00900 }
00901 if ( targ->flags & FL_NO_KNOCKBACK ) {
00902 knockback = 0;
00903 }
00904 if ( dflags & DAMAGE_NO_KNOCKBACK ) {
00905 knockback = 0;
00906 }
00907
00908 // figure momentum add, even if the damage won't be taken
00909 if ( knockback && targ->client ) {
00910 vec3_t kvel;
00911 float mass;
00912
00913 mass = 200;
00914
00915 VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel);
00916 VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity);
00917
00918 // set the timer so that the other client can't cancel
00919 // out the movement immediately
00920 if ( !targ->client->ps.pm_time ) {
00921 int t;
00922
00923 t = knockback * 2;
00924 if ( t < 50 ) {
00925 t = 50;
00926 }
00927 if ( t > 200 ) {
00928 t = 200;
00929 }
00930 targ->client->ps.pm_time = t;
00931 targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
00932 }
00933 }
00934
00935 // check for completely getting out of the damage
00936 if ( !(dflags & DAMAGE_NO_PROTECTION) ) {
00937
00938 // if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target
00939 // if the attacker was on the same team
00940 #ifdef MISSIONPACK
00941 if ( mod != MOD_JUICED && targ != attacker && !(dflags & DAMAGE_NO_TEAM_PROTECTION) && OnSameTeam (targ, attacker) ) {
00942 #else
00943 if ( targ != attacker && OnSameTeam (targ, attacker) ) {
00944 #endif
00945 if ( !g_friendlyFire.integer ) {
00946 return;
00947 }
00948 }
00949 #ifdef MISSIONPACK
00950 if (mod == MOD_PROXIMITY_MINE) {
00951 if (inflictor && inflictor->parent && OnSameTeam(targ, inflictor->parent)) {
00952 return;
00953 }
00954 if (targ == attacker) {
00955 return;
00956 }
00957 }
00958 #endif
00959
00960 // check for godmode
00961 if ( targ->flags & FL_GODMODE ) {
00962 return;
00963 }
00964 }
00965
00966 // battlesuit protects from all radius damage (but takes knockback)
00967 // and protects 50% against all damage
00968 if ( client && client->ps.powerups[PW_BATTLESUIT] ) {
00969 G_AddEvent( targ, EV_POWERUP_BATTLESUIT, 0 );
00970 if ( ( dflags & DAMAGE_RADIUS ) || ( mod == MOD_FALLING ) ) {
00971 return;
00972 }
00973 damage *= 0.5;
00974 }
00975
00976 // add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
00977 if ( attacker->client && targ != attacker && targ->health > 0
00978 && targ->s.eType != ET_MISSILE
00979 && targ->s.eType != ET_GENERAL) {
00980 if ( OnSameTeam( targ, attacker ) ) {
00981 attacker->client->ps.persistant[PERS_HITS]--;
00982 } else {
00983 attacker->client->ps.persistant[PERS_HITS]++;
00984 }
00985 attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health<<8)|(client->ps.stats[STAT_ARMOR]);
00986 }
00987
00988 // always give half damage if hurting self
00989 // calculated after knockback, so rocket jumping works
00990 if ( targ == attacker) {
00991 damage *= 0.5;
00992 }
00993
00994 if ( damage < 1 ) {
00995 damage = 1;
00996 }
00997 take = damage;
00998 save = 0;
00999
01000 // save some from armor
01001 asave = CheckArmor (targ, take, dflags);
01002 take -= asave;
01003
01004 if ( g_debugDamage.integer ) {
01005 G_Printf( "%i: client:%i health:%i damage:%i armor:%i\n", level.time, targ->s.number,
01006 targ->health, take, asave );
01007 }
01008
01009 // add to the damage inflicted on a player this frame
01010 // the total will be turned into screen blends and view angle kicks
01011 // at the end of the frame
01012 if ( client ) {
01013 if ( attacker ) {
01014 client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
01015 } else {
01016 client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD;
01017 }
01018 client->damage_armor += asave;
01019 client->damage_blood += take;
01020 client->damage_knockback += knockback;
01021 if ( dir ) {
01022 VectorCopy ( dir, client->damage_from );
01023 client->damage_fromWorld = qfalse;
01024 } else {
01025 VectorCopy ( targ->r.currentOrigin, client->damage_from );
01026 client->damage_fromWorld = qtrue;
01027 }
01028 }
01029
01030 // See if it's the player hurting the emeny flag carrier
01031 #ifdef MISSIONPACK
01032 if( g_gametype.integer == GT_CTF || g_gametype.integer == GT_1FCTF ) {
01033 #else
01034 if( g_gametype.integer == GT_CTF) {
01035 #endif
01036 Team_CheckHurtCarrier(targ, attacker);
01037 }
01038
01039 if (targ->client) {
01040 // set the last client who damaged the target
01041 targ->client->lasthurt_client = attacker->s.number;
01042 targ->client->lasthurt_mod = mod;
01043 }
01044
01045 // do the damage
01046 if (take) {
01047 targ->health = targ->health - take;
01048 if ( targ->client ) {
01049 targ->client->ps.stats[STAT_HEALTH] = targ->health;
01050 }
01051
01052 if ( targ->health <= 0 ) {
01053 if ( client )
01054 targ->flags |= FL_NO_KNOCKBACK;
01055
01056 if (targ->health < -999)
01057 targ->health = -999;
01058
01059 targ->enemy = attacker;
01060 targ->die (targ, inflictor, attacker, take, mod);
01061 return;
01062 } else if ( targ->pain ) {
01063 targ->pain (targ, attacker, take);
01064 }
01065 }
01066
01067 }
|
Here is the call graph for this function:

|
||||||||||||||||||||||||||||
|
Definition at line 1133 of file g_combat.c. References entityShared_t::absmax, entityShared_t::absmin, CanDamage(), entityShared_t::currentOrigin, DAMAGE_RADIUS, e, G_Damage(), g_entities, gentity_t, i, LogAccuracyHit(), MAX_GENTITIES, NULL, points, qboolean, gentity_s::r, gentity_s::takedamage, trap_EntitiesInBox(), v, vec3_t, VectorLength(), and VectorSubtract. Referenced by G_ExplodeMissile(), and G_MissileImpact(). 01134 {
01135 float points, dist;
01136 gentity_t *ent;
01137 int entityList[MAX_GENTITIES];
01138 int numListedEntities;
01139 vec3_t mins, maxs;
01140 vec3_t v;
01141 vec3_t dir;
01142 int i, e;
01143 qboolean hitClient = qfalse;
01144
01145 if ( radius < 1 ) {
01146 radius = 1;
01147 }
01148
01149 for ( i = 0 ; i < 3 ; i++ ) {
01150 mins[i] = origin[i] - radius;
01151 maxs[i] = origin[i] + radius;
01152 }
01153
01154 numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
01155
01156 for ( e = 0 ; e < numListedEntities ; e++ ) {
01157 ent = &g_entities[entityList[ e ]];
01158
01159 if (ent == ignore)
01160 continue;
01161 if (!ent->takedamage)
01162 continue;
01163
01164 // find the distance from the edge of the bounding box
01165 for ( i = 0 ; i < 3 ; i++ ) {
01166 if ( origin[i] < ent->r.absmin[i] ) {
01167 v[i] = ent->r.absmin[i] - origin[i];
01168 } else if ( origin[i] > ent->r.absmax[i] ) {
01169 v[i] = origin[i] - ent->r.absmax[i];
01170 } else {
01171 v[i] = 0;
01172 }
01173 }
01174
01175 dist = VectorLength( v );
01176 if ( dist >= radius ) {
01177 continue;
01178 }
01179
01180 points = damage * ( 1.0 - dist / radius );
01181
01182 if( CanDamage (ent, origin) ) {
01183 if( LogAccuracyHit( ent, attacker ) ) {
01184 hitClient = qtrue;
01185 }
01186 VectorSubtract (ent->r.currentOrigin, origin, dir);
01187 // push the center of mass higher than the origin so players
01188 // get knocked into the air more
01189 dir[2] += 24;
01190 G_Damage (ent, NULL, attacker, dir, origin, (int)points, DAMAGE_RADIUS, mod);
01191 }
01192 }
01193
01194 return hitClient;
01195 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 242 of file g_combat.c. References gentity_s::activator, gentity_s::classname, entityState_s::eType, EV_GIB_PLAYER, G_AddEvent(), g_entities, G_FreeEntity(), gentity_t, i, gentity_s::inuse, gentity_s::s, strcmp(), and gentity_s::takedamage. Referenced by body_die(), and player_die(). 00242 {
00243 gentity_t *ent;
00244 int i;
00245
00246 //if this entity still has kamikaze
00247 if (self->s.eFlags & EF_KAMIKAZE) {
00248 // check if there is a kamikaze timer around for this owner
00249 for (i = 0; i < MAX_GENTITIES; i++) {
00250 ent = &g_entities[i];
00251 if (!ent->inuse)
00252 continue;
00253 if (ent->activator != self)
00254 continue;
00255 if (strcmp(ent->classname, "kamikaze timer"))
00256 continue;
00257 G_FreeEntity(ent);
00258 break;
00259 }
00260 }
00261 G_AddEvent( self, EV_GIB_PLAYER, killer );
00262 self->takedamage = qfalse;
00263 self->s.eType = ET_INVISIBLE;
00264 self->r.contents = 0;
00265 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 217 of file g_combat.c. References gentity_t, entityState_s::pos, gclient_s::ps, gentity_s::s, playerState_s::stats, trajectory_t::trBase, vec3_t, VectorSubtract, and vectoyaw(). Referenced by player_die(). 00217 {
00218 vec3_t dir;
00219 vec3_t angles;
00220
00221 if ( attacker && attacker != self ) {
00222 VectorSubtract (attacker->s.pos.trBase, self->s.pos.trBase, dir);
00223 } else if ( inflictor && inflictor != self ) {
00224 VectorSubtract (inflictor->s.pos.trBase, self->s.pos.trBase, dir);
00225 } else {
00226 self->client->ps.stats[STAT_DEAD_YAW] = self->s.angles[YAW];
00227 return;
00228 }
00229
00230 self->client->ps.stats[STAT_DEAD_YAW] = vectoyaw ( dir );
00231
00232 angles[YAW] = vectoyaw ( dir );
00233 angles[PITCH] = 0;
00234 angles[ROLL] = 0;
00235 }
|
Here is the call graph for this function:

|
||||||||||||||||||||||||
|
Definition at line 439 of file g_combat.c. References AddScore(), entityState_s::angles, CheckAlmostCapture(), CheckAlmostScored(), gentity_s::client, level_locals_t::clients, Cmd_Score_f(), clientPersistant_t::connected, entityShared_t::currentOrigin, EF_AWARD_ASSIST, EF_AWARD_DEFEND, EF_AWARD_EXCELLENT, EF_AWARD_GAUNTLET, EF_AWARD_IMPRESSIVE, playerState_s::eFlags, EV_DEATH1, EV_OBITUARY, entityState_s::eventParm, G_AddEvent(), g_blood, g_entities, g_gametype, G_LogPrintf(), G_TempEntity(), gclient_t, gentity_t, GIB_HEALTH, GibEntity(), gclient_s::hook, i, vmCvar_t::integer, level_locals_t::intermissiontime, gclient_s::lastkilled_client, gclient_s::lastKillTime, level, LookAtKiller(), level_locals_t::maxclients, memset(), modNames, clientPersistant_t::netname, entityState_s::number, OnSameTeam(), entityState_s::otherEntityNum, entityState_s::otherEntityNum2, gclient_s::pers, playerState_s::persistant, playerState_s::powerups, gclient_s::ps, gentity_s::r, gclient_s::respawnTime, gclient_s::rewardTime, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, clientSession_t::spectatorClient, entityShared_t::svFlags, TEAM_BLUE, Team_FragBonuses(), TEAM_FREE, TEAM_RED, Team_ReturnFlag(), level_locals_t::time, TossClientCubes(), TossClientItems(), trap_LinkEntity(), trap_PointContents(), VectorCopy, playerState_s::viewangles, and Weapon_HookFree(). Referenced by Cmd_Kill_f(), and SetTeam(). 00439 {
00440 gentity_t *ent;
00441 int anim;
00442 int contents;
00443 int killer;
00444 int i;
00445 char *killerName, *obit;
00446
00447 if ( self->client->ps.pm_type == PM_DEAD ) {
00448 return;
00449 }
00450
00451 if ( level.intermissiontime ) {
00452 return;
00453 }
00454
00455 // check for an almost capture
00456 CheckAlmostCapture( self, attacker );
00457 // check for a player that almost brought in cubes
00458 CheckAlmostScored( self, attacker );
00459
00460 if (self->client && self->client->hook) {
00461 Weapon_HookFree(self->client->hook);
00462 }
00463 #ifdef MISSIONPACK
00464 if ((self->client->ps.eFlags & EF_TICKING) && self->activator) {
00465 self->client->ps.eFlags &= ~EF_TICKING;
00466 self->activator->think = G_FreeEntity;
00467 self->activator->nextthink = level.time;
00468 }
00469 #endif
00470 self->client->ps.pm_type = PM_DEAD;
00471
00472 if ( attacker ) {
00473 killer = attacker->s.number;
00474 if ( attacker->client ) {
00475 killerName = attacker->client->pers.netname;
00476 } else {
00477 killerName = "<non-client>";
00478 }
00479 } else {
00480 killer = ENTITYNUM_WORLD;
00481 killerName = "<world>";
00482 }
00483
00484 if ( killer < 0 || killer >= MAX_CLIENTS ) {
00485 killer = ENTITYNUM_WORLD;
00486 killerName = "<world>";
00487 }
00488
00489 if ( meansOfDeath < 0 || meansOfDeath >= sizeof( modNames ) / sizeof( modNames[0] ) ) {
00490 obit = "<bad obituary>";
00491 } else {
00492 obit = modNames[ meansOfDeath ];
00493 }
00494
00495 G_LogPrintf("Kill: %i %i %i: %s killed %s by %s\n",
00496 killer, self->s.number, meansOfDeath, killerName,
00497 self->client->pers.netname, obit );
00498
00499 // broadcast the death event to everyone
00500 ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY );
00501 ent->s.eventParm = meansOfDeath;
00502 ent->s.otherEntityNum = self->s.number;
00503 ent->s.otherEntityNum2 = killer;
00504 ent->r.svFlags = SVF_BROADCAST; // send to everyone
00505
00506 self->enemy = attacker;
00507
00508 self->client->ps.persistant[PERS_KILLED]++;
00509
00510 if (attacker && attacker->client) {
00511 attacker->client->lastkilled_client = self->s.number;
00512
00513 if ( attacker == self || OnSameTeam (self, attacker ) ) {
00514 AddScore( attacker, self->r.currentOrigin, -1 );
00515 } else {
00516 AddScore( attacker, self->r.currentOrigin, 1 );
00517
00518 if( meansOfDeath == MOD_GAUNTLET ) {
00519
00520 // play humiliation on player
00521 attacker->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT]++;
00522
00523 // add the sprite over the player's head
00524 attacker->client->ps.eFlags &= ~(EF_AWARD_IMPRESSIVE | EF_AWARD_EXCELLENT | EF_AWARD_GAUNTLET | EF_AWARD_ASSIST | EF_AWARD_DEFEND | EF_AWARD_CAP );
00525 attacker->client->ps.eFlags |= EF_AWARD_GAUNTLET;
00526 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00527
00528 // also play humiliation on target
00529 self->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_GAUNTLETREWARD;
00530 }
00531
00532 // check for two kills in a short amount of time
00533 // if this is close enough to the last kill, give a reward sound
00534 if ( level.time - attacker->client->lastKillTime < CARNAGE_REWARD_TIME ) {
00535 // play excellent on player
00536 attacker->client->ps.persistant[PERS_EXCELLENT_COUNT]++;
00537
00538 // add the sprite over the player's head
00539 attacker->client->ps.eFlags &= ~(EF_AWARD_IMPRESSIVE | EF_AWARD_EXCELLENT | EF_AWARD_GAUNTLET | EF_AWARD_ASSIST | EF_AWARD_DEFEND | EF_AWARD_CAP );
00540 attacker->client->ps.eFlags |= EF_AWARD_EXCELLENT;
00541 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00542 }
00543 attacker->client->lastKillTime = level.time;
00544
00545 }
00546 } else {
00547 AddScore( self, self->r.currentOrigin, -1 );
00548 }
00549
00550 // Add team bonuses
00551 Team_FragBonuses(self, inflictor, attacker);
00552
00553 // if I committed suicide, the flag does not fall, it returns.
00554 if (meansOfDeath == MOD_SUICIDE) {
00555 if ( self->client->ps.powerups[PW_NEUTRALFLAG] ) { // only happens in One Flag CTF
00556 Team_ReturnFlag( TEAM_FREE );
00557 self->client->ps.powerups[PW_NEUTRALFLAG] = 0;
00558 }
00559 else if ( self->client->ps.powerups[PW_REDFLAG] ) { // only happens in standard CTF
00560 Team_ReturnFlag( TEAM_RED );
00561 self->client->ps.powerups[PW_REDFLAG] = 0;
00562 }
00563 else if ( self->client->ps.powerups[PW_BLUEFLAG] ) { // only happens in standard CTF
00564 Team_ReturnFlag( TEAM_BLUE );
00565 self->client->ps.powerups[PW_BLUEFLAG] = 0;
00566 }
00567 }
00568
00569 // if client is in a nodrop area, don't drop anything (but return CTF flags!)
00570 contents = trap_PointContents( self->r.currentOrigin, -1 );
00571 if ( !( contents & CONTENTS_NODROP )) {
00572 TossClientItems( self );
00573 }
00574 else {
00575 if ( self->client->ps.powerups[PW_NEUTRALFLAG] ) { // only happens in One Flag CTF
00576 Team_ReturnFlag( TEAM_FREE );
00577 }
00578 else if ( self->client->ps.powerups[PW_REDFLAG] ) { // only happens in standard CTF
00579 Team_ReturnFlag( TEAM_RED );
00580 }
00581 else if ( self->client->ps.powerups[PW_BLUEFLAG] ) { // only happens in standard CTF
00582 Team_ReturnFlag( TEAM_BLUE );
00583 }
00584 }
00585 #ifdef MISSIONPACK
00586 TossClientPersistantPowerups( self );
00587 if( g_gametype.integer == GT_HARVESTER ) {
00588 TossClientCubes( self );
00589 }
00590 #endif
00591
00592 Cmd_Score_f( self ); // show scores
00593 // send updated scores to any clients that are following this one,
00594 // or they would get stale scoreboards
00595 for ( i = 0 ; i < level.maxclients ; i++ ) {
00596 gclient_t *client;
00597
00598 client = &level.clients[i];
00599 if ( client->pers.connected != CON_CONNECTED ) {
00600 continue;
00601 }
00602 if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
00603 continue;
00604 }
00605 if ( client->sess.spectatorClient == self->s.number ) {
00606 Cmd_Score_f( g_entities + i );
00607 }
00608 }
00609
00610 self->takedamage = qtrue; // can still be gibbed
00611
00612 self->s.weapon = WP_NONE;
00613 self->s.powerups = 0;
00614 self->r.contents = CONTENTS_CORPSE;
00615
00616 self->s.angles[0] = 0;
00617 self->s.angles[2] = 0;
00618 LookAtKiller (self, inflictor, attacker);
00619
00620 VectorCopy( self->s.angles, self->client->ps.viewangles );
00621
00622 self->s.loopSound = 0;
00623
00624 self->r.maxs[2] = -8;
00625
00626 // don't allow respawn until the death anim is done
00627 // g_forcerespawn may force spawning at some later time
00628 self->client->respawnTime = level.time + 1700;
00629
00630 // remove powerups
00631 memset( self->client->ps.powerups, 0, sizeof(self->client->ps.powerups) );
00632
00633 // never gib in a nodrop
00634 if ( (self->health <= GIB_HEALTH && !(contents & CONTENTS_NODROP) && g_blood.integer) || meansOfDeath == MOD_SUICIDE) {
00635 // gib death
00636 GibEntity( self, killer );
00637 } else {
00638 // normal death
00639 static int i;
00640
00641 switch ( i ) {
00642 case 0:
00643 anim = BOTH_DEATH1;
00644 break;
00645 case 1:
00646 anim = BOTH_DEATH2;
00647 break;
00648 case 2:
00649 default:
00650 anim = BOTH_DEATH3;
00651 break;
00652 }
00653
00654 // for the no-blood option, we need to prevent the health
00655 // from going to gib level
00656 if ( self->health <= GIB_HEALTH ) {
00657 self->health = GIB_HEALTH+1;
00658 }
00659
00660 self->client->ps.legsAnim =
00661 ( ( self->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
00662 self->client->ps.torsoAnim =
00663 ( ( self->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
00664
00665 G_AddEvent( self, EV_DEATH1 + i, killer );
00666
00667 // the body can still be gibbed
00668 self->die = body_die;
00669
00670 // globally cycle through the different death animations
00671 i = ( i + 1 ) % 3;
00672
00673 #ifdef MISSIONPACK
00674 if (self->s.eFlags & EF_KAMIKAZE) {
00675 Kamikaze_DeathTimer( self );
00676 }
00677 #endif
00678 }
00679
00680 trap_LinkEntity (self);
00681
00682 }
|
Here is the call graph for this function:

|