From bd9fab6cf5b8736513f9722c507eee27cb94a2d4 Mon Sep 17 00:00:00 2001 From: Scott Ehlert Date: Wed, 18 Feb 2009 02:19:22 -0600 Subject: [PATCH] Added support for Dark Messiah engine and game. (no bug, r=me). The development of this feature would not be possible without the support of the following people from the game's community: Dylan Riggs, Carl Pettengill, Ed Moreland, and Christian. --- core/ConVarManager.cpp | 14 +- core/ConVarManager.h | 7 + core/CoreConfig.cpp | 5 +- core/ExtensionSys.cpp | 2 + core/GameConfigs.cpp | 2 + core/HalfLife2.cpp | 39 ++- core/HalfLife2.h | 3 +- core/NextMap.cpp | 14 + core/NextMap.h | 4 + core/PlayerManager.cpp | 2 + core/msvc9/sourcemod_mm.sln | 9 + core/msvc9/sourcemod_mm.vcproj | 299 ++++++++++++++++++-- core/sm_srvcmds.cpp | 4 +- core/smn_banning.cpp | 6 + core/smn_halflife.cpp | 4 + extensions/bintools/msvc9/bintools.sln | 6 + extensions/bintools/msvc9/bintools.vcproj | 155 +++++++++++ extensions/sdktools/msvc9/sdktools.sln | 6 + extensions/sdktools/msvc9/sdktools.vcproj | 179 +++++++++++- extensions/sdktools/tempents.cpp | 2 +- extensions/sdktools/vhelpers.cpp | 9 +- extensions/sdktools/vnatives.cpp | 73 +++++ gamedata/core.games/common.games.txt | 45 +++ gamedata/sdktools.games/engine.darkm.txt | 322 ++++++++++++++++++++++ gamedata/sdktools.games/master.games.txt | 5 + loader/loader.cpp | 22 +- plugins/basechat.sp | 12 +- plugins/funcommands.sp | 3 + plugins/funcommands/ice.sp | 22 +- plugins/include/entity_prop_stocks.inc | 265 ++++++++++++++++-- plugins/include/halflife.inc | 1 + tools/builder/ABuilder.cs | 4 + tools/builder/Config.cs | 1 + tools/builder/Package.cs | 19 +- tools/builder/PkgCore.cs | 28 ++ tools/builder/Win32Builder.cs | 4 + 36 files changed, 1523 insertions(+), 74 deletions(-) create mode 100644 gamedata/sdktools.games/engine.darkm.txt diff --git a/core/ConVarManager.cpp b/core/ConVarManager.cpp index 1ea3eab5..0670c17f 100644 --- a/core/ConVarManager.cpp +++ b/core/ConVarManager.cpp @@ -41,7 +41,7 @@ ConVarManager g_ConVarManager; -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH #define CallGlobalChangeCallbacks CallGlobalChangeCallback #endif @@ -51,8 +51,10 @@ SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *); #endif +#if SOURCE_ENGINE != SE_DARKMESSIAH SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *); SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *); +#endif const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String}; typedef List ConVarList; @@ -141,6 +143,7 @@ void ConVarManager::OnSourceModShutdown() } convar_cache.clear(); +#if SOURCE_ENGINE != SE_DARKMESSIAH /* Unhook things */ if (m_bIsDLLQueryHooked) { @@ -152,6 +155,7 @@ void ConVarManager::OnSourceModShutdown() SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false); m_bIsVSPQueryHooked = false; } +#endif SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false); @@ -189,8 +193,10 @@ void ConVarManager::OnSourceModVSPReceived() } #endif +#if SOURCE_ENGINE != SE_DARKMESSIAH SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false); m_bIsVSPQueryHooked = true; +#endif } bool convar_cache_lookup(const char *name, ConVarInfo **pVar) @@ -528,8 +534,9 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl) { - QueryCvarCookie_t cookie; + QueryCvarCookie_t cookie = 0; +#if SOURCE_ENGINE != SE_DARKMESSIAH /* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */ if (m_bIsDLLQueryHooked) { @@ -546,6 +553,7 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char ConVarQuery query = {cookie, pCallback, hndl}; m_ConVarQueries.push_back(query); +#endif return cookie; } @@ -639,6 +647,7 @@ bool ConVarManager::IsQueryingSupported() return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked); } +#if SOURCE_ENGINE != SE_DARKMESSIAH void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue) { IPluginFunction *pCallback = NULL; @@ -680,6 +689,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t * m_ConVarQueries.erase(iter); } } +#endif HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar) { diff --git a/core/ConVarManager.h b/core/ConVarManager.h index a55636ed..6c9ddc9a 100644 --- a/core/ConVarManager.h +++ b/core/ConVarManager.h @@ -42,6 +42,11 @@ #include #include "concmd_cleaner.h" +#if SOURCE_ENGINE == SE_DARKMESSIAH +class EQueryCvarValueStatus; +typedef int QueryCvarCookie_t; +#endif + using namespace SourceHook; class IConVarChangeListener @@ -149,8 +154,10 @@ private: /** * Callback for when StartQueryCvarValue() has finished. */ +#if SOURCE_ENGINE != SE_DARKMESSIAH void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue); +#endif private: HandleType_t m_ConVarType; List m_ConVars; diff --git a/core/CoreConfig.cpp b/core/CoreConfig.cpp index 73ae3871..db8235cf 100644 --- a/core/CoreConfig.cpp +++ b/core/CoreConfig.cpp @@ -64,13 +64,16 @@ void CheckAndFinalizeConfigs(); #if SOURCE_ENGINE >= SE_ORANGEBOX SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); void Hook_ExecDispatchPre(const CCommand &cmd) +#elif SOURCE_ENGINE == SE_DARKMESSIAH +SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); +void Hook_ExecDispatchPre() #else extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); void Hook_ExecDispatchPre() #endif { -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand cmd; #endif diff --git a/core/ExtensionSys.cpp b/core/ExtensionSys.cpp index 08ec1a15..146bb168 100644 --- a/core/ExtensionSys.cpp +++ b/core/ExtensionSys.cpp @@ -73,6 +73,8 @@ CLocalExtension::CLocalExtension(const char *filename) "extensions/auto.2.l4d/%s", #elif SOURCE_ENGINE == SE_ORANGEBOX "extensions/auto.2.ep2/%s", +#elif SOURCE_ENGINE == SE_DARKMESSIAH + "extensions/auto.2.darkm/%s", #else "extensions/auto.2.ep1/%s", #endif //SOURCE_ENGINE == SE_LEFT4DEAD diff --git a/core/GameConfigs.cpp b/core/GameConfigs.cpp index c58aaecb..caec131e 100644 --- a/core/GameConfigs.cpp +++ b/core/GameConfigs.cpp @@ -105,6 +105,8 @@ static bool DoesEngineMatch(const char *value) { #if SOURCE_ENGINE == SE_EPISODEONE if (strcmp(value, "original") == 0) +#elif SOURCE_ENGINE == SE_DARKMESSIAH + if (strcmp(value, "darkmessiah") == 0) #elif SOURCE_ENGINE == SE_ORANGEBOX if (strcmp(value, "orangebox") == 0) #elif SOURCE_ENGINE == SE_LEFT4DEAD diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index 3595b7bd..4760fd6b 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -88,11 +88,16 @@ CHalfLife2::~CHalfLife2() m_Maps.clear(); } +#if SOURCE_ENGINE != SE_DARKMESSIAH CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL; +#endif + bool is_original_engine = false; void CHalfLife2::OnSourceModStartup(bool late) { +#if SOURCE_ENGINE != SE_DARKMESSIAH + /* The Ship currently is the only known game to use an older version of the engine */ #if defined METAMOD_PLAPI_VERSION if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL) @@ -106,12 +111,14 @@ void CHalfLife2::OnSourceModStartup(bool late) { g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo(); } +#endif } void CHalfLife2::OnSourceModAllInitialized() { m_MsgTextMsg = g_UserMsgs.GetMessageIndex("TextMsg"); m_HinTextMsg = g_UserMsgs.GetMessageIndex("HintText"); + m_SayTextMsg = g_UserMsgs.GetMessageIndex("SayText"); m_VGUIMenu = g_UserMsgs.GetMessageIndex("VGUIMenu"); g_ShareSys.AddInterface(NULL, this); } @@ -123,10 +130,12 @@ bool CHalfLife2::IsOriginalEngine() } #endif +#if SOURCE_ENGINE != SE_DARKMESSIAH IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() { return engine->GetChangeAccessor( (const edict_t *)this ); } +#endif bool UTIL_FindInSendTable(SendTable *pTable, const char *name, @@ -296,6 +305,7 @@ typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset) { +#if SOURCE_ENGINE != SE_DARKMESSIAH if (g_pSharedChangeInfo != NULL) { if (offset) @@ -308,6 +318,7 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset) } } else +#endif { pEdict->m_fStateFlags |= FL_EDICT_CHANGED; } @@ -318,6 +329,31 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg) bf_write *pBitBuf = NULL; cell_t players[] = {client}; + if (dest == HUD_PRINTTALK) + { + const char *chat_saytext = g_pGameConf->GetKeyValue("ChatSayText"); + + /* Use SayText user message instead */ + if (chat_saytext != NULL && strcmp(chat_saytext, "yes") == 0) + { + char buffer[192]; + UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg); + + if ((pBitBuf = g_UserMsgs.StartMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL) + { + return false; + } + + pBitBuf->WriteByte(0); + pBitBuf->WriteString(buffer); + pBitBuf->WriteByte(1); + + g_UserMsgs.EndMessage(); + + return true; + } + } + if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL) { return false; @@ -325,6 +361,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg) pBitBuf->WriteByte(dest); pBitBuf->WriteString(msg); + g_UserMsgs.EndMessage(); return true; @@ -481,7 +518,7 @@ void CHalfLife2::PushCommandStack(const CCommand *cmd) CachedCommandInfo info; info.args = cmd; -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH strncopy(info.cmd, cmd->Arg(0), sizeof(info.cmd)); #endif diff --git a/core/HalfLife2.h b/core/HalfLife2.h index 8808b0a6..b3ea334e 100644 --- a/core/HalfLife2.h +++ b/core/HalfLife2.h @@ -74,7 +74,7 @@ struct DelayedFakeCliCmd struct CachedCommandInfo { const CCommand *args; -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH char cmd[300]; #endif }; @@ -130,6 +130,7 @@ private: THash m_Maps; int m_MsgTextMsg; int m_HinTextMsg; + int m_SayTextMsg; int m_VGUIMenu; Queue m_CmdQueue; CStack m_FreeCmds; diff --git a/core/NextMap.cpp b/core/NextMap.cpp index a7c2699c..d88776ce 100644 --- a/core/NextMap.cpp +++ b/core/NextMap.cpp @@ -38,10 +38,16 @@ NextMapManager g_NextMap; +#if SOURCE_ENGINE != SE_DARKMESSIAH SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *); +#else +SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool); +#endif #if SOURCE_ENGINE >= SE_ORANGEBOX SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); +#elif SOURCE_ENGINE == SE_DARKMESSIAH +SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); #else extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); @@ -109,7 +115,11 @@ bool NextMapManager::SetNextMap(const char *map) return true; } +#if SOURCE_ENGINE != SE_DARKMESSIAH void NextMapManager::HookChangeLevel(const char *map, const char *unknown) +#else +void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading) +#endif { if (g_forcedChange) { @@ -129,7 +139,11 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown) UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap); UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change"); +#if SOURCE_ENGINE != SE_DARKMESSIAH RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown)); +#else + RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown, video, bLongLoading)); +#endif } void NextMapManager::OnSourceModLevelChange( const char *mapName ) diff --git a/core/NextMap.h b/core/NextMap.h index aa1b8c84..c6986582 100644 --- a/core/NextMap.h +++ b/core/NextMap.h @@ -84,7 +84,11 @@ public: void ForceChangeLevel(const char *mapName, const char* changeReason); +#if SOURCE_ENGINE != SE_DARKMESSIAH void HookChangeLevel(const char *map, const char *unknown); +#else + void HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading); +#endif public: SourceHook::List m_mapHistory; diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 930031fe..db584c0e 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -72,6 +72,8 @@ SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, in #if SOURCE_ENGINE >= SE_ORANGEBOX SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); +#elif SOURCE_ENGINE == SE_DARKMESSIAH +SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); #else extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); diff --git a/core/msvc9/sourcemod_mm.sln b/core/msvc9/sourcemod_mm.sln index ca801e17..3da1d5ce 100644 --- a/core/msvc9/sourcemod_mm.sln +++ b/core/msvc9/sourcemod_mm.sln @@ -5,20 +5,25 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sourcemod_mm", "sourcemod_m EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + CrazyDebug - Dark Messiah|Win32 = CrazyDebug - Dark Messiah|Win32 CrazyDebug - Episode 1|Win32 = CrazyDebug - Episode 1|Win32 CrazyDebug - Left 4 Dead|Win32 = CrazyDebug - Left 4 Dead|Win32 CrazyDebug - Old Metamod|Win32 = CrazyDebug - Old Metamod|Win32 CrazyDebug - Orange Box|Win32 = CrazyDebug - Orange Box|Win32 + Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 Debug - Episode 1|Win32 = Debug - Episode 1|Win32 Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 Debug - Old Metamod|Win32 = Debug - Old Metamod|Win32 Debug - Orange Box|Win32 = Debug - Orange Box|Win32 + Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 Release - Episode 1|Win32 = Release - Episode 1|Win32 Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 Release - Old Metamod|Win32 = Release - Old Metamod|Win32 Release - Orange Box|Win32 = Release - Orange Box|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Dark Messiah|Win32.ActiveCfg = CrazyDebug - Dark Messiah|Win32 + {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Dark Messiah|Win32.Build.0 = CrazyDebug - Dark Messiah|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Episode 1|Win32.ActiveCfg = CrazyDebug - Episode 1|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Episode 1|Win32.Build.0 = CrazyDebug - Episode 1|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Left 4 Dead|Win32.ActiveCfg = CrazyDebug - Left 4 Dead|Win32 @@ -27,6 +32,8 @@ Global {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Old Metamod|Win32.Build.0 = CrazyDebug - Old Metamod|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Orange Box|Win32.ActiveCfg = CrazyDebug - Orange Box|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.CrazyDebug - Orange Box|Win32.Build.0 = CrazyDebug - Orange Box|Win32 + {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 + {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Episode 1|Win32.ActiveCfg = Debug - Episode 1|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Episode 1|Win32.Build.0 = Debug - Episode 1|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 @@ -35,6 +42,8 @@ Global {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Old Metamod|Win32.Build.0 = Debug - Old Metamod|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 + {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 + {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Episode 1|Win32.ActiveCfg = Release - Episode 1|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Episode 1|Win32.Build.0 = Release - Episode 1|Win32 {E39527CD-7CAB-4420-97CC-DA1B93B260BC}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 diff --git a/core/msvc9/sourcemod_mm.vcproj b/core/msvc9/sourcemod_mm.vcproj index 4721e3f3..2f939677 100644 --- a/core/msvc9/sourcemod_mm.vcproj +++ b/core/msvc9/sourcemod_mm.vcproj @@ -40,10 +40,10 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ThrowNativeError("No valid ban method flags specified"); } +#else + /* Dark Messiah doesn't have Steam IDs so there is only one ban method to choose */ + ban_flags |= BANFLAG_IP; + ban_flags &= ~BANFLAG_AUTHID; +#endif cell_t handled = 0; if (ban_cmd[0] != '\0' && g_pOnBanClient->GetFunctionCount() > 0) diff --git a/core/smn_halflife.cpp b/core/smn_halflife.cpp index 301a16c5..fd5898d5 100644 --- a/core/smn_halflife.cpp +++ b/core/smn_halflife.cpp @@ -445,6 +445,10 @@ static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params) { return 10; } + else if (version == SOURCE_ENGINE_DARKMESSIAH) + { + return 15; + } else if (version == SOURCE_ENGINE_EPISODEONE) { return 20; diff --git a/extensions/bintools/msvc9/bintools.sln b/extensions/bintools/msvc9/bintools.sln index 48d57f9b..35f7b9c3 100644 --- a/extensions/bintools/msvc9/bintools.sln +++ b/extensions/bintools/msvc9/bintools.sln @@ -5,16 +5,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bintools", "bintools.vcproj EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 Debug - Episode 1|Win32 = Debug - Episode 1|Win32 Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 Debug - Old Metamod|Win32 = Debug - Old Metamod|Win32 Debug - Orange Box|Win32 = Debug - Orange Box|Win32 + Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 Release - Episode 1|Win32 = Release - Episode 1|Win32 Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 Release - Old Metamod|Win32 = Release - Old Metamod|Win32 Release - Orange Box|Win32 = Release - Orange Box|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 + {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Episode 1|Win32.ActiveCfg = Debug - Episode 1|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Episode 1|Win32.Build.0 = Debug - Episode 1|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 @@ -23,6 +27,8 @@ Global {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Old Metamod|Win32.Build.0 = Debug - Old Metamod|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 + {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 + {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Release - Episode 1|Win32.ActiveCfg = Release - Episode 1|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Release - Episode 1|Win32.Build.0 = Release - Episode 1|Win32 {E38F65D9-74B2-4373-B46A-DBB76F579F98}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 diff --git a/extensions/bintools/msvc9/bintools.vcproj b/extensions/bintools/msvc9/bintools.vcproj index f5fbada7..7688b363 100644 --- a/extensions/bintools/msvc9/bintools.vcproj +++ b/extensions/bintools/msvc9/bintools.vcproj @@ -644,6 +644,161 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/sdktools/msvc9/sdktools.sln b/extensions/sdktools/msvc9/sdktools.sln index 78e814c4..ce1ff0c4 100644 --- a/extensions/sdktools/msvc9/sdktools.sln +++ b/extensions/sdktools/msvc9/sdktools.sln @@ -5,16 +5,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdktools", "sdktools.vcproj EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 Debug - Episode 1|Win32 = Debug - Episode 1|Win32 Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 Debug - Old Metamod|Win32 = Debug - Old Metamod|Win32 Debug - Orange Box|Win32 = Debug - Orange Box|Win32 + Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 Release - Episode 1|Win32 = Release - Episode 1|Win32 Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 Release - Old Metamod|Win32 = Release - Old Metamod|Win32 Release - Orange Box|Win32 = Release - Orange Box|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 + {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.ActiveCfg = Debug - Episode 1|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Episode 1|Win32.Build.0 = Debug - Episode 1|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 @@ -23,6 +27,8 @@ Global {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Old Metamod|Win32.Build.0 = Debug - Old Metamod|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 + {7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 + {7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.ActiveCfg = Release - Episode 1|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Episode 1|Win32.Build.0 = Release - Episode 1|Win32 {7A740927-C751-4312-BF9D-6367F8C508F8}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 diff --git a/extensions/sdktools/msvc9/sdktools.vcproj b/extensions/sdktools/msvc9/sdktools.vcproj index e75d1f26..ed3c0a37 100644 --- a/extensions/sdktools/msvc9/sdktools.vcproj +++ b/extensions/sdktools/msvc9/sdktools.vcproj @@ -40,7 +40,7 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/sdktools/tempents.cpp b/extensions/sdktools/tempents.cpp index f6bbd744..46f1185a 100644 --- a/extensions/sdktools/tempents.cpp +++ b/extensions/sdktools/tempents.cpp @@ -47,7 +47,7 @@ CON_COMMAND(sm_print_telist, "Prints the temp entity list") CON_COMMAND(sm_dump_teprops, "Dumps tempentity props to a file") { -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; #endif if (!g_TEManager.IsAvailable()) diff --git a/extensions/sdktools/vhelpers.cpp b/extensions/sdktools/vhelpers.cpp index b119bbf4..1c25c742 100644 --- a/extensions/sdktools/vhelpers.cpp +++ b/extensions/sdktools/vhelpers.cpp @@ -420,7 +420,7 @@ void UTIL_DrawSendTable(FILE *fp, SendTable *pTable, int level) CON_COMMAND(sm_dump_netprops_xml, "Dumps the networkable property table as an XML file") { -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; #endif @@ -462,7 +462,7 @@ CON_COMMAND(sm_dump_netprops_xml, "Dumps the networkable property table as an XM CON_COMMAND(sm_dump_netprops, "Dumps the networkable property table as a text file") { -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; #endif @@ -517,7 +517,7 @@ void _ignore_invalid_parameter( CON_COMMAND(sm_dump_classes, "Dumps the class list as a text file") { -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; #endif @@ -605,7 +605,6 @@ 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]); *eflags |= (1<<0); // EFL_KILLME } @@ -710,7 +709,7 @@ void UTIL_DrawDataTable(FILE *fp, datamap_t *pMap, int level) CON_COMMAND(sm_dump_datamaps, "Dumps the data map list as a text file") { -#if SOURCE_ENGINE == SE_EPISODEONE +#if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; #endif diff --git a/extensions/sdktools/vnatives.cpp b/extensions/sdktools/vnatives.cpp index 99271e22..5fc75b66 100644 --- a/extensions/sdktools/vnatives.cpp +++ b/extensions/sdktools/vnatives.cpp @@ -214,6 +214,7 @@ static cell_t GetPlayerWeaponSlot(IPluginContext *pContext, const cell_t *params return IndexOfEdict(pEdict); } +#if SOURCE_ENGINE != SE_DARKMESSIAH static cell_t IgniteEntity(IPluginContext *pContext, const cell_t *params) { static ValveCall *pCall = NULL; @@ -242,6 +243,42 @@ static cell_t IgniteEntity(IPluginContext *pContext, const cell_t *params) return 1; } +#else +/* Dark Messiah specific version */ +static cell_t IgniteEntity(IPluginContext *pContext, const cell_t *params) +{ + static ValveCall *pCall = NULL; + if (!pCall) + { + ValvePassInfo pass[6]; + InitPass(pass[0], Valve_Float, PassType_Float, PASSFLAG_BYVAL); + InitPass(pass[1], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL); + InitPass(pass[2], Valve_Float, PassType_Float, PASSFLAG_BYVAL); + InitPass(pass[3], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL); + InitPass(pass[4], Valve_POD, PassType_Basic, PASSFLAG_BYVAL); + InitPass(pass[5], Valve_POD, PassType_Basic, PASSFLAG_BYVAL); + if (!CreateBaseCall("Ignite", ValveCall_Entity, NULL, pass, 6, &pCall)) + { + return pContext->ThrowNativeError("\"Ignite\" not supported by this mod"); + } else if (!pCall) { + return pContext->ThrowNativeError("\"Ignite\" wrapper failed to initialized"); + } + } + + START_CALL(); + DECODE_VALVE_PARAM(1, thisinfo, 0); + DECODE_VALVE_PARAM(2, vparams, 0); + DECODE_VALVE_PARAM(3, vparams, 1); + DECODE_VALVE_PARAM(4, vparams, 2); + DECODE_VALVE_PARAM(5, vparams, 3); + /* Not sure what these params do, but they appear to be the default values */ + *(int *)(vptr + 14) = 3; + *(int *)(vptr + 18) = 0; + FINISH_CALL_SIMPLE(NULL); + + return 1; +} +#endif static cell_t ExtinguishEntity(IPluginContext *pContext, const cell_t *params) { @@ -456,7 +493,9 @@ static cell_t SlapPlayer(IPluginContext *pContext, const cell_t *params) bool should_slay = false; if (params[2]) { +#if SOURCE_ENGINE != SE_DARKMESSIAH int *health = (int *)((char *)pEntity + s_health_offs); + if (*health - params[2] <= 0) { *health = 1; @@ -464,6 +503,17 @@ static cell_t SlapPlayer(IPluginContext *pContext, const cell_t *params) } else { *health -= params[2]; } +#else + float *health = (float *)((char *)pEntity + s_health_offs); + + if (*health - (float)params[2] <= 0) + { + *health = 1.0f; + should_slay = true; + } else { + *health -= (float)params[2]; + } +#endif } /* Teleport in a random direction - thank you, Mani!*/ @@ -996,6 +1046,21 @@ static cell_t SetClientInfo(IPluginContext *pContext, const cell_t *params) } } +/* TODO: Use UpdateUserSettings function for all engines */ +#if SOURCE_ENGINE == SE_DARKMESSIAH + static ValveCall *pUpdateSettings = NULL; + if (!pUpdateSettings) + { + if (!CreateBaseCall("UpdateUserSettings", ValveCall_Entity, NULL, NULL, 0, &pUpdateSettings)) + { + return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod"); + } + else if (!pUpdateSettings) + { + return pContext->ThrowNativeError("\"SetUserCvar\" wrapper failed to initialized"); + } + } +#else static int changedOffset = -1; if (changedOffset == -1) @@ -1005,6 +1070,7 @@ static cell_t SetClientInfo(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod"); } } +#endif unsigned char *CGameClient = (unsigned char *)pClient - 4; @@ -1016,8 +1082,15 @@ static cell_t SetClientInfo(IPluginContext *pContext, const cell_t *params) DECODE_VALVE_PARAM(3, vparams, 1); FINISH_CALL_SIMPLE(NULL); +#if SOURCE_ENGINE == SE_DARKMESSIAH + unsigned char *args = pUpdateSettings->stk_get(); + *(void **)args = CGameClient; + pUpdateSettings->call->Execute(args, NULL); + pUpdateSettings->stk_put(args); +#else uint8_t* changed = (uint8_t *)(CGameClient + changedOffset); *changed = 1; +#endif return 1; } diff --git a/gamedata/core.games/common.games.txt b/gamedata/core.games/common.games.txt index 7c3eb034..02853156 100644 --- a/gamedata/core.games/common.games.txt +++ b/gamedata/core.games/common.games.txt @@ -12,6 +12,22 @@ } } + /* Send properties and datamaps used by stocks in entity_prop_stocks.inc */ + "#default" + { + "Keys" + { + "m_fFlags" "m_fFlags" + "m_MoveType" "m_MoveType" + "m_nRenderMode" "m_nRenderMode" + "m_nRenderFX" "m_nRenderFX" + "m_clrRender" "m_clrRender" + "m_flGravity" "m_flGravity" + "m_iHealth" "m_iHealth" + "m_nButtons" "m_nButtons" + } + } + /* Original engine specifics */ "#default" { @@ -20,6 +36,11 @@ "engine" "original" } + "Keys" + { + "m_iHealth" "m_fHealth" + } + "Offsets" { "GetDataDescMap" @@ -30,6 +51,30 @@ } } + /* Dark Messiah engine specifics */ + "#default" + { + "#supported" + { + "engine" "darkmessiah" + } + + "Keys" + { + "m_iHealth" "m_fHealth" + "HintTextPreByte" "yes" + "ChatSayText" "yes" + } + + "Offsets" + { + "GetDataDescMap" + { + "windows" "12" + } + } + } + /* OB/L4D engine specifics */ "#default" { diff --git a/gamedata/sdktools.games/engine.darkm.txt b/gamedata/sdktools.games/engine.darkm.txt new file mode 100644 index 00000000..55939625 --- /dev/null +++ b/gamedata/sdktools.games/engine.darkm.txt @@ -0,0 +1,322 @@ +"Games" +{ + /* Sounds */ + "#default" + { + "Keys" + { + "SlapSoundCount" "3" + "SlapSound1" "default/player/sword_on_flesh_std01.wav" + "SlapSound2" "default/player/sword_on_flesh_std05.wav" + "SlapSound3" "default/player/bone_breaking03.wav" + } + } + + /* Properties */ + "#default" + { + "Offsets" + { + "m_iHealth" + { + "class" "CBasePlayer" + "prop" "m_fHealth" + } + } + } + + /* General Temp Entities */ + "#default" + { + "#supported" + { + "game" "!Might and Magic Multiplayer" + } + + "Offsets" + { + /* Offset into CBaseTempEntity constructor */ + "s_pTempEntities" + { + "windows" "17" + } + "GetTEName" + { + "windows" "4" + } + "GetTENext" + { + "windows" "8" + } + "TE_GetServerClass" + { + "windows" "0" + } + } + + "Signatures" + { + "CBaseTempEntity" + { + "library" "server" + "windows" "\x8B\xC1\x8B\x4C\x24\x04\xC7\x00\x2A\x2A\x2A\x2A\x89\x48\x04\x8B\x15\x2A\x2A\x2A\x2A\x89\x50\x08\xA3\x2A\x2A\x2A\x2A\xC2\x04\x00" + } + } + } + + /* Create Entity Signatures */ + "#default" + { + "#supported" + { + "game" "!Might and Magic Multiplayer" + } + + "Signatures" + { + "DispatchSpawn" + { + "library" "server" + "windows" "\x53\x56\x8B\x74\x24\x0C\x85\xF6\x57\x0F\x84\x2A\x2A\x2A\x2A\x8B\x1D\x2A\x2A\x2A\x2A\x8B\x03\x8B\xCB\xFF\x50\x60\x8B\x16" + } + "CreateEntityByName" + { + "library" "server" + "windows" "\x56\x8B\x74\x24\x0C\x83\xFE\xFF\x57\x8B\x7C\x24\x0C\x74\x25\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\x56\xFF\x50\x2A\x85\xC0" + } + } + } + + /* CGlobalEntityList */ + "#default" + { + "#supported" + { + "game" "!Might and Magic Multiplayer" + } + + "Offsets" + { + /* Offset into LevelShutdown */ + "gEntList" + { + "windows" "11" + } + } + + "Signatures" + { + "LevelShutdown" + { + "library" "server" + "windows" "\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8" + } + + /* Functions in CGlobalEntityList */ + "FindEntityByClassname" + { + "library" "server" + "windows" "\x53\x55\x56\x8B\xF1\x8B\x4C\x24\x10\x85\xC9\x57\x74\x18\x8B\x01\xFF\x50\x08\x8B\x08\x81\xE1\xFF\x0F\x00\x00\x83\xC1\x01\xC1\xE1\x04\x8B\x3C\x31\xEB\x06\x8B\xBE\x2A\x2A\x2A\x2A\x85\xFF\x74\x3A\x8B\x5C\x24\x18\x8B\x2D\x2A\x2A\x2A\x2A\x8D" + } + } + } + + /* General GameRules */ + "#default" + { + "#supported" + { + "game" "!Might and Magic Multiplayer" + } + + "Offsets" + { + /* Offset into CreateGameRulesObject */ + "g_pGameRules" + { + "windows" "2" + } + } + + "Signatures" + { + /* This signature sometimes has multiple matches, but this + * does not matter as g_pGameRules is involved in all of them. + * The same g_pGameRules offset applies to each match. + * + * Sometimes this block of bytes is at the beginning of the static + * CreateGameRulesObject function and sometimes it is in the middle + * of an entirely different function. This depends on the game. + */ + "CreateGameRulesObject" + { + "library" "server" + "windows" "\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9\x74\x2A\x8B\x01\x6A\x01\xFF\x50" + } + } + } + + /* IServer interface pointer */ + "#default" + { + "Keys" + { + /* Signature for the beginning of IVEngineServer::CreateFakeClient. + * + * The engine binary is not actually scanned in order to look for + * this. SourceHook is used to used to determine the address of the + * function and this signature is used to verify that it contains + * the expected code. A pointer to sv (IServer interface) is used + * here. + */ + "CreateFakeClient_Windows" "\x8B\x44\x24\x2A\x50\xB9\x2A\x2A\x2A\x2A\xE8" + } + + "Offsets" + { + /* Offset into IVEngineServer::CreateFakeClient */ + "sv" + { + "windows" "6" + } + } + } + + /* EntityFactoryDictionary function */ + "#default" + { + "Signatures" + { + "EntityFactory" + { + "library" "server" + "windows" "\xB8\x01\x00\x00\x00\x84\x2A\x2A\x2A\x2A\x2A\x75\x1D\x09\x2A\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x83\xC4\x04\xB8\x2A\x2A\x2A\x2A\xC3" + } + } + } + + /* CBaseEntityOutput::FireOutput */ + "#default" + { + "#supported" + { + "game" "!Might and Magic Multiplayer" + } + "Signatures" + { + "FireOutput" + { + "library" "server" + "windows" "\x83\xEC\x1C\x53\x55\x56\x8B\x71\x14" + "linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f" + } + } + "Offsets" + { + "FireOutputBackup" + { + "windows" "6" + } + } + } + + /* SetUserInfo data */ + "#default" + { + "Offsets" + { + /** + * CBaseClient::SetUserCVar(char const*,char const*); + * Linux offset straight from VTable dump. + * Windows offset is crazy. Found the windows 'SetName' function using string "(%d)%-0.*s" + * Cross referenced back to the vtable and counted manually (SetUserCvar is 1 higher, offsets start from 1) + */ + "SetUserCvar" + { + "windows" "17" + } + + "UpdateUserSettings" + { + "windows" "7" + } + } + } + + /* Dark Messiah */ + "!Might and Magic Multiplayer" + { + "Offsets" + { + "GiveNamedItem" + { + "windows" "309" + } + "RemovePlayerItem" + { + "windows" "210" + } + "Weapon_GetSlot" + { + "windows" "208" + } + "Ignite" + { + "windows" "172" + } + "Extinguish" + { + "windows" "173" + } + "Teleport" + { + "windows" "92" + } + "GetVelocity" + { + "windows" "115" + } + "EyeAngles" + { + "windows" "107" + } + "AcceptInput" + { + "windows" "34" + } + "DispatchKeyValue" + { + "windows" "30" + } + "DispatchKeyValueFloat" + { + "windows" "29" + } + "DispatchKeyValueVector" + { + "windows" "28" + } + "SetEntityModel" + { + "windows" "25" + } + "WeaponEquip" + { + "windows" "202" + } + "Activate" + { + "windows" "32" + } + } + + "Signatures" + { + "CommitSuicide" + { + "library" "server" + "windows" "\x83\xEC\x44\x56\x8B\xF1\x8B\x8E\x2A\x00\x00\x00\x85\xC9" + } + } + } +} diff --git a/gamedata/sdktools.games/master.games.txt b/gamedata/sdktools.games/master.games.txt index 5abc13ba..38a0a4b6 100644 --- a/gamedata/sdktools.games/master.games.txt +++ b/gamedata/sdktools.games/master.games.txt @@ -19,6 +19,11 @@ "engine" "original" } + "engine.darkm.txt" + { + "engine" "darkmessiah" + } + "game.tf.txt" { "game" "tf" diff --git a/loader/loader.cpp b/loader/loader.cpp index d05fccf7..113661b4 100644 --- a/loader/loader.cpp +++ b/loader/loader.cpp @@ -67,7 +67,8 @@ #define FILENAME_1_4_EP1 "sourcemod.1.ep1" PLATFORM_EXT #define FILENAME_1_6_EP2 "sourcemod.2.ep2" PLATFORM_EXT #define FILENAME_1_6_EP1 "sourcemod.2.ep1" PLATFORM_EXT -#define FILENAME_1_7_L4D "sourcemod.2.l4d" PLATFORM_EXT +#define FILENAME_1_6_L4D "sourcemod.2.l4d" PLATFORM_EXT +#define FILENAME_1_6_DARKM "sourcemod.2.darkm" PLATFORM_EXT HINSTANCE g_hCore = NULL; bool load_attempted = false; @@ -203,20 +204,25 @@ DLL_EXPORT METAMOD_PLUGIN *CreateInterface_MMS(const MetamodVersionInfo *mvi, co switch (mvi->source_engine) { + case SOURCE_ENGINE_ORIGINAL: + case SOURCE_ENGINE_EPISODEONE: + { + filename = FILENAME_1_6_EP1; + break; + } case SOURCE_ENGINE_ORANGEBOX: { filename = FILENAME_1_6_EP2; break; } - case SOURCE_ENGINE_EPISODEONE: - case SOURCE_ENGINE_ORIGINAL: - { - filename = FILENAME_1_6_EP1; - break; - } case SOURCE_ENGINE_LEFT4DEAD: { - filename = FILENAME_1_7_L4D; + filename = FILENAME_1_6_L4D; + break; + } + case SOURCE_ENGINE_DARKMESSIAH: + { + filename = FILENAME_1_6_DARKM; break; } default: diff --git a/plugins/basechat.sp b/plugins/basechat.sp index 25d01fe5..847ec942 100644 --- a/plugins/basechat.sp +++ b/plugins/basechat.sp @@ -53,9 +53,13 @@ new Handle:g_Cvar_Chatmode = INVALID_HANDLE; new bool:g_DoColor = true; +new g_GameEngine = SOURCE_SDK_UNKNOWN; + public OnPluginStart() { LoadTranslations("common.phrases"); + + g_GameEngine = GuessSDKVersion(); g_Cvar_Chatmode = CreateConVar("sm_chat_mode", "1", "Allows player's to send messages to admin chat.", 0, true, 0.0, true, 1.0); @@ -63,7 +67,13 @@ public OnPluginStart() RegConsoleCmd("say_team", Command_SayAdmin); RegAdminCmd("sm_say", Command_SmSay, ADMFLAG_CHAT, "sm_say - sends message to all players"); RegAdminCmd("sm_csay", Command_SmCsay, ADMFLAG_CHAT, "sm_csay - sends centered message to all players"); - RegAdminCmd("sm_hsay", Command_SmHsay, ADMFLAG_CHAT, "sm_hsay - sends hint message to all players"); + + /* HintText does not work on Dark Messiah */ + if (g_GameEngine != SOURCE_SDK_DARKMESSIAH) + { + RegAdminCmd("sm_hsay", Command_SmHsay, ADMFLAG_CHAT, "sm_hsay - sends hint message to all players"); + } + RegAdminCmd("sm_tsay", Command_SmTsay, ADMFLAG_CHAT, "sm_tsay [color] - sends top-left message to all players"); RegAdminCmd("sm_chat", Command_SmChat, ADMFLAG_CHAT, "sm_chat - sends message to admins"); RegAdminCmd("sm_psay", Command_SmPsay, ADMFLAG_CHAT, "sm_psay - sends private message"); diff --git a/plugins/funcommands.sp b/plugins/funcommands.sp index 7416bd8c..d98b996b 100644 --- a/plugins/funcommands.sp +++ b/plugins/funcommands.sp @@ -78,6 +78,8 @@ new UserMsg:g_FadeUserMsgId; // Serial Generator for Timer Safety new g_Serial_Gen = 0; +new g_GameEngine = SOURCE_SDK_UNKNOWN; + // Flags used in various timers #define DEFAULT_TIMER_FLAGS TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE @@ -100,6 +102,7 @@ public OnPluginStart() LoadTranslations("common.phrases"); LoadTranslations("funcommands.phrases"); + g_GameEngine = GuessSDKVersion(); g_FadeUserMsgId = GetUserMessageId("Fade"); RegisterCvars( ); diff --git a/plugins/funcommands/ice.sp b/plugins/funcommands/ice.sp index a39d9434..fd48871c 100644 --- a/plugins/funcommands/ice.sp +++ b/plugins/funcommands/ice.sp @@ -157,11 +157,29 @@ public Action:Timer_Freeze(Handle:timer, any:value) if (g_FreezeTime[client] == 0) { UnfreezeClient(client); - PrintHintText(client, "You are now unfrozen."); + + /* HintText doesn't work on Dark Messiah */ + if (g_GameEngine != SOURCE_SDK_DARKMESSIAH) + { + PrintHintText(client, "You are now unfrozen."); + } + else + { + PrintCenterText(client, "You are now unfrozen."); + } + return Plugin_Stop; } + + if (g_GameEngine != SOURCE_SDK_DARKMESSIAH) + { + PrintHintText(client, "You will be unfrozen in %d seconds.", g_FreezeTime[client]); + } + else + { + PrintCenterText(client, "You will be unfrozen in %d seconds.", g_FreezeTime[client]); + } - PrintHintText(client, "You will be unfrozen in %d seconds.", g_FreezeTime[client]); g_FreezeTime[client]--; SetEntityMoveType(client, MOVETYPE_NONE); SetEntityRenderColor(client, 0, 128, 255, 135); diff --git a/plugins/include/entity_prop_stocks.inc b/plugins/include/entity_prop_stocks.inc index 897d97ad..2e9d9811 100644 --- a/plugins/include/entity_prop_stocks.inc +++ b/plugins/include/entity_prop_stocks.inc @@ -170,9 +170,27 @@ enum RenderFx */ stock GetEntityFlags(entity) { - return GetEntProp(entity, Prop_Data, "m_fFlags"); + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_fFlags", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_fFlags"); + } + + gotconfig = true; + } + + return GetEntProp(entity, Prop_Data, datamap); } + /** * Gets an entity's movetype. * @@ -182,8 +200,24 @@ stock GetEntityFlags(entity) */ stock MoveType:GetEntityMoveType(entity) { - new offset = GetEntSendPropOffs(entity, "movetype"); - return MoveType:GetEntData(entity, offset, 1); + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_MoveType", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_MoveType"); + } + + gotconfig = true; + } + + return MoveType:GetEntProp(entity, Prop_Data, datamap); } /** @@ -196,8 +230,24 @@ stock MoveType:GetEntityMoveType(entity) */ stock SetEntityMoveType(entity, MoveType:mt) { - new offset = GetEntSendPropOffs(entity, "movetype"); - SetEntData(entity, offset, mt, 1, true); + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_MoveType", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_MoveType"); + } + + gotconfig = true; + } + + SetEntProp(entity, Prop_Data, datamap, mt); } /** @@ -209,7 +259,24 @@ stock SetEntityMoveType(entity, MoveType:mt) */ stock RenderMode:GetEntityRenderMode(entity) { - return RenderMode:GetEntProp(entity, Prop_Send, "m_nRenderMode", 1); + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderMode", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderMode"); + } + + gotconfig = true; + } + + return RenderMode:GetEntProp(entity, Prop_Send, prop, 1); } /** @@ -222,7 +289,24 @@ stock RenderMode:GetEntityRenderMode(entity) */ stock SetEntityRenderMode(entity, RenderMode:mode) { - SetEntProp(entity, Prop_Send, "m_nRenderMode", mode, 1); + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderMode", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderMode"); + } + + gotconfig = true; + } + + SetEntProp(entity, Prop_Send, prop, mode, 1); } /** @@ -234,7 +318,24 @@ stock SetEntityRenderMode(entity, RenderMode:mode) */ stock RenderFx:GetEntityRenderFx(entity) { - return RenderFx:GetEntProp(entity, Prop_Send, "m_nRenderFX", 1); + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderFX", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderFX"); + } + + gotconfig = true; + } + + return RenderFx:GetEntProp(entity, Prop_Send, prop, 1); } /** @@ -247,7 +348,24 @@ stock RenderFx:GetEntityRenderFx(entity) */ stock SetEntityRenderFx(entity, RenderFx:fx) { - SetEntProp(entity, Prop_Send, "m_nRenderFX", fx, 1); + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderFX", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderFX"); + } + + gotconfig = true; + } + + SetEntProp(entity, Prop_Send, prop, fx, 1); } /** @@ -263,15 +381,36 @@ stock SetEntityRenderFx(entity, RenderFx:fx) */ stock SetEntityRenderColor(entity, r=255, g=255, b=255, a=255) { - new offset = GetEntSendPropOffs(entity, "m_clrRender"); + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + new offset = GetEntSendPropOffs(entity, prop); + + if (offset <= 0) + { + ThrowError("SetEntityRenderColor not supported by this mod"); + } + SetEntData(entity, offset, r, 1, true); SetEntData(entity, offset + 1, g, 1, true); SetEntData(entity, offset + 2, b, 1, true); SetEntData(entity, offset + 3, a, 1, true); } -/* GuessSDKVersion */ - /** * Gets an entity's gravity. * @@ -281,7 +420,24 @@ stock SetEntityRenderColor(entity, r=255, g=255, b=255, a=255) */ stock Float:GetEntityGravity(entity) { - return GetEntPropFloat(entity, Prop_Data, "m_flGravity"); + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_flGravity", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_flGravity"); + } + + gotconfig = true; + } + + return GetEntPropFloat(entity, Prop_Data, datamap); } /** @@ -294,7 +450,24 @@ stock Float:GetEntityGravity(entity) */ stock SetEntityGravity(entity, Float:amount) { - SetEntPropFloat(entity, Prop_Data, "m_flGravity", amount); + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_flGravity", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_flGravity"); + } + + gotconfig = true; + } + + SetEntPropFloat(entity, Prop_Data, datamap, amount); } /** @@ -307,7 +480,50 @@ stock SetEntityGravity(entity, Float:amount) */ stock SetEntityHealth(entity, amount) { - SetEntProp(entity, Prop_Send, "m_iHealth", amount); + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_iHealth", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_iHeath"); + } + + gotconfig = true; + } + + decl String:cls[64]; + new PropFieldType:type; + new offset; + + if (!GetEntityNetClass(ent, cls, sizeof(cls))) + { + ThrowError("SetEntityHealth not supported by this mod: Could not get serverclass name"); + return; + } + + offset = FindSendPropInfo(cls, prop, type); + + if (offset <= 0) + { + ThrowError("SetEntityHealth not supported by this mod"); + return; + } + + /* Dark Messiah uses a float for the health instead an integer */ + if (type == PropField_Float) + { + SetEntDataFloat(entity, offset, float(amount)); + } + else + { + SetEntProp(entity, prop, amount); + } } /** @@ -320,5 +536,22 @@ stock SetEntityHealth(entity, amount) */ stock GetClientButtons(client) { - return GetEntProp(client, Prop_Data, "m_nButtons"); + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nButtons", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_nButtons"); + } + + gotconfig = true; + } + + return GetEntProp(client, Prop_Data, datamap); } diff --git a/plugins/include/halflife.inc b/plugins/include/halflife.inc index 24e9b89c..1d59a188 100644 --- a/plugins/include/halflife.inc +++ b/plugins/include/halflife.inc @@ -37,6 +37,7 @@ #define SOURCE_SDK_UNKNOWN 0 /**< Could not determine the engine version */ #define SOURCE_SDK_ORIGINAL 10 /**< Original Source engine (still used by "The Ship") */ +#define SOURCE_SDK_DARKMESSIAH 15 /**< Modified version of original engine used by Dark Messiah (no SDK) */ #define SOURCE_SDK_EPISODE1 20 /**< SDK+Engine released after Episode 1 */ #define SOURCE_SDK_EPISODE2 30 /**< SDK+Engine released after Episode 2/Orange Box */ #define SOURCE_SDK_LEFT4DEAD 40 /**< Engine released after Left 4 Dead (no SDK yet) */ diff --git a/tools/builder/ABuilder.cs b/tools/builder/ABuilder.cs index 4796f89d..dd2a34fa 100644 --- a/tools/builder/ABuilder.cs +++ b/tools/builder/ABuilder.cs @@ -175,6 +175,10 @@ namespace builder { continue; } + if ((libs[i].platform & cfg.Platform) != cfg.Platform) + { + continue; + } if (!BuildLibrary(pkg, libs[i])) { throw new System.Exception("Failed to compile library: " + libs[i].binary_name); diff --git a/tools/builder/Config.cs b/tools/builder/Config.cs index 3deb61fe..d5096219 100644 --- a/tools/builder/Config.cs +++ b/tools/builder/Config.cs @@ -4,6 +4,7 @@ using System.Text; namespace builder { + [Flags] public enum BasePlatform { Platform_Windows, diff --git a/tools/builder/Package.cs b/tools/builder/Package.cs index cb69bcb1..852a3bf5 100644 --- a/tools/builder/Package.cs +++ b/tools/builder/Package.cs @@ -12,6 +12,7 @@ namespace builder { BuildMode_Simple, BuildMode_OldMetamod, + BuildMode_DarkMessiah, BuildMode_Episode1, BuildMode_Episode2, BuildMode_Left4Dead @@ -25,15 +26,17 @@ namespace builder is_executable = false; release_mode = ReleaseMode.ReleaseMode_Release; build_mode = BuildMode.BuildMode_Simple; + platform = BasePlatform.Platform_Linux | BasePlatform.Platform_Windows; } - public string binary_name; /* Name of binary */ - public string source_path; /* Local path to library build scripts */ - public ReleaseMode release_mode; /* Release mode */ - public BuildMode build_mode; /* Build mode */ - public string package_path; /* Final relative path */ - public bool has_platform_ext; /* Add extra platform extension? */ - public string vcproj_name; /* Project file, NULL for standard */ - public bool is_executable; /* If this is an EXE instead of a DLL */ + public string binary_name; /* Name of binary */ + public string source_path; /* Local path to library build scripts */ + public ReleaseMode release_mode; /* Release mode */ + public BuildMode build_mode; /* Build mode */ + public string package_path; /* Final relative path */ + public bool has_platform_ext; /* Add extra platform extension? */ + public string vcproj_name; /* Project file, NULL for standard */ + public bool is_executable; /* If this is an EXE instead of a DLL */ + public BasePlatform platform; /* Platforms for which the binary should be built */ }; public class Plugin diff --git a/tools/builder/PkgCore.cs b/tools/builder/PkgCore.cs index 0301d0ff..99207a54 100644 --- a/tools/builder/PkgCore.cs +++ b/tools/builder/PkgCore.cs @@ -66,6 +66,7 @@ namespace builder folders.Add("addons/sourcemod/scripting/basebans"); folders.Add("addons/sourcemod/scripting/funcommands"); folders.Add("addons/sourcemod/extensions/auto.1.ep1"); + folders.Add("addons/sourcemod/extensions/auto.2.darkm"); //folders.Add("addons/sourcemod/extensions/auto.2.ep1"); folders.Add("addons/sourcemod/extensions/auto.2.ep2"); folders.Add("addons/sourcemod/extensions/auto.2.l4d"); @@ -159,6 +160,15 @@ namespace builder lib.build_mode = BuildMode.BuildMode_OldMetamod; libraries.Add(lib); + lib = new Library(); + lib.package_path = "addons/sourcemod/bin"; + lib.source_path = "core"; + lib.binary_name = "sourcemod.2.darkm"; + lib.vcproj_name = "sourcemod_mm"; + lib.build_mode = BuildMode.BuildMode_DarkMessiah; + lib.platform = BasePlatform.Platform_Windows; + libraries.Add(lib); + lib = new Library(); lib.package_path = "addons/sourcemod/bin"; lib.source_path = "core"; @@ -204,6 +214,15 @@ namespace builder lib.build_mode = BuildMode.BuildMode_OldMetamod; libraries.Add(lib); + lib = new Library(); + lib.package_path = "addons/sourcemod/extensions/auto.2.darkm"; + lib.source_path = "extensions/bintools"; + lib.binary_name = "bintools.ext"; + lib.vcproj_name = "bintools"; + lib.build_mode = BuildMode.BuildMode_DarkMessiah; + lib.platform = BasePlatform.Platform_Windows; + libraries.Add(lib); + lib = new Library(); lib.package_path = "addons/sourcemod/extensions/auto.2.ep2"; lib.source_path = "extensions/bintools"; @@ -235,6 +254,15 @@ namespace builder lib.build_mode = BuildMode.BuildMode_OldMetamod; libraries.Add(lib); + lib = new Library(); + lib.package_path = "addons/sourcemod/extensions/auto.2.darkm"; + lib.source_path = "extensions/sdktools"; + lib.binary_name = "sdktools.ext"; + lib.vcproj_name = "sdktools"; + lib.build_mode = BuildMode.BuildMode_DarkMessiah; + lib.platform = BasePlatform.Platform_Windows; + libraries.Add(lib); + lib = new Library(); lib.package_path = "addons/sourcemod/extensions/auto.2.ep2"; lib.source_path = "extensions/sdktools"; diff --git a/tools/builder/Win32Builder.cs b/tools/builder/Win32Builder.cs index 762bb8ba..fc83fb44 100644 --- a/tools/builder/Win32Builder.cs +++ b/tools/builder/Win32Builder.cs @@ -38,6 +38,10 @@ namespace builder config_name = "Debug"; } + if (lib.build_mode == BuildMode.BuildMode_DarkMessiah) + { + config_name = config_name + " - Dark Messiah"; + } if (lib.build_mode == BuildMode.BuildMode_Episode1) { config_name = config_name + " - Episode 1";