//----------------------------------------------------------------------------- // // $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); }