diff --git a/src/game/server/baseentity.cpp b/src/game/server/baseentity.cpp index 3462fd370..876d1c297 100644 --- a/src/game/server/baseentity.cpp +++ b/src/game/server/baseentity.cpp @@ -63,6 +63,7 @@ #include "tier1/utlstring.h" #include "utlhashtable.h" #include "vscript_server.h" +#include "subs.h" #if defined( TF_DLL ) #include "tf_gamerules.h" @@ -5705,6 +5706,65 @@ void CC_Ent_Remove( const CCommand& args ) { CBaseEntity *pEntity = NULL; + CBasePlayer *pPlayer = UTIL_GetCommandClient(); + if ( pPlayer ) + { + CBaseEntity *targetEntity = NULL; + if ( FStrEq( args[ 1 ], "" ) ) + { + targetEntity = FindPickerEntity( pPlayer ); + } + else + { + int index = atoi( args[ 1 ] ); + if ( index ) + { + targetEntity = CBaseEntity::Instance( index ); + } + else + { + targetEntity = gEntList.FindEntityByName( NULL, args[ 1 ] ); + + if ( !targetEntity ) + { + targetEntity = gEntList.FindEntityByClassname( NULL, args[ 1 ] ); + } + } + } + + // Don't check against a classname. They can be changed maliciously + // e.g. ent_fire player addoutput "classname abc";ent_remove abc + if ( targetEntity ) + { + // Check if it's a player + if ( dynamic_cast< CBasePlayer * >( targetEntity ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove players\n" ); + return; + } + + // Check if it's the world entity + if ( targetEntity->edict() == INDEXENT( 0 ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove the world entity\n" ); + return; + } + + // Check if it's a DM spawn point + if ( dynamic_cast< CBaseDMStart * >( targetEntity ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove spawn points\n" ); + return; + } + + if ( dynamic_cast< CBaseTeamSpawn * >( targetEntity ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove spawn points\n" ); + return; + } + } + } + // If no name was given set bits based on the picked if ( FStrEq( args[1],"") ) { @@ -5753,6 +5813,65 @@ void CC_Ent_RemoveAll( const CCommand& args ) } else { + CBasePlayer *pPlayer = UTIL_GetCommandClient(); + if ( pPlayer ) + { + CBaseEntity *targetEntity = NULL; + if ( FStrEq( args[ 1 ], "" ) ) + { + targetEntity = FindPickerEntity( pPlayer ); + } + else + { + int index = atoi( args[ 1 ] ); + if ( index ) + { + targetEntity = CBaseEntity::Instance( index ); + } + else + { + targetEntity = gEntList.FindEntityByName( NULL, args[ 1 ] ); + + if ( !targetEntity ) + { + targetEntity = gEntList.FindEntityByClassname( NULL, args[ 1 ] ); + } + } + } + + // If we found an entity, check if it's a protected one + if ( targetEntity ) + { + // Check if it's a player + if ( dynamic_cast< CBasePlayer * >( targetEntity ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove players\n" ); + return; + } + + // Check if it's the world entity + if ( targetEntity->edict() == INDEXENT( 0 ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove the world entity\n" ); + return; + } + + // Check if it's a DM spawn point + if ( dynamic_cast< CBaseDMStart * >( targetEntity ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove spawn points\n" ); + return; + } + + // Check if it's a TDM spawn point + if ( dynamic_cast< CBaseTeamSpawn * >( targetEntity ) ) + { + ClientPrint( pPlayer, HUD_PRINTCONSOLE, "You cannot remove spawn points\n" ); + return; + } + } + } + // Otherwise remove based on name or classname int iCount = 0; CBaseEntity *ent = NULL; diff --git a/src/game/server/hl2mp/hl2mp_player.cpp b/src/game/server/hl2mp/hl2mp_player.cpp index 9457928a0..3ec27178a 100644 --- a/src/game/server/hl2mp/hl2mp_player.cpp +++ b/src/game/server/hl2mp/hl2mp_player.cpp @@ -22,6 +22,7 @@ #include "gamestats.h" #include "ammodef.h" #include "NextBot.h" +#include "subs.h" #include "engine/IEngineSound.h" #include "SoundEmitterSystem/isoundemittersystembase.h" @@ -43,8 +44,8 @@ void DropPrimedFragGrenade( CHL2MP_Player *pPlayer, CBaseCombatWeapon *pGrenade LINK_ENTITY_TO_CLASS( player, CHL2MP_Player ); -LINK_ENTITY_TO_CLASS( info_player_combine, CPointEntity ); -LINK_ENTITY_TO_CLASS( info_player_rebel, CPointEntity ); +LINK_ENTITY_TO_CLASS( info_player_combine, CBaseTeamSpawn ); +LINK_ENTITY_TO_CLASS( info_player_rebel, CBaseTeamSpawn ); // specific to the local player BEGIN_SEND_TABLE_NOBASE( CHL2MP_Player, DT_HL2MPLocalPlayerExclusive ) diff --git a/src/game/server/server_base.vpc b/src/game/server/server_base.vpc index 32567c5df..218106af7 100644 --- a/src/game/server/server_base.vpc +++ b/src/game/server/server_base.vpc @@ -621,6 +621,7 @@ $Project $File "$SRCDIR\public\stringregistry.h" $File "$SRCDIR\game\shared\studio_shared.cpp" $File "subs.cpp" + $File "subs.h" $File "sun.cpp" $File "tactical_mission.cpp" $File "tactical_mission.h" diff --git a/src/game/server/subs.cpp b/src/game/server/subs.cpp index b2bf003f4..12d38be59 100644 --- a/src/game/server/subs.cpp +++ b/src/game/server/subs.cpp @@ -10,6 +10,7 @@ #include "doors.h" #include "entitylist.h" #include "globals.h" +#include "subs.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -38,19 +39,6 @@ void CNullEntity::Spawn( void ) } LINK_ENTITY_TO_CLASS(info_null,CNullEntity); -class CBaseDMStart : public CPointEntity -{ -public: - DECLARE_CLASS( CBaseDMStart, CPointEntity ); - - bool IsTriggered( CBaseEntity *pEntity ); - - DECLARE_DATADESC(); - - string_t m_Master; - -private: -}; BEGIN_DATADESC( CBaseDMStart ) diff --git a/src/game/server/subs.h b/src/game/server/subs.h new file mode 100644 index 000000000..b3b7b85b4 --- /dev/null +++ b/src/game/server/subs.h @@ -0,0 +1,24 @@ +#include "cbase.h" + +class CBaseDMStart : public CPointEntity +{ +public: + DECLARE_CLASS( CBaseDMStart, CPointEntity ); + + bool IsTriggered( CBaseEntity *pEntity ); + + DECLARE_DATADESC(); + + string_t m_Master; + +private: +}; + +// Peter: I don't see a reason why this could not use CBaseDMStart, +// but as a precaution because team spawn points were set to use CPointEntity, +// I will create a class for this. +class CBaseTeamSpawn : public CPointEntity +{ +public: + DECLARE_CLASS( CBaseTeamSpawn, CPointEntity ); +}; \ No newline at end of file