// Records weapon headshots void G_addStatsHeadShot(gentity_t *attacker, int mod) { #ifndef DEBUG_STATS if(g_gamestate.integer != GS_PLAYING) { return; } #endif if(!attacker || !attacker->client) return; attacker->client->sess.aWeaponStats[G_weapStatIndex_MOD(mod)].headshots++; }
// Records accuracy, damage, and kill/death stats. void G_addStats(gentity_t *targ, gentity_t *attacker, int dmg_ref, int mod) { int dmg, ref; if (!targ || !targ->client) { return; } // Keep track of only active player-to-player interactions in a real game if ( #ifndef DEBUG_STATS g_gamestate.integer != GS_PLAYING || #endif mod == MOD_SWITCHTEAM || (g_gametype.integer >= GT_WOLF && (targ->client->ps.pm_flags & PMF_LIMBO)) || // FIXME: inspect - this is a bit odd by gametype (g_gametype.integer < GT_WOLF && (targ->s.eFlags == EF_DEAD || targ->client->ps.pm_type == PM_DEAD))) { return; } // Special hack for intentional gibbage if (targ->health <= 0 && targ->client->ps.pm_type == PM_DEAD) { if (attacker && attacker->client) { int x; ref = G_weapStatIndex_MOD(mod); x = attacker->client->sess.aWeaponStats[ref].atts--; if (x < 1) { attacker->client->sess.aWeaponStats[ref].atts = 1; } } return; } // G_Printf("mod: %d, Index: %d, dmg: %d\n", mod, G_weapStatIndex_MOD(mod), dmg_ref); // Selfkills only affect the player specifically if (targ == attacker || !attacker || !attacker->client || mod == MOD_SUICIDE) // FIXME: inspect world kills count as selfkill? { if (targ->health <= 0) { targ->client->sess.selfkills++; } #ifdef DEBUG_STATS if (!attacker || !attacker->client) #endif return; } // Telefrags only add 100 points.. not 100k!! if (mod == MOD_TELEFRAG) { dmg = 100; } else { dmg = dmg_ref; } // Player team stats if (g_gametype.integer >= GT_WOLF && targ->client->sess.sessionTeam == attacker->client->sess.sessionTeam) { attacker->client->sess.team_damage_given += dmg; targ->client->sess.team_damage_received += dmg; if (targ->health <= 0) { attacker->client->sess.team_kills++; } #ifndef DEBUG_STATS return; #endif } // General player stats if (mod != MOD_SYRINGE) { attacker->client->sess.damage_given += dmg; targ->client->sess.damage_received += dmg; if (targ->health <= 0) { attacker->client->sess.kills++; targ->client->sess.deaths++; } } // Player weapon stats ref = G_weapStatIndex_MOD(mod); if (dmg > 0) { attacker->client->sess.aWeaponStats[ref].hits++; } if (targ->health <= 0) { attacker->client->sess.aWeaponStats[ref].kills++; targ->client->sess.aWeaponStats[ref].deaths++; } }
// Records accuracy, damage, and kill/death stats. void G_addStats(gentity_t *targ, gentity_t *attacker, int dmg_ref, int mod) { int dmg, ref; //forty - #349 - Moved this to the end of ClientEndFrame to prevent invisible clips from forming. //float teamHitPct = 0; //int banTime = 0; qboolean onSameTeam; int limbo_health = FORCE_LIMBO_HEALTH; /* // Keep track of only active player-to-player interactions in a real game if(!targ || !targ->client || #ifndef DEBUG_STATS g_gamestate.integer != GS_PLAYING || #endif mod == MOD_SWITCHTEAM || (g_gametype.integer >= GT_WOLF && (targ->client->ps.pm_flags & PMF_LIMBO)) || (g_gametype.integer < GT_WOLF && (targ->s.eFlags == EF_DEAD || targ->client->ps.pm_type == PM_DEAD))) { return; } */ if(!targ || !targ->client) return; // Special hack for intentional gibbage if(targ->health <= 0 && targ->client->ps.pm_type == PM_DEAD) { // tjw: I'm not sure what the mod check is for, but it was // in the original etmain, so I'm leaving it. if((g_stats.integer & STATF_CORPSE_NO_SHOT) && mod < MOD_CROSS && attacker && attacker->client) { int idx = G_weapStatIndex_MOD(mod); int x; x = attacker->client->sess.aWeaponStats[idx].atts--; if(x < 1) attacker->client->sess.aWeaponStats[idx].atts = 1; } if(g_stats.integer & STATF_CORPSE_NO_HIT) { return; } } if(g_gamestate.integer != GS_PLAYING) return; if(mod == MOD_SWITCHTEAM) return; if((targ->client->ps.pm_flags & PMF_LIMBO)) return; if((targ->client->ps.eFlags & EF_DEAD) && !(targ->client->ps.eFlags & EF_PLAYDEAD) && attacker->client) { attacker->client->sess.aWeaponStats[G_weapStatIndex_MOD(mod)].hits++; return; } // G_Printf("mod: %d, Index: %d, dmg: %d\n", mod, G_weapStatIndex_MOD(mod), dmg_ref); // Suicides only affect the player specifically if(targ == attacker || !attacker || !attacker->client || mod == MOD_SUICIDE) { if(targ->health <= 0) targ->client->sess.suicides++; #ifdef DEBUG_STATS if(!attacker || !attacker->client) #endif return; } // Telefrags only add 100 points.. not 100k!! if(mod == MOD_TELEFRAG) dmg = 100; else dmg = dmg_ref; // tjw: you can't do more damage than the victim has to give if(g_forceLimboHealth.integer == 1) limbo_health = FORCE_LIMBO_HEALTH2; //G_Printf("Damage before : %d\n", dmg); //G_Printf("targ->health : %d\n", targ->health); //G_Printf("limbo_health : %d\n", limbo_health); if(targ->health > 0) { if(dmg > (targ->health + abs(limbo_health))) dmg = (targ->health + abs(limbo_health)); } else { /* - forty this gives negative damage stats. if(dmg > (abs(limbo_health) - abs(targ->health))) dmg = (abs(limbo_health) - abs(targ->health)); */ // forty - I guess don't let them add up more than gib health with a single shot. // since we don't know what the health was at before the add-stats. if(dmg > abs(GIB_HEALTH)) dmg = abs(GIB_HEALTH); } //G_Printf("Damage after : %d\n", dmg); // Player team stats /* if(g_gametype.integer >= GT_WOLF && targ->client->sess.sessionTeam == attacker->client->sess.sessionTeam) { attacker->client->sess.team_damage += dmg; if(targ->health <= 0) attacker->client->sess.team_kills++; #ifndef DEBUG_STATS return; #endif }*/ if(g_gametype.integer < GT_WOLF) return; onSameTeam = targ->client->sess.sessionTeam == attacker->client->sess.sessionTeam; // forty - #607 - Merge in Density's damage received display code if( onSameTeam ) { switch(mod) { case MOD_SYRINGE: break; case MOD_FLAMETHROWER: attacker->client->sess.team_damage_given += dmg; targ->client->sess.team_damage_received += dmg; attacker->client->sess.team_hits += 0.1f; attacker->client->sess.hits += 0.1f; break; case MOD_LANDMINE: attacker->client->sess.team_damage_given += dmg; targ->client->sess.team_damage_received += dmg; attacker->client->sess.team_hits += 0.5f; attacker->client->sess.hits += 0.5f; break; default: attacker->client->sess.team_damage_given += dmg; targ->client->sess.team_damage_received += dmg; attacker->client->sess.team_hits++; attacker->client->sess.hits++; } if(targ->health <= 0) attacker->client->sess.team_kills++; } else { attacker->client->sess.damage_given += dmg; switch(mod) { case MOD_POISON: // only count initial syringe hit // not subsequent MOD_POISON G_Damage calls if(!targ->client->pmext.poisoned) { attacker->client->sess.hits++; } break; case MOD_FLAMETHROWER: attacker->client->sess.hits += 0.1f; break; default: attacker->client->sess.hits++; } targ->client->sess.damage_received += dmg; if(targ->health <= 0) { attacker->client->sess.kills++; targ->client->sess.deaths++; // josh: track kill rating with enhanced glicko if (g_killRating.integer) { G_UpdateKillRatings(attacker,targ,mod); } if (g_killRating.integer & KILL_RATING_DATASET) { G_LogKillGUID(attacker,targ,mod); } } } // General player stats /* if(mod != MOD_SYRINGE && targ->client->sess.sessionTeam != attacker->client->sess.sessionTeam) { attacker->client->sess.damage_given += dmg; targ->client->sess.damage_received += dmg; if(targ->health <= 0) { attacker->client->sess.kills++; targ->client->sess.deaths++; } */ // Player weapon stats ref = G_weapStatIndex_MOD(mod); // tjw: only record syringe hits for the initial hit if(dmg > 0 && !targ->client->pmext.poisoned) attacker->client->sess.aWeaponStats[ref].hits++; // matt: strict shrub implementation doesn't count weapon kills/deaths // if done to a teammate if(targ->health <= 0 && !onSameTeam) { attacker->client->sess.aWeaponStats[ref].kills++; targ->client->sess.aWeaponStats[ref].deaths++; } /* forty - #349 - Moved this to the end of ClientEndFrame to prevent invisible clips from forming. if ( g_teamDamageRestriction.integer > 0 && !G_shrubbot_permission(attacker, SBF_IMMUNITY)) { if ( attacker->client->sess.hits > 0 ) teamHitPct = (attacker->client->sess.team_hits / attacker->client->sess.hits)*(100); if ( attacker->client->sess.hits >= g_minHits.integer && teamHitPct > g_teamDamageRestriction.integer ) { if ( g_autoTempBan.integer && g_autoTempBanTime.integer ) banTime = g_autoTempBanTime.integer; // reset team_hits and hits to avoid // vicious kick/rejoin/kick cycle attacker->client->sess.team_hits = 0.f; attacker->client->sess.hits = 0.f; // forty - enforce the temp ban consistently using shrubbot. if(banTime) G_shrubbot_tempban(attacker-g_entities,"Temporarily banned - Stop team killing!", banTime); trap_DropClient(attacker-g_entities, va("Kicked for %d seconds for" " excessive team damage", banTime),banTime); } } */ }