/***
*
*	Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*	
*	This product contains software technology licensed from Id 
*	Software, Inc. ("Id Technology").  Id Technology (c) 1996 Id Software, Inc. 
*	All Rights Reserved.
*
*   Use, distribution, and modification of this source code and/or resulting
*   object code is restricted to non-commercial enhancements to products from
*   Valve LLC.  All other use, distribution, or modification is prohibited
*   without written permission from Valve LLC.
*
****/
//
// death notice
//
/*
* redone by harSens, original file in death.bak
*/

#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"

#include <string.h>
#include <stdio.h>

#include "vgui_TeamFortressViewport.h"

DECLARE_MESSAGE( m_DeathNotice, DeathMsg );

struct DeathNoticeItem {
	char szKiller[MAX_PLAYER_NAME_LENGTH*2];
	char szVictim[MAX_PLAYER_NAME_LENGTH*2];
	char szKilledWith[32];
	int iSuicide;
	int iTeamKill;
	int iNonPlayerKill;
	int iId;
	float flDisplayTime;
	float *KillerColor;
	float *VictimColor;
};

#define MAX_DEATHNOTICES	4
static int DEATHNOTICE_DISPLAY_TIME = 6;

#define DEATHNOTICE_TOP		10
// Added by Pcjoe, spectator panel height
#define PANEL_HEIGHT 32

DeathNoticeItem rgDeathNoticeList[ MAX_DEATHNOTICES + 1 ];

float g_ColorBlue[3]	= { 0.6, 0.8, 1.0 };
float g_ColorRed[3]		= { 1.0, 0.25, 0.25 };
float g_ColorGreen[3]	= { 0.6, 1.0, 0.6 };
float g_ColorYellow[3]	= { 1.0, 0.7, 0.0 };
float g_ColorWhite[3]	= { 1.0, 1.0, 1.0 };

float *GetClientColor( int clientIndex )
{
	switch ( g_PlayerExtraInfo[clientIndex].teamnumber )
	{
	//added by harSens, no teams in free fighting
	case 0: return g_ColorYellow;

	case 1:	return g_ColorBlue;
	case 2: return g_ColorRed;
	case 3: return g_ColorYellow;
	case 4: return g_ColorGreen;
	}

	return NULL;
}

int CHudDeathNotice :: Init( void )
{
	gHUD.AddHudElem( this );

	HOOK_MESSAGE( DeathMsg );

	CVAR_CREATE( "hud_deathnotice_time", "6", 0 );

	return 1;
}


void CHudDeathNotice :: InitHUDData( void )
{
	memset( rgDeathNoticeList, 0, sizeof(rgDeathNoticeList) );
}

int CHudDeathNotice :: Draw( float flTime )
{
	int x, y;

	for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
	{
		if ( rgDeathNoticeList[i].iId == 0 )
			break;  // we've gone through them all

		if ( rgDeathNoticeList[i].flDisplayTime < flTime )
		{ // display time has expired
			// remove the current item from the list
			memmove( &rgDeathNoticeList[i], &rgDeathNoticeList[i+1], sizeof(DeathNoticeItem) * (MAX_DEATHNOTICES - i) );
			i--;  // continue on the next item;  stop the counter getting incremented
			continue;
		}

		rgDeathNoticeList[i].flDisplayTime = min( rgDeathNoticeList[i].flDisplayTime, gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME );

		// Only draw if the viewport will let me
		if ( gViewPort && gViewPort->AllowedToPrintText() )
		{	int iWidth, iHeight;
			//just get text height
			gEngfuncs.pfnDrawConsoleStringLen("blaat",&iWidth,&iHeight);

			// Draw the death notice
			y = DEATHNOTICE_TOP + (iHeight * i);  //!!!

			x = 0;

			// Added by Pcjoe, push down the text a little bit if the spectator menu is being rendered
			if(g_iUser1 && gHUD.m_pCvarDraw->value && !gHUD.m_iIntermission)
			{	y += YRES(PANEL_HEIGHT);
			}

			if (rgDeathNoticeList[i].iNonPlayerKill)
			{	if ( rgDeathNoticeList[i].KillerColor )
				{	gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
				}
				x = DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
				gEngfuncs.pfnDrawSetTextColor( g_ColorWhite[0], g_ColorWhite[1], g_ColorWhite[2] );
				x = DrawConsoleString( x, y, " killed a ");
				x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );				
			}
			else
			{	// record the death notice in the console
				if ( rgDeathNoticeList[i].iSuicide )
				{	if ( rgDeathNoticeList[i].VictimColor )
					{	gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
					}
					x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
					
					if ( !strcmp( rgDeathNoticeList[i].szKilledWith, "d_world" ) )
					{	gEngfuncs.pfnDrawSetTextColor( g_ColorWhite[0], g_ColorWhite[1], g_ColorWhite[2] );
						x = DrawConsoleString( x, y, " died");
					}
					else
					{	gEngfuncs.pfnDrawSetTextColor( g_ColorWhite[0], g_ColorWhite[1], g_ColorWhite[2] );
						x = DrawConsoleString( x, y, " killed self");
					}
				}
				else if ( rgDeathNoticeList[i].iTeamKill )
				{	if ( rgDeathNoticeList[i].KillerColor )
					{	gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
					}				
					x = DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
					gEngfuncs.pfnDrawSetTextColor( g_ColorWhite[0], g_ColorWhite[1], g_ColorWhite[2] );
					x = DrawConsoleString( x, y, " killed his teammate " );
					if ( rgDeathNoticeList[i].VictimColor )
					{	gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
					}					
					x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
				}
				else
				{	if ( rgDeathNoticeList[i].KillerColor )
					{	gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
					}									
					x = DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
					gEngfuncs.pfnDrawSetTextColor( g_ColorWhite[0], g_ColorWhite[1], g_ColorWhite[2] );
					x = DrawConsoleString( x, y, " killed " );
					if ( rgDeathNoticeList[i].VictimColor )
					{	gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
					}					
					x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
				}

				if ( rgDeathNoticeList[i].szKilledWith && *rgDeathNoticeList[i].szKilledWith && (*rgDeathNoticeList[i].szKilledWith > 13 ) && strcmp( rgDeathNoticeList[i].szKilledWith, "d_world" ) && !rgDeathNoticeList[i].iTeamKill )
				{	gEngfuncs.pfnDrawSetTextColor( g_ColorWhite[0], g_ColorWhite[1], g_ColorWhite[2] );
					x = DrawConsoleString( x, y, " with " );
					gEngfuncs.pfnDrawSetTextColor( g_ColorWhite[0], g_ColorWhite[1], g_ColorWhite[2] );					
					x = DrawConsoleString( x, y, rgDeathNoticeList[i].szKilledWith+2 ); // skip over the "d_" part
				}				
			}
		}
	}
	return 1;
}

// This message handler may be better off elsewhere
int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf )
{
	m_iFlags |= HUD_ACTIVE;

	BEGIN_READ( pbuf, iSize );

	int killer = READ_BYTE();
	int victim = READ_BYTE();

	char killedwith[32];
	strcpy( killedwith, "d_" );
	strncat( killedwith, READ_STRING(), 32 );
	
	//added by harSens
	if(strcmp(killedwith,"d_worldspawn")==0)
		killedwith[7]='\0';

	if (gViewPort)
		gViewPort->DeathMsg( killer, victim );

	gHUD.m_Spectator.DeathMessage(victim);
	int i;
	for (i = 0; i < MAX_DEATHNOTICES; i++ )
	{
		if ( rgDeathNoticeList[i].iId == 0 )
			break;
	}
	if ( i == MAX_DEATHNOTICES )
	{ // move the rest of the list forward to make room for this item
		memmove( rgDeathNoticeList, rgDeathNoticeList+1, sizeof(DeathNoticeItem) * MAX_DEATHNOTICES );
		i = MAX_DEATHNOTICES - 1;
	}

	if (gViewPort)
		gViewPort->GetAllPlayersInfo();

	//make 
	strncpy(rgDeathNoticeList[i].szKilledWith, killedwith, 32);
	// Get the Killer's name

	char *killer_name = NULL;
	// Added by Rick: If killed by a buddy
	if ((char)killer == -2) // -2 simply means that its a buddy
	{
		killer_name = READ_STRING();
		strncpy( rgDeathNoticeList[i].szKiller, killer_name, MAX_PLAYER_NAME_LENGTH );
		rgDeathNoticeList[i].szKiller[MAX_PLAYER_NAME_LENGTH-1] = 0;
		rgDeathNoticeList[i].KillerColor = g_ColorGreen;
	}
	else
	{
		killer_name = g_PlayerInfoList[ killer ].name;
	
		if ( !killer_name )
		{
			killer_name = "";
			rgDeathNoticeList[i].szKiller[0] = 0;
		}
		else
		{
			rgDeathNoticeList[i].KillerColor = GetClientColor( killer );
			strncpy( rgDeathNoticeList[i].szKiller, killer_name, MAX_PLAYER_NAME_LENGTH );
			rgDeathNoticeList[i].szKiller[MAX_PLAYER_NAME_LENGTH-1] = 0;
		}
	}

	// Get the Victim's name
	char *victim_name = NULL;

	// Added by Rick: Check for buddy
	if ((char)victim == -2) // -2 simply means that its a buddy
	{
		victim_name = READ_STRING();
		strncpy( rgDeathNoticeList[i].szVictim, victim_name, MAX_PLAYER_NAME_LENGTH );
		rgDeathNoticeList[i].szVictim[MAX_PLAYER_NAME_LENGTH-1] = 0;
		rgDeathNoticeList[i].VictimColor = g_ColorGreen;
	}
	else
	{
		// If victim is -1, the killer killed a specific, non-player object (like a sentrygun)
		if ( ((char)victim) != -1 )
			victim_name = g_PlayerInfoList[ victim ].name;
		if ( !victim_name )
		{
			victim_name = "";
			rgDeathNoticeList[i].szVictim[0] = 0;
		}
		else
		{
			rgDeathNoticeList[i].VictimColor = GetClientColor( victim );
			strncpy( rgDeathNoticeList[i].szVictim, victim_name, MAX_PLAYER_NAME_LENGTH );
			rgDeathNoticeList[i].szVictim[MAX_PLAYER_NAME_LENGTH-1] = 0;
		}

		// Is it a non-player object kill?
		if ( ((char)victim) == -1 )
		{
			rgDeathNoticeList[i].iNonPlayerKill = TRUE;

			// Store the object's name in the Victim slot (skip the d_ bit)
			strcpy( rgDeathNoticeList[i].szVictim, killedwith+2 );
		}
		else
		{
			// Modified by Rick
			//if ( killer == victim || killer == 0 )
			//	rgDeathNoticeList[i].iSuicide = TRUE;
			if (killer == victim)
			{
				// Buddy killed by a buddy?
				if ((char)killer == -2)
					rgDeathNoticeList[i].iSuicide = !strcmp(rgDeathNoticeList[i].szVictim, rgDeathNoticeList[i].szKiller);
				else
					rgDeathNoticeList[i].iSuicide = TRUE;
			}

			if ( !strcmp( killedwith, "d_teammate" ) )
				rgDeathNoticeList[i].iTeamKill = TRUE;
		}
	}
	rgDeathNoticeList[i].iId = 1;

	DEATHNOTICE_DISPLAY_TIME = CVAR_GET_FLOAT( "hud_deathnotice_time" );
	rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME;
	return 1;	
}