diff --git a/hook_lib/Main.cpp b/hook_lib/Main.cpp index bade3a0..26bcab1 100644 --- a/hook_lib/Main.cpp +++ b/hook_lib/Main.cpp @@ -2,6 +2,7 @@ #include "game_inc.h" #include "debug_output.h" +#include "discord.h" #include "addr_utils.hpp" void entry_point() @@ -30,6 +31,8 @@ void entry_point() extern "C" __declspec(dllexport) int DiscordCreate() { CreateThread(0, 0xA0, (LPTHREAD_START_ROUTINE)entry_point, 0, 0, 0); + + CreateThread(0, 0, (LPTHREAD_START_ROUTINE)DiscordThread, 0, 0, 0); return 1; } diff --git a/hook_lib/discord.cpp b/hook_lib/discord.cpp new file mode 100644 index 0000000..e4ff640 --- /dev/null +++ b/hook_lib/discord.cpp @@ -0,0 +1,102 @@ +#include "discord.h" +#include "discord_rpc.h" + +#include "Main.hpp" + +#include "addr_utils.hpp" + +struct DiscordInfo { + const char* mapName; + const char* gameType; + int partySize; + int partyMax; + const char* largeImageKey; + const char* smallImageKey; +}; + +bool discordInitalized; + +void DiscordInitialize() { + DiscordEventHandlers handlers; + memset(&handlers, 0, sizeof(handlers)); + Discord_Initialize("1183441008168534016", &handlers, 1, NULL); + discordInitalized = true; +} + +__int64 startTime; +void Discord_UpdateStatus_Internal(DiscordInfo info) { + DiscordRichPresence discordPresence; + memset(&discordPresence, 0, sizeof(discordPresence)); + discordPresence.details = info.mapName; + discordPresence.state = info.gameType; + discordPresence.partySize = info.partySize; + discordPresence.partyMax = info.partyMax; + discordPresence.startTimestamp = startTime; + //discordPresence.endTimestamp = 1507665886; + discordPresence.largeImageKey = info.largeImageKey; + discordPresence.largeImageText = info.mapName; + discordPresence.smallImageKey = info.smallImageKey; + discordPresence.smallImageText = info.gameType; + /*discordPresence.partyId = ""; + discordPresence.joinSecret = "";*/ + Discord_UpdatePresence(&discordPresence); +} + +void DiscordUpdate() { + if (discordInitalized) { + DiscordInfo info; + bool inFrontend = *(bool*)(0x1459D1750_g); + const char* dvarMap = Dvar_GetStringSafe("ui_mapname"); + const char* dvarMode = Dvar_GetStringSafe("ui_gametype"); + const char* mapName = GetMapName(dvarMap); + if (inFrontend) { + startTime = std::time(0); + int partySize = *(int*)(0x14C7B0958_g); + info.mapName = "In Menus"; + info.gameType = "Waiting"; + info.partySize = partySize; + info.partyMax = Dvar_GetIntSafe("party_maxplayers"); + info.largeImageKey = "mw"; + info.smallImageKey = ""; + } + else { + startTime = std::time(0); + int partySize = *(int*)(0x14C7B0958_g); + info.mapName = mapName; + info.gameType = GetGametypeName(dvarMode); + info.partySize = partySize; + info.partyMax = Dvar_GetIntSafe("party_maxplayers"); + info.largeImageKey = dvarMap; + info.smallImageKey = dvarMode; + } + Discord_UpdateStatus_Internal(info); + printf("Discord Status Updated\n"); + } +} + +void DiscordThread() +{ + puts("Initializing Discord Presence."); + DiscordInitialize(); + + if (discordInitalized == false) + { + puts("Initializing Discord Presence failed."); + } + else + { + DiscordUpdate(); + } + + while (discordInitalized) + { + bool inFrontend = *(bool*)(0x1459D1750_g); + + Sleep(5000); + + if (inFrontend != *(bool*)(0x1459D1750_g)) + { + DiscordUpdate(); + } + } +} \ No newline at end of file diff --git a/hook_lib/discord.h b/hook_lib/discord.h new file mode 100644 index 0000000..a4f1cb9 --- /dev/null +++ b/hook_lib/discord.h @@ -0,0 +1,5 @@ +#pragma once + +#pragma comment(lib, "discord-rpc.lib") + +void DiscordThread(); \ No newline at end of file diff --git a/hook_lib/discord_rpc.h b/hook_lib/discord_rpc.h new file mode 100644 index 0000000..1992929 --- /dev/null +++ b/hook_lib/discord_rpc.h @@ -0,0 +1,87 @@ +#pragma once +#include + +// clang-format off + +#if defined(DISCORD_DYNAMIC_LIB) +# if defined(_WIN32) +# if defined(DISCORD_BUILDING_SDK) +# define DISCORD_EXPORT __declspec(dllexport) +# else +# define DISCORD_EXPORT __declspec(dllimport) +# endif +# else +# define DISCORD_EXPORT __attribute__((visibility("default"))) +# endif +#else +# define DISCORD_EXPORT +#endif + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct DiscordRichPresence { + const char* state; /* max 128 bytes */ + const char* details; /* max 128 bytes */ + int64_t startTimestamp; + int64_t endTimestamp; + const char* largeImageKey; /* max 32 bytes */ + const char* largeImageText; /* max 128 bytes */ + const char* smallImageKey; /* max 32 bytes */ + const char* smallImageText; /* max 128 bytes */ + const char* partyId; /* max 128 bytes */ + int partySize; + int partyMax; + const char* matchSecret; /* max 128 bytes */ + const char* joinSecret; /* max 128 bytes */ + const char* spectateSecret; /* max 128 bytes */ + int8_t instance; + } DiscordRichPresence; + + typedef struct DiscordUser { + const char* userId; + const char* username; + const char* discriminator; + const char* avatar; + } DiscordUser; + + typedef struct DiscordEventHandlers { + void (*ready)(const DiscordUser* request); + void (*disconnected)(int errorCode, const char* message); + void (*errored)(int errorCode, const char* message); + void (*joinGame)(const char* joinSecret); + void (*spectateGame)(const char* spectateSecret); + void (*joinRequest)(const DiscordUser* request); + } DiscordEventHandlers; + +#define DISCORD_REPLY_NO 0 +#define DISCORD_REPLY_YES 1 +#define DISCORD_REPLY_IGNORE 2 + + DISCORD_EXPORT void Discord_Initialize(const char* applicationId, + DiscordEventHandlers* handlers, + int autoRegister, + const char* optionalSteamId); + DISCORD_EXPORT void Discord_Shutdown(void); + + /* checks for incoming messages, dispatches callbacks */ + DISCORD_EXPORT void Discord_RunCallbacks(void); + + /* If you disable the lib starting its own io thread, you'll need to call this from your own */ +#ifdef DISCORD_DISABLE_IO_THREAD + DISCORD_EXPORT void Discord_UpdateConnection(void); +#endif + + DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence); + DISCORD_EXPORT void Discord_ClearPresence(void); + + DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply); + + DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/hook_lib/functions.cpp b/hook_lib/functions.cpp index 28ef946..c1da09c 100644 --- a/hook_lib/functions.cpp +++ b/hook_lib/functions.cpp @@ -499,7 +499,7 @@ uintptr_t G_GetEntityPlayerState(gentity_s* ent) int G_Main_GetTime() { - return *(int*)0x14BC21730; + return *(int*)0x14BC21730_g; } const char* _va(const char* format, ...) @@ -513,6 +513,34 @@ const char* _va(const char* format, ...) return _buf; } +const char* SEH_StringEd_GetString(const char* string) { + auto func = reinterpret_cast (0x1413CC2A0_g); + return func(string); +} + +mapInfo* Com_GameInfo_GetMapInfoForLoadName(const char* mapName) { + auto func = reinterpret_cast(0x1410C77F0_g); + return func(mapName); +} + +const char* GetMapName(const char* mapName) { + mapInfo* mapinfo = Com_GameInfo_GetMapInfoForLoadName(mapName); + if (!mapinfo) return "Unknown Map"; + if (mapinfo->mapName[0] == 31) return "error"; + return SEH_StringEd_GetString(mapinfo->mapName); +} + +gameTypeInfo* Com_GameInfo_GetGameTypeForInternalName(const char* mapName) { + auto func = reinterpret_cast(0x1410C7580_g); + return func(mapName); +} +const char* GetGametypeName(const char* gameType) { + gameTypeInfo* gametypeinfo = Com_GameInfo_GetGameTypeForInternalName(gameType); + if (!gametypeinfo) return "Unknown Mode"; + if (gametypeinfo->gameTypeName[0] == 31) return "error"; + return SEH_StringEd_GetString(gametypeinfo->gameTypeName); +} + #pragma endregion dvar_t* player_name; diff --git a/hook_lib/functions.hpp b/hook_lib/functions.hpp index 9fe12c5..e664c17 100644 --- a/hook_lib/functions.hpp +++ b/hook_lib/functions.hpp @@ -102,6 +102,8 @@ struct DBFile struct Weapon; struct scrContext_t; +struct mapInfo; +struct gameTypeInfo; extern dvar_t* player_name; extern dvar_t* sv_cheats; @@ -253,4 +255,14 @@ int G_Main_GetTime(); const char* _va(const char* format, ...); +const char* SEH_StringEd_GetString(const char* string); + +mapInfo* Com_GameInfo_GetMapInfoForLoadName(const char* mapName); + +const char* GetMapName(const char* mapName); + +gameTypeInfo* Com_GameInfo_GetGameTypeForInternalName(const char* mapName); + +const char* GetGametypeName(const char* gameType); + #pragma endregion diff --git a/hook_lib/hook_lib.vcxproj b/hook_lib/hook_lib.vcxproj index 0f7fc88..8b90d17 100644 --- a/hook_lib/hook_lib.vcxproj +++ b/hook_lib/hook_lib.vcxproj @@ -167,6 +167,7 @@ + @@ -212,6 +213,8 @@ + + diff --git a/hook_lib/hook_lib.vcxproj.filters b/hook_lib/hook_lib.vcxproj.filters index 99614d2..2dd9356 100644 --- a/hook_lib/hook_lib.vcxproj.filters +++ b/hook_lib/hook_lib.vcxproj.filters @@ -20,6 +20,9 @@ {0999b80b-b47c-4d8e-8776-f5c778bcac9f} + + {8d71ea0c-2bb4-42e8-9e46-36f0aa487cbf} + @@ -142,6 +145,9 @@ hook_lib\game + + hook_lib\discord + @@ -282,5 +288,11 @@ hook_lib\game + + hook_lib\discord + + + hook_lib\discord + \ No newline at end of file diff --git a/hook_lib/party.cpp b/hook_lib/party.cpp index 090911d..4f81ed2 100644 --- a/hook_lib/party.cpp +++ b/hook_lib/party.cpp @@ -10,5 +10,6 @@ void PartyHost_StartPrivateParty_Detour(int localClientNum, int localControllerI { Cbuf_AddText("exec autoexec.cfg"); LoadInventory(); + autoexec = true; } } \ No newline at end of file diff --git a/hook_lib/patch.cpp b/hook_lib/patch.cpp index b227920..41e2d6a 100644 --- a/hook_lib/patch.cpp +++ b/hook_lib/patch.cpp @@ -158,6 +158,7 @@ void hooks() // remove FF Header version check // db_checkxfileversion.create(0x1411A7840_g, DB_CheckXFileVersion_Detour); + // utils::hook::jump(0x1411A7840_g, DB_CheckXFileVersion_Detour); } void patchGame() @@ -203,6 +204,9 @@ void patchGame() // enable functionality for jump_height dvar utils::hook::set(0x141101946_g, 0xEB); + // enable friction dvar + utils::hook::set(0x14112141E_g, (int8_t)2); + // remove FF Header version check // utils::hook::set(0x1411A776B_g, 0xEB); } \ No newline at end of file diff --git a/hook_lib/script.cpp b/hook_lib/script.cpp index afd649c..434a827 100644 --- a/hook_lib/script.cpp +++ b/hook_lib/script.cpp @@ -4,7 +4,6 @@ void ProcessScriptFile(void* scrContext, ScriptFile* scriptfile) { - if (scriptfile) { printf("loading gsc: %s\n", scriptfile->name); @@ -24,9 +23,9 @@ void ProcessScriptFile(void* scrContext, ScriptFile* scriptfile) return; } - auto Load_scriptFileAsset = reinterpret_cast(0x140F134D0_g); + auto Load_ScriptFileAsset = reinterpret_cast(0x140F134D0_g); - char* allocMemAddress = (char*)Load_scriptFileAsset(size, 4, 0, 0, nullptr); + char* allocMemAddress = (char*)Load_ScriptFileAsset(size, 4, 0, 0, nullptr); script.read(allocMemAddress, size); script.seekg(0, std::ios::beg); diff --git a/hook_lib/structs.h b/hook_lib/structs.h index effb879..92a99c3 100644 --- a/hook_lib/structs.h +++ b/hook_lib/structs.h @@ -2086,6 +2086,27 @@ struct __declspec(align(8)) OmnvarDef byte userType[1]; }; +struct gameTypeInfo +{ + char gameTypeInternalName[12]; + char gameTypeName[32]; + char customizedGameTypeName[64]; + char customizedGameTypeDesc[64]; +}; + +struct mapInfo +{ + char mapName[32]; + char mapLoadName[16]; + char mapDescription[32]; + char mapLoadImage[32]; + char mapVoteImage[32]; + char mapCamoTypes[2][16]; + char mapDefaultGameType[32]; + char mapGameTypes[1024]; + int isAliensMap; + int mapPack; +}; struct scrContext_t :class_helper { diff --git a/lib/discord-rpc.lib b/lib/discord-rpc.lib new file mode 100644 index 0000000..1f3e825 Binary files /dev/null and b/lib/discord-rpc.lib differ