reaction/code/game/g_rankings.c
2013-01-04 13:27:22 +00:00

1030 lines
25 KiB
C

//-----------------------------------------------------------------------------
//
// $Id$
//
//-----------------------------------------------------------------------------
//
// $Log$
// Revision 1.7 2005/02/15 16:33:39 makro
// Tons of updates (entity tree attachment system, UI vectors)
//
// Revision 1.6 2002/07/22 06:32:43 niceass
// cleaned up the powerup code
//
// Revision 1.5 2002/06/16 20:06:14 jbravo
// Reindented all the source files with "indent -kr -ut -i8 -l120 -lc120 -sob -bad -bap"
//
// Revision 1.4 2002/01/11 19:48:30 jbravo
// Formatted the source in non DOS format.
//
// Revision 1.3 2001/12/31 16:28:42 jbravo
// I made a Booboo with the Log tag.
//
//
//-----------------------------------------------------------------------------
// g_rankings.c -- reports for global rankings system
#include "g_local.h"
#include "g_rankings.h"
/*
================
G_RankRunFrame
================
*/
void G_RankRunFrame()
{
gentity_t *ent;
gentity_t *ent2;
grank_status_t old_status;
grank_status_t status;
int time;
int i;
int j;
if (!trap_RankCheckInit()) {
trap_RankBegin(GR_GAMEKEY);
}
trap_RankPoll();
if (trap_RankActive()) {
for (i = 0; i < level.maxclients; i++) {
ent = &(g_entities[i]);
if (!ent->inuse)
continue;
if (ent->client == NULL)
continue;
if (ent->r.svFlags & SVF_BOT) {
// no bots in ranked games
trap_SendConsoleCommand(EXEC_INSERT, va("kick %s\n", ent->client->pers.netname));
continue;
}
old_status = ent->client->client_status;
status = trap_RankUserStatus(i);
if (ent->client->client_status != status) {
// inform client of current status
// not needed for client side log in
trap_SendServerCommand(i, va("rank_status %i\n", status));
if (i == 0) {
int j = 0;
}
ent->client->client_status = status;
}
switch (status) {
case QGR_STATUS_NEW:
case QGR_STATUS_SPECTATOR:
if (ent->client->sess.sessionTeam != TEAM_SPECTATOR) {
ent->client->sess.sessionTeam = TEAM_SPECTATOR;
ent->client->sess.spectatorState = SPECTATOR_FREE;
ClientSpawn(ent);
// make sure by now CS_GRAND rankingsGameID is ready
trap_SendServerCommand(i, va("rank_status %i\n", status));
trap_SendServerCommand(i, "rank_menu\n");
}
break;
case QGR_STATUS_NO_USER:
case QGR_STATUS_BAD_PASSWORD:
case QGR_STATUS_TIMEOUT:
case QGR_STATUS_NO_MEMBERSHIP:
case QGR_STATUS_INVALIDUSER:
case QGR_STATUS_ERROR:
if ((ent->r.svFlags & SVF_BOT) == 0) {
trap_RankUserReset(ent->s.clientNum);
}
break;
case QGR_STATUS_ACTIVE:
if ((ent->client->sess.sessionTeam == TEAM_SPECTATOR) && (g_gametype.integer < GT_TEAM)) {
SetTeam(ent, "free");
}
if (old_status != QGR_STATUS_ACTIVE) {
// player has just become active
for (j = 0; j < level.maxclients; j++) {
ent2 = &(g_entities[j]);
if (!ent2->inuse)
continue;
if (ent2->client == NULL)
continue;
if (ent2->r.svFlags & SVF_BOT)
continue;
if ((i != j) && (trap_RankUserStatus(j) == QGR_STATUS_ACTIVE)) {
trap_RankReportInt(i, j, QGR_KEY_PLAYED_WITH, 1, 0);
}
// send current scores so the player's rank will show
// up under the crosshair immediately
DeathmatchScoreboardMessage(ent2);
}
}
break;
default:
break;
}
}
// don't let ranked games last forever
if (((g_fraglimit.integer == 0) || (g_fraglimit.integer > 100)) &&
((g_timelimit.integer == 0) || (g_timelimit.integer > 1000))) {
trap_Cvar_Set("timelimit", "1000");
}
}
// tell time to clients so they can show current match rating
if (level.intermissiontime == 0) {
for (i = 0; i < level.maxclients; i++) {
ent = &(g_entities[i]);
if (ent->client == NULL) {
continue;
}
time = (level.time - ent->client->pers.enterTime) / 1000;
ent->client->ps.persistant[PERS_MATCH_TIME] = time;
}
}
}
/*
================
G_RankFireWeapon
================
*/
void G_RankFireWeapon(int self, int weapon)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
if (weapon == WP_GAUNTLET) {
// the gauntlet only "fires" when it actually hits something
return;
}
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED, 1, 1);
switch (weapon) {
case WP_MACHINEGUN:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_MACHINEGUN, 1, 1);
break;
case WP_SHOTGUN:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_SHOTGUN, 1, 1);
break;
case WP_GRENADE_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_GRENADE, 1, 1);
break;
case WP_ROCKET_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_ROCKET, 1, 1);
break;
case WP_LIGHTNING:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_LIGHTNING, 1, 1);
break;
case WP_RAILGUN:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_RAILGUN, 1, 1);
break;
case WP_PLASMAGUN:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_PLASMA, 1, 1);
break;
case WP_BFG:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_BFG, 1, 1);
break;
case WP_GRAPPLING_HOOK:
trap_RankReportInt(self, -1, QGR_KEY_SHOT_FIRED_GRAPPLE, 1, 1);
break;
default:
break;
}
}
/*
================
G_RankDamage
================
*/
void G_RankDamage(int self, int attacker, int damage, int means_of_death)
{
// state information to avoid counting each shotgun pellet as a hit
static int last_framenum = -1;
static int last_self = -1;
static int last_attacker = -1;
static int last_means_of_death = MOD_UNKNOWN;
qboolean new_hit;
int splash;
int key_hit;
int key_damage;
int key_splash;
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
new_hit = (level.framenum != last_framenum) ||
(self != last_self) || (attacker != last_attacker) || (means_of_death != last_means_of_death);
// update state information
last_framenum = level.framenum;
last_self = self;
last_attacker = attacker;
last_means_of_death = means_of_death;
// the gauntlet only "fires" when it actually hits something
if ((attacker != ENTITYNUM_WORLD) && (attacker != self) &&
(means_of_death == MOD_GAUNTLET) && (g_entities[attacker].client)) {
trap_RankReportInt(attacker, -1, QGR_KEY_SHOT_FIRED_GAUNTLET, 1, 1);
}
// don't track hazard damage, just deaths
switch (means_of_death) {
case MOD_WATER:
case MOD_SLIME:
case MOD_LAVA:
case MOD_CRUSH:
case MOD_TELEFRAG:
case MOD_FALLING:
case MOD_SUICIDE:
case MOD_TRIGGER_HURT:
return;
default:
//Makro - custom death message implies a trigger_hurt
if (means_of_death >= MOD_CUSTOM)
return;
break;
}
// get splash damage
switch (means_of_death) {
case MOD_GRENADE_SPLASH:
case MOD_ROCKET_SPLASH:
case MOD_PLASMA_SPLASH:
case MOD_BFG_SPLASH:
splash = damage;
break;
default:
splash = 0;
key_splash = -1;
break;
}
// hit, damage, and splash taken
switch (means_of_death) {
case MOD_GAUNTLET:
key_hit = QGR_KEY_HIT_TAKEN_GAUNTLET;
key_damage = QGR_KEY_DAMAGE_TAKEN_GAUNTLET;
break;
case MOD_MACHINEGUN:
key_hit = QGR_KEY_HIT_TAKEN_MACHINEGUN;
key_damage = QGR_KEY_DAMAGE_TAKEN_MACHINEGUN;
break;
case MOD_SHOTGUN:
key_hit = QGR_KEY_HIT_TAKEN_SHOTGUN;
key_damage = QGR_KEY_DAMAGE_TAKEN_SHOTGUN;
break;
case MOD_GRENADE:
case MOD_GRENADE_SPLASH:
key_hit = QGR_KEY_HIT_TAKEN_GRENADE;
key_damage = QGR_KEY_DAMAGE_TAKEN_GRENADE;
key_splash = QGR_KEY_SPLASH_TAKEN_GRENADE;
break;
case MOD_ROCKET:
case MOD_ROCKET_SPLASH:
key_hit = QGR_KEY_HIT_TAKEN_ROCKET;
key_damage = QGR_KEY_DAMAGE_TAKEN_ROCKET;
key_splash = QGR_KEY_SPLASH_TAKEN_ROCKET;
break;
case MOD_PLASMA:
case MOD_PLASMA_SPLASH:
key_hit = QGR_KEY_HIT_TAKEN_PLASMA;
key_damage = QGR_KEY_DAMAGE_TAKEN_PLASMA;
key_splash = QGR_KEY_SPLASH_TAKEN_PLASMA;
break;
case MOD_RAILGUN:
key_hit = QGR_KEY_HIT_TAKEN_RAILGUN;
key_damage = QGR_KEY_DAMAGE_TAKEN_RAILGUN;
break;
case MOD_LIGHTNING:
key_hit = QGR_KEY_HIT_TAKEN_LIGHTNING;
key_damage = QGR_KEY_DAMAGE_TAKEN_LIGHTNING;
break;
case MOD_BFG:
case MOD_BFG_SPLASH:
key_hit = QGR_KEY_HIT_TAKEN_BFG;
key_damage = QGR_KEY_DAMAGE_TAKEN_BFG;
key_splash = QGR_KEY_SPLASH_TAKEN_BFG;
break;
case MOD_GRAPPLE:
key_hit = QGR_KEY_HIT_TAKEN_GRAPPLE;
key_damage = QGR_KEY_DAMAGE_TAKEN_GRAPPLE;
break;
default:
key_hit = QGR_KEY_HIT_TAKEN_UNKNOWN;
key_damage = QGR_KEY_DAMAGE_TAKEN_UNKNOWN;
break;
}
// report general and specific hit taken
if (new_hit) {
trap_RankReportInt(self, -1, QGR_KEY_HIT_TAKEN, 1, 1);
trap_RankReportInt(self, -1, key_hit, 1, 1);
}
// report general and specific damage taken
trap_RankReportInt(self, -1, QGR_KEY_DAMAGE_TAKEN, damage, 1);
trap_RankReportInt(self, -1, key_damage, damage, 1);
// report general and specific splash taken
if (splash != 0) {
trap_RankReportInt(self, -1, QGR_KEY_SPLASH_TAKEN, splash, 1);
trap_RankReportInt(self, -1, key_splash, splash, 1);
}
// hit, damage, and splash given
if ((attacker != ENTITYNUM_WORLD) && (attacker != self)) {
switch (means_of_death) {
case MOD_GAUNTLET:
key_hit = QGR_KEY_HIT_GIVEN_GAUNTLET;
key_damage = QGR_KEY_DAMAGE_GIVEN_GAUNTLET;
break;
case MOD_MACHINEGUN:
key_hit = QGR_KEY_HIT_GIVEN_MACHINEGUN;
key_damage = QGR_KEY_DAMAGE_GIVEN_MACHINEGUN;
break;
case MOD_SHOTGUN:
key_hit = QGR_KEY_HIT_GIVEN_SHOTGUN;
key_damage = QGR_KEY_DAMAGE_GIVEN_SHOTGUN;
break;
case MOD_GRENADE:
case MOD_GRENADE_SPLASH:
key_hit = QGR_KEY_HIT_GIVEN_GRENADE;
key_damage = QGR_KEY_DAMAGE_GIVEN_GRENADE;
key_splash = QGR_KEY_SPLASH_GIVEN_GRENADE;
break;
case MOD_ROCKET:
case MOD_ROCKET_SPLASH:
key_hit = QGR_KEY_HIT_GIVEN_ROCKET;
key_damage = QGR_KEY_DAMAGE_GIVEN_ROCKET;
key_splash = QGR_KEY_SPLASH_GIVEN_ROCKET;
break;
case MOD_PLASMA:
case MOD_PLASMA_SPLASH:
key_hit = QGR_KEY_HIT_GIVEN_PLASMA;
key_damage = QGR_KEY_DAMAGE_GIVEN_PLASMA;
key_splash = QGR_KEY_SPLASH_GIVEN_PLASMA;
break;
case MOD_RAILGUN:
key_hit = QGR_KEY_HIT_GIVEN_RAILGUN;
key_damage = QGR_KEY_DAMAGE_GIVEN_RAILGUN;
break;
case MOD_LIGHTNING:
key_hit = QGR_KEY_HIT_GIVEN_LIGHTNING;
key_damage = QGR_KEY_DAMAGE_GIVEN_LIGHTNING;
break;
case MOD_BFG:
case MOD_BFG_SPLASH:
key_hit = QGR_KEY_HIT_GIVEN_BFG;
key_damage = QGR_KEY_DAMAGE_GIVEN_BFG;
key_splash = QGR_KEY_SPLASH_GIVEN_BFG;
break;
case MOD_GRAPPLE:
key_hit = QGR_KEY_HIT_GIVEN_GRAPPLE;
key_damage = QGR_KEY_DAMAGE_GIVEN_GRAPPLE;
break;
default:
key_hit = QGR_KEY_HIT_GIVEN_UNKNOWN;
key_damage = QGR_KEY_DAMAGE_GIVEN_UNKNOWN;
break;
}
// report general and specific hit given
// jwu 8/26/00
// had a case where attacker is 245 which is grnadeshooter attacker is
// g_entities index not necessarilly clientnum
if (g_entities[attacker].client) {
if (new_hit) {
trap_RankReportInt(attacker, -1, QGR_KEY_HIT_GIVEN, 1, 1);
trap_RankReportInt(attacker, -1, key_hit, 1, 1);
}
// report general and specific damage given
trap_RankReportInt(attacker, -1, QGR_KEY_DAMAGE_GIVEN, damage, 1);
trap_RankReportInt(attacker, -1, key_damage, damage, 1);
// report general and specific splash given
if (splash != 0) {
trap_RankReportInt(attacker, -1, QGR_KEY_SPLASH_GIVEN, splash, 1);
trap_RankReportInt(attacker, -1, key_splash, splash, 1);
}
}
}
// friendly fire
if ((attacker != self) &&
OnSameTeam(&(g_entities[self]), &(g_entities[attacker])) && (g_entities[attacker].client)) {
// report teammate hit
if (new_hit) {
trap_RankReportInt(self, -1, QGR_KEY_TEAMMATE_HIT_TAKEN, 1, 1);
trap_RankReportInt(attacker, -1, QGR_KEY_TEAMMATE_HIT_GIVEN, 1, 1);
}
// report teammate damage
trap_RankReportInt(self, -1, QGR_KEY_TEAMMATE_DAMAGE_TAKEN, damage, 1);
trap_RankReportInt(attacker, -1, QGR_KEY_TEAMMATE_DAMAGE_GIVEN, damage, 1);
// report teammate splash
if (splash != 0) {
trap_RankReportInt(self, -1, QGR_KEY_TEAMMATE_SPLASH_TAKEN, splash, 1);
trap_RankReportInt(attacker, -1, QGR_KEY_TEAMMATE_SPLASH_GIVEN, splash, 1);
}
}
}
/*
================
G_RankPlayerDie
================
*/
void G_RankPlayerDie(int self, int attacker, int means_of_death)
{
int p1;
int p2;
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
if (attacker == ENTITYNUM_WORLD) {
p1 = self;
p2 = -1;
trap_RankReportInt(p1, p2, QGR_KEY_HAZARD_DEATH, 1, 1);
switch (means_of_death) {
case MOD_WATER:
trap_RankReportInt(p1, p2, QGR_KEY_WATER, 1, 1);
break;
case MOD_SLIME:
trap_RankReportInt(p1, p2, QGR_KEY_SLIME, 1, 1);
break;
case MOD_LAVA:
trap_RankReportInt(p1, p2, QGR_KEY_LAVA, 1, 1);
break;
case MOD_CRUSH:
trap_RankReportInt(p1, p2, QGR_KEY_CRUSH, 1, 1);
break;
case MOD_TELEFRAG:
trap_RankReportInt(p1, p2, QGR_KEY_TELEFRAG, 1, 1);
break;
case MOD_FALLING:
trap_RankReportInt(p1, p2, QGR_KEY_FALLING, 1, 1);
break;
case MOD_SUICIDE:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_CMD, 1, 1);
break;
case MOD_TRIGGER_HURT:
trap_RankReportInt(p1, p2, QGR_KEY_TRIGGER_HURT, 1, 1);
break;
default:
//Makro - custom msg implies a trigger_hurt
if (means_of_death >= MOD_CUSTOM)
{
trap_RankReportInt(p1, p2, QGR_KEY_TRIGGER_HURT, 1, 1);
} else {
trap_RankReportInt(p1, p2, QGR_KEY_HAZARD_MISC, 1, 1);
}
break;
}
} else if (attacker == self) {
p1 = self;
p2 = -1;
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE, 1, 1);
switch (means_of_death) {
case MOD_GAUNTLET:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_GAUNTLET, 1, 1);
break;
case MOD_MACHINEGUN:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_MACHINEGUN, 1, 1);
break;
case MOD_SHOTGUN:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_SHOTGUN, 1, 1);
break;
case MOD_GRENADE:
case MOD_GRENADE_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_GRENADE, 1, 1);
break;
case MOD_ROCKET:
case MOD_ROCKET_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_ROCKET, 1, 1);
break;
case MOD_PLASMA:
case MOD_PLASMA_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_PLASMA, 1, 1);
break;
case MOD_RAILGUN:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_RAILGUN, 1, 1);
break;
case MOD_LIGHTNING:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_LIGHTNING, 1, 1);
break;
case MOD_BFG:
case MOD_BFG_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_BFG, 1, 1);
break;
case MOD_GRAPPLE:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_GRAPPLE, 1, 1);
break;
default:
trap_RankReportInt(p1, p2, QGR_KEY_SUICIDE_UNKNOWN, 1, 1);
break;
}
} else {
p1 = attacker;
p2 = self;
trap_RankReportInt(p1, p2, QGR_KEY_FRAG, 1, 1);
switch (means_of_death) {
case MOD_GAUNTLET:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_GAUNTLET, 1, 1);
break;
case MOD_MACHINEGUN:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_MACHINEGUN, 1, 1);
break;
case MOD_SHOTGUN:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_SHOTGUN, 1, 1);
break;
case MOD_GRENADE:
case MOD_GRENADE_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_GRENADE, 1, 1);
break;
case MOD_ROCKET:
case MOD_ROCKET_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_ROCKET, 1, 1);
break;
case MOD_PLASMA:
case MOD_PLASMA_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_PLASMA, 1, 1);
break;
case MOD_RAILGUN:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_RAILGUN, 1, 1);
break;
case MOD_LIGHTNING:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_LIGHTNING, 1, 1);
break;
case MOD_BFG:
case MOD_BFG_SPLASH:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_BFG, 1, 1);
break;
case MOD_GRAPPLE:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_GRAPPLE, 1, 1);
break;
default:
trap_RankReportInt(p1, p2, QGR_KEY_FRAG_UNKNOWN, 1, 1);
break;
}
}
}
/*
================
G_RankWeaponTime
================
*/
void G_RankWeaponTime(int self, int weapon)
{
gclient_t *client;
int time;
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
client = g_entities[self].client;
time = (level.time - client->weapon_change_time) / 1000;
client->weapon_change_time = level.time;
if (time <= 0) {
return;
}
trap_RankReportInt(self, -1, QGR_KEY_TIME, time, 1);
switch (weapon) {
case WP_GAUNTLET:
trap_RankReportInt(self, -1, QGR_KEY_TIME_GAUNTLET, time, 1);
break;
case WP_MACHINEGUN:
trap_RankReportInt(self, -1, QGR_KEY_TIME_MACHINEGUN, time, 1);
break;
case WP_SHOTGUN:
trap_RankReportInt(self, -1, QGR_KEY_TIME_SHOTGUN, time, 1);
break;
case WP_GRENADE_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_TIME_GRENADE, time, 1);
break;
case WP_ROCKET_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_TIME_ROCKET, time, 1);
break;
case WP_LIGHTNING:
trap_RankReportInt(self, -1, QGR_KEY_TIME_LIGHTNING, time, 1);
break;
case WP_RAILGUN:
trap_RankReportInt(self, -1, QGR_KEY_TIME_RAILGUN, time, 1);
break;
case WP_PLASMAGUN:
trap_RankReportInt(self, -1, QGR_KEY_TIME_PLASMA, time, 1);
break;
case WP_BFG:
trap_RankReportInt(self, -1, QGR_KEY_TIME_BFG, time, 1);
break;
case WP_GRAPPLING_HOOK:
trap_RankReportInt(self, -1, QGR_KEY_TIME_GRAPPLE, time, 1);
break;
default:
break;
}
}
/*
================
G_RankPickupWeapon
================
*/
void G_RankPickupWeapon(int self, int weapon)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_WEAPON, 1, 1);
switch (weapon) {
case WP_GAUNTLET:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_GAUNTLET, 1, 1);
break;
case WP_MACHINEGUN:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_MACHINEGUN, 1, 1);
break;
case WP_SHOTGUN:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_SHOTGUN, 1, 1);
break;
case WP_GRENADE_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_GRENADE, 1, 1);
break;
case WP_ROCKET_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_ROCKET, 1, 1);
break;
case WP_LIGHTNING:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_LIGHTNING, 1, 1);
break;
case WP_RAILGUN:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_RAILGUN, 1, 1);
break;
case WP_PLASMAGUN:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_PLASMA, 1, 1);
break;
case WP_BFG:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_BFG, 1, 1);
break;
case WP_GRAPPLING_HOOK:
trap_RankReportInt(self, -1, QGR_KEY_PICKUP_GRAPPLE, 1, 1);
break;
default:
break;
}
}
/*
================
G_RankPickupAmmo
================
*/
void G_RankPickupAmmo(int self, int weapon, int quantity)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
trap_RankReportInt(self, -1, QGR_KEY_BOXES, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS, quantity, 1);
switch (weapon) {
case WP_MACHINEGUN:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_BULLETS, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_BULLETS, quantity, 1);
break;
case WP_SHOTGUN:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_SHELLS, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_SHELLS, quantity, 1);
break;
case WP_GRENADE_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_GRENADES, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_GRENADES, quantity, 1);
break;
case WP_ROCKET_LAUNCHER:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_ROCKETS, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_ROCKETS, quantity, 1);
break;
case WP_LIGHTNING:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_LG_AMMO, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_LG_AMMO, quantity, 1);
break;
case WP_RAILGUN:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_SLUGS, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_SLUGS, quantity, 1);
break;
case WP_PLASMAGUN:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_CELLS, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_CELLS, quantity, 1);
break;
case WP_BFG:
trap_RankReportInt(self, -1, QGR_KEY_BOXES_BFG_AMMO, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ROUNDS_BFG_AMMO, quantity, 1);
break;
default:
break;
}
}
/*
================
G_RankPickupHealth
================
*/
void G_RankPickupHealth(int self, int quantity)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
trap_RankReportInt(self, -1, QGR_KEY_HEALTH, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_HEALTH_TOTAL, quantity, 1);
switch (quantity) {
case 5:
trap_RankReportInt(self, -1, QGR_KEY_HEALTH_5, 1, 1);
break;
case 25:
trap_RankReportInt(self, -1, QGR_KEY_HEALTH_25, 1, 1);
break;
case 50:
trap_RankReportInt(self, -1, QGR_KEY_HEALTH_50, 1, 1);
break;
case 100:
trap_RankReportInt(self, -1, QGR_KEY_HEALTH_MEGA, 1, 1);
break;
default:
break;
}
}
/*
================
G_RankPickupArmor
================
*/
void G_RankPickupArmor(int self, int quantity)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
trap_RankReportInt(self, -1, QGR_KEY_ARMOR, 1, 1);
trap_RankReportInt(self, -1, QGR_KEY_ARMOR_TOTAL, quantity, 1);
switch (quantity) {
case 5:
trap_RankReportInt(self, -1, QGR_KEY_ARMOR_SHARD, 1, 1);
break;
case 50:
trap_RankReportInt(self, -1, QGR_KEY_ARMOR_YELLOW, 1, 1);
break;
case 100:
trap_RankReportInt(self, -1, QGR_KEY_ARMOR_RED, 1, 1);
break;
default:
break;
}
}
/*
================
G_RankPickupPowerup
================
*/
void G_RankPickupPowerup(int self, int powerup)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
// ctf flags are treated as powerups
if ((powerup == PW_REDFLAG) || (powerup == PW_BLUEFLAG)) {
trap_RankReportInt(self, -1, QGR_KEY_FLAG_PICKUP, 1, 1);
return;
}
trap_RankReportInt(self, -1, QGR_KEY_POWERUP, 1, 1);
}
/*
================
G_RankPickupHoldable
================
*/
void G_RankPickupHoldable(int self, int holdable)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
switch (holdable) {
case HI_MEDKIT:
trap_RankReportInt(self, -1, QGR_KEY_MEDKIT, 1, 1);
break;
case HI_TELEPORTER:
trap_RankReportInt(self, -1, QGR_KEY_TELEPORTER, 1, 1);
break;
default:
break;
}
}
/*
================
G_RankUseHoldable
================
*/
void G_RankUseHoldable(int self, int holdable)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
switch (holdable) {
case HI_MEDKIT:
trap_RankReportInt(self, -1, QGR_KEY_MEDKIT_USE, 1, 1);
break;
case HI_TELEPORTER:
trap_RankReportInt(self, -1, QGR_KEY_TELEPORTER_USE, 1, 1);
break;
default:
break;
}
}
/*
================
G_RankReward
================
*/
void G_RankReward(int self, int award)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
switch (award) {
case EF_AWARD_IMPRESSIVE:
trap_RankReportInt(self, -1, QGR_KEY_IMPRESSIVE, 1, 1);
break;
case EF_AWARD_EXCELLENT:
trap_RankReportInt(self, -1, QGR_KEY_EXCELLENT, 1, 1);
break;
default:
break;
}
}
/*
================
G_RankCapture
================
*/
void G_RankCapture(int self)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
trap_RankReportInt(self, -1, QGR_KEY_FLAG_CAPTURE, 1, 1);
}
/*
================
G_RankUserTeamName
================
*/
void G_RankUserTeamName(int self, char *team_name)
{
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
trap_RankReportStr(self, -1, QGR_KEY_TEAM_NAME, team_name);
}
/*
================
G_RankClientDisconnect
================
*/
void G_RankClientDisconnect(int self)
{
gclient_t *client;
int time;
int match_rating;
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
// match rating
client = g_entities[self].client;
time = (level.time - client->pers.enterTime) / 1000;
if (time < 60) {
match_rating = 0;
} else {
match_rating = client->ps.persistant[PERS_MATCH_RATING] / time;
}
trap_RankReportInt(self, -1, QGR_KEY_MATCH_RATING, match_rating, 0);
}
/*
================
G_RankGameOver
================
*/
void G_RankGameOver(void)
{
int i;
char str[MAX_INFO_VALUE];
int num;
if (level.warmupTime != 0) {
// no reports during warmup period
return;
}
for (i = 0; i < level.maxclients; i++) {
if (trap_RankUserStatus(i) == QGR_STATUS_ACTIVE) {
G_RankClientDisconnect(i);
}
}
// hostname
trap_Cvar_VariableStringBuffer("sv_hostname", str, sizeof(str));
trap_RankReportStr(-1, -1, QGR_KEY_HOSTNAME, str);
// map
trap_Cvar_VariableStringBuffer("mapname", str, sizeof(str));
trap_RankReportStr(-1, -1, QGR_KEY_MAP, str);
// mod
trap_Cvar_VariableStringBuffer("fs_game", str, sizeof(str));
trap_RankReportStr(-1, -1, QGR_KEY_MOD, str);
// gametype
num = trap_Cvar_VariableIntegerValue("g_gametype");
trap_RankReportInt(-1, -1, QGR_KEY_GAMETYPE, num, 0);
// fraglimit
num = trap_Cvar_VariableIntegerValue("fraglimit");
trap_RankReportInt(-1, -1, QGR_KEY_FRAGLIMIT, num, 0);
// timelimit
num = trap_Cvar_VariableIntegerValue("timelimit");
trap_RankReportInt(-1, -1, QGR_KEY_TIMELIMIT, num, 0);
// maxclients
num = trap_Cvar_VariableIntegerValue("sv_maxclients");
trap_RankReportInt(-1, -1, QGR_KEY_MAXCLIENTS, num, 0);
// maxrate
num = trap_Cvar_VariableIntegerValue("sv_maxRate");
trap_RankReportInt(-1, -1, QGR_KEY_MAXRATE, num, 0);
// minping
num = trap_Cvar_VariableIntegerValue("sv_minPing");
trap_RankReportInt(-1, -1, QGR_KEY_MINPING, num, 0);
// maxping
num = trap_Cvar_VariableIntegerValue("sv_maxPing");
trap_RankReportInt(-1, -1, QGR_KEY_MAXPING, num, 0);
// dedicated
num = trap_Cvar_VariableIntegerValue("dedicated");
trap_RankReportInt(-1, -1, QGR_KEY_DEDICATED, num, 0);
// version
trap_Cvar_VariableStringBuffer("version", str, sizeof(str));
trap_RankReportStr(-1, -1, QGR_KEY_VERSION, str);
}