diff --git a/AMBuildScript b/AMBuildScript index 902adcda..3c60bff7 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -21,6 +21,8 @@ class SM: 'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux']} self.sdkInfo['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2', 'name': 'DARKMESSIAH', 'platform': ['windows']} + self.sdkInfo['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '7', + 'name': 'ALIENSWARM', 'platform': ['windows']} if AMBuild.mode == 'config': #Detect compilers @@ -41,6 +43,7 @@ class SM: #Dark Messiah is Windows-only if AMBuild.target['platform'] == 'windows': envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm' + envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm' #Must have a path for each envvar (file a bug if you don't like this) for i in envvars: @@ -93,6 +96,7 @@ class SM: self.vendor = 'msvc' if AMBuild.options.debug == '1': self.compiler.AddToListVar('CFLAGS', '/MTd') + self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt') else: self.compiler.AddToListVar('CFLAGS', '/MT') self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE') @@ -253,7 +257,10 @@ class SM: except: job.AddCommand(SymlinkCommand(link, target)) elif AMBuild.target['platform'] == 'windows': - for lib in ['tier0', 'tier1', 'vstdlib', 'mathlib']: + libs = ['tier0', 'tier1', 'vstdlib', 'mathlib'] + if sdk == 'swarm': + libs.append('interfaces') + for lib in libs: libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib' builder.RebuildIfNewer(libPath) builder['POSTLINKFLAGS'].append(libPath) @@ -290,6 +297,9 @@ class SM: compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def']) + if sdk == 'swarm' and AMBuild.target['platform'] == 'windows': + compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32']) + if sdk == 'ep1': if AMBuild.target['platform'] == 'linux': staticLibs = os.path.join(sdkPath, 'linux_sdk') diff --git a/core/ConCommandBaseIterator.h b/core/ConCommandBaseIterator.h index dfe84ac5..c86c9f0f 100644 --- a/core/ConCommandBaseIterator.h +++ b/core/ConCommandBaseIterator.h @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod - * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -31,59 +31,59 @@ #ifndef _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_ #define _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_ +#if SOURCE_ENGINE >= SE_LEFT4DEAD class ConCommandBaseIterator { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - ICvarIteratorInternal *cvarIter; -#else - ConCommandBase *cvarIter; -#endif - public: - ConCommandBaseIterator() + inline ConCommandBaseIterator() : iter(icvar) { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - cvarIter = icvar->FactoryInternalIterator(); - cvarIter->SetFirst(); -#else - cvarIter = icvar->GetCommands(); -#endif - } - - ~ConCommandBaseIterator() - { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - g_pMemAlloc->Free(cvarIter); -#endif + iter.SetFirst(); } inline bool IsValid() { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - return cvarIter->IsValid(); -#else - return cvarIter != NULL; -#endif + return iter.IsValid(); } inline void Next() { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - cvarIter->Next(); -#else - cvarIter = const_cast(cvarIter->GetNext()); -#endif + iter.Next(); } inline ConCommandBase *Get() { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - return cvarIter->Get(); -#else - return cvarIter; -#endif + return iter.Get(); } +private: + ICvar::Iterator iter; }; +#else +class ConCommandBaseIterator +{ +public: + inline ConCommandBaseIterator() + { + iter = icvar->GetCommands(); + } + + inline bool IsValid() + { + return iter != NULL; + } + + inline void Next() + { + iter = const_cast(iter->GetNext()); + } + + inline ConCommandBase *Get() + { + return iter; + } +private: + ConCommandBase *iter; +}; +#endif #endif /* _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_ */ diff --git a/core/EventManager.cpp b/core/EventManager.cpp index ebfcd8c7..a6554d58 100644 --- a/core/EventManager.cpp +++ b/core/EventManager.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -161,6 +161,13 @@ void EventManager::FireGameEvent(IGameEvent *pEvent) Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */ } +#if SOURCE_ENGINE >= SE_LEFT4DEAD +int EventManager::GetEventDebugID() +{ + return EVENT_DEBUG_ID_INIT; +} +#endif + EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode) { EventHook *pHook; diff --git a/core/EventManager.h b/core/EventManager.h index 684cbbc5..4a0b86bc 100644 --- a/core/EventManager.h +++ b/core/EventManager.h @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -105,6 +105,9 @@ public: // IPluginsListener void OnPluginUnloaded(IPlugin *plugin); public: // IGameEventListener2 void FireGameEvent(IGameEvent *pEvent); +#if SOURCE_ENGINE >= SE_LEFT4DEAD + int GetEventDebugID(); +#endif public: /** * Get the 'GameEvent' handle type ID. diff --git a/core/ExtensionSys.cpp b/core/ExtensionSys.cpp index 127f5aa6..adf5332e 100644 --- a/core/ExtensionSys.cpp +++ b/core/ExtensionSys.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod - * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -65,6 +65,8 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena #define GAMEFIX "2.l4d" #elif SOURCE_ENGINE == SE_LEFT4DEAD2 #define GAMEFIX "2.l4d2" +#elif SOURCE_ENGINE == SE_ALIENSWARM +#define GAMEFIX "2.swarm" #elif SOURCE_ENGINE == SE_ORANGEBOX #define GAMEFIX "2.ep2" #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index 55d9ef62..4fc44fe6 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -360,13 +360,11 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset) #if SOURCE_ENGINE != SE_DARKMESSIAH if (g_pSharedChangeInfo != NULL) { -#if SOURCE_ENGINE != SE_LEFT4DEAD2 if (offset) { pEdict->StateChanged(offset); } else -#endif { pEdict->StateChanged(); } diff --git a/core/PluginSys.h b/core/PluginSys.h index 9a657d9e..51cf54af 100644 --- a/core/PluginSys.h +++ b/core/PluginSys.h @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -47,7 +47,9 @@ #include "sm_trie.h" #include "sourcemod.h" #include -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE == SE_ALIENSWARM +#include "convar_sm_swarm.h" +#elif (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) #include "convar_sm_l4d.h" #elif (SOURCE_ENGINE == SE_ORANGEBOX) || (SOURCE_ENGINE == SE_ORANGEBOXVALVE) #include "convar_sm_ob.h" diff --git a/core/UserMessages.cpp b/core/UserMessages.cpp index 3900c536..5f4738c6 100644 --- a/core/UserMessages.cpp +++ b/core/UserMessages.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -34,7 +34,7 @@ UserMessages g_UserMsgs; -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *); #else SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int); @@ -168,13 +168,13 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne if (m_CurFlags & USERMSG_BLOCKHOOKS) { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD buffer = ENGINE_CALL(UserMessageBegin)(static_cast(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id)); #else buffer = ENGINE_CALL(UserMessageBegin)(static_cast(&m_CellRecFilter), msg_id); #endif } else { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD buffer = engine->UserMessageBegin(static_cast(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id)); #else buffer = engine->UserMessageBegin(static_cast(&m_CellRecFilter), msg_id); @@ -316,7 +316,7 @@ void UserMessages::_DecRefCounter() } } -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name) #else bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type) @@ -346,7 +346,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ RETURN_META_VALUE(MRES_IGNORED, NULL); } -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name) #else bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type) @@ -500,7 +500,7 @@ void UserMessages::OnMessageEnd_Pre() { bf_write *engine_bfw; -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId)); #else engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId); diff --git a/core/UserMessages.h b/core/UserMessages.h index d8af3fd6..f6c5c197 100644 --- a/core/UserMessages.h +++ b/core/UserMessages.h @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -79,7 +79,7 @@ public: //IUserMessages IUserMessageListener *pListener, bool intercept=false); public: -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name); bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name); #else diff --git a/core/convar_sm_l4d.h b/core/convar_sm_l4d.h index e6519da6..2e569da1 100644 --- a/core/convar_sm_l4d.h +++ b/core/convar_sm_l4d.h @@ -386,7 +386,7 @@ public: virtual void SetValue( const char *value ); virtual void SetValue( float value ); virtual void SetValue( int value ); -#if SOURCE_ENGINE == SE_LEFT4DEAD2 +#if SOURCE_ENGINE >= SE_LEFT4DEAD2 virtual void SetValue( Color value ); #endif @@ -404,6 +404,9 @@ private: // For CVARs marked FCVAR_NEVER_AS_STRING virtual void InternalSetFloatValue( float fNewValue ); virtual void InternalSetIntValue( int nValue ); +#if SOURCE_ENGINE >= SE_LEFT4DEAD2 + virtual void InternalSetColorValue( Color value ); +#endif virtual bool ClampValue( float& value ); virtual void ChangeStringValue( const char *tempVal, float flOldValue ); diff --git a/core/convar_sm_swarm.h b/core/convar_sm_swarm.h new file mode 100644 index 00000000..9f5178b7 --- /dev/null +++ b/core/convar_sm_swarm.h @@ -0,0 +1,1032 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $NoKeywords: $ +//===========================================================================// + +#ifndef CONVAR_H +#define CONVAR_H + +#if _WIN32 +#pragma once +#endif + +#include "tier0/dbg.h" +#include "tier1/iconvar.h" +#include "tier1/utlvector.h" +#include "tier1/utlstring.h" +#include "color.h" +#include "icvar.h" + +#ifdef _WIN32 +#define FORCEINLINE_CVAR FORCEINLINE +#elif POSIX +#define FORCEINLINE_CVAR inline +#else +#error "implement me" +#endif + + +//----------------------------------------------------------------------------- +// Uncomment me to test for threading issues for material system convars +// NOTE: You want to disable all threading when you do this +// +host_thread_mode 0 +r_threaded_particles 0 +sv_parallel_packentities 0 +sv_disable_querycache 0 +//----------------------------------------------------------------------------- +//#define CONVAR_TEST_MATERIAL_THREAD_CONVARS 1 + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class ConVar; +class CCommand; +class ConCommand; +class ConCommandBase; +struct characterset_t; + + + +//----------------------------------------------------------------------------- +// Any executable that wants to use ConVars need to implement one of +// these to hook up access to console variables. +//----------------------------------------------------------------------------- +class IConCommandBaseAccessor +{ +public: + // Flags is a combination of FCVAR flags in cvar.h. + // hOut is filled in with a handle to the variable. + virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0; +}; + + +//----------------------------------------------------------------------------- +// Helper method for console development +//----------------------------------------------------------------------------- +#if defined( _X360 ) +void ConVar_PublishToVXConsole(); +#endif + + +//----------------------------------------------------------------------------- +// Called when a ConCommand needs to execute +//----------------------------------------------------------------------------- +typedef void ( *FnCommandCallbackV1_t )( void ); +typedef void ( *FnCommandCallback_t )( const CCommand &command ); + +#define COMMAND_COMPLETION_MAXITEMS 64 +#define COMMAND_COMPLETION_ITEM_LENGTH 64 + +//----------------------------------------------------------------------------- +// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings +//----------------------------------------------------------------------------- +typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); + + +//----------------------------------------------------------------------------- +// Interface version +//----------------------------------------------------------------------------- +class ICommandCallback +{ +public: + virtual void CommandCallback( const CCommand &command ) = 0; +}; + +class ICommandCompletionCallback +{ +public: + virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0; +}; + +//----------------------------------------------------------------------------- +// Purpose: The base console invoked command/cvar interface +//----------------------------------------------------------------------------- +class ConCommandBase +{ + friend class CCvar; + friend class ConVar; + friend class ConCommand; + friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor ); + friend void ConVar_PublishToVXConsole(); + + // FIXME: Remove when ConVar changes are done + friend class CDefaultCvar; + +public: + ConCommandBase( void ); + ConCommandBase( const char *pName, const char *pHelpString = 0, + int flags = 0 ); + + virtual ~ConCommandBase( void ); + + virtual bool IsCommand( void ) const; + + // Check flag + virtual bool IsFlagSet( int flag ) const; + // Set flag + virtual void AddFlags( int flags ); + // Clear flag + virtual void RemoveFlags( int flags ); + + virtual int GetFlags() const; + + // Return name of cvar + virtual const char *GetName( void ) const; + + // Return help text for cvar + virtual const char *GetHelpText( void ) const; + + // Deal with next pointer + const ConCommandBase *GetNext( void ) const; + ConCommandBase *GetNext( void ); + + virtual bool IsRegistered( void ) const; + + // Returns the DLL identifier + virtual CVarDLLIdentifier_t GetDLLIdentifier() const; + +protected: + virtual void Create( const char *pName, const char *pHelpString = 0, + int flags = 0 ); + + // Used internally by OneTimeInit to initialize/shutdown + virtual void Init(); + void Shutdown(); + + // Internal copy routine ( uses new operator from correct module ) + char *CopyString( const char *from ); + +private: + // Next ConVar in chain + // Prior to register, it points to the next convar in the DLL. + // Once registered, though, m_pNext is reset to point to the next + // convar in the global list + ConCommandBase *m_pNext; + + // Has the cvar been added to the global list? + bool m_bRegistered; + + // Static data + const char *m_pszName; + const char *m_pszHelpString; + + // ConVar flags + int m_nFlags; + +protected: + // ConVars add themselves to this list for the executable. + // Then ConVar_Register runs through all the console variables + // and registers them into a global list stored in vstdlib.dll + static ConCommandBase *s_pConCommandBases; + + // ConVars in this executable use this 'global' to access values. + static IConCommandBaseAccessor *s_pAccessor; +public: + inline void SetFlags(int flags) + { + m_nFlags = flags; + } +}; + + +//----------------------------------------------------------------------------- +// Command tokenizer +//----------------------------------------------------------------------------- +class CCommand +{ +public: + CCommand(); + CCommand( int nArgC, const char **ppArgV ); + bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL ); + void Reset(); + + int ArgC() const; + const char **ArgV() const; + const char *ArgS() const; // All args that occur after the 0th arg, in string form + const char *GetCommandString() const; // The entire command in string form, including the 0th arg + const char *operator[]( int nIndex ) const; // Gets at arguments + const char *Arg( int nIndex ) const; // Gets at arguments + + // Helper functions to parse arguments to commands. + const char* FindArg( const char *pName ) const; + int FindArgInt( const char *pName, int nDefaultVal ) const; + + static int MaxCommandLength(); + static characterset_t* DefaultBreakSet(); + +private: + enum + { + COMMAND_MAX_ARGC = 64, + COMMAND_MAX_LENGTH = 512, + }; + + int m_nArgc; + int m_nArgv0Size; + char m_pArgSBuffer[ COMMAND_MAX_LENGTH ]; + char m_pArgvBuffer[ COMMAND_MAX_LENGTH ]; + const char* m_ppArgv[ COMMAND_MAX_ARGC ]; +}; + +inline int CCommand::MaxCommandLength() +{ + return COMMAND_MAX_LENGTH - 1; +} + +inline int CCommand::ArgC() const +{ + return m_nArgc; +} + +inline const char **CCommand::ArgV() const +{ + return m_nArgc ? (const char**)m_ppArgv : NULL; +} + +inline const char *CCommand::ArgS() const +{ + return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : ""; +} + +inline const char *CCommand::GetCommandString() const +{ + return m_nArgc ? m_pArgSBuffer : ""; +} + +inline const char *CCommand::Arg( int nIndex ) const +{ + // FIXME: Many command handlers appear to not be particularly careful + // about checking for valid argc range. For now, we're going to + // do the extra check and return an empty string if it's out of range + if ( nIndex < 0 || nIndex >= m_nArgc ) + return ""; + return m_ppArgv[nIndex]; +} + +inline const char *CCommand::operator[]( int nIndex ) const +{ + return Arg( nIndex ); +} + + +//----------------------------------------------------------------------------- +// Purpose: The console invoked command +//----------------------------------------------------------------------------- +class ConCommand : public ConCommandBase +{ +friend class CCvar; + +public: + typedef ConCommandBase BaseClass; + + ConCommand( const char *pName, FnCommandCallbackV1_t callback, + const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); + ConCommand( const char *pName, FnCommandCallback_t callback, + const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); + ConCommand( const char *pName, ICommandCallback *pCallback, + const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); + + virtual ~ConCommand( void ); + + virtual bool IsCommand( void ) const; + + virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands ); + + virtual bool CanAutoComplete( void ); + + // Invoke the function + virtual void Dispatch( const CCommand &command ); + +private: + // NOTE: To maintain backward compat, we have to be very careful: + // All public virtual methods must appear in the same order always + // since engine code will be calling into this code, which *does not match* + // in the mod code; it's using slightly different, but compatible versions + // of this class. Also: Be very careful about adding new fields to this class. + // Those fields will not exist in the version of this class that is instanced + // in mod code. + + // Call this function when executing the command + union + { + FnCommandCallbackV1_t m_fnCommandCallbackV1; + FnCommandCallback_t m_fnCommandCallback; + ICommandCallback *m_pCommandCallback; + }; + + union + { + FnCommandCompletionCallback m_fnCompletionCallback; + ICommandCompletionCallback *m_pCommandCompletionCallback; + }; + + bool m_bHasCompletionCallback : 1; + bool m_bUsingNewCommandCallback : 1; + bool m_bUsingCommandCallbackInterface : 1; +public: + inline FnCommandCallback_t GetCallback() const + { + return m_fnCommandCallback; + } +}; + + +//----------------------------------------------------------------------------- +// Purpose: A console variable +//----------------------------------------------------------------------------- +class ConVar : public ConCommandBase, public IConVar +{ +friend class CCvar; +friend class ConVarRef; +friend class SplitScreenConVarRef; + +public: + typedef ConCommandBase BaseClass; + + ConVar( const char *pName, const char *pDefaultValue, int flags = 0); + + ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString ); + ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax ); + ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString, FnChangeCallback_t callback ); + ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax, + FnChangeCallback_t callback ); + + virtual ~ConVar( void ); + + virtual bool IsFlagSet( int flag ) const; + virtual const char* GetHelpText( void ) const; + virtual bool IsRegistered( void ) const; + virtual const char *GetName( void ) const; + // Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars + virtual const char *GetBaseName( void ) const; + virtual int GetSplitScreenPlayerSlot() const; + + virtual void AddFlags( int flags ); + virtual int GetFlags() const; + virtual bool IsCommand( void ) const; + + // Install a change callback (there shouldn't already be one....) + void InstallChangeCallback( FnChangeCallback_t callback, bool bInvoke = true ); + void RemoveChangeCallback( FnChangeCallback_t callbackToRemove ); + + int GetChangeCallbackCount() const { return m_pParent->m_fnChangeCallbacks.Count(); } + FnChangeCallback_t GetChangeCallback( int slot ) const { return m_pParent->m_fnChangeCallbacks[ slot ]; } + + // Retrieve value + FORCEINLINE_CVAR float GetFloat( void ) const; + FORCEINLINE_CVAR int GetInt( void ) const; + FORCEINLINE_CVAR Color GetColor( void ) const; + FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); } + FORCEINLINE_CVAR char const *GetString( void ) const; + + // Compiler driven selection for template use + template T Get( void ) const; + template T Get( T * ) const; + + // Any function that allocates/frees memory needs to be virtual or else you'll have crashes + // from alloc/free across dll/exe boundaries. + + // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue). + virtual void SetValue( const char *value ); + virtual void SetValue( float value ); + virtual void SetValue( int value ); + virtual void SetValue( Color value ); + + // Reset to default value + void Revert( void ); + + // True if it has a min/max setting + bool HasMin() const; + bool HasMax() const; + + bool GetMin( float& minVal ) const; + bool GetMax( float& maxVal ) const; + + float GetMinValue() const; + float GetMaxValue() const; + + const char *GetDefault( void ) const; + + // Value + struct CVValue_t + { + char *m_pszString; + int m_StringLength; + + // Values + float m_fValue; + int m_nValue; + }; + + FORCEINLINE_CVAR CVValue_t &GetRawValue() + { + return m_Value; + } + FORCEINLINE_CVAR const CVValue_t &GetRawValue() const + { + return m_Value; + } + +private: + bool InternalSetColorFromString( const char *value ); + // Called by CCvar when the value of a var is changing. + virtual void InternalSetValue(const char *value); + // For CVARs marked FCVAR_NEVER_AS_STRING + virtual void InternalSetFloatValue( float fNewValue ); + virtual void InternalSetIntValue( int nValue ); + virtual void InternalSetColorValue( Color value ); + + virtual bool ClampValue( float& value ); + virtual void ChangeStringValue( const char *tempVal, float flOldValue ); + + virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0, + const char *pHelpString = 0, bool bMin = false, float fMin = 0.0, + bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 ); + + // Used internally by OneTimeInit to initialize. + virtual void Init(); + + + +protected: + + // This either points to "this" or it points to the original declaration of a ConVar. + // This allows ConVars to exist in separate modules, and they all use the first one to be declared. + // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar). + ConVar *m_pParent; + + // Static data + const char *m_pszDefaultValue; + + CVValue_t m_Value; + + // Min/Max values + bool m_bHasMin; + float m_fMinVal; + bool m_bHasMax; + float m_fMaxVal; + + // Call this function when ConVar changes + CUtlVector< FnChangeCallback_t > m_fnChangeCallbacks; +public: + inline void SetMin(bool set, float min=0.0) + { + m_bHasMin = set; + m_fMinVal = min; + } + inline void SetMax(bool set, float max=0.0) + { + m_bHasMax = set; + m_fMaxVal = max; + } +}; + + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a float +// Output : float +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR float ConVar::GetFloat( void ) const +{ +#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS + Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) ); +#endif + return m_pParent->m_Value.m_fValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as an int +// Output : int +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR int ConVar::GetInt( void ) const +{ +#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS + Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) ); +#endif + return m_pParent->m_Value.m_nValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a color +// Output : Color +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR Color ConVar::GetColor( void ) const +{ +#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS + Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) ); +#endif + unsigned char *pColorElement = ((unsigned char *)&m_pParent->m_Value.m_nValue); + return Color( pColorElement[0], pColorElement[1], pColorElement[2], pColorElement[3] ); +} + + +//----------------------------------------------------------------------------- + +template <> FORCEINLINE_CVAR float ConVar::Get( void ) const { return GetFloat(); } +template <> FORCEINLINE_CVAR int ConVar::Get( void ) const { return GetInt(); } +template <> FORCEINLINE_CVAR bool ConVar::Get( void ) const { return GetBool(); } +template <> FORCEINLINE_CVAR const char * ConVar::Get( void ) const { return GetString(); } +template <> FORCEINLINE_CVAR float ConVar::Get( float *p ) const { return ( *p = GetFloat() ); } +template <> FORCEINLINE_CVAR int ConVar::Get( int *p ) const { return ( *p = GetInt() ); } +template <> FORCEINLINE_CVAR bool ConVar::Get( bool *p ) const { return ( *p = GetBool() ); } +template <> FORCEINLINE_CVAR const char * ConVar::Get( char const **p ) const { return ( *p = GetString() ); } + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. +// Output : const char * +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR const char *ConVar::GetString( void ) const +{ +#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS + Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) ); +#endif + if ( m_nFlags & FCVAR_NEVER_AS_STRING ) + return "FCVAR_NEVER_AS_STRING"; + + char const *str = m_pParent->m_Value.m_pszString; + return str ? str : ""; +} + +class CSplitScreenAddedConVar : public ConVar +{ + typedef ConVar BaseClass; +public: + CSplitScreenAddedConVar( int nSplitScreenSlot, const char *pName, const ConVar *pBaseVar ) : + BaseClass + ( + pName, + pBaseVar->GetDefault(), + // Keep basevar flags, except remove _SS and add _SS_ADDED instead + ( pBaseVar->GetFlags() & ~FCVAR_SS ) | FCVAR_SS_ADDED, + pBaseVar->GetHelpText(), + pBaseVar->HasMin(), + pBaseVar->GetMinValue(), + pBaseVar->HasMax(), + pBaseVar->GetMaxValue() + ), + m_pBaseVar( pBaseVar ), + m_nSplitScreenSlot( nSplitScreenSlot ) + { + for ( int i = 0; i < pBaseVar->GetChangeCallbackCount(); ++i ) + { + InstallChangeCallback( pBaseVar->GetChangeCallback( i ), false ); + } + Assert( nSplitScreenSlot >= 1 ); + Assert( nSplitScreenSlot < MAX_SPLITSCREEN_CLIENTS ); + Assert( m_pBaseVar ); + Assert( IsFlagSet( FCVAR_SS_ADDED ) ); + Assert( !IsFlagSet( FCVAR_SS ) ); + } + + const ConVar *GetBaseVar() const; + virtual const char *GetBaseName() const; + void SetSplitScreenPlayerSlot( int nSlot ); + virtual int GetSplitScreenPlayerSlot() const; + +protected: + + const ConVar *m_pBaseVar; + int m_nSplitScreenSlot; +}; + +FORCEINLINE_CVAR const ConVar *CSplitScreenAddedConVar::GetBaseVar() const +{ + Assert( m_pBaseVar ); + return m_pBaseVar; +} + +FORCEINLINE_CVAR const char *CSplitScreenAddedConVar::GetBaseName() const +{ + Assert( m_pBaseVar ); + return m_pBaseVar->GetName(); +} + +FORCEINLINE_CVAR void CSplitScreenAddedConVar::SetSplitScreenPlayerSlot( int nSlot ) +{ + m_nSplitScreenSlot = nSlot; +} + +FORCEINLINE_CVAR int CSplitScreenAddedConVar::GetSplitScreenPlayerSlot() const +{ + return m_nSplitScreenSlot; +} + +//----------------------------------------------------------------------------- +// Used to read/write convars that already exist (replaces the FindVar method) +//----------------------------------------------------------------------------- +class ConVarRef +{ +public: + ConVarRef( const char *pName ); + ConVarRef( const char *pName, bool bIgnoreMissing ); + ConVarRef( IConVar *pConVar ); + + void Init( const char *pName, bool bIgnoreMissing ); + bool IsValid() const; + bool IsFlagSet( int nFlags ) const; + IConVar *GetLinkedConVar(); + + // Get/Set value + float GetFloat( void ) const; + int GetInt( void ) const; + Color GetColor( void ) const; + bool GetBool() const { return !!GetInt(); } + const char *GetString( void ) const; + + void SetValue( const char *pValue ); + void SetValue( float flValue ); + void SetValue( int nValue ); + void SetValue( Color value ); + void SetValue( bool bValue ); + + const char *GetName() const; + + const char *GetDefault() const; + + const char *GetBaseName() const; + + int GetSplitScreenPlayerSlot() const; + +private: + // High-speed method to read convar data + IConVar *m_pConVar; + ConVar *m_pConVarState; +}; + + +//----------------------------------------------------------------------------- +// Did we find an existing convar of that name? +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const +{ + return ( m_pConVar->IsFlagSet( nFlags ) != 0 ); +} + +FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar() +{ + return m_pConVar; +} + +FORCEINLINE_CVAR const char *ConVarRef::GetName() const +{ + return m_pConVar->GetName(); +} + +FORCEINLINE_CVAR const char *ConVarRef::GetBaseName() const +{ + return m_pConVar->GetBaseName(); +} + +FORCEINLINE_CVAR int ConVarRef::GetSplitScreenPlayerSlot() const +{ + return m_pConVar->GetSplitScreenPlayerSlot(); +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a float +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const +{ + return m_pConVarState->m_Value.m_fValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as an int +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const +{ + return m_pConVarState->m_Value.m_nValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a color +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR Color ConVarRef::GetColor( void ) const +{ + return m_pConVarState->GetColor(); +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const +{ + Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) ); + return m_pConVarState->m_Value.m_pszString; +} + + +FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue ) +{ + m_pConVar->SetValue( pValue ); +} + +FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue ) +{ + m_pConVar->SetValue( flValue ); +} + +FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue ) +{ + m_pConVar->SetValue( nValue ); +} + +FORCEINLINE_CVAR void ConVarRef::SetValue( Color value ) +{ + m_pConVar->SetValue( value ); +} + +FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue ) +{ + m_pConVar->SetValue( bValue ? 1 : 0 ); +} + +FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const +{ + return m_pConVarState->m_pszDefaultValue; +} + +//----------------------------------------------------------------------------- +// Helper for referencing splitscreen convars (i.e., "name" and "name2") +//----------------------------------------------------------------------------- +class SplitScreenConVarRef +{ +public: + SplitScreenConVarRef( const char *pName ); + SplitScreenConVarRef( const char *pName, bool bIgnoreMissing ); + SplitScreenConVarRef( IConVar *pConVar ); + + void Init( const char *pName, bool bIgnoreMissing ); + bool IsValid() const; + bool IsFlagSet( int nFlags ) const; + + // Get/Set value + float GetFloat( int nSlot ) const; + int GetInt( int nSlot ) const; + Color GetColor( int nSlot ) const; + bool GetBool( int nSlot ) const { return !!GetInt( nSlot ); } + const char *GetString( int nSlot ) const; + + void SetValue( int nSlot, const char *pValue ); + void SetValue( int nSlot, float flValue ); + void SetValue( int nSlot, int nValue ); + void SetValue( int nSlot, Color value ); + void SetValue( int nSlot, bool bValue ); + + const char *GetName( int nSlot ) const; + + const char *GetDefault() const; + + const char *GetBaseName() const; + +private: + struct cv_t + { + IConVar *m_pConVar; + ConVar *m_pConVarState; + }; + + cv_t m_Info[ MAX_SPLITSCREEN_CLIENTS ]; +}; + +//----------------------------------------------------------------------------- +// Did we find an existing convar of that name? +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR bool SplitScreenConVarRef::IsFlagSet( int nFlags ) const +{ + return ( m_Info[ 0 ].m_pConVar->IsFlagSet( nFlags ) != 0 ); +} + +FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetName( int nSlot ) const +{ + return m_Info[ nSlot ].m_pConVar->GetName(); +} + +FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetBaseName() const +{ + return m_Info[ 0 ].m_pConVar->GetBaseName(); +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a float +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR float SplitScreenConVarRef::GetFloat( int nSlot ) const +{ + return m_Info[ nSlot ].m_pConVarState->m_Value.m_fValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as an int +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR int SplitScreenConVarRef::GetInt( int nSlot ) const +{ + return m_Info[ nSlot ].m_pConVarState->m_Value.m_nValue; +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as an int +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR Color SplitScreenConVarRef::GetColor( int nSlot ) const +{ + return m_Info[ nSlot ].m_pConVarState->GetColor(); +} + +//----------------------------------------------------------------------------- +// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. +//----------------------------------------------------------------------------- +FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetString( int nSlot ) const +{ + Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) ); + return m_Info[ nSlot ].m_pConVarState->m_Value.m_pszString; +} + + +FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, const char *pValue ) +{ + m_Info[ nSlot ].m_pConVar->SetValue( pValue ); +} + +FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, float flValue ) +{ + m_Info[ nSlot ].m_pConVar->SetValue( flValue ); +} + +FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, int nValue ) +{ + m_Info[ nSlot ].m_pConVar->SetValue( nValue ); +} + +FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, Color value ) +{ + m_Info[ nSlot ].m_pConVar->SetValue( value ); +} + +FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, bool bValue ) +{ + m_Info[ nSlot ].m_pConVar->SetValue( bValue ? 1 : 0 ); +} + +FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetDefault() const +{ + return m_Info[ 0 ].m_pConVarState->m_pszDefaultValue; +} + +//----------------------------------------------------------------------------- +// Called by the framework to register ConCommands with the ICVar +//----------------------------------------------------------------------------- +void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL ); +void ConVar_Unregister( ); + + +//----------------------------------------------------------------------------- +// Utility methods +//----------------------------------------------------------------------------- +void ConVar_PrintDescription( const ConCommandBase *pVar ); + + +//----------------------------------------------------------------------------- +// Purpose: Utility class to quickly allow ConCommands to call member methods +//----------------------------------------------------------------------------- +#pragma warning (disable : 4355 ) + +template< class T > +class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback +{ + typedef ConCommand BaseClass; + typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command ); + typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands ); + +public: + CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0, + int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) : + BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL ) + { + m_pOwner = pOwner; + m_Func = callback; + m_CompletionFunc = completionFunc; + } + + ~CConCommandMemberAccessor() + { + Shutdown(); + } + + void SetOwner( T* pOwner ) + { + m_pOwner = pOwner; + } + + virtual void CommandCallback( const CCommand &command ) + { + Assert( m_pOwner && m_Func ); + (m_pOwner->*m_Func)( command ); + } + + virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) + { + Assert( m_pOwner && m_CompletionFunc ); + return (m_pOwner->*m_CompletionFunc)( pPartial, commands ); + } + +private: + T* m_pOwner; + FnMemberCommandCallback_t m_Func; + FnMemberCommandCompletionCallback_t m_CompletionFunc; +}; + +#pragma warning ( default : 4355 ) + + +//----------------------------------------------------------------------------- +// Purpose: Utility macros to quicky generate a simple console command +//----------------------------------------------------------------------------- +#define CON_COMMAND( name, description ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command( #name, name, description ); \ + static void name( const CCommand &args ) + +#ifdef CLIENT_DLL + #define CON_COMMAND_SHARED( name, description ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command_client( #name "_client", name, description ); \ + static void name( const CCommand &args ) +#else + #define CON_COMMAND_SHARED( name, description ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command( #name, name, description ); \ + static void name( const CCommand &args ) +#endif + + +#define CON_COMMAND_F( name, description, flags ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command( #name, name, description, flags ); \ + static void name( const CCommand &args ) + +#ifdef CLIENT_DLL + #define CON_COMMAND_F_SHARED( name, description, flags ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command_client( #name "_client", name, description, flags ); \ + static void name( const CCommand &args ) +#else + #define CON_COMMAND_F_SHARED( name, description, flags ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command( #name, name, description, flags ); \ + static void name( const CCommand &args ) +#endif + + +#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command( #name, name, description, flags, completion ); \ + static void name( const CCommand &args ) + +#ifdef CLIENT_DLL + #define CON_COMMAND_F_COMPLETION_SHARED( name, description, flags, completion ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command_client( #name "_client", name, description, flags, completion ); \ + static void name( const CCommand &args ) +#else + #define CON_COMMAND_F_COMPLETION_SHARED( name, description, flags, completion ) \ + static void name( const CCommand &args ); \ + static ConCommand name##_command( #name, name, description, flags, completion ); \ + static void name( const CCommand &args ) +#endif + + +#define CON_COMMAND_EXTERN( name, _funcname, description ) \ + void _funcname( const CCommand &args ); \ + static ConCommand name##_command( #name, _funcname, description ); \ + void _funcname( const CCommand &args ) + +#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \ + void _funcname( const CCommand &args ); \ + static ConCommand name##_command( #name, _funcname, description, flags ); \ + void _funcname( const CCommand &args ) + +#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \ + void _funcname( const CCommand &args ); \ + friend class CCommandMemberInitializer_##_funcname; \ + class CCommandMemberInitializer_##_funcname \ + { \ + public: \ + CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \ + { \ + m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \ + } \ + private: \ + CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \ + }; \ + \ + CCommandMemberInitializer_##_funcname m_##_funcname##_register; \ + + +#endif // CONVAR_H diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index d8d625f7..606964e7 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -145,6 +145,8 @@ static const char *get_source_engine_name() return "left4dead"; #elif SOURCE_ENGINE == SE_LEFT4DEAD2 return "left4dead2"; +#elif SOURCE_ENGINE == SE_ALIENSWARM + return "alienswarm"; #endif } diff --git a/core/smn_console.cpp b/core/smn_console.cpp index 52549add..307fcbcb 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -45,6 +45,7 @@ #include #include "Logger.h" #include "ConsoleDetours.h" +#include "ConCommandBaseIterator.h" #if SOURCE_ENGINE >= SE_ORANGEBOXVALVE #define NETMSG_BITS 6 @@ -52,7 +53,7 @@ #define NETMSG_BITS 5 #endif -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD #define NET_SETCONVAR 6 #else #define NET_SETCONVAR 5 @@ -73,15 +74,6 @@ struct GlobCmdIter List::iterator iter; }; -struct ConCmdIter -{ -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - ICvarIteratorInternal *pLast; -#else - const ConCommandBase *pLast; -#endif -}; - class ConsoleHelpers : public SMGlobalClass, public IHandleTypeDispatch @@ -108,11 +100,7 @@ public: } else if (type == htConCmdIter) { - ConCmdIter *iter = (ConCmdIter * )object; -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - // ICvarIteratorInternal has no virtual destructor - g_pMemAlloc->Free(iter->pLast); -#endif + ConCommandBaseIterator *iter = (ConCommandBaseIterator * )object; delete iter; } } @@ -120,7 +108,7 @@ public: { if (type == htConCmdIter) { - *pSize = sizeof(ConCmdIter); + *pSize = sizeof(ConCommandBaseIterator); return true; } else if (type == hCmdIterType) @@ -1199,7 +1187,7 @@ static cell_t GetCommandFlags(IPluginContext *pContext, const cell_t *params) static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params) { Handle_t hndl; - ConCmdIter *pIter; + ConCommandBaseIterator *pIter; cell_t *pIsCmd, *pFlags; const ConCommandBase *pConCmd; const char *desc; @@ -1207,21 +1195,15 @@ static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params pContext->LocalToPhysAddr(params[3], &pIsCmd); pContext->LocalToPhysAddr(params[4], &pFlags); -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - ICvarIteratorInternal *cvarIter = icvar->FactoryInternalIterator(); - cvarIter->SetFirst(); - if (!cvarIter->IsValid()) + pIter = new ConCommandBaseIterator(); + + if (!pIter->IsValid()) { + delete pIter; return BAD_HANDLE; } - pConCmd = cvarIter->Get(); -#else - pConCmd = icvar->GetCommands(); - if (pConCmd == NULL) - { - return BAD_HANDLE; - } -#endif + + pConCmd = pIter->Get(); pContext->StringToLocalUTF8(params[1], params[2], pConCmd->GetName(), NULL); *pIsCmd = pConCmd->IsCommand() ? 1 : 0; @@ -1233,13 +1215,6 @@ static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params pContext->StringToLocalUTF8(params[5], params[6], (desc && desc[0]) ? desc : "", NULL); } - pIter = new ConCmdIter; -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - pIter->pLast = cvarIter; -#else - pIter->pLast = pConCmd; -#endif - if ((hndl = g_HandleSys.CreateHandle(htConCmdIter, pIter, pContext->GetIdentity(), g_pCoreIdent, NULL)) == BAD_HANDLE) { @@ -1253,7 +1228,7 @@ static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params static cell_t FindNextConCommand(IPluginContext *pContext, const cell_t *params) { HandleError err; - ConCmdIter *pIter; + ConCommandBaseIterator *pIter; cell_t *pIsCmd, *pFlags; const char *desc; const ConCommandBase *pConCmd; @@ -1264,27 +1239,17 @@ static cell_t FindNextConCommand(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err); } - if (pIter->pLast == NULL) + if (!pIter->IsValid()) { return 0; } -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - ICvarIteratorInternal *cvarIter = pIter->pLast; - cvarIter->Next(); - if (!cvarIter->IsValid()) + pIter->Next(); + if (!pIter->IsValid()) { return 0; } - pConCmd = cvarIter->Get(); -#else - pConCmd = pIter->pLast->GetNext(); - if (pConCmd == NULL) - { - return 0; - } - pIter->pLast = pConCmd; -#endif + pConCmd = pIter->Get(); pContext->LocalToPhysAddr(params[4], &pIsCmd); pContext->LocalToPhysAddr(params[5], &pFlags); diff --git a/core/smn_entities.cpp b/core/smn_entities.cpp index 8a42240a..b2a25b3f 100644 --- a/core/smn_entities.cpp +++ b/core/smn_entities.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -860,7 +860,7 @@ static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params) } } - return td->fieldOffset[TD_OFFSET_NORMAL]; + return GetTypeDescOffs(td); } static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params) @@ -1004,7 +1004,7 @@ static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params) td->fieldType); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1093,7 +1093,7 @@ static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params) td->fieldType); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1184,7 +1184,7 @@ static cell_t GetEntPropFloat(IPluginContext *pContext, const cell_t *params) FIELD_TIME); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1253,7 +1253,7 @@ static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params) FIELD_TIME); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1325,7 +1325,7 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) FIELD_EHANDLE); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1393,7 +1393,7 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) FIELD_EHANDLE); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1484,7 +1484,7 @@ static cell_t GetEntPropVector(IPluginContext *pContext, const cell_t *params) FIELD_POSITION_VECTOR); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1560,7 +1560,7 @@ static cell_t SetEntPropVector(IPluginContext *pContext, const cell_t *params) FIELD_POSITION_VECTOR); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1647,7 +1647,7 @@ static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params) bIsStringIndex = (td->fieldType != FIELD_CHARACTER); - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); break; } case Prop_Send: @@ -1726,7 +1726,7 @@ static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params) { return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop); } - offset = td->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(td); maxlen = td->fieldSize; break; } diff --git a/core/smn_halflife.cpp b/core/smn_halflife.cpp index 40f16678..df2df3e2 100644 --- a/core/smn_halflife.cpp +++ b/core/smn_halflife.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -73,7 +73,7 @@ static cell_t IsDedicatedServer(IPluginContext *pContext, const cell_t *params) static cell_t GetEngineTime(IPluginContext *pContext, const cell_t *params) { -#if SOURCE_ENGINE == SE_LEFT4DEAD2 +#if SOURCE_ENGINE >= SE_LEFT4DEAD2 float fTime = Plat_FloatTime(); #else float fTime = engine->Time(); @@ -465,6 +465,8 @@ static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params) return 40; case SOURCE_ENGINE_LEFT4DEAD2: return 50; + case SOURCE_ENGINE_ALIENSWARM: + return 60; # endif } #else diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h index ed244c63..0f2130c0 100644 --- a/core/sourcemm_api.h +++ b/core/sourcemm_api.h @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -32,7 +32,9 @@ #ifndef _INCLUDE_SOURCEMOD_MM_API_H_ #define _INCLUDE_SOURCEMOD_MM_API_H_ -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE == SE_ALIENSWARM +#include "convar_sm_swarm.h" +#elif (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) #include "convar_sm_l4d.h" #elif (SOURCE_ENGINE == SE_ORANGEBOX) || (SOURCE_ENGINE == SE_ORANGEBOXVALVE) #include "convar_sm_ob.h" diff --git a/extensions/sdktools/output.cpp b/extensions/sdktools/output.cpp index cb453d5e..0aa55c3b 100644 --- a/extensions/sdktools/output.cpp +++ b/extensions/sdktools/output.cpp @@ -330,7 +330,7 @@ const char *EntityOutputManager::FindOutputName(void *pOutput, CBaseEntity *pCal { if (pMap->dataDesc[i].flags & FTYPEDESC_OUTPUT) { - if ((char *)pCaller + pMap->dataDesc[i].fieldOffset[0] == pOutput) + if ((char *)pCaller + GetTypeDescOffs(&pMap->dataDesc[i]) == pOutput) { return pMap->dataDesc[i].externalName; } @@ -349,7 +349,7 @@ const char *EntityOutputManager::GetEntityClassname(CBaseEntity *pEntity) { datamap_t *pMap = gamehelpers->GetDataMap(pEntity); typedescription_t *pDesc = gamehelpers->FindInDataMap(pMap, "m_iClassname"); - offset = pDesc->fieldOffset[TD_OFFSET_NORMAL]; + offset = GetTypeDescOffs(pDesc); } return *(const char **)(((unsigned char *)pEntity) + offset); diff --git a/extensions/sdktools/trnatives.cpp b/extensions/sdktools/trnatives.cpp index 1c5043fa..8b212ac2 100644 --- a/extensions/sdktools/trnatives.cpp +++ b/extensions/sdktools/trnatives.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod SDKTools Extension - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -530,8 +530,8 @@ static cell_t smn_TRGetPointContents(IPluginContext *pContext, const cell_t *par { mask = enginetrace->GetPointContents(pos); } else { -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) - mask = enginetrace->GetPointContents(pos, 0, &hentity); +#if SOURCE_ENGINE >= SE_LEFT4DEAD + mask = enginetrace->GetPointContents(pos, MASK_ALL, &hentity); #else mask = enginetrace->GetPointContents(pos, &hentity); #endif diff --git a/extensions/sdktools/vhelpers.cpp b/extensions/sdktools/vhelpers.cpp index 1dccaf2e..30016ebd 100644 --- a/extensions/sdktools/vhelpers.cpp +++ b/extensions/sdktools/vhelpers.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod SDKTools Extension - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -600,7 +600,7 @@ CON_COMMAND(sm_dump_classes, "Dumps the class list as a text file") fprintf(fp,"%s - %s\n",sclass->GetName(), dict->m_Factories.GetElementName(i)); typedescription_t *datamap = gamehelpers->FindInDataMap(gamehelpers->GetDataMap(entity->GetBaseEntity()), "m_iEFlags"); - int *eflags = (int *)((char *)entity->GetBaseEntity() + datamap->fieldOffset[TD_OFFSET_NORMAL]); + int *eflags = (int *)((char *)entity->GetBaseEntity() + GetTypeDescOffs(datamap)); *eflags |= (1<<0); // EFL_KILLME } @@ -816,7 +816,7 @@ CON_COMMAND(sm_dump_datamaps, "Dumps the data map list as a text file") continue; } - int *eflags = (int *)((char *)entity->GetBaseEntity() + datamap->fieldOffset[TD_OFFSET_NORMAL]); + int *eflags = (int *)((char *)entity->GetBaseEntity() + GetTypeDescOffs(datamap)); *eflags |= (1<<0); // EFL_KILLME } diff --git a/extensions/sdktools/vnatives.cpp b/extensions/sdktools/vnatives.cpp index 561e931a..f626cf2f 100644 --- a/extensions/sdktools/vnatives.cpp +++ b/extensions/sdktools/vnatives.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod SDKTools Extension - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. +* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -541,7 +541,7 @@ static cell_t SlapPlayer(IPluginContext *pContext, const cell_t *params) typedescription_t *pType = gamehelpers->FindInDataMap(pMap, frag_prop); if (pType != NULL) { - s_frag_offs = pType->fieldOffset[TD_OFFSET_NORMAL]; + s_frag_offs = GetTypeDescOffs(pType); } } if (!s_frag_offs) @@ -657,7 +657,7 @@ static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *para return gamehelpers->EntityToBCompatRef(pEntity); } -#if (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) +#if SOURCE_ENGINE >= SE_LEFT4DEAD static cell_t CreateEntityByName(IPluginContext *pContext, const cell_t *params) { static ValveCall *pCall = NULL; @@ -713,7 +713,7 @@ static cell_t CreateEntityByName(IPluginContext *pContext, const cell_t *params) } #endif -#if SOURCE_ENGINE == SE_LEFT4DEAD2 +#if SOURCE_ENGINE >= SE_LEFT4DEAD2 static cell_t DispatchSpawn(IPluginContext *pContext, const cell_t *params) { static ValveCall *pCall = NULL; diff --git a/loader/loader.cpp b/loader/loader.cpp index 8b3ab03f..d2fc8a67 100644 --- a/loader/loader.cpp +++ b/loader/loader.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod - * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -73,6 +73,7 @@ #define FILENAME_1_6_L4D "sourcemod.2.l4d" PLATFORM_EXT #define FILENAME_1_6_DARKM "sourcemod.2.darkm" PLATFORM_EXT #define FILENAME_1_6_L4D2 "sourcemod.2.l4d2" PLATFORM_EXT +#define FILENAME_1_6_SWARM "sourcemod.2.swarm" PLATFORM_EXT HINSTANCE g_hCore = NULL; bool load_attempted = false; @@ -239,6 +240,11 @@ DLL_EXPORT METAMOD_PLUGIN *CreateInterface_MMS(const MetamodVersionInfo *mvi, co filename = FILENAME_1_6_L4D2; break; } + case SOURCE_ENGINE_ALIENSWARM: + { + filename = FILENAME_1_6_SWARM; + break; + } default: { return NULL; diff --git a/plugins/include/halflife.inc b/plugins/include/halflife.inc index e3d4e6e5..63f23ad3 100644 --- a/plugins/include/halflife.inc +++ b/plugins/include/halflife.inc @@ -42,7 +42,7 @@ #define SOURCE_SDK_EPISODE2 30 /**< SDK+Engine released after Episode 2/Orange Box */ #define SOURCE_SDK_EPISODE2VALVE 35 /**< SDK+Engine released after Episode 2/Orange Box */ #define SOURCE_SDK_LEFT4DEAD 40 /**< Engine released after Left 4 Dead (no SDK yet) */ -#define SOURCE_SDK_LEFT4DEAD2 50 /**< Engine released after Left 4 Dead 2 (no SDK yet) */ +#define SOURCE_SDK_LEFT4DEAD2 50 /**< Engine released after Left 4 Dead 2 (no SDK yet) */ #define SOURCE_SDK_ALIENSWARM 60 /**< SDK+Engine released after Alien Swarm */ #define MOTDPANEL_TYPE_TEXT 0 /**< Treat msg as plain text */ #define MOTDPANEL_TYPE_INDEX 1 /**< Msg is auto determined by the engine */ diff --git a/public/compat_wrappers.h b/public/compat_wrappers.h index cf4db072..ee4a7b0e 100644 --- a/public/compat_wrappers.h +++ b/public/compat_wrappers.h @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -32,6 +32,8 @@ #ifndef _INCLUDE_SOURCEMOD_COMPAT_WRAPPERS_H_ #define _INCLUDE_SOURCEMOD_COMPAT_WRAPPERS_H_ +#include + #if SOURCE_ENGINE >= SE_ORANGEBOX #define CONVAR_REGISTER(object) ConVar_Register(0, object) @@ -123,16 +125,20 @@ #if SOURCE_ENGINE >= SE_LEFT4DEAD inline int IndexOfEdict(const edict_t *pEdict) { - return (int)(pEdict - gpGlobals->baseEdict); + return (int)(pEdict - gpGlobals->pEdicts); } inline edict_t *PEntityOfEntIndex(int iEntIndex) { if (iEntIndex >= 0 && iEntIndex < gpGlobals->maxEntities) { - return (edict_t *)(gpGlobals->baseEdict + iEntIndex); + return (edict_t *)(gpGlobals->pEdicts + iEntIndex); } return NULL; } + inline int GetTypeDescOffs(typedescription_t *td) + { + return td->fieldOffset; + } #else inline int IndexOfEdict(const edict_t *pEdict) { @@ -142,6 +148,10 @@ { return engine->PEntityOfEntIndex(iEntIndex); } + inline int GetTypeDescOffs(typedescription_t *td) + { + return td->fieldOffset[TD_OFFSET_NORMAL]; + } #endif //SOURCE_ENGINE >= SE_LEFT4DEAD #endif //_INCLUDE_SOURCEMOD_COMPAT_WRAPPERS_H_ diff --git a/public/sm_platform.h b/public/sm_platform.h index 0459a554..44ce8798 100644 --- a/public/sm_platform.h +++ b/public/sm_platform.h @@ -38,7 +38,9 @@ */ #if defined WIN32 || defined WIN64 +#ifndef PLATFORM_WINDOWS #define PLATFORM_WINDOWS +#endif #if !defined WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif