halflife-thewastes-sdk/cl_dll/death.cpp
2023-09-06 03:25:39 +03:00

339 lines
8.7 KiB
C++

/***
*
* 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
//
#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
#include "tw_vgui.h"
#include "vgui_TheWastesViewport.h"
DECLARE_MESSAGE( m_DeathNotice, DeathMsg );
struct DeathNoticeItem {
char szKiller[MAX_PLAYER_NAME_LENGTH*2];
char szVictim[MAX_PLAYER_NAME_LENGTH*2];
char szDeathMessage[128];
int iId; // the index number of the associated sprite
int iSuicide;
int iTeamKill;
int iNonPlayerKill;
int iSpecialDeath;
float flDisplayTime;
float *KillerColor;
float *VictimColor;
};
#define MAX_DEATHNOTICES 4
static int DEATHNOTICE_DISPLAY_TIME = 6;
#define DEATHNOTICE_TOP ScreenHeight - 72
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 *GetClientColor( int clientIndex )
{
switch ( g_PlayerExtraInfo[clientIndex].teamnumber )
{
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 :: VidInit( void )
{
m_HUD_d_skull = gHUD.GetSpriteIndex( "d_skull" );
m_HUD_d_headshot = gHUD.GetSpriteIndex( "d_headshot" );
m_HUD_d_bleeding = gHUD.GetSpriteIndex( "d_bleed" );
return 1;
}
int CHudDeathNotice :: Draw( float flTime )
{
int x, y, r, g, b;
int text_y;
int deathcount = 0;
// How many death messages are there.
for( int i = 0;i < MAX_DEATHNOTICES; i++)
{
if(rgDeathNoticeList[i].iId == 0)
break;
deathcount++;
}
for ( 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() )
{
// Get the initial offset.
int offset = (20 * deathcount );
// Draw the death notice
y = DEATHNOTICE_TOP + (20 * i) - offset; //!!!
int id,special_id = 0;
switch(rgDeathNoticeList[i].iSpecialDeath)
{
default:
case 0:
break;
case 1:
special_id = m_HUD_d_headshot;
break;
case 2:
special_id = m_HUD_d_bleeding;
break;
}
id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId;
int id_length;
if(rgDeathNoticeList[i].iSpecialDeath == 2 && !rgDeathNoticeList[i].iSuicide)
id_length = 0;
else
id_length = (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
int special_id_length = (rgDeathNoticeList[i].iSpecialDeath && !rgDeathNoticeList[i].iSuicide) ? (gHUD.GetSpriteRect(special_id).right - gHUD.GetSpriteRect(special_id).left) : 0;
// Put in center
x = (ScreenWidth/2) -
(ConsoleStringLen(rgDeathNoticeList[i].szVictim) - id_length - special_id_length)/2;
if ( !rgDeathNoticeList[i].iSuicide )
{
x -= (5 + ConsoleStringLen( rgDeathNoticeList[i].szKiller ) );
// Draw killers name
if ( rgDeathNoticeList[i].KillerColor )
gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
}
// r = 255; g = 80; b = 0;
r = g = b = 255; // WHITE - Gage
if ( rgDeathNoticeList[i].iTeamKill )
{
r = 10; g = 240; b = 10; // display it in sickly green
}
// Draw death weapon if needed
if(!(special_id_length && rgDeathNoticeList[i].iSuicide) && id_length)
{
SPR_Set( gHUD.GetSprite(id), r, g, b );
SPR_DrawHoles( 0, x, y, &gHUD.GetSpriteRect(id) );
x += (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
}
if(special_id_length)
{
SPR_Set(gHUD.GetSprite(special_id),r,g,b);
SPR_DrawHoles(0,x,y,&gHUD.GetSpriteRect(special_id));
x += (gHUD.GetSpriteRect(special_id).right - gHUD.GetSpriteRect(special_id).left);
}
// Draw victims name (if it was a player that was killed)
if (rgDeathNoticeList[i].iNonPlayerKill == FALSE)
{
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 );
}
int text_w,text_h;
GetConsoleStringSize(rgDeathNoticeList[i].szDeathMessage,&text_w,&text_h);
text_y = text_h*i;
DrawConsoleString(ScreenWidth-text_w,text_y,rgDeathNoticeList[i].szDeathMessage);
}
}
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();
int special = READ_BYTE();
char killedwith[32];
strcpy( killedwith, "d_" );
strncat( killedwith, READ_STRING(), 32 );
if (gViewPort)
gViewPort->DeathMsg( killer, victim );
gHUD.m_Spectator.DeathMessage(victim);
for ( int 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();
// Set special death
rgDeathNoticeList[i].iSpecialDeath = special;
// Get the Killer's name
char *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;
// 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
{
if ( killer == victim || killer == 0 )
rgDeathNoticeList[i].iSuicide = TRUE;
if ( !strcmp( killedwith, "d_teammate" ) )
rgDeathNoticeList[i].iTeamKill = TRUE;
}
char *szDeathMessage = READ_STRING();
// fill deathmessage string
if(killer == victim || killer == 0)
sprintf(rgDeathNoticeList[i].szDeathMessage,"%s commited suicide",victim_name);
else
sprintf(rgDeathNoticeList[i].szDeathMessage,szDeathMessage,killer_name,victim_name);
// Find the sprite in the list
int spr = gHUD.GetSpriteIndex( killedwith );
rgDeathNoticeList[i].iId = spr;
DEATHNOTICE_DISPLAY_TIME = CVAR_GET_FLOAT( "hud_deathnotice_time" );
rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME;
if (rgDeathNoticeList[i].iNonPlayerKill)
{
ConsolePrint( rgDeathNoticeList[i].szKiller );
ConsolePrint( " killed a " );
ConsolePrint( rgDeathNoticeList[i].szVictim );
ConsolePrint( "\n" );
}
else
{
// record new death notices
ConsolePrint(rgDeathNoticeList[i].szDeathMessage);
ConsolePrint("\n");
}
return 1;
}