mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2024-11-25 13:41:45 +00:00
351 lines
9.5 KiB
C
351 lines
9.5 KiB
C
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Id$
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Log$
|
|
// Revision 1.10 2003/03/22 20:29:26 jbravo
|
|
// wrapping linkent and unlinkent calls
|
|
//
|
|
// Revision 1.9 2002/09/24 05:06:16 blaze
|
|
// fixed spectating so ref\'s can now use all the chasecam modes.
|
|
//
|
|
// Revision 1.8 2002/06/16 20:06:14 jbravo
|
|
// Reindented all the source files with "indent -kr -ut -i8 -l120 -lc120 -sob -bad -bap"
|
|
//
|
|
// Revision 1.7 2002/06/16 17:38:00 jbravo
|
|
// Removed the MISSIONPACK ifdefs and missionpack only code.
|
|
//
|
|
// Revision 1.6 2002/01/11 19:48:30 jbravo
|
|
// Formatted the source in non DOS format.
|
|
//
|
|
// Revision 1.5 2001/12/31 16:28:42 jbravo
|
|
// I made a Booboo with the Log tag.
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 1999-2000 Id Software, Inc.
|
|
//
|
|
//
|
|
// g_arenas.c
|
|
//
|
|
|
|
#include "g_local.h"
|
|
|
|
gentity_t *podium1;
|
|
gentity_t *podium2;
|
|
gentity_t *podium3;
|
|
|
|
/*
|
|
==================
|
|
UpdateTournamentInfo
|
|
==================
|
|
*/
|
|
void UpdateTournamentInfo(void)
|
|
{
|
|
int i;
|
|
gentity_t *player;
|
|
// int playerClientNum;
|
|
//int n, accuracy, perfect, msglen;
|
|
int n, msglen;
|
|
char buf[32];
|
|
char msg[MAX_STRING_CHARS];
|
|
|
|
// find the real player
|
|
player = NULL;
|
|
for (i = 0; i < level.maxclients; i++) {
|
|
//Blaze: Print out some debug info
|
|
if (&g_entities[i] == NULL) G_Printf("Ln 0052\n");
|
|
|
|
player = &g_entities[i];
|
|
if (!player->inuse) {
|
|
continue;
|
|
}
|
|
if (!(player->r.svFlags & SVF_BOT)) {
|
|
break;
|
|
}
|
|
}
|
|
// this should never happen!
|
|
if (!player || i == level.maxclients) {
|
|
return;
|
|
}
|
|
// playerClientNum = i;
|
|
|
|
CalculateRanks();
|
|
|
|
/* if (level.clients[playerClientNum].sess.sessionTeam == TEAM_SPECTATOR) {
|
|
Com_sprintf(msg, sizeof(msg), "postgame %i %i 0 0 0 0 0 0", level.numNonSpectatorClients,
|
|
playerClientNum);
|
|
} else {
|
|
if (player->client->accuracy_shots) {
|
|
accuracy = player->client->accuracy_hits * 100 / player->client->accuracy_shots;
|
|
} else {
|
|
accuracy = 0;
|
|
}
|
|
perfect = (level.clients[playerClientNum].ps.persistant[PERS_RANK] == 0
|
|
&& player->client->ps.persistant[PERS_KILLED] == 0) ? 1 : 0;
|
|
//Blaze: Removed because it uses the persistant stats stuff
|
|
Com_sprintf( msg, sizeof(msg), "postgame %i %i %i %i %i %i %i %i", level.numNonSpectatorClients, playerClientNum, accuracy,
|
|
player->client->ps.persistant[PERS_IMPRESSIVE_COUNT], player->client->ps.persistant[PERS_EXCELLENT_COUNT],
|
|
player->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT], player->client->ps.persistant[PERS_SCORE],
|
|
perfect );
|
|
} */
|
|
|
|
msglen = strlen(msg);
|
|
for (i = 0; i < level.numNonSpectatorClients; i++) {
|
|
n = level.sortedClients[i];
|
|
Com_sprintf(buf, sizeof(buf), " %i %i %i", n, level.clients[n].ps.persistant[PERS_RANK],
|
|
level.clients[n].ps.persistant[PERS_SCORE]);
|
|
msglen += strlen(buf);
|
|
if (msglen >= sizeof(msg)) {
|
|
break;
|
|
}
|
|
strcat(msg, buf);
|
|
}
|
|
trap_SendConsoleCommand(EXEC_APPEND, msg);
|
|
}
|
|
|
|
static gentity_t *SpawnModelOnVictoryPad(gentity_t * pad, vec3_t offset, gentity_t * ent, int place)
|
|
{
|
|
gentity_t *body;
|
|
vec3_t vec;
|
|
vec3_t f, r, u;
|
|
|
|
body = G_Spawn();
|
|
if (!body) {
|
|
G_Printf(S_COLOR_RED "ERROR: out of gentities\n");
|
|
return NULL;
|
|
}
|
|
|
|
body->classname = ent->client->pers.netname;
|
|
body->client = ent->client;
|
|
body->s = ent->s;
|
|
body->s.eType = ET_PLAYER; // could be ET_INVISIBLE
|
|
body->s.eFlags = 0; // clear EF_TALK, etc
|
|
body->s.powerups = 0; // clear powerups
|
|
body->s.loopSound = 0; // clear lava burning
|
|
body->s.number = body - g_entities;
|
|
body->timestamp = level.time;
|
|
body->physicsObject = qtrue;
|
|
body->physicsBounce = 0; // don't bounce
|
|
body->s.event = 0;
|
|
body->s.pos.trType = TR_STATIONARY;
|
|
body->s.groundEntityNum = ENTITYNUM_WORLD;
|
|
body->s.legsAnim = LEGS_IDLE;
|
|
body->s.torsoAnim = TORSO_STAND;
|
|
if (body->s.weapon == WP_NONE) {
|
|
body->s.weapon = WP_PISTOL;
|
|
}
|
|
if (body->s.weapon == WP_KNIFE) {
|
|
body->s.torsoAnim = TORSO_STAND2;
|
|
}
|
|
body->s.event = 0;
|
|
body->r.svFlags = ent->r.svFlags;
|
|
VectorCopy(ent->r.mins, body->r.mins);
|
|
VectorCopy(ent->r.maxs, body->r.maxs);
|
|
VectorCopy(ent->r.absmin, body->r.absmin);
|
|
VectorCopy(ent->r.absmax, body->r.absmax);
|
|
body->clipmask = CONTENTS_SOLID | CONTENTS_PLAYERCLIP;
|
|
body->r.contents = CONTENTS_BODY;
|
|
body->r.ownerNum = ent->r.ownerNum;
|
|
body->takedamage = qfalse;
|
|
|
|
VectorSubtract(level.intermission_origin, pad->r.currentOrigin, vec);
|
|
vectoangles(vec, body->s.apos.trBase);
|
|
body->s.apos.trBase[PITCH] = 0;
|
|
body->s.apos.trBase[ROLL] = 0;
|
|
|
|
AngleVectors(body->s.apos.trBase, f, r, u);
|
|
VectorMA(pad->r.currentOrigin, offset[0], f, vec);
|
|
VectorMA(vec, offset[1], r, vec);
|
|
VectorMA(vec, offset[2], u, vec);
|
|
|
|
G_SetOrigin(body, vec);
|
|
|
|
trap_LinkEntity(body);
|
|
|
|
body->count = place;
|
|
|
|
return body;
|
|
}
|
|
|
|
static void CelebrateStop(gentity_t * player)
|
|
{
|
|
int anim;
|
|
|
|
//Blaze: gah, dont need to change stance for using gauntlet
|
|
// if( player->s.weapon == WP_GAUNTLET) {
|
|
// anim = TORSO_STAND2;
|
|
// }
|
|
// else {
|
|
anim = TORSO_STAND;
|
|
// }
|
|
player->s.torsoAnim = ((player->s.torsoAnim & ANIM_TOGGLEBIT) ^ ANIM_TOGGLEBIT) | anim;
|
|
}
|
|
|
|
#define TIMER_GESTURE (34*66+50)
|
|
static void CelebrateStart(gentity_t * player)
|
|
{
|
|
player->s.torsoAnim = ((player->s.torsoAnim & ANIM_TOGGLEBIT) ^ ANIM_TOGGLEBIT) | TORSO_GESTURE;
|
|
player->nextthink = level.time + TIMER_GESTURE;
|
|
player->think = CelebrateStop;
|
|
|
|
/*
|
|
player->client->ps.events[player->client->ps.eventSequence & (MAX_PS_EVENTS-1)] = EV_TAUNT;
|
|
player->client->ps.eventParms[player->client->ps.eventSequence & (MAX_PS_EVENTS-1)] = 0;
|
|
player->client->ps.eventSequence++;
|
|
*/
|
|
G_AddEvent(player, EV_TAUNT, 0);
|
|
}
|
|
|
|
static vec3_t offsetFirst = { 0, 0, 74 };
|
|
static vec3_t offsetSecond = { -10, 60, 54 };
|
|
static vec3_t offsetThird = { -19, -60, 45 };
|
|
|
|
static void PodiumPlacementThink(gentity_t * podium)
|
|
{
|
|
vec3_t vec;
|
|
vec3_t origin;
|
|
vec3_t f, r, u;
|
|
|
|
podium->nextthink = level.time + 100;
|
|
|
|
AngleVectors(level.intermission_angle, vec, NULL, NULL);
|
|
VectorMA(level.intermission_origin, trap_Cvar_VariableIntegerValue("g_podiumDist"), vec, origin);
|
|
origin[2] -= trap_Cvar_VariableIntegerValue("g_podiumDrop");
|
|
G_SetOrigin(podium, origin);
|
|
|
|
if (podium1) {
|
|
VectorSubtract(level.intermission_origin, podium->r.currentOrigin, vec);
|
|
vectoangles(vec, podium1->s.apos.trBase);
|
|
podium1->s.apos.trBase[PITCH] = 0;
|
|
podium1->s.apos.trBase[ROLL] = 0;
|
|
|
|
AngleVectors(podium1->s.apos.trBase, f, r, u);
|
|
VectorMA(podium->r.currentOrigin, offsetFirst[0], f, vec);
|
|
VectorMA(vec, offsetFirst[1], r, vec);
|
|
VectorMA(vec, offsetFirst[2], u, vec);
|
|
|
|
G_SetOrigin(podium1, vec);
|
|
}
|
|
|
|
if (podium2) {
|
|
VectorSubtract(level.intermission_origin, podium->r.currentOrigin, vec);
|
|
vectoangles(vec, podium2->s.apos.trBase);
|
|
podium2->s.apos.trBase[PITCH] = 0;
|
|
podium2->s.apos.trBase[ROLL] = 0;
|
|
|
|
AngleVectors(podium2->s.apos.trBase, f, r, u);
|
|
VectorMA(podium->r.currentOrigin, offsetSecond[0], f, vec);
|
|
VectorMA(vec, offsetSecond[1], r, vec);
|
|
VectorMA(vec, offsetSecond[2], u, vec);
|
|
|
|
G_SetOrigin(podium2, vec);
|
|
}
|
|
|
|
if (podium3) {
|
|
VectorSubtract(level.intermission_origin, podium->r.currentOrigin, vec);
|
|
vectoangles(vec, podium3->s.apos.trBase);
|
|
podium3->s.apos.trBase[PITCH] = 0;
|
|
podium3->s.apos.trBase[ROLL] = 0;
|
|
|
|
AngleVectors(podium3->s.apos.trBase, f, r, u);
|
|
VectorMA(podium->r.currentOrigin, offsetThird[0], f, vec);
|
|
VectorMA(vec, offsetThird[1], r, vec);
|
|
VectorMA(vec, offsetThird[2], u, vec);
|
|
|
|
G_SetOrigin(podium3, vec);
|
|
}
|
|
}
|
|
|
|
static gentity_t *SpawnPodium(void)
|
|
{
|
|
gentity_t *podium;
|
|
vec3_t vec;
|
|
vec3_t origin;
|
|
|
|
podium = G_Spawn();
|
|
if (!podium) {
|
|
return NULL;
|
|
}
|
|
|
|
podium->classname = "podium";
|
|
podium->s.eType = ET_GENERAL;
|
|
podium->s.number = podium - g_entities;
|
|
podium->clipmask = CONTENTS_SOLID;
|
|
podium->r.contents = CONTENTS_SOLID;
|
|
podium->s.modelindex = G_ModelIndex(SP_PODIUM_MODEL);
|
|
|
|
AngleVectors(level.intermission_angle, vec, NULL, NULL);
|
|
VectorMA(level.intermission_origin, trap_Cvar_VariableIntegerValue("g_podiumDist"), vec, origin);
|
|
origin[2] -= trap_Cvar_VariableIntegerValue("g_podiumDrop");
|
|
G_SetOrigin(podium, origin);
|
|
|
|
VectorSubtract(level.intermission_origin, podium->r.currentOrigin, vec);
|
|
podium->s.apos.trBase[YAW] = vectoyaw(vec);
|
|
trap_LinkEntity(podium);
|
|
|
|
podium->think = PodiumPlacementThink;
|
|
podium->nextthink = level.time + 100;
|
|
return podium;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
SpawnModelsOnVictoryPads
|
|
==================
|
|
*/
|
|
void SpawnModelsOnVictoryPads(void)
|
|
{
|
|
gentity_t *player;
|
|
gentity_t *podium;
|
|
|
|
podium1 = NULL;
|
|
podium2 = NULL;
|
|
podium3 = NULL;
|
|
|
|
podium = SpawnPodium();
|
|
|
|
player = SpawnModelOnVictoryPad(podium, offsetFirst, &g_entities[level.sortedClients[0]],
|
|
level.clients[level.sortedClients[0]].ps.
|
|
persistant[PERS_RANK] & ~RANK_TIED_FLAG);
|
|
if (player) {
|
|
player->nextthink = level.time + 2000;
|
|
player->think = CelebrateStart;
|
|
podium1 = player;
|
|
}
|
|
|
|
player = SpawnModelOnVictoryPad(podium, offsetSecond, &g_entities[level.sortedClients[1]],
|
|
level.clients[level.sortedClients[1]].ps.
|
|
persistant[PERS_RANK] & ~RANK_TIED_FLAG);
|
|
if (player) {
|
|
podium2 = player;
|
|
}
|
|
|
|
if (level.numNonSpectatorClients > 2) {
|
|
player = SpawnModelOnVictoryPad(podium, offsetThird, &g_entities[level.sortedClients[2]],
|
|
level.clients[level.sortedClients[2]].ps.
|
|
persistant[PERS_RANK] & ~RANK_TIED_FLAG);
|
|
if (player) {
|
|
podium3 = player;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
Svcmd_AbortPodium_f
|
|
===============
|
|
*/
|
|
void Svcmd_AbortPodium_f(void)
|
|
{
|
|
if (g_gametype.integer != GT_SINGLE_PLAYER) {
|
|
return;
|
|
}
|
|
|
|
if (podium1) {
|
|
podium1->nextthink = level.time;
|
|
podium1->think = CelebrateStop;
|
|
}
|
|
}
|