2016-06-04 15:24:23 +02:00
/***
*
* Copyright ( c ) 1996 - 2002 , 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 .
*
* * * */
//
// teamplay_gamerules.cpp
//
2016-06-25 18:33:39 +02:00
2016-06-04 15:24:23 +02:00
# include "extdll.h"
# include "util.h"
# include "cbase.h"
# include "player.h"
# include "weapons.h"
# include "gamerules.h"
2017-06-11 22:20:16 +02:00
# include "player.h"
2016-06-04 15:24:23 +02:00
# include "skill.h"
# include "game.h"
# include "items.h"
2021-06-07 02:05:58 +02:00
# if !NO_VOICEGAMEMGR
2016-06-04 15:24:23 +02:00
# include "voice_gamemgr.h"
2016-08-01 19:18:54 +02:00
# endif
2016-06-04 15:24:23 +02:00
# include "hltv.h"
2024-01-28 10:14:47 +01:00
# include "trains.h"
2024-02-25 22:05:17 +01:00
# include "string.h"
2017-06-11 22:20:16 +02:00
// START BOT
# include "bot.h"
# include "botcam.h"
extern respawn_t bot_respawn [ 32 ] ;
// END BOT
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
extern DLL_GLOBAL CGameRules * g_pGameRules ;
2016-06-04 15:24:23 +02:00
extern DLL_GLOBAL BOOL g_fGameOver ;
extern int gmsgDeathMsg ; // client dll messages
extern int gmsgScoreInfo ;
extern int gmsgMOTD ;
extern int gmsgServerName ;
2017-06-11 22:20:16 +02:00
extern int gmsgItemPickup ;
extern int gmsgTimer ;
extern int gmsgPlayBGM ;
extern int gmsgStopMP3 ;
2016-06-04 15:24:23 +02:00
2017-06-11 22:20:16 +02:00
extern int g_gameplay ;
int check = 0 ;
2016-06-04 15:24:23 +02:00
# define ITEM_RESPAWN_TIME 30
# define WEAPON_RESPAWN_TIME 20
# define AMMO_RESPAWN_TIME 20
float g_flIntermissionStartTime = 0 ;
2021-06-07 02:05:58 +02:00
# if !NO_VOICEGAMEMGR
2016-06-04 15:24:23 +02:00
CVoiceGameMgr g_VoiceGameMgr ;
class CMultiplayGameMgrHelper : public IVoiceGameMgrHelper
{
public :
2016-07-31 15:48:50 +02:00
virtual bool CanPlayerHearPlayer ( CBasePlayer * pListener , CBasePlayer * pTalker )
2016-06-04 15:24:23 +02:00
{
2017-06-11 22:20:16 +02:00
if ( g_gameplay = = HL_TEAMPLAY | | HS_SHYTPLAY )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( g_pGameRules - > PlayerRelationship ( pListener , pTalker ) ! = GR_TEAMMATE )
2016-06-04 15:24:23 +02:00
{
return false ;
}
}
return true ;
}
} ;
2016-06-25 18:33:39 +02:00
static CMultiplayGameMgrHelper g_GameMgrHelper ;
2016-08-01 19:18:54 +02:00
# endif
2016-06-04 15:24:23 +02:00
//*********************************************************
// Rules for the half-life multiplayer game.
//*********************************************************
2016-07-31 15:48:50 +02:00
CHalfLifeMultiplay : : CHalfLifeMultiplay ( )
2016-06-04 15:24:23 +02:00
{
2021-06-07 02:05:58 +02:00
# if !NO_VOICEGAMEMGR
2016-07-31 15:48:50 +02:00
g_VoiceGameMgr . Init ( & g_GameMgrHelper , gpGlobals - > maxClients ) ;
2016-06-12 22:43:32 +02:00
# endif
2016-06-04 15:24:23 +02:00
RefreshSkillData ( ) ;
m_flIntermissionEndTime = 0 ;
g_flIntermissionStartTime = 0 ;
// 11/8/98
// Modified by YWB: Server .cfg file is now a cvar, so that
// server ops can run multiple game servers, with different server .cfg files,
// from a single installed directory.
// Mapcyclefile is already a cvar.
// 3/31/99
// Added lservercfg file cvar, since listen and dedicated servers should not
// share a single config file. (sjb)
2016-07-31 15:48:50 +02:00
if ( IS_DEDICATED_SERVER ( ) )
2016-06-04 15:24:23 +02:00
{
// dedicated server
2017-07-23 23:24:55 +02:00
/*const char *servercfgfile = CVAR_GET_STRING( "servercfgfile" );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if ( servercfgfile & & servercfgfile [ 0 ] )
2016-06-04 15:24:23 +02:00
{
char szCommand [ 256 ] ;
ALERT ( at_console , " Executing dedicated server config file \n " ) ;
sprintf ( szCommand , " exec %s \n " , servercfgfile ) ;
SERVER_COMMAND ( szCommand ) ;
}
2017-06-26 02:47:19 +02:00
*/
// this code has been moved into engine, to only run server.cfg once
2016-06-04 15:24:23 +02:00
}
else
{
// listen server
2017-07-23 23:24:55 +02:00
const char * lservercfgfile = CVAR_GET_STRING ( " lservercfgfile " ) ;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if ( lservercfgfile & & lservercfgfile [ 0 ] )
2016-06-04 15:24:23 +02:00
{
char szCommand [ 256 ] ;
ALERT ( at_console , " Executing listen server config file \n " ) ;
sprintf ( szCommand , " exec %s \n " , lservercfgfile ) ;
SERVER_COMMAND ( szCommand ) ;
}
}
}
BOOL CHalfLifeMultiplay : : ClientCommand ( CBasePlayer * pPlayer , const char * pcmd )
{
2021-06-07 02:05:58 +02:00
# if !NO_VOICEGAMEMGR
2016-07-31 15:48:50 +02:00
if ( g_VoiceGameMgr . ClientCommand ( pPlayer , pcmd ) )
2016-06-04 15:24:23 +02:00
return TRUE ;
2016-06-12 22:43:32 +02:00
# endif
2016-07-31 15:48:50 +02:00
return CGameRules : : ClientCommand ( pPlayer , pcmd ) ;
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
void CHalfLifeMultiplay : : RefreshSkillData ( void )
{
2016-06-25 18:33:39 +02:00
// load all default values
2016-06-04 15:24:23 +02:00
CGameRules : : RefreshSkillData ( ) ;
2016-06-25 18:33:39 +02:00
// override some values for multiplay.
2016-06-04 15:24:23 +02:00
// suitcharger
gSkillData . suitchargerCapacity = 30 ;
// Crowbar whack
gSkillData . plrDmgCrowbar = 25 ;
// Glock Round
gSkillData . plrDmg9MM = 12 ;
// 357 Round
2023-11-18 07:56:53 +01:00
gSkillData . plrDmg357 = 50 ;
2016-06-04 15:24:23 +02:00
// MP5 Round
gSkillData . plrDmgMP5 = 12 ;
2017-06-11 22:20:16 +02:00
gSkillData . plrDmgZAPPER = 25 ;
2016-06-04 15:24:23 +02:00
// M203 grenade
gSkillData . plrDmgM203Grenade = 100 ;
// Shotgun buckshot
gSkillData . plrDmgBuckshot = 20 ; // fewer pellets in deathmatch
2017-06-11 22:20:16 +02:00
gSkillData . plrDmgJackal = 50 ;
2016-06-04 15:24:23 +02:00
// Crossbow
2017-06-11 22:20:16 +02:00
//gSkillData.plrDmgCrossbowClient = 20;
gSkillData . plrDmgModmanClient = 25 ;
2016-06-04 15:24:23 +02:00
// RPG
gSkillData . plrDmgRPG = 120 ;
// Egon
gSkillData . plrDmgEgonWide = 20 ;
gSkillData . plrDmgEgonNarrow = 10 ;
// Hand Grendade
gSkillData . plrDmgHandGrenade = 100 ;
// Satchel Charge
gSkillData . plrDmgSatchel = 120 ;
// Tripmine
gSkillData . plrDmgTripmine = 150 ;
2017-06-11 22:20:16 +02:00
gSkillData . plrDmgGOLDENGUN = 400 ;
// Tripmine
//gSkillData.plrDmgBow = 999;
// Tripmine
//gSkillData.plrDmgStar = 35;
2016-06-04 15:24:23 +02:00
// hornet
gSkillData . plrDmgHornet = 10 ;
2017-06-11 22:20:16 +02:00
// beam katana
gSkillData . plrDmgBeamKatana = 35 ;
// beam katana
gSkillData . plrDmgFOTN = 15 ;
// Bow
gSkillData . plrDmgBow = 999 ;
//gSkillData.plrDmgBowMonster = 999;
// Jihad
gSkillData . plrDmgJihad = 9999 ;
// Ninja Star
gSkillData . plrDmgStar = 35 ;
//gSkillData.plrDmgStarMonster = 35;
2016-06-04 15:24:23 +02:00
}
// longest the intermission can last, in seconds
# define MAX_INTERMISSION_TIME 120
extern cvar_t timeleft , fragsleft ;
extern cvar_t mp_chattime ;
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : Think ( void )
2016-06-04 15:24:23 +02:00
{
2021-06-07 02:05:58 +02:00
# if !NO_VOICEGAMEMGR
2016-07-31 15:48:50 +02:00
g_VoiceGameMgr . Update ( gpGlobals - > frametime ) ;
2016-06-12 22:43:32 +02:00
# endif
2016-06-04 15:24:23 +02:00
///// Check game rules /////
static int last_frags ;
static int last_time ;
int frags_remaining = 0 ;
int time_remaining = 0 ;
2017-06-11 22:20:16 +02:00
int ltime = 0 ; // Check to see if the times have changed
2016-07-31 15:48:50 +02:00
if ( g_fGameOver ) // someone else quit the game already
2016-06-04 15:24:23 +02:00
{
// bounds check
int time = ( int ) CVAR_GET_FLOAT ( " mp_chattime " ) ;
2016-07-31 15:48:50 +02:00
if ( time < 1 )
2016-06-04 15:24:23 +02:00
CVAR_SET_STRING ( " mp_chattime " , " 1 " ) ;
2016-07-31 15:48:50 +02:00
else if ( time > MAX_INTERMISSION_TIME )
2016-06-04 15:24:23 +02:00
CVAR_SET_STRING ( " mp_chattime " , UTIL_dtos1 ( MAX_INTERMISSION_TIME ) ) ;
m_flIntermissionEndTime = g_flIntermissionStartTime + mp_chattime . value ;
// check to see if we should change levels now
2016-07-31 15:48:50 +02:00
if ( m_flIntermissionEndTime < gpGlobals - > time )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( m_iEndIntermissionButtonHit // check that someone has pressed a key, or the max intermission time is over
| | ( ( g_flIntermissionStartTime + MAX_INTERMISSION_TIME ) < gpGlobals - > time ) )
2016-06-04 15:24:23 +02:00
ChangeLevel ( ) ; // intermission is over
}
return ;
}
float flTimeLimit = timelimit . value * 60 ;
float flFragLimit = fraglimit . value ;
2016-07-31 15:48:50 +02:00
time_remaining = ( int ) ( flTimeLimit ? ( flTimeLimit - gpGlobals - > time ) : 0 ) ;
if ( flTimeLimit ! = 0 & & gpGlobals - > time > = flTimeLimit )
2016-06-04 15:24:23 +02:00
{
GoToIntermission ( ) ;
return ;
}
2016-07-31 15:48:50 +02:00
if ( flFragLimit )
2016-06-04 15:24:23 +02:00
{
int bestfrags = 9999 ;
int remain ;
// check if any player is over the frag limit
2016-07-31 15:48:50 +02:00
for ( int i = 1 ; i < = gpGlobals - > maxClients ; i + + )
2016-06-04 15:24:23 +02:00
{
CBaseEntity * pPlayer = UTIL_PlayerByIndex ( i ) ;
2016-07-31 15:48:50 +02:00
if ( pPlayer & & pPlayer - > pev - > frags > = flFragLimit )
2016-06-04 15:24:23 +02:00
{
GoToIntermission ( ) ;
return ;
}
2016-07-31 15:48:50 +02:00
if ( pPlayer )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
remain = ( int ) ( flFragLimit - pPlayer - > pev - > frags ) ;
2016-07-31 15:48:50 +02:00
if ( remain < bestfrags )
2016-06-04 15:24:23 +02:00
{
bestfrags = remain ;
}
}
}
frags_remaining = bestfrags ;
}
// Updates when frags change
2016-07-31 15:48:50 +02:00
if ( frags_remaining ! = last_frags )
2016-06-04 15:24:23 +02:00
{
g_engfuncs . pfnCvar_DirectSet ( & fragsleft , UTIL_VarArgs ( " %i " , frags_remaining ) ) ;
}
// Updates once per second
2016-07-31 15:48:50 +02:00
if ( timeleft . value ! = last_time )
2016-06-04 15:24:23 +02:00
{
g_engfuncs . pfnCvar_DirectSet ( & timeleft , UTIL_VarArgs ( " %i " , time_remaining ) ) ;
2017-06-11 22:20:16 +02:00
//MESSAGE_BEGIN( MSG_ALL, gmsgTimer, NULL );
//WRITE_LONG( time_remaining );
//MESSAGE_END();
2016-06-04 15:24:23 +02:00
}
last_frags = frags_remaining ;
2016-07-31 15:48:50 +02:00
last_time = time_remaining ;
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay : : IsMultiplayer ( void )
{
return TRUE ;
}
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay : : IsDeathmatch ( void )
{
return TRUE ;
}
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay : : IsCoOp ( void )
{
2017-06-29 15:56:03 +02:00
return gpGlobals - > coop ? TRUE : FALSE ;
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay : : FShouldSwitchWeapon ( CBasePlayer * pPlayer , CBasePlayerItem * pWeapon )
{
2016-07-31 15:48:50 +02:00
if ( ! pWeapon - > CanDeploy ( ) )
2016-06-04 15:24:23 +02:00
{
// that weapon can't deploy anyway.
return FALSE ;
}
2016-07-31 15:48:50 +02:00
if ( ! pPlayer - > m_pActiveItem )
2016-06-04 15:24:23 +02:00
{
// player doesn't have an active item!
return TRUE ;
}
2019-11-03 18:59:33 +01:00
if ( ! pPlayer - > m_iAutoWepSwitch )
{
return FALSE ;
}
2020-10-10 21:08:47 +02:00
if ( pPlayer - > m_iAutoWepSwitch = = 2
& & pPlayer - > m_afButtonLast & ( IN_ATTACK | IN_ATTACK2 ) )
{
return FALSE ;
}
2016-07-31 15:48:50 +02:00
if ( ! pPlayer - > m_pActiveItem - > CanHolster ( ) )
2016-06-04 15:24:23 +02:00
{
// can't put away the active item.
return FALSE ;
}
2016-07-31 15:48:50 +02:00
if ( pWeapon - > iWeight ( ) > pPlayer - > m_pActiveItem - > iWeight ( ) )
2016-06-04 15:24:23 +02:00
{
return TRUE ;
}
return FALSE ;
}
2024-02-03 21:15:33 +01:00
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
BOOL CHalfLifeMultiplay : : GetNextBestWeapon ( CBasePlayer * pPlayer , CBasePlayerItem * pCurrentWeapon )
2016-06-04 15:24:23 +02:00
{
2024-02-03 21:15:33 +01:00
return HLGetNextBestWeapon ( pPlayer , pCurrentWeapon ) ;
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
BOOL CHalfLifeMultiplay : : ClientConnected ( edict_t * pEntity , const char * pszName , const char * pszAddress , char szRejectReason [ 128 ] )
2016-06-04 15:24:23 +02:00
{
2021-06-07 02:05:58 +02:00
# if !NO_VOICEGAMEMGR
2016-07-31 15:48:50 +02:00
g_VoiceGameMgr . ClientConnected ( pEntity ) ;
2016-06-12 22:43:32 +02:00
# endif
2016-06-04 15:24:23 +02:00
return TRUE ;
}
extern int gmsgSayText ;
extern int gmsgGameMode ;
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : UpdateGameMode ( CBasePlayer * pPlayer )
2016-06-04 15:24:23 +02:00
{
MESSAGE_BEGIN ( MSG_ONE , gmsgGameMode , NULL , pPlayer - > edict ( ) ) ;
WRITE_BYTE ( 0 ) ; // game mode none
MESSAGE_END ( ) ;
}
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : InitHUD ( CBasePlayer * pl )
2016-06-04 15:24:23 +02:00
{
// notify other clients of player joining the game
2018-09-17 23:07:30 +02:00
UTIL_ClientPrintAll ( HUD_PRINTNOTIFY , UTIL_VarArgs ( " %s is gonna ruin your shit \n " ,
2017-07-20 20:32:06 +02:00
( pl - > pev - > netname & & ( STRING ( pl - > pev - > netname ) ) [ 0 ] ! = 0 ) ? STRING ( pl - > pev - > netname ) : " unconnected " ) ) ;
2016-06-04 15:24:23 +02:00
// team match?
2017-06-11 22:20:16 +02:00
if ( g_gameplay )
2016-06-04 15:24:23 +02:00
{
2017-06-11 22:20:16 +02:00
UTIL_LogPrintf ( " \" %s<%i><%s><%s> \" coming at ya \n " ,
2016-06-04 15:24:23 +02:00
STRING ( pl - > pev - > netname ) ,
GETPLAYERUSERID ( pl - > edict ( ) ) ,
GETPLAYERAUTHID ( pl - > edict ( ) ) ,
g_engfuncs . pfnInfoKeyValue ( g_engfuncs . pfnGetInfoKeyBuffer ( pl - > edict ( ) ) , " model " ) ) ;
}
else
{
2017-06-11 22:20:16 +02:00
UTIL_LogPrintf ( " \" %s<%i><%s><%i> \" is here; run! \n " ,
2016-06-04 15:24:23 +02:00
STRING ( pl - > pev - > netname ) ,
GETPLAYERUSERID ( pl - > edict ( ) ) ,
GETPLAYERAUTHID ( pl - > edict ( ) ) ,
GETPLAYERUSERID ( pl - > edict ( ) ) ) ;
}
UpdateGameMode ( pl ) ;
2017-06-11 22:20:16 +02:00
pl - > m_fHSDev = CHalfLifeMultiplay : : ClientDevCheck ( pl ) ;
2016-06-04 15:24:23 +02:00
// sending just one score makes the hud scoreboard active; otherwise
// it is just disabled for single play
2023-04-09 15:31:30 +02:00
//fix a bug in the information about the player's score when he left the server, so that his score would not be transferred to another player(seems to work)
MESSAGE_BEGIN ( MSG_ALL , gmsgScoreInfo ) ;
2016-06-04 15:24:23 +02:00
WRITE_BYTE ( ENTINDEX ( pl - > edict ( ) ) ) ;
2023-04-09 15:31:30 +02:00
WRITE_SHORT ( ( int ) pl - > pev - > frags ) ;
WRITE_SHORT ( pl - > m_iDeaths ) ;
2016-06-04 15:24:23 +02:00
WRITE_SHORT ( 0 ) ;
WRITE_SHORT ( 0 ) ;
WRITE_SHORT ( 0 ) ;
WRITE_SHORT ( 0 ) ;
2017-06-11 22:20:16 +02:00
WRITE_SHORT ( pl - > m_fHSDev ) ;
2016-06-04 15:24:23 +02:00
MESSAGE_END ( ) ;
2017-06-11 22:20:16 +02:00
char buf [ 256 ] ;
sprintf ( buf , " media/maps/%s.mp3 " , STRING ( gpGlobals - > mapname ) ) ;
//ALERT( at_console, buf );
MESSAGE_BEGIN ( MSG_ONE , gmsgPlayBGM , NULL , pl - > edict ( ) ) ;
WRITE_STRING ( buf ) ;
MESSAGE_END ( ) ;
2016-06-04 15:24:23 +02:00
SendMOTDToClient ( pl - > edict ( ) ) ;
// loop through all active players and send their score info to the new client
2016-07-31 15:48:50 +02:00
for ( int i = 1 ; i < = gpGlobals - > maxClients ; i + + )
2016-06-04 15:24:23 +02:00
{
// FIXME: Probably don't need to cast this just to read m_iDeaths
CBasePlayer * plr = ( CBasePlayer * ) UTIL_PlayerByIndex ( i ) ;
2016-07-31 15:48:50 +02:00
if ( plr )
2016-06-04 15:24:23 +02:00
{
MESSAGE_BEGIN ( MSG_ONE , gmsgScoreInfo , NULL , pl - > edict ( ) ) ;
WRITE_BYTE ( i ) ; // client number
2017-06-29 15:56:03 +02:00
WRITE_SHORT ( ( int ) plr - > pev - > frags ) ;
2016-06-04 15:24:23 +02:00
WRITE_SHORT ( plr - > m_iDeaths ) ;
WRITE_SHORT ( 0 ) ;
WRITE_SHORT ( GetTeamIndex ( plr - > m_szTeamName ) + 1 ) ;
2017-06-11 22:20:16 +02:00
WRITE_SHORT ( plr - > m_fHSDev ) ;
2016-06-04 15:24:23 +02:00
MESSAGE_END ( ) ;
}
}
2016-07-31 15:48:50 +02:00
if ( g_fGameOver )
2016-06-04 15:24:23 +02:00
{
MESSAGE_BEGIN ( MSG_ONE , SVC_INTERMISSION , NULL , pl - > edict ( ) ) ;
MESSAGE_END ( ) ;
}
}
2017-06-11 22:20:16 +02:00
//Dev Label Check
int CHalfLifeMultiplay : : ClientDevCheck ( CBasePlayer * pPlayer )
{
char buffer [ 64 ] ;
sprintf ( buffer , " %s " , GETPLAYERAUTHID ( pPlayer - > edict ( ) ) ) ;
if ( ( strcmp ( buffer , " STEAM_0:1:3793395 " ) = = 0 ) )
return 1 ; //Buff Drinklots
if ( ( strcmp ( buffer , " STEAM_0:0:19779589 " ) = = 0 ) )
return 2 ;
if ( ( strcmp ( buffer , " STEAM_0:0:4058273 " ) = = 0 ) )
return 1 ; //Patrick Bateman
if ( ( strcmp ( buffer , " STEAM_0:1:13188531 " ) = = 0 ) )
return 2 ;
if ( ( strcmp ( buffer , " STEAM_0:1:35013002 " ) = = 0 ) )
return 2 ;
if ( ( strcmp ( buffer , " STEAM_0:0:2515846 " ) = = 0 ) )
return 2 ;
if ( ( strcmp ( buffer , " STEAM_0:1:16401600 " ) = = 0 ) )
return 3 ; //JONNY ROCK - Voice of Barney
if ( ( strcmp ( buffer , " STEAM_0:1:7505685 " ) = = 0 ) )
return 2 ; //Peter Barton
//if( ( strcmp( buffer, "BOT" ) <= 0 ) )
//return 1;
return 0 ;
}
2016-06-04 15:24:23 +02:00
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : ClientDisconnected ( edict_t * pClient )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( pClient )
2016-06-04 15:24:23 +02:00
{
CBasePlayer * pPlayer = ( CBasePlayer * ) CBaseEntity : : Instance ( pClient ) ;
2016-07-31 15:48:50 +02:00
if ( pPlayer )
2016-06-04 15:24:23 +02:00
{
FireTargets ( " game_playerleave " , pPlayer , pPlayer , USE_TOGGLE , 0 ) ;
// team match?
2017-06-12 18:37:46 +02:00
if ( g_gameplay )
2016-06-04 15:24:23 +02:00
{
2017-06-11 22:20:16 +02:00
UTIL_LogPrintf ( " \" %s<%i><%s><%s> \" just fucking ran \n " ,
2016-06-04 15:24:23 +02:00
STRING ( pPlayer - > pev - > netname ) ,
GETPLAYERUSERID ( pPlayer - > edict ( ) ) ,
GETPLAYERAUTHID ( pPlayer - > edict ( ) ) ,
g_engfuncs . pfnInfoKeyValue ( g_engfuncs . pfnGetInfoKeyBuffer ( pPlayer - > edict ( ) ) , " model " ) ) ;
}
else
{
2017-06-11 22:20:16 +02:00
UTIL_LogPrintf ( " \" %s<%i><%s><%i> \" ran the fuck out! \n " ,
2016-06-04 15:24:23 +02:00
STRING ( pPlayer - > pev - > netname ) ,
GETPLAYERUSERID ( pPlayer - > edict ( ) ) ,
GETPLAYERAUTHID ( pPlayer - > edict ( ) ) ,
GETPLAYERUSERID ( pPlayer - > edict ( ) ) ) ;
}
pPlayer - > RemoveAllItems ( TRUE ) ; // destroy all of the players weapons and items
}
}
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
float CHalfLifeMultiplay : : FlPlayerFallDamage ( CBasePlayer * pPlayer )
2016-06-04 15:24:23 +02:00
{
int iFallDamage = ( int ) falldamage . value ;
2016-07-31 15:48:50 +02:00
switch ( iFallDamage )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
case 1 :
//progressive
2016-06-04 15:24:23 +02:00
pPlayer - > m_flFallVelocity - = PLAYER_MAX_SAFE_FALL_SPEED ;
return pPlayer - > m_flFallVelocity * DAMAGE_FOR_FALL_SPEED ;
break ;
default :
2016-07-31 15:48:50 +02:00
case 0 :
// fixed
2016-06-04 15:24:23 +02:00
return 10 ;
break ;
}
}
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay : : FPlayerCanTakeDamage ( CBasePlayer * pPlayer , CBaseEntity * pAttacker )
{
return TRUE ;
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : PlayerThink ( CBasePlayer * pPlayer )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( g_fGameOver )
2016-06-04 15:24:23 +02:00
{
// check for button presses
2016-07-31 15:48:50 +02:00
if ( pPlayer - > m_afButtonPressed & ( IN_DUCK | IN_ATTACK | IN_ATTACK2 | IN_USE | IN_JUMP ) )
2016-06-04 15:24:23 +02:00
m_iEndIntermissionButtonHit = TRUE ;
// clear attack/use commands from player
pPlayer - > m_afButtonPressed = 0 ;
pPlayer - > pev - > button = 0 ;
pPlayer - > m_afButtonReleased = 0 ;
}
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : PlayerSpawn ( CBasePlayer * pPlayer )
2016-06-04 15:24:23 +02:00
{
BOOL addDefault ;
CBaseEntity * pWeaponEntity = NULL ;
2020-10-10 21:08:47 +02:00
int iOldAutoWepSwitch ;
iOldAutoWepSwitch = pPlayer - > m_iAutoWepSwitch ;
2016-06-04 15:24:23 +02:00
2020-10-10 21:08:47 +02:00
pPlayer - > m_iAutoWepSwitch = 1 ;
2016-07-31 15:48:50 +02:00
pPlayer - > pev - > weapons | = ( 1 < < WEAPON_SUIT ) ;
2016-06-04 15:24:23 +02:00
addDefault = TRUE ;
2017-06-11 22:20:16 +02:00
CBasePlayer * m_pPlayer ;
2016-07-31 15:48:50 +02:00
while ( ( pWeaponEntity = UTIL_FindEntityByClassname ( pWeaponEntity , " game_player_equip " ) ) )
2016-06-04 15:24:23 +02:00
{
pWeaponEntity - > Touch ( pPlayer ) ;
addDefault = FALSE ;
}
2017-06-12 15:51:43 +02:00
if ( IsChristmas ( true ) )
2017-06-11 22:20:16 +02:00
{ // This will never use mp_christmas, cant cheat presents ;)
EMIT_SOUND ( ENT ( m_pPlayer - > pev ) , CHAN_VOICE , " misc/b2.wav " , 0.8 , ATTN_NORM ) ;
ClientPrint ( pPlayer - > pev , HUD_PRINTCENTER , " MERRY CHRISTMAS! \n Have a shotgun and a bow! " ) ; //digamos al cliente
pPlayer - > GiveNamedItem ( " weapon_shotgun " ) ;
pPlayer - > GiveNamedItem ( " weapon_bow " ) ;
//CLIENT_COMMAND( ENT( pPlayer->pev ), "spk \"have some presence\"\n" );
}
2017-06-12 15:51:43 +02:00
if ( IsHalloween ( ) )
2017-06-11 22:20:16 +02:00
{
ClientPrint ( pPlayer - > pev , HUD_PRINTCENTER , " Happy Halloween! \n Have a good one! " ) ; //digamos al cliente
}
2016-07-31 15:48:50 +02:00
if ( addDefault )
2016-06-04 15:24:23 +02:00
{
pPlayer - > GiveNamedItem ( " weapon_crowbar " ) ;
pPlayer - > GiveNamedItem ( " weapon_9mmhandgun " ) ;
2017-06-11 22:20:16 +02:00
pPlayer - > GiveNamedItem ( " ammo_9mmclip " ) ;
pPlayer - > GiveNamedItem ( " weapon_dosh " ) ;
pPlayer - > GiveNamedItem ( " weapon_beamkatana " ) ;
pPlayer - > GiveNamedItem ( " weapon_fotn " ) ;
pPlayer - > GiveNamedItem ( " weapon_ak47 " ) ;
pPlayer - > GiveNamedItem ( " weapon_jason " ) ;
pPlayer - > GiveNamedItem ( " weapon_jihad " ) ;
pPlayer - > GiveNamedItem ( " weapon_nstar " ) ;
pPlayer - > GiveNamedItem ( " weapon_zapper " ) ;
pPlayer - > GiveNamedItem ( " weapon_boombox " ) ;
2016-06-04 15:24:23 +02:00
}
2020-10-10 21:08:47 +02:00
pPlayer - > m_iAutoWepSwitch = iOldAutoWepSwitch ;
2016-06-04 15:24:23 +02:00
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
BOOL CHalfLifeMultiplay : : FPlayerCanRespawn ( CBasePlayer * pPlayer )
2016-06-04 15:24:23 +02:00
{
return TRUE ;
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
float CHalfLifeMultiplay : : FlPlayerSpawnTime ( CBasePlayer * pPlayer )
2016-06-04 15:24:23 +02:00
{
return gpGlobals - > time ; //now!
}
2016-07-31 15:48:50 +02:00
BOOL CHalfLifeMultiplay : : AllowAutoTargetCrosshair ( void )
2016-06-04 15:24:23 +02:00
{
return ( aimcrosshair . value ! = 0 ) ;
}
//=========================================================
// IPointsForKill - how many points awarded to anyone
// that kills this player?
//=========================================================
2016-07-31 15:48:50 +02:00
int CHalfLifeMultiplay : : IPointsForKill ( CBasePlayer * pAttacker , CBasePlayer * pKilled )
2016-06-04 15:24:23 +02:00
{
return 1 ;
}
//=========================================================
// PlayerKilled - someone/something killed this player
//=========================================================
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : PlayerKilled ( CBasePlayer * pVictim , entvars_t * pKiller , entvars_t * pInflictor )
2016-06-04 15:24:23 +02:00
{
DeathNotice ( pVictim , pKiller , pInflictor ) ;
pVictim - > m_iDeaths + = 1 ;
FireTargets ( " game_playerdie " , pVictim , pVictim , USE_TOGGLE , 0 ) ;
CBasePlayer * peKiller = NULL ;
CBaseEntity * ktmp = CBaseEntity : : Instance ( pKiller ) ;
2016-07-31 15:48:50 +02:00
if ( ktmp & & ( ktmp - > Classify ( ) = = CLASS_PLAYER ) )
2016-06-04 15:24:23 +02:00
peKiller = ( CBasePlayer * ) ktmp ;
2024-01-28 10:14:47 +01:00
else if ( ktmp & & ktmp - > Classify ( ) = = CLASS_VEHICLE )
{
CBasePlayer * pDriver = ( CBasePlayer * ) ( ( CFuncVehicle * ) ktmp ) - > m_pDriver ;
if ( pDriver ! = NULL )
{
pKiller = pDriver - > pev ;
peKiller = ( CBasePlayer * ) pDriver ;
}
}
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if ( pVictim - > pev = = pKiller )
2016-06-25 18:33:39 +02:00
{
// killed self
2016-06-04 15:24:23 +02:00
pKiller - > frags - = 1 ;
}
2016-07-31 15:48:50 +02:00
else if ( ktmp & & ktmp - > IsPlayer ( ) )
2016-06-04 15:24:23 +02:00
{
// if a player dies in a deathmatch game and the killer is a client, award the killer some points
pKiller - > frags + = IPointsForKill ( peKiller , pVictim ) ;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
FireTargets ( " game_playerkill " , ktmp , ktmp , USE_TOGGLE , 0 ) ;
}
else
2016-06-25 18:33:39 +02:00
{
// killed by the world
2016-06-04 15:24:23 +02:00
pKiller - > frags - = 1 ;
}
// update the scores
// killed scores
MESSAGE_BEGIN ( MSG_ALL , gmsgScoreInfo ) ;
WRITE_BYTE ( ENTINDEX ( pVictim - > edict ( ) ) ) ;
2017-06-29 15:56:03 +02:00
WRITE_SHORT ( ( int ) pVictim - > pev - > frags ) ;
2016-06-04 15:24:23 +02:00
WRITE_SHORT ( pVictim - > m_iDeaths ) ;
WRITE_SHORT ( 0 ) ;
WRITE_SHORT ( GetTeamIndex ( pVictim - > m_szTeamName ) + 1 ) ;
2017-06-11 22:20:16 +02:00
WRITE_SHORT ( pVictim - > m_fHSDev ) ;
2016-06-04 15:24:23 +02:00
MESSAGE_END ( ) ;
// killers score, if it's a player
CBaseEntity * ep = CBaseEntity : : Instance ( pKiller ) ;
2016-07-31 15:48:50 +02:00
if ( ep & & ep - > Classify ( ) = = CLASS_PLAYER )
2016-06-04 15:24:23 +02:00
{
CBasePlayer * PK = ( CBasePlayer * ) ep ;
MESSAGE_BEGIN ( MSG_ALL , gmsgScoreInfo ) ;
2016-07-31 15:48:50 +02:00
WRITE_BYTE ( ENTINDEX ( PK - > edict ( ) ) ) ;
2017-06-29 15:56:03 +02:00
WRITE_SHORT ( ( int ) PK - > pev - > frags ) ;
2016-06-04 15:24:23 +02:00
WRITE_SHORT ( PK - > m_iDeaths ) ;
WRITE_SHORT ( 0 ) ;
2016-07-31 15:48:50 +02:00
WRITE_SHORT ( GetTeamIndex ( PK - > m_szTeamName ) + 1 ) ;
2017-06-11 22:20:16 +02:00
WRITE_SHORT ( PK - > m_fHSDev ) ;
2016-06-04 15:24:23 +02:00
MESSAGE_END ( ) ;
// let the killer paint another decal as soon as he'd like.
PK - > m_flNextDecalTime = gpGlobals - > time ;
2017-06-11 22:20:16 +02:00
PK - > m_flNextShame = gpGlobals - > time ;
2016-06-04 15:24:23 +02:00
}
}
//=========================================================
// Deathnotice.
//=========================================================
void CHalfLifeMultiplay : : DeathNotice ( CBasePlayer * pVictim , entvars_t * pKiller , entvars_t * pevInflictor )
{
// Work out what killed the player, and send a message to all clients about it
2017-06-29 15:56:03 +02:00
CBaseEntity : : Instance ( pKiller ) ;
2016-06-04 15:24:23 +02:00
const char * killer_weapon_name = " world " ; // by default, the player is killed by the world
int killer_index = 0 ;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
// Hack to fix name change
2017-06-29 15:56:03 +02:00
const char * tau = " tau_cannon " ;
const char * gluon = " gluon gun " ;
2018-09-17 23:07:30 +02:00
const char * xmast = " a Christmas Tree " ;
2016-06-04 15:24:23 +02:00
2021-05-10 05:10:35 +02:00
if ( pevInflictor )
2016-06-04 15:24:23 +02:00
{
2021-05-10 05:10:35 +02:00
if ( pKiller - > flags & FL_CLIENT )
2016-06-04 15:24:23 +02:00
{
2021-05-10 05:10:35 +02:00
killer_index = ENTINDEX ( ENT ( pKiller ) ) ;
2016-07-31 15:48:50 +02:00
if ( pevInflictor = = pKiller )
2016-06-04 15:24:23 +02:00
{
// If the inflictor is the killer, then it must be their current weapon doing the damage
CBasePlayer * pPlayer = ( CBasePlayer * ) CBaseEntity : : Instance ( pKiller ) ;
2016-07-31 15:48:50 +02:00
if ( pPlayer - > m_pActiveItem )
2016-06-04 15:24:23 +02:00
{
killer_weapon_name = pPlayer - > m_pActiveItem - > pszName ( ) ;
}
}
else
{
killer_weapon_name = STRING ( pevInflictor - > classname ) ; // it's just that easy
}
}
2021-05-10 05:10:35 +02:00
else
{
killer_weapon_name = STRING ( pevInflictor - > classname ) ;
}
2016-06-04 15:24:23 +02:00
}
// strip the monster_* or weapon_* from the inflictor's classname
2016-07-31 15:48:50 +02:00
if ( strncmp ( killer_weapon_name , " weapon_ " , 7 ) = = 0 )
2016-06-04 15:24:23 +02:00
killer_weapon_name + = 7 ;
2016-07-31 15:48:50 +02:00
else if ( strncmp ( killer_weapon_name , " monster_ " , 8 ) = = 0 )
2016-06-04 15:24:23 +02:00
killer_weapon_name + = 8 ;
2016-07-31 15:48:50 +02:00
else if ( strncmp ( killer_weapon_name , " func_ " , 5 ) = = 0 )
2016-06-04 15:24:23 +02:00
killer_weapon_name + = 5 ;
MESSAGE_BEGIN ( MSG_ALL , gmsgDeathMsg ) ;
WRITE_BYTE ( killer_index ) ; // the killer
2016-07-31 15:48:50 +02:00
WRITE_BYTE ( ENTINDEX ( pVictim - > edict ( ) ) ) ; // the victim
2016-06-04 15:24:23 +02:00
WRITE_STRING ( killer_weapon_name ) ; // what they were killed by (should this be a string?)
MESSAGE_END ( ) ;
// replace the code names with the 'real' names
2016-07-31 15:48:50 +02:00
if ( ! strcmp ( killer_weapon_name , " egon " ) )
2016-06-04 15:24:23 +02:00
killer_weapon_name = gluon ;
2016-07-31 15:48:50 +02:00
else if ( ! strcmp ( killer_weapon_name , " gauss " ) )
2016-06-04 15:24:23 +02:00
killer_weapon_name = tau ;
2017-06-11 22:20:16 +02:00
else if ( ! strcmp ( killer_weapon_name , " xmast " ) )
killer_weapon_name = xmast ;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if ( pVictim - > pev = = pKiller )
2016-06-04 15:24:23 +02:00
{
// killed self
// team match?
2017-06-11 22:20:16 +02:00
if ( g_gameplay = = HL_TEAMPLAY | | HS_SHYTPLAY )
2016-06-04 15:24:23 +02:00
{
UTIL_LogPrintf ( " \" %s<%i><%s><%s> \" committed suicide with \" %s \" \n " ,
STRING ( pVictim - > pev - > netname ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
GETPLAYERAUTHID ( pVictim - > edict ( ) ) ,
g_engfuncs . pfnInfoKeyValue ( g_engfuncs . pfnGetInfoKeyBuffer ( pVictim - > edict ( ) ) , " model " ) ,
killer_weapon_name ) ;
}
else
{
UTIL_LogPrintf ( " \" %s<%i><%s><%i> \" committed suicide with \" %s \" \n " ,
STRING ( pVictim - > pev - > netname ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
GETPLAYERAUTHID ( pVictim - > edict ( ) ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
killer_weapon_name ) ;
}
}
2016-07-31 15:48:50 +02:00
else if ( pKiller - > flags & FL_CLIENT )
2016-06-04 15:24:23 +02:00
{
// team match?
2017-06-11 22:20:16 +02:00
if ( g_gameplay = = 1 | | 2 )
2016-06-04 15:24:23 +02:00
{
UTIL_LogPrintf ( " \" %s<%i><%s><%s> \" killed \" %s<%i><%s><%s> \" with \" %s \" \n " ,
STRING ( pKiller - > netname ) ,
GETPLAYERUSERID ( ENT ( pKiller ) ) ,
GETPLAYERAUTHID ( ENT ( pKiller ) ) ,
g_engfuncs . pfnInfoKeyValue ( g_engfuncs . pfnGetInfoKeyBuffer ( ENT ( pKiller ) ) , " model " ) ,
STRING ( pVictim - > pev - > netname ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
GETPLAYERAUTHID ( pVictim - > edict ( ) ) ,
g_engfuncs . pfnInfoKeyValue ( g_engfuncs . pfnGetInfoKeyBuffer ( pVictim - > edict ( ) ) , " model " ) ,
killer_weapon_name ) ;
}
else
{
UTIL_LogPrintf ( " \" %s<%i><%s><%i> \" killed \" %s<%i><%s><%i> \" with \" %s \" \n " ,
STRING ( pKiller - > netname ) ,
GETPLAYERUSERID ( ENT ( pKiller ) ) ,
GETPLAYERAUTHID ( ENT ( pKiller ) ) ,
GETPLAYERUSERID ( ENT ( pKiller ) ) ,
STRING ( pVictim - > pev - > netname ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
GETPLAYERAUTHID ( pVictim - > edict ( ) ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
killer_weapon_name ) ;
}
}
2017-06-11 22:20:16 +02:00
else if ( pKiller - > flags & FL_MONSTER )
{
UTIL_LogPrintf ( " \" %s<%i><%s><%i> \" died from a monster " ,
STRING ( pVictim - > pev - > netname ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
GETPLAYERAUTHID ( pVictim - > edict ( ) ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
killer_weapon_name ) ;
}
2016-06-04 15:24:23 +02:00
else
{
// killed by the world
// team match?
2017-06-11 22:20:16 +02:00
if ( g_gameplay = = HL_TEAMPLAY | | HS_SHYTPLAY )
2016-06-04 15:24:23 +02:00
{
UTIL_LogPrintf ( " \" %s<%i><%s><%s> \" committed suicide with \" %s \" (world) \n " ,
STRING ( pVictim - > pev - > netname ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
GETPLAYERAUTHID ( pVictim - > edict ( ) ) ,
g_engfuncs . pfnInfoKeyValue ( g_engfuncs . pfnGetInfoKeyBuffer ( pVictim - > edict ( ) ) , " model " ) ,
killer_weapon_name ) ;
}
else
{
UTIL_LogPrintf ( " \" %s<%i><%s><%i> \" committed suicide with \" %s \" (world) \n " ,
STRING ( pVictim - > pev - > netname ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
GETPLAYERAUTHID ( pVictim - > edict ( ) ) ,
GETPLAYERUSERID ( pVictim - > edict ( ) ) ,
killer_weapon_name ) ;
}
}
MESSAGE_BEGIN ( MSG_SPEC , SVC_DIRECTOR ) ;
2016-07-31 15:48:50 +02:00
WRITE_BYTE ( 9 ) ; // command length in bytes
WRITE_BYTE ( DRC_CMD_EVENT ) ; // player killed
WRITE_SHORT ( ENTINDEX ( pVictim - > edict ( ) ) ) ; // index number of primary entity
if ( pevInflictor )
WRITE_SHORT ( ENTINDEX ( ENT ( pevInflictor ) ) ) ; // index number of secondary entity
2016-06-04 15:24:23 +02:00
else
2016-07-31 15:48:50 +02:00
WRITE_SHORT ( ENTINDEX ( ENT ( pKiller ) ) ) ; // index number of secondary entity
WRITE_LONG ( 7 | DRC_FLAG_DRAMATIC ) ; // eventflags (priority and flags)
2016-06-04 15:24:23 +02:00
MESSAGE_END ( ) ;
// Print a standard message
// TODO: make this go direct to console
return ; // just remove for now
/*
2016-07-31 15:48:50 +02:00
char szText [ 128 ] ;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if ( pKiller - > flags & FL_MONSTER )
2016-06-04 15:24:23 +02:00
{
// killed by a monster
2016-07-31 15:48:50 +02:00
strcpy ( szText , STRING ( pVictim - > pev - > netname ) ) ;
strcat ( szText , " was killed by a monster. \n " ) ;
2016-06-04 15:24:23 +02:00
return ;
}
2016-07-31 15:48:50 +02:00
if ( pKiller = = pVictim - > pev )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
strcpy ( szText , STRING ( pVictim - > pev - > netname ) ) ;
strcat ( szText , " commited suicide. \n " ) ;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
else if ( pKiller - > flags & FL_CLIENT )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
strcpy ( szText , STRING ( pKiller - > netname ) ) ;
2016-06-04 15:24:23 +02:00
strcat ( szText , " : " ) ;
strcat ( szText , killer_weapon_name ) ;
strcat ( szText , " : " ) ;
2016-07-31 15:48:50 +02:00
strcat ( szText , STRING ( pVictim - > pev - > netname ) ) ;
strcat ( szText , " \n " ) ;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
else if ( FClassnameIs ( pKiller , " worldspawn " ) )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
strcpy ( szText , STRING ( pVictim - > pev - > netname ) ) ;
strcat ( szText , " fell or drowned or something. \n " ) ;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
else if ( pKiller - > solid = = SOLID_BSP )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
strcpy ( szText , STRING ( pVictim - > pev - > netname ) ) ;
strcat ( szText , " was mooshed. \n " ) ;
2016-06-04 15:24:23 +02:00
}
else
{
2016-07-31 15:48:50 +02:00
strcpy ( szText , STRING ( pVictim - > pev - > netname ) ) ;
strcat ( szText , " died mysteriously. \n " ) ;
2016-06-04 15:24:23 +02:00
}
UTIL_ClientPrintAll ( szText ) ;
*/
}
//=========================================================
// PlayerGotWeapon - player has grabbed a weapon that was
// sitting in the world
//=========================================================
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : PlayerGotWeapon ( CBasePlayer * pPlayer , CBasePlayerItem * pWeapon )
2016-06-04 15:24:23 +02:00
{
2017-06-11 22:20:16 +02:00
EMIT_SOUND ( ENT ( pPlayer - > pev ) , CHAN_ITEM , " item/cv2_get.wav " , 1 , ATTN_NORM ) ;
2016-06-04 15:24:23 +02:00
}
//=========================================================
// FlWeaponRespawnTime - what is the time in the future
// at which this weapon may spawn?
//=========================================================
2016-07-31 15:48:50 +02:00
float CHalfLifeMultiplay : : FlWeaponRespawnTime ( CBasePlayerItem * pWeapon )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( weaponstay . value > 0 )
2016-06-04 15:24:23 +02:00
{
// make sure it's only certain weapons
2016-07-31 15:48:50 +02:00
if ( ! ( pWeapon - > iFlags ( ) & ITEM_FLAG_LIMITINWORLD ) )
2016-06-04 15:24:23 +02:00
{
return gpGlobals - > time + 0 ; // weapon respawns almost instantly
}
}
return gpGlobals - > time + WEAPON_RESPAWN_TIME ;
}
// when we are within this close to running out of entities, items
// marked with the ITEM_FLAG_LIMITINWORLD will delay their respawn
# define ENTITY_INTOLERANCE 100
//=========================================================
// FlWeaponRespawnTime - Returns 0 if the weapon can respawn
// now, otherwise it returns the time at which it can try
// to spawn again.
//=========================================================
2016-07-31 15:48:50 +02:00
float CHalfLifeMultiplay : : FlWeaponTryRespawn ( CBasePlayerItem * pWeapon )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( pWeapon & & pWeapon - > m_iId & & ( pWeapon - > iFlags ( ) & ITEM_FLAG_LIMITINWORLD ) )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( NUMBER_OF_ENTITIES ( ) < ( gpGlobals - > maxEntities - ENTITY_INTOLERANCE ) )
2016-06-04 15:24:23 +02:00
return 0 ;
// we're past the entity tolerance level, so delay the respawn
return FlWeaponRespawnTime ( pWeapon ) ;
}
return 0 ;
}
//=========================================================
// VecWeaponRespawnSpot - where should this weapon spawn?
// Some game variations may choose to randomize spawn locations
//=========================================================
2016-07-31 15:48:50 +02:00
Vector CHalfLifeMultiplay : : VecWeaponRespawnSpot ( CBasePlayerItem * pWeapon )
2016-06-04 15:24:23 +02:00
{
return pWeapon - > pev - > origin ;
}
//=========================================================
// WeaponShouldRespawn - any conditions inhibiting the
// respawning of this weapon?
//=========================================================
2016-07-31 15:48:50 +02:00
int CHalfLifeMultiplay : : WeaponShouldRespawn ( CBasePlayerItem * pWeapon )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( pWeapon - > pev - > spawnflags & SF_NORESPAWN )
2016-06-04 15:24:23 +02:00
{
return GR_WEAPON_RESPAWN_NO ;
}
return GR_WEAPON_RESPAWN_YES ;
}
//=========================================================
// CanHaveWeapon - returns FALSE if the player is not allowed
// to pick up this weapon
//=========================================================
BOOL CHalfLifeMultiplay : : CanHavePlayerItem ( CBasePlayer * pPlayer , CBasePlayerItem * pItem )
{
2016-07-31 15:48:50 +02:00
if ( weaponstay . value > 0 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( pItem - > iFlags ( ) & ITEM_FLAG_LIMITINWORLD )
2016-06-04 15:24:23 +02:00
return CGameRules : : CanHavePlayerItem ( pPlayer , pItem ) ;
// check if the player already has this weapon
2016-07-31 15:48:50 +02:00
for ( int i = 0 ; i < MAX_ITEM_TYPES ; i + + )
2016-06-04 15:24:23 +02:00
{
CBasePlayerItem * it = pPlayer - > m_rgpPlayerItems [ i ] ;
2016-07-31 15:48:50 +02:00
while ( it ! = NULL )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( it - > m_iId = = pItem - > m_iId )
2016-06-04 15:24:23 +02:00
{
return FALSE ;
}
it = it - > m_pNext ;
}
}
}
return CGameRules : : CanHavePlayerItem ( pPlayer , pItem ) ;
}
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay : : CanHaveItem ( CBasePlayer * pPlayer , CItem * pItem )
{
return TRUE ;
}
//=========================================================
//=========================================================
void CHalfLifeMultiplay : : PlayerGotItem ( CBasePlayer * pPlayer , CItem * pItem )
{
}
//=========================================================
//=========================================================
int CHalfLifeMultiplay : : ItemShouldRespawn ( CItem * pItem )
{
2016-07-31 15:48:50 +02:00
if ( pItem - > pev - > spawnflags & SF_NORESPAWN )
2016-06-04 15:24:23 +02:00
{
return GR_ITEM_RESPAWN_NO ;
}
return GR_ITEM_RESPAWN_YES ;
}
//=========================================================
// At what time in the future may this Item respawn?
//=========================================================
float CHalfLifeMultiplay : : FlItemRespawnTime ( CItem * pItem )
{
return gpGlobals - > time + ITEM_RESPAWN_TIME ;
}
//=========================================================
// Where should this item respawn?
// Some game variations may choose to randomize spawn locations
//=========================================================
Vector CHalfLifeMultiplay : : VecItemRespawnSpot ( CItem * pItem )
{
return pItem - > pev - > origin ;
}
//=========================================================
//=========================================================
void CHalfLifeMultiplay : : PlayerGotAmmo ( CBasePlayer * pPlayer , char * szName , int iCount )
{
}
//=========================================================
//=========================================================
BOOL CHalfLifeMultiplay : : IsAllowedToSpawn ( CBaseEntity * pEntity )
{
2016-07-31 15:48:50 +02:00
// if( pEntity->pev->flags & FL_MONSTER )
2016-06-04 15:24:23 +02:00
// return FALSE;
return TRUE ;
}
//=========================================================
//=========================================================
int CHalfLifeMultiplay : : AmmoShouldRespawn ( CBasePlayerAmmo * pAmmo )
{
2016-07-31 15:48:50 +02:00
if ( pAmmo - > pev - > spawnflags & SF_NORESPAWN )
2016-06-04 15:24:23 +02:00
{
return GR_AMMO_RESPAWN_NO ;
}
return GR_AMMO_RESPAWN_YES ;
}
//=========================================================
//=========================================================
float CHalfLifeMultiplay : : FlAmmoRespawnTime ( CBasePlayerAmmo * pAmmo )
{
return gpGlobals - > time + AMMO_RESPAWN_TIME ;
}
//=========================================================
//=========================================================
Vector CHalfLifeMultiplay : : VecAmmoRespawnSpot ( CBasePlayerAmmo * pAmmo )
{
return pAmmo - > pev - > origin ;
}
//=========================================================
//=========================================================
float CHalfLifeMultiplay : : FlHealthChargerRechargeTime ( void )
{
return 60 ;
}
float CHalfLifeMultiplay : : FlHEVChargerRechargeTime ( void )
{
return 30 ;
}
//=========================================================
//=========================================================
int CHalfLifeMultiplay : : DeadPlayerWeapons ( CBasePlayer * pPlayer )
{
return GR_PLR_DROP_GUN_ACTIVE ;
}
//=========================================================
//=========================================================
int CHalfLifeMultiplay : : DeadPlayerAmmo ( CBasePlayer * pPlayer )
{
return GR_PLR_DROP_AMMO_ACTIVE ;
}
edict_t * CHalfLifeMultiplay : : GetPlayerSpawnSpot ( CBasePlayer * pPlayer )
{
edict_t * pentSpawnSpot = CGameRules : : GetPlayerSpawnSpot ( pPlayer ) ;
2016-07-31 15:48:50 +02:00
if ( IsMultiplayer ( ) & & pentSpawnSpot - > v . target )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
FireTargets ( STRING ( pentSpawnSpot - > v . target ) , pPlayer , pPlayer , USE_TOGGLE , 0 ) ;
2016-06-04 15:24:23 +02:00
}
return pentSpawnSpot ;
}
//=========================================================
//=========================================================
int CHalfLifeMultiplay : : PlayerRelationship ( CBaseEntity * pPlayer , CBaseEntity * pTarget )
{
// half life deathmatch has only enemies
return GR_NOTTEAMMATE ;
}
2016-07-31 15:48:50 +02:00
BOOL CHalfLifeMultiplay : : PlayFootstepSounds ( CBasePlayer * pl , float fvol )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( g_footsteps & & g_footsteps - > value = = 0 )
2016-06-04 15:24:23 +02:00
return FALSE ;
2016-07-31 15:48:50 +02:00
if ( pl - > IsOnLadder ( ) | | pl - > pev - > velocity . Length2D ( ) > 220 )
2016-06-04 15:24:23 +02:00
return TRUE ; // only make step sounds in multiplayer if the player is moving fast enough
return FALSE ;
}
2016-07-31 15:48:50 +02:00
BOOL CHalfLifeMultiplay : : FAllowFlashlight ( void )
{
2016-06-04 15:24:23 +02:00
return flashlight . value ! = 0 ;
}
//=========================================================
//=========================================================
2016-07-31 15:48:50 +02:00
BOOL CHalfLifeMultiplay : : FAllowMonsters ( void )
2016-06-04 15:24:23 +02:00
{
return ( allowmonsters . value ! = 0 ) ;
}
//=========================================================
//======== CHalfLifeMultiplay private functions ===========
# define INTERMISSION_TIME 6
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : GoToIntermission ( void )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( g_fGameOver )
2016-06-04 15:24:23 +02:00
return ; // intermission has already been triggered, so ignore.
2017-06-11 22:20:16 +02:00
//Turn off any Map BGM.
MESSAGE_BEGIN ( MSG_ALL , gmsgStopMP3 ) ;
MESSAGE_END ( ) ;
2016-07-31 15:48:50 +02:00
MESSAGE_BEGIN ( MSG_ALL , SVC_INTERMISSION ) ;
2016-06-04 15:24:23 +02:00
MESSAGE_END ( ) ;
// bounds check
int time = ( int ) CVAR_GET_FLOAT ( " mp_chattime " ) ;
2016-07-31 15:48:50 +02:00
if ( time < 1 )
2016-06-04 15:24:23 +02:00
CVAR_SET_STRING ( " mp_chattime " , " 1 " ) ;
2016-07-31 15:48:50 +02:00
else if ( time > MAX_INTERMISSION_TIME )
2016-06-04 15:24:23 +02:00
CVAR_SET_STRING ( " mp_chattime " , UTIL_dtos1 ( MAX_INTERMISSION_TIME ) ) ;
2017-06-11 22:20:16 +02:00
//edict_t *pClient;
//pClient = g_engfuncs.pfnPEntityOfEntIndex( 1 );
2016-06-04 15:24:23 +02:00
m_flIntermissionEndTime = gpGlobals - > time + ( ( int ) mp_chattime . value ) ;
g_flIntermissionStartTime = gpGlobals - > time ;
g_fGameOver = TRUE ;
m_iEndIntermissionButtonHit = FALSE ;
}
# define MAX_RULE_BUFFER 1024
typedef struct mapcycle_item_s
{
struct mapcycle_item_s * next ;
2016-07-31 15:48:50 +02:00
char mapname [ 32 ] ;
int minplayers , maxplayers ;
char rulebuffer [ MAX_RULE_BUFFER ] ;
2016-06-04 15:24:23 +02:00
} mapcycle_item_t ;
typedef struct mapcycle_s
{
struct mapcycle_item_s * items ;
struct mapcycle_item_s * next_item ;
} mapcycle_t ;
/*
= = = = = = = = = = = = = =
DestroyMapCycle
Clean up memory used by mapcycle when switching it
= = = = = = = = = = = = = =
*/
void DestroyMapCycle ( mapcycle_t * cycle )
{
mapcycle_item_t * p , * n , * start ;
p = cycle - > items ;
2016-07-31 15:48:50 +02:00
if ( p )
2016-06-04 15:24:23 +02:00
{
start = p ;
p = p - > next ;
2016-07-31 15:48:50 +02:00
while ( p ! = start )
2016-06-04 15:24:23 +02:00
{
n = p - > next ;
delete p ;
p = n ;
}
delete cycle - > items ;
}
cycle - > items = NULL ;
cycle - > next_item = NULL ;
}
2016-07-31 15:48:50 +02:00
static char com_token [ 1500 ] ;
2016-06-04 15:24:23 +02:00
/*
= = = = = = = = = = = = = =
COM_Parse
Parse a token out of a string
= = = = = = = = = = = = = =
*/
2017-07-23 23:24:55 +02:00
const char * COM_Parse ( const char * data )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
int c ;
int len ;
2016-06-25 18:33:39 +02:00
2016-06-04 15:24:23 +02:00
len = 0 ;
com_token [ 0 ] = 0 ;
2016-06-25 18:33:39 +02:00
2016-07-31 15:48:50 +02:00
if ( ! data )
2016-06-04 15:24:23 +02:00
return NULL ;
2016-06-25 18:33:39 +02:00
2016-06-04 15:24:23 +02:00
// skip whitespace
skipwhite :
2016-07-31 15:48:50 +02:00
while ( ( c = * data ) < = ' ' )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( c = = 0 )
2016-06-04 15:24:23 +02:00
return NULL ; // end of file;
data + + ;
}
2016-06-25 18:33:39 +02:00
// skip // comments
2016-07-31 15:48:50 +02:00
if ( c = = ' / ' & & data [ 1 ] = = ' / ' )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
while ( * data & & * data ! = ' \n ' )
2016-06-04 15:24:23 +02:00
data + + ;
goto skipwhite ;
}
2016-06-25 18:33:39 +02:00
// handle quoted strings specially
2016-07-31 15:48:50 +02:00
if ( c = = ' \" ' )
2016-06-04 15:24:23 +02:00
{
data + + ;
2016-07-31 15:48:50 +02:00
while ( 1 )
2016-06-04 15:24:23 +02:00
{
c = * data + + ;
2016-07-31 15:48:50 +02:00
if ( c = = ' \" ' | | ! c )
2016-06-04 15:24:23 +02:00
{
com_token [ len ] = 0 ;
return data ;
}
com_token [ len ] = c ;
len + + ;
}
}
2016-06-25 18:33:39 +02:00
// parse single characters
2016-07-31 15:48:50 +02:00
if ( c = = ' { ' | | c = = ' } ' | | c = = ' ) ' | | c = = ' ( ' | | c = = ' \' ' | | c = = ' , ' )
2016-06-04 15:24:23 +02:00
{
com_token [ len ] = c ;
len + + ;
com_token [ len ] = 0 ;
2016-07-31 15:48:50 +02:00
return data + 1 ;
2016-06-04 15:24:23 +02:00
}
2016-06-25 18:33:39 +02:00
// parse a regular word
2016-06-04 15:24:23 +02:00
do
{
com_token [ len ] = c ;
data + + ;
len + + ;
c = * data ;
2016-07-31 15:48:50 +02:00
if ( c = = ' { ' | | c = = ' } ' | | c = = ' ) ' | | c = = ' ( ' | | c = = ' \' ' | | c = = ' , ' )
2016-06-04 15:24:23 +02:00
break ;
2016-07-31 15:48:50 +02:00
} while ( c > 32 ) ;
2016-06-25 18:33:39 +02:00
2016-06-04 15:24:23 +02:00
com_token [ len ] = 0 ;
return data ;
}
/*
= = = = = = = = = = = = = =
COM_TokenWaiting
Returns 1 if additional data is waiting to be processed on this line
= = = = = = = = = = = = = =
*/
2017-07-23 23:24:55 +02:00
int COM_TokenWaiting ( const char * buffer )
2016-06-04 15:24:23 +02:00
{
2017-07-23 23:24:55 +02:00
const char * p ;
2016-06-04 15:24:23 +02:00
p = buffer ;
2016-07-31 15:48:50 +02:00
while ( * p & & * p ! = ' \n ' )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( ! isspace ( * p ) | | isalnum ( * p ) )
2016-06-04 15:24:23 +02:00
return 1 ;
p + + ;
}
return 0 ;
}
/*
= = = = = = = = = = = = = =
ReloadMapCycleFile
Parses mapcycle . txt file into mapcycle_t structure
= = = = = = = = = = = = = =
*/
2017-07-23 23:24:55 +02:00
int ReloadMapCycleFile ( const char * filename , mapcycle_t * cycle )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
char szMap [ 32 ] ;
2016-06-04 15:24:23 +02:00
int length ;
2017-07-23 23:24:55 +02:00
const char * pFileList ;
const char * aFileList = pFileList = ( const char * ) LOAD_FILE_FOR_ME ( filename , & length ) ;
2016-06-04 15:24:23 +02:00
int hasbuffer ;
mapcycle_item_s * item , * newlist = NULL , * next ;
2016-07-31 15:48:50 +02:00
if ( pFileList & & length )
2016-06-04 15:24:23 +02:00
{
// the first map name in the file becomes the default
2016-07-31 15:48:50 +02:00
while ( 1 )
2016-06-04 15:24:23 +02:00
{
2016-08-02 13:59:22 +02:00
char szBuffer [ MAX_RULE_BUFFER ] = { 0 } ;
2016-06-04 15:24:23 +02:00
hasbuffer = 0 ;
pFileList = COM_Parse ( pFileList ) ;
2019-09-24 00:00:37 +02:00
if ( com_token [ 0 ] = = ' \0 ' )
2016-06-04 15:24:23 +02:00
break ;
strcpy ( szMap , com_token ) ;
// Any more tokens on this line?
2016-07-31 15:48:50 +02:00
if ( COM_TokenWaiting ( pFileList ) )
2016-06-04 15:24:23 +02:00
{
pFileList = COM_Parse ( pFileList ) ;
2019-09-24 00:00:37 +02:00
if ( com_token [ 0 ] ! = ' \0 ' )
2016-06-04 15:24:23 +02:00
{
hasbuffer = 1 ;
strcpy ( szBuffer , com_token ) ;
}
}
// Check map
2016-07-31 15:48:50 +02:00
if ( IS_MAP_VALID ( szMap ) )
2016-06-04 15:24:23 +02:00
{
// Create entry
char * s ;
item = new mapcycle_item_s ;
strcpy ( item - > mapname , szMap ) ;
item - > minplayers = 0 ;
item - > maxplayers = 0 ;
memset ( item - > rulebuffer , 0 , MAX_RULE_BUFFER ) ;
2016-07-31 15:48:50 +02:00
if ( hasbuffer )
2016-06-04 15:24:23 +02:00
{
s = g_engfuncs . pfnInfoKeyValue ( szBuffer , " minplayers " ) ;
2016-07-31 15:48:50 +02:00
if ( s & & s [ 0 ] )
2016-06-04 15:24:23 +02:00
{
item - > minplayers = atoi ( s ) ;
2017-10-14 21:57:55 +02:00
item - > minplayers = Q_max ( item - > minplayers , 0 ) ;
item - > minplayers = Q_min ( item - > minplayers , gpGlobals - > maxClients ) ;
2016-06-04 15:24:23 +02:00
}
s = g_engfuncs . pfnInfoKeyValue ( szBuffer , " maxplayers " ) ;
2016-07-31 15:48:50 +02:00
if ( s & & s [ 0 ] )
2016-06-04 15:24:23 +02:00
{
item - > maxplayers = atoi ( s ) ;
2017-10-14 21:57:55 +02:00
item - > maxplayers = Q_max ( item - > maxplayers , 0 ) ;
item - > maxplayers = Q_min ( item - > maxplayers , gpGlobals - > maxClients ) ;
2016-06-04 15:24:23 +02:00
}
// Remove keys
//
g_engfuncs . pfnInfo_RemoveKey ( szBuffer , " minplayers " ) ;
g_engfuncs . pfnInfo_RemoveKey ( szBuffer , " maxplayers " ) ;
strcpy ( item - > rulebuffer , szBuffer ) ;
}
item - > next = cycle - > items ;
cycle - > items = item ;
}
else
{
ALERT ( at_console , " Skipping %s from mapcycle, not a valid map \n " , szMap ) ;
}
}
2017-07-23 23:24:55 +02:00
FREE_FILE ( ( void * ) aFileList ) ;
2016-06-04 15:24:23 +02:00
}
// Fixup circular list pointer
item = cycle - > items ;
// Reverse it to get original order
2016-07-31 15:48:50 +02:00
while ( item )
2016-06-04 15:24:23 +02:00
{
next = item - > next ;
item - > next = newlist ;
newlist = item ;
item = next ;
}
cycle - > items = newlist ;
item = cycle - > items ;
// Didn't parse anything
2016-07-31 15:48:50 +02:00
if ( ! item )
2016-06-04 15:24:23 +02:00
{
return 0 ;
}
2016-07-31 15:48:50 +02:00
while ( item - > next )
2016-06-04 15:24:23 +02:00
{
item = item - > next ;
}
item - > next = cycle - > items ;
2016-06-25 18:33:39 +02:00
2016-06-04 15:24:23 +02:00
cycle - > next_item = item - > next ;
return 1 ;
}
/*
= = = = = = = = = = = = = =
CountPlayers
Determine the current # of active players on the server for map cycling logic
= = = = = = = = = = = = = =
*/
int CountPlayers ( void )
{
2016-07-31 15:48:50 +02:00
int num = 0 ;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
for ( int i = 1 ; i < = gpGlobals - > maxClients ; i + + )
2016-06-04 15:24:23 +02:00
{
CBaseEntity * pEnt = UTIL_PlayerByIndex ( i ) ;
2016-07-31 15:48:50 +02:00
if ( pEnt )
2016-06-04 15:24:23 +02:00
{
num = num + 1 ;
}
}
return num ;
}
/*
= = = = = = = = = = = = = =
ExtractCommandString
Parse commands / key value pairs to issue right after map xxx command is issued on server
level transition
= = = = = = = = = = = = = =
*/
void ExtractCommandString ( char * s , char * szCommand )
{
// Now make rules happen
2016-07-31 15:48:50 +02:00
char pkey [ 512 ] ;
char value [ 512 ] ; // use two buffers so compares
2016-06-25 18:33:39 +02:00
// work without stomping on each other
2016-07-31 15:48:50 +02:00
char * o ;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if ( * s = = ' \\ ' )
2016-06-04 15:24:23 +02:00
s + + ;
2016-07-31 15:48:50 +02:00
while ( 1 )
2016-06-04 15:24:23 +02:00
{
o = pkey ;
2016-07-31 15:48:50 +02:00
while ( * s ! = ' \\ ' )
2016-06-04 15:24:23 +02:00
{
if ( ! * s )
return ;
* o + + = * s + + ;
}
* o = 0 ;
s + + ;
o = value ;
2016-07-31 15:48:50 +02:00
while ( * s ! = ' \\ ' & & * s )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( ! * s )
2016-06-04 15:24:23 +02:00
return ;
* o + + = * s + + ;
}
* o = 0 ;
strcat ( szCommand , pkey ) ;
2019-09-24 00:00:37 +02:00
if ( value [ 0 ] ! = ' \0 ' )
2016-06-04 15:24:23 +02:00
{
strcat ( szCommand , " " ) ;
strcat ( szCommand , value ) ;
}
strcat ( szCommand , " \n " ) ;
2016-07-31 15:48:50 +02:00
if ( ! * s )
2016-06-04 15:24:23 +02:00
return ;
s + + ;
}
}
/*
= = = = = = = = = = = = = =
ChangeLevel
Server is changing to a new level , check mapcycle . txt for map name and setup info
= = = = = = = = = = = = = =
*/
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : ChangeLevel ( void )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
static char szPreviousMapCycleFile [ 256 ] ;
2016-06-04 15:24:23 +02:00
static mapcycle_t mapcycle ;
char szNextMap [ 32 ] ;
char szFirstMapInList [ 32 ] ;
2016-07-31 15:48:50 +02:00
char szCommands [ 1500 ] ;
char szRules [ 1500 ] ;
2016-06-04 15:24:23 +02:00
int minplayers = 0 , maxplayers = 0 ;
strcpy ( szFirstMapInList , " hldm1 " ) ; // the absolute default level is hldm1
2016-07-31 15:48:50 +02:00
int curplayers ;
2016-06-04 15:24:23 +02:00
BOOL do_cycle = TRUE ;
// find the map to change to
2017-07-23 23:24:55 +02:00
const char * mapcfile = CVAR_GET_STRING ( " mapcyclefile " ) ;
2016-06-04 15:24:23 +02:00
ASSERT ( mapcfile ! = NULL ) ;
2016-07-31 15:48:50 +02:00
szCommands [ 0 ] = ' \0 ' ;
szRules [ 0 ] = ' \0 ' ;
2016-06-04 15:24:23 +02:00
curplayers = CountPlayers ( ) ;
// Has the map cycle filename changed?
2016-07-31 15:48:50 +02:00
if ( stricmp ( mapcfile , szPreviousMapCycleFile ) )
2016-06-04 15:24:23 +02:00
{
strcpy ( szPreviousMapCycleFile , mapcfile ) ;
DestroyMapCycle ( & mapcycle ) ;
2016-07-31 15:48:50 +02:00
if ( ! ReloadMapCycleFile ( mapcfile , & mapcycle ) | | ( ! mapcycle . items ) )
2016-06-04 15:24:23 +02:00
{
ALERT ( at_console , " Unable to load map cycle file %s \n " , mapcfile ) ;
do_cycle = FALSE ;
}
}
2016-07-31 15:48:50 +02:00
if ( do_cycle & & mapcycle . items )
2016-06-04 15:24:23 +02:00
{
BOOL keeplooking = FALSE ;
BOOL found = FALSE ;
mapcycle_item_s * item ;
// Assume current map
2016-07-31 15:48:50 +02:00
strcpy ( szNextMap , STRING ( gpGlobals - > mapname ) ) ;
strcpy ( szFirstMapInList , STRING ( gpGlobals - > mapname ) ) ;
2016-06-04 15:24:23 +02:00
// Traverse list
2016-07-31 15:48:50 +02:00
for ( item = mapcycle . next_item ; item - > next ! = mapcycle . next_item ; item = item - > next )
2016-06-04 15:24:23 +02:00
{
keeplooking = FALSE ;
ASSERT ( item ! = NULL ) ;
2016-07-31 15:48:50 +02:00
if ( item - > minplayers ! = 0 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( curplayers > = item - > minplayers )
2016-06-04 15:24:23 +02:00
{
found = TRUE ;
minplayers = item - > minplayers ;
}
else
{
keeplooking = TRUE ;
}
}
2016-07-31 15:48:50 +02:00
if ( item - > maxplayers ! = 0 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if ( curplayers < = item - > maxplayers )
2016-06-04 15:24:23 +02:00
{
found = TRUE ;
maxplayers = item - > maxplayers ;
}
else
{
keeplooking = TRUE ;
}
}
2016-07-31 15:48:50 +02:00
if ( keeplooking )
2016-06-04 15:24:23 +02:00
continue ;
found = TRUE ;
break ;
}
2016-07-31 15:48:50 +02:00
if ( ! found )
2016-06-04 15:24:23 +02:00
{
item = mapcycle . next_item ;
2016-07-31 15:48:50 +02:00
}
2016-06-04 15:24:23 +02:00
// Increment next item pointer
mapcycle . next_item = item - > next ;
// Perform logic on current item
strcpy ( szNextMap , item - > mapname ) ;
ExtractCommandString ( item - > rulebuffer , szCommands ) ;
strcpy ( szRules , item - > rulebuffer ) ;
}
2016-07-31 15:48:50 +02:00
if ( ! IS_MAP_VALID ( szNextMap ) )
2016-06-04 15:24:23 +02:00
{
strcpy ( szNextMap , szFirstMapInList ) ;
}
g_fGameOver = TRUE ;
2017-06-11 22:20:16 +02:00
edict_t * pClient ;
pClient = g_engfuncs . pfnPEntityOfEntIndex ( 1 ) ;
CLIENT_COMMAND ( pClient , " stopaudio \n " ) ;
// START BOT
// loop through all the players...
for ( int i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
CBaseEntity * pEntity ;
pEntity = UTIL_PlayerByIndex ( i ) ;
if ( ! pEntity ) // if invalid then continue with next index...
continue ;
CBasePlayer * pPlayer = ( CBasePlayer * ) pEntity ;
// if botcam is in use, disconnect so buttons will work...
if ( pPlayer - > pBotCam )
pPlayer - > pBotCam - > Disconnect ( ) ;
}
// kick any bot off of the server after time/frag limit...
for ( int index = 0 ; index < 32 ; index + + )
{
if ( bot_respawn [ index ] . is_used ) // is this slot used?
{
char cmd [ 40 ] ;
sprintf ( cmd , " kick \" %s \" \n " , bot_respawn [ index ] . name ) ;
bot_respawn [ index ] . state = BOT_NEED_TO_RESPAWN ;
SERVER_COMMAND ( cmd ) ; // kick the bot using (kick "name")
}
}
// END BOT
2016-06-04 15:24:23 +02:00
ALERT ( at_console , " CHANGE LEVEL: %s \n " , szNextMap ) ;
2016-07-31 15:48:50 +02:00
if ( minplayers | | maxplayers )
2016-06-04 15:24:23 +02:00
{
ALERT ( at_console , " PLAYER COUNT: min %i max %i current %i \n " , minplayers , maxplayers , curplayers ) ;
}
2019-09-24 00:00:37 +02:00
2019-09-24 00:06:07 +02:00
if ( szRules [ 0 ] ! = ' \0 ' )
2016-06-04 15:24:23 +02:00
{
ALERT ( at_console , " RULES: %s \n " , szRules ) ;
}
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
CHANGE_LEVEL ( szNextMap , NULL ) ;
2019-09-24 00:00:37 +02:00
if ( szCommands [ 0 ] ! = ' \0 ' )
2016-06-04 15:24:23 +02:00
{
SERVER_COMMAND ( szCommands ) ;
}
}
# define MAX_MOTD_CHUNK 60
# define MAX_MOTD_LENGTH 1536 // (MAX_MOTD_CHUNK * 4)
2016-07-31 15:48:50 +02:00
void CHalfLifeMultiplay : : SendMOTDToClient ( edict_t * client )
2016-06-04 15:24:23 +02:00
{
// read from the MOTD.txt file
int length , char_count = 0 ;
char * pFileList ;
2018-04-11 01:48:42 +02:00
char * aFileList = pFileList = ( char * ) LOAD_FILE_FOR_ME ( CVAR_GET_STRING ( " motdfile " ) , & length ) ;
2016-06-04 15:24:23 +02:00
// send the server name
MESSAGE_BEGIN ( MSG_ONE , gmsgServerName , NULL , client ) ;
2016-07-31 15:48:50 +02:00
WRITE_STRING ( CVAR_GET_STRING ( " hostname " ) ) ;
2016-06-04 15:24:23 +02:00
MESSAGE_END ( ) ;
// Send the message of the day
// read it chunk-by-chunk, and send it in parts
2016-07-31 15:48:50 +02:00
while ( pFileList & & * pFileList & & char_count < MAX_MOTD_LENGTH )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
char chunk [ MAX_MOTD_CHUNK + 1 ] ;
2016-06-25 18:33:39 +02:00
2016-07-31 15:48:50 +02:00
if ( strlen ( pFileList ) < MAX_MOTD_CHUNK )
2016-06-04 15:24:23 +02:00
{
strcpy ( chunk , pFileList ) ;
}
else
{
strncpy ( chunk , pFileList , MAX_MOTD_CHUNK ) ;
chunk [ MAX_MOTD_CHUNK ] = 0 ; // strncpy doesn't always append the null terminator
}
char_count + = strlen ( chunk ) ;
2016-07-31 15:48:50 +02:00
if ( char_count < MAX_MOTD_LENGTH )
2016-06-04 15:24:23 +02:00
pFileList = aFileList + char_count ;
else
* pFileList = 0 ;
MESSAGE_BEGIN ( MSG_ONE , gmsgMOTD , NULL , client ) ;
WRITE_BYTE ( * pFileList ? FALSE : TRUE ) ; // FALSE means there is still more message to come
WRITE_STRING ( chunk ) ;
MESSAGE_END ( ) ;
}
2017-07-23 23:24:55 +02:00
FREE_FILE ( ( void * ) aFileList ) ;
2016-06-04 15:24:23 +02:00
}
2024-02-02 14:02:25 +01:00
2024-02-25 22:05:17 +01:00
/*
2024-02-02 14:02:25 +01:00
int CMultiplayBusters : : WeaponShouldRespawn ( CBasePlayerItem * pWeapon )
{
if ( pWeapon - > m_iId = = WEAPON_EGON )
return GR_WEAPON_RESPAWN_NO ;
return CHalfLifeMultiplay : : WeaponShouldRespawn ( pWeapon ) ;
}
BOOL CMultiplayBusters : : CanHaveItem ( CBasePlayer * pPlayer , CItem * pItem )
{
return BustingCanHaveItem ( pPlayer , pItem ) ;
}
BOOL CMultiplayBusters : : CanHavePlayerItem ( CBasePlayer * pPlayer , CBasePlayerItem * pItem )
{
if ( ! BustingCanHaveItem ( pPlayer , pItem ) )
return FALSE ;
return CHalfLifeMultiplay : : CanHavePlayerItem ( pPlayer , pItem ) ;
}
int CMultiplayBusters : : IPointsForKill ( CBasePlayer * pAttacker , CBasePlayer * pKilled )
{
if ( IsPlayerBusting ( pAttacker ) )
return 1 ;
if ( IsPlayerBusting ( pKilled ) )
return 2 ;
return 0 ;
}
void CMultiplayBusters : : DeathNotice ( CBasePlayer * pVictim , entvars_t * pKiller , entvars_t * pevInflictor )
{
if ( IsPlayerBusting ( pVictim )
| | IsPlayerBusting ( CBaseEntity : : Instance ( pKiller ) ) )
CHalfLifeMultiplay : : DeathNotice ( pVictim , pKiller , pevInflictor ) ;
}
void CMultiplayBusters : : PlayerKilled ( CBasePlayer * pVictim , entvars_t * pKiller , entvars_t * pInflictor )
{
if ( IsPlayerBusting ( pVictim ) )
{
UTIL_ClientPrintAll ( HUD_PRINTCENTER , " The Buster is dead!! " ) ;
m_flEgonBustingCheckTime = - 1.0f ;
CBasePlayer * peKiller = NULL ;
CBaseEntity * ktmp = CBaseEntity : : Instance ( pKiller ) ;
if ( ktmp & & ( ktmp - > Classify ( ) = = CLASS_PLAYER ) )
peKiller = ( CBasePlayer * ) ktmp ;
else if ( ktmp & & ktmp - > Classify ( ) = = CLASS_VEHICLE )
{
CBasePlayer * pDriver = ( CBasePlayer * ) ( ( CFuncVehicle * ) ktmp ) - > m_pDriver ;
if ( pDriver ! = NULL )
{
pKiller = pDriver - > pev ;
peKiller = ( CBasePlayer * ) pDriver ;
}
}
if ( peKiller & & peKiller - > IsPlayer ( ) )
{
UTIL_ClientPrintAll ( HUD_PRINTTALK , UTIL_VarArgs ( " %s has killed the Buster! " , STRING ( peKiller - > pev - > netname ) ) ) ;
}
pVictim - > pev - > renderfx = 0 ;
pVictim - > pev - > rendercolor = g_vecZero ;
}
CHalfLifeMultiplay : : PlayerKilled ( pVictim , pKiller , pInflictor ) ;
}
void CMultiplayBusters : : ClientUserInfoChanged ( CBasePlayer * pPlayer , char * infobuffer )
{
SetPlayerModel ( pPlayer , FALSE ) ;
CHalfLifeMultiplay : : ClientUserInfoChanged ( pPlayer , infobuffer ) ;
}
void CMultiplayBusters : : PlayerSpawn ( CBasePlayer * pPlayer )
{
CHalfLifeMultiplay : : PlayerSpawn ( pPlayer ) ;
SetPlayerModel ( pPlayer , FALSE ) ;
}
bool IsPlayerBusting ( CBaseEntity * pPlayer )
{
if ( g_pGameRules - > IsBustingGame ( )
& & pPlayer & & pPlayer - > IsPlayer ( )
& & ( ( CBasePlayer * ) pPlayer ) - > HasPlayerItemFromID ( WEAPON_EGON ) )
return true ;
return false ;
}
BOOL BustingCanHaveItem ( CBasePlayer * pPlayer , CBaseEntity * pItem )
{
if ( IsPlayerBusting ( pPlayer )
& & ! ( strncmp ( STRING ( pItem - > pev - > classname ) , " weapon_ " , 7 )
& & strncmp ( STRING ( pItem - > pev - > classname ) , " ammo_ " , 5 ) ) )
return FALSE ;
return TRUE ;
}
CMultiplayBusters : : CMultiplayBusters ( )
{
CHalfLifeMultiplay ( ) ;
m_flEgonBustingCheckTime = - 1.0 ;
}
void CMultiplayBusters : : CheckForEgons ( void )
{
CBaseEntity * pPlayer ;
CWeaponBox * pWeaponBox = NULL ;
CBasePlayerItem * pWeapon ;
CBasePlayer * pNewBuster = NULL ;
int i , bestfrags = 9999 ;
if ( m_flEgonBustingCheckTime < = 0.0f )
{
m_flEgonBustingCheckTime = gpGlobals - > time + 10.0f ;
return ;
}
if ( gpGlobals - > time < m_flEgonBustingCheckTime )
return ;
m_flEgonBustingCheckTime = - 1.0f ;
for ( i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
pPlayer = UTIL_PlayerByIndex ( i ) ;
if ( IsPlayerBusting ( pPlayer ) )
return ;
}
for ( i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
pPlayer = UTIL_PlayerByIndex ( i ) ;
if ( pPlayer & & pPlayer - > pev - > frags < bestfrags )
{
pNewBuster = ( CBasePlayer * ) pPlayer ;
bestfrags = pPlayer - > pev - > frags ;
}
}
if ( ! pNewBuster )
return ;
pNewBuster - > GiveNamedItem ( " weapon_egon " ) ;
while ( ( pWeaponBox = ( CWeaponBox * ) UTIL_FindEntityByClassname ( pWeaponBox , " weaponbox " ) ) )
{
// destroy weaponboxes with egons
for ( i = 0 ; i < MAX_ITEM_TYPES ; i + + )
{
pWeapon = pWeaponBox - > m_rgpPlayerItems [ i ] ;
while ( pWeapon )
{
if ( pWeapon - > m_iId ! = WEAPON_EGON )
{
pWeapon = pWeapon - > m_pNext ;
continue ;
}
pWeaponBox - > Kill ( ) ;
pWeapon = 0 ;
i = MAX_ITEM_TYPES ;
}
}
}
}
void CMultiplayBusters : : Think ( void )
{
CheckForEgons ( ) ;
CHalfLifeMultiplay : : Think ( ) ;
}
void CMultiplayBusters : : SetPlayerModel ( CBasePlayer * pPlayer , BOOL bKnownBuster )
{
const char * pszModel = NULL ;
if ( bKnownBuster | | IsPlayerBusting ( pPlayer ) )
{
pszModel = " ivan " ;
}
else
{
pszModel = " skeleton " ;
}
g_engfuncs . pfnSetClientKeyValue ( ENTINDEX ( pPlayer - > edict ( ) ) , g_engfuncs . pfnGetInfoKeyBuffer ( pPlayer - > edict ( ) ) , " model " , pszModel ) ;
}
void CMultiplayBusters : : PlayerGotWeapon ( CBasePlayer * pPlayer , CBasePlayerItem * pWeapon )
{
if ( pWeapon - > m_iId ! = WEAPON_EGON )
return ;
pPlayer - > RemoveAllItems ( FALSE ) ;
UTIL_ClientPrintAll ( HUD_PRINTCENTER , " Long live the new Buster! " ) ;
UTIL_ClientPrintAll ( HUD_PRINTTALK , UTIL_VarArgs ( " %s is busting! \n " , STRING ( pPlayer - > pev - > netname ) ) ) ;
SetPlayerModel ( pPlayer , TRUE ) ;
pPlayer - > pev - > health = pPlayer - > pev - > max_health ;
pPlayer - > pev - > armorvalue = MAX_NORMAL_BATTERY ;
pPlayer - > pev - > renderfx = kRenderFxGlowShell ;
pPlayer - > pev - > renderamt = 25 ;
pPlayer - > pev - > rendercolor = Vector ( 0 , 75 , 250 ) ;
pPlayer - > m_rgAmmo [ pWeapon - > PrimaryAmmoIndex ( ) ] = pPlayer - > ammo_uranium = 100 ;
2024-02-25 22:05:17 +01:00
} */