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