New Gamerules

From Valve Developer Community
Jump to: navigation, search

For all of those who need to implement new gamerules in their mod, or have tried and failed these two snippets will help you along.

You can find/replace

InheritedGameRules

and then replace with your game rules name.

The header file:

#ifndef INHERITED_GAMERULES_H
#define INHERITED_GAMERULES_H
#pragma once

#include "gamerules.h"
#include "teamplay_gamerules.h"
#include "hl2mp_gamerules.h"
#include "gamevars_shared.h"

#ifndef CLIENT_DLL
#include "hl2mp_player.h"
#endif

#ifdef CLIENT_DLL
	#define CInheritedGameRules C_InheritedGameRules
	#define CInheritedGameRulesProxy C_InheritedGameRulesProxy
#endif

class CInheritedGameRulesProxy : public CHL2MPGameRulesProxy
{
public:
	DECLARE_CLASS( CInheritedGameRulesProxy, CHL2MPGameRulesProxy );
	DECLARE_NETWORKCLASS();
};

class CInheritedGameRules : public CHL2MPRules
{
public:
	DECLARE_CLASS( CInheritedGameRules, CHL2MPRules );

#ifdef CLIENT_DLL

	DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars.

#else

	DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars.
#endif

	// Constructor
	CInheritedGameRules();
	// Destructor
	virtual ~CInheritedGameRules();

	virtual void Precache( void );
	virtual bool ClientCommand( const char *pcmd, CBaseEntity *pEdict );

	virtual void Think( void );

	virtual const char *GetGameDescription( void ){ return "Inherited"; }
	virtual void CreateStandardEntities( void );

#ifndef CLIENT_DLL


#endif
	
private:

};

inline CInheritedGameRules* InheritedGameRules()
{
	return static_cast<CInheritedGameRules*>(g_pGameRules);
}

#endif //INHERITED_GAMERULES_H

The main CPP file:

#include "cbase.h"
#include "inherited_gamerules.h"
#include "viewport_panel_names.h"
#include "gameeventdefs.h"
#include <KeyValues.h>
#include "ammodef.h"

#ifdef CLIENT_DLL
	#include "c_hl2mp_player.h"
#else

	#include "eventqueue.h"
	#include "player.h"
	#include "gamerules.h"
	#include "game.h"
	#include "items.h"
	#include "entitylist.h"
	#include "mapentities.h"
	#include "in_buttons.h"
	#include <ctype.h>
	#include "voice_gamemgr.h"
	#include "iscorer.h"
	#include "hl2mp_player.h"
	#include "weapon_hl2mpbasehlmpcombatweapon.h"
	#include "team.h"
	#include "voice_gamemgr.h"
	#include "hl2mp_gameinterface.h"
	#include "hl2mp_cvars.h"

#ifdef DEBUG	
	#include "hl2mp_bot_temp.h"
#endif

#endif

REGISTER_GAMERULES_CLASS( CInheritedGameRules );

BEGIN_NETWORK_TABLE_NOBASE( CInheritedGameRules, DT_InheritedGameRules )

	#ifdef CLIENT_DLL

	#else

	#endif

END_NETWORK_TABLE()


LINK_ENTITY_TO_CLASS( inherited_gamerules, CInheritedGameRulesProxy );
IMPLEMENT_NETWORKCLASS_ALIASED( InheritedGameRulesProxy, DT_InheritedGameRulesProxy )

#ifdef CLIENT_DLL
	void RecvProxy_InheritedGameRules( const RecvProp *pProp, void **pOut, void *pData, int objectID )
	{
		CInheritedGameRules *pRules = InheritedGameRules();
		Assert( pRules );
		*pOut = pRules;
	}

	BEGIN_RECV_TABLE( CInheritedGameRulesProxy, DT_InheritedGameRulesProxy )
		RecvPropDataTable( "inherited_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_InheritedGameRules ), RecvProxy_InheritedGameRules )
	END_RECV_TABLE()
#else
	void* SendProxy_InheritedGameRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID )
	{
		CInheritedGameRules *pRules = InheritedGameRules();
		Assert( pRules );
		return pRules;
	}

	BEGIN_SEND_TABLE( CInheritedGameRulesProxy, DT_InheritedGameRulesProxy )
		SendPropDataTable( "inherited_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_InheritedGameRules ), SendProxy_InheritedGameRules )
	END_SEND_TABLE()
#endif

CInheritedGameRules::CInheritedGameRules()
{
#ifndef CLIENT_DLL

#endif
}
	
CInheritedGameRules::~CInheritedGameRules( void )
{
#ifndef CLIENT_DLL
	// Note, don't delete each team since they are in the gEntList and will 
	// automatically be deleted from there, instead.
	g_Teams.Purge();
#endif
}

void CInheritedGameRules::Think( void )
{

#ifndef CLIENT_DLL
	
	BaseClass::Think();

#endif
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CInheritedGameRules::Precache( void )
{
	BaseClass::Precache();
}

bool CInheritedGameRules::ClientCommand(const char *pcmd, CBaseEntity *pEdict )
{

return BaseClass::ClientCommand( pcmd, pEdict );

}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CInheritedGameRules::CreateStandardEntities( void )
{
#ifndef CLIENT_DLL
	BaseClass::CreateStandardEntities();
        // Create entity that will handle gamrules and networking for our entity
	CBaseEntity::Create( "inherited_gamerules", vec3_origin, vec3_angle );
#endif
}

In hl2mp_gamerules.cpp

Note: If you would like to implement a new gamerules class without modifying hl2mp_gamerules.cpp then you will need to reimplemented the CleanUpMap() and RestartGame()[unconfirmed] methods
// Note: It is important for you to add the gamerules entity to the 
// preserved entity list or networked variables will not work. 
static const char *s_PreserveEnts[] =
{
	"ai_network",
	"ai_hint",
	"hl2mp_gamerules",
	"team_manager",
	"player_manager",
	"env_soundscape",
	"env_soundscape_proxy",
	"env_soundscape_triggerable",
	"env_sun",
	"env_wind",
	"env_fog_controller",
	"func_brush",
	"func_wall",
	"func_buyzone",
	"func_illusionary",
	"infodecal",
	"info_projecteddecal",
	"info_node",
	"info_target",
	"info_node_hint",
	"info_player_deathmatch",
	"info_player_combine",
	"info_player_rebel",
	"info_map_parameters",
	"keyframe_rope",
	"move_rope",
	"info_ladder",
	"player",
	"point_viewcontrol",
	"scene_manager",
	"shadow_control",
	"sky_camera",
	"soundent",
	"trigger_soundscape",
	"viewmodel",
	"predicted_viewmodel",
	"worldspawn",
	"point_devshot_camera",
        "inherited_gamerules",                // Inherited game rules entity
	"", // END Marker
};