diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index 4573b4fd..3b6c7dff 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
@@ -16,7 +16,7 @@
-
+
@@ -27,7 +27,7 @@
-
+
@@ -38,7 +38,7 @@
-
+
diff --git a/TODO b/TODO
index 6e1921f0..9075f1e7 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,13 @@
+MULTIPLATFORM:
+
+Signature Scanner
+Whole IPC thing | actually, no. cathook for windows WON'T have followbots/ipc.
+Signatures and offsets
+File handling (playerlist, spam, etc...)
+CMake?
+
+------------====-----------
+
alias clearcond "host_timescale 300;wait 500;host_timescale 1"
alias clearcond_taunt "taunt;wait 50;host_timescale 300;wait 500;host_timescale 1"
bind l clearcond_taunt
diff --git a/src/chatstack.cpp b/src/chatstack.cpp
index 689e3bac..b73bab20 100644
--- a/src/chatstack.cpp
+++ b/src/chatstack.cpp
@@ -11,15 +11,23 @@
namespace chat_stack {
+
+void Say(const std::string& message, bool team) {
+ stack.push({ message, team });
+}
+
void OnCreateMove() {
if (last_say > g_GlobalVars->curtime) last_say = 0;
if (g_GlobalVars->curtime - last_say <= CHATSTACK_INTERVAL) return;
- std::string message;
if (!stack.empty()) {
- message = stack.top();
+ const msg_t& msg = stack.top();
stack.pop();
- if (message.size()) {
- g_IEngine->ServerCmd(format("say \"", message, '"').c_str());
+ if (msg.text.size()) {
+ //logging::Info("Saying %s %i", msg.text.c_str(), msg.text.size());
+ if (msg.team)
+ g_IEngine->ServerCmd(format("say_team \"", msg.text.c_str(), '"').c_str());
+ else
+ g_IEngine->ServerCmd(format("say \"", msg.text.c_str(), '"').c_str());
last_say = g_GlobalVars->curtime;
}
}
@@ -30,7 +38,7 @@ void Reset() {
last_say = 0.0f;
}
-std::stack stack;
+std::stack stack;
float last_say = 0.0f;
}
diff --git a/src/chatstack.h b/src/chatstack.h
index 10c68de4..4026a9fd 100644
--- a/src/chatstack.h
+++ b/src/chatstack.h
@@ -18,10 +18,16 @@
namespace chat_stack {
+struct msg_t {
+ std::string text;
+ bool team;
+};
+
+void Say(const std::string& message, bool team = false);
void OnCreateMove();
void Reset();
-extern std::stack stack;
+extern std::stack stack;
extern float last_say;
};
diff --git a/src/common.h b/src/common.h
index fdd0772d..9a405a95 100644
--- a/src/common.h
+++ b/src/common.h
@@ -10,6 +10,14 @@
#include
+
+#ifdef LINUX
+#define IPC_ENABLED 1
+#else
+#undef IPC_ENABLED
+#endif
+
+
#include "beforecheaders.h"
#include
#include
@@ -27,6 +35,7 @@
#include
#include
#include "aftercheaders.h"
+#include "offsets.hpp"
#include "drawing.h"
#include "resource.hpp"
#include "entitycache.h"
@@ -131,7 +140,6 @@ constexpr T _clamp(T _min, T _max, T _val) {
#endif
#define GET_RENDER_CONTEXT (TF2 ? g_IMaterialSystem->GetRenderContext() : g_IMaterialSystemHL->GetRenderContext())
-
/*#define ADD_HACK(x) \
hack::AddHack(g_ph##x = new x());
diff --git a/src/gui/ncc/Menu.cpp b/src/gui/ncc/Menu.cpp
index 520d1bff..c8dde06b 100644
--- a/src/gui/ncc/Menu.cpp
+++ b/src/gui/ncc/Menu.cpp
@@ -536,6 +536,7 @@ static const std::string list_tf2 = R"(
"uberspam_ready"
"uberspam_used"
"uberspam_ended"
+ "uberspam_team"
]
"Follow Bot" [
diff --git a/src/hack.cpp b/src/hack.cpp
index 1432a221..f36d2423 100644
--- a/src/hack.cpp
+++ b/src/hack.cpp
@@ -127,49 +127,39 @@ void hack::Initialize() {
InitNetVars();
g_pLocalPlayer = new LocalPlayer();
g_pPlayerResource = new TFPlayerResource();
- hooks::hkPanel = new hooks::VMTHook();
- hooks::hkPanel->Init(g_IPanel, 0);
- //hooks::hkPanel->HookMethod((void*)&hack::Hk_PaintTraverse, hooks::offPaintTraverse);
- hooks::hkPanel->HookMethod((void*)PaintTraverse_hook, hooks::offPaintTraverse);
- hooks::hkPanel->Apply();
- hooks::hkClientMode = new hooks::VMTHook();
+
+ /*
+ * TIME FOR HOOKING! wow
+ */
+ hooks::panel.Set(g_IPanel);
+ hooks::panel.HookMethod((void*)PaintTraverse_hook, offsets::PaintTraverse());
+ hooks::panel.Apply();
uintptr_t* clientMode = 0;
+ // Bad way to get clientmode.
+ // FIXME [MP]?
while(!(clientMode = **(uintptr_t***)((uintptr_t)((*(void***)g_IBaseClient)[10]) + 1))) {
sleep(1);
}
- //hooks::hkMatSurface = new hooks::VMTHook();
- //hooks::hkMatSurface->Init((void*)matsurface, 0);
- //hooks::hkMatSurface->HookMethod((void*)test_handleevent, 1);
- hooks::hkClientMode->Init((void*)clientMode, 0);
- //hooks::hkClientMode->HookMethod((void*)&hack::Hk_CreateMove, hooks::offCreateMove);
- hooks::hkClientMode->HookMethod((void*)CreateMove_hook, hooks::offCreateMove);
- hooks::hkClientMode->HookMethod((void*)OverrideView_hook, hooks::offOverrideView);
- hooks::hkClientMode->HookMethod((void*)LevelInit_hook, hooks::offLevelInit);
- hooks::hkClientMode->HookMethod((void*)LevelShutdown_hook, hooks::offLevelShutdown);
- hooks::hkClientMode->Apply();
- hooks::hkStudioRender = new hooks::VMTHook();
- hooks::hkStudioRender->Init((void*)g_IStudioRender, 0);
- hooks::hkStudioRender->HookMethod((void*)BeginFrame_hook, hooks::offBeginFrame);
- hooks::hkStudioRender->Apply();
- hooks::hkClient = new hooks::VMTHook();
- hooks::hkClient->Init((void*)g_IBaseClient, 0);
- hooks::hkClient->HookMethod((void*)FrameStageNotify_hook, hooks::offFrameStageNotify);
- hooks::hkClient->HookMethod((void*)DispatchUserMessage_hook, hooks::offFrameStageNotify + 1);
- hooks::hkClient->HookMethod((void*)IN_KeyEvent_hook, hooks::offKeyEvent);
- hooks::hkClient->Apply();
- hooks::hkInput = new hooks::VMTHook();
- hooks::hkInput->Init((void*)g_IInput, 0);
- hooks::hkInput->HookMethod((void*)GetUserCmd_hook, hooks::offGetUserCmd);
- hooks::hkInput->Apply();
- //logging::Info("Before hacking: %s", g_ISteamFriends->GetPersonaName());
- hooks::hkIVModelRender = new hooks::VMTHook();
- hooks::hkIVModelRender->Init(g_IVModelRender, 0);
- hooks::hkIVModelRender->HookMethod((void*)DrawModelExecute_hook, hooks::offDrawModelExecute);
- hooks::hkIVModelRender->Apply();
- hooks::hkSteamFriends = new hooks::VMTHook();
- hooks::hkSteamFriends->Init(g_ISteamFriends, 0);
- hooks::hkSteamFriends->HookMethod((void*)GetFriendPersonaName_hook, hooks::offGetFriendPersonaName);
- hooks::hkSteamFriends->Apply();
+ hooks::clientmode.Set((void*)clientMode);
+ hooks::clientmode.HookMethod((void*)CreateMove_hook, offsets::CreateMove());
+ hooks::clientmode.HookMethod((void*)OverrideView_hook, offsets::OverrideView());
+ hooks::clientmode.HookMethod((void*)LevelInit_hook, offsets::LevelInit());
+ hooks::clientmode.HookMethod((void*)LevelShutdown_hook, offsets::LevelShutdown());
+ hooks::clientmode.Apply();
+ hooks::client.Set(g_IBaseClient);
+ hooks::client.HookMethod((void*)FrameStageNotify_hook, offsets::FrameStageNotify());
+ hooks::client.HookMethod((void*)DispatchUserMessage_hook, offsets::DispatchUserMessage());
+ hooks::client.HookMethod((void*)IN_KeyEvent_hook, offsets::IN_KeyEvent());
+ hooks::client.Apply();
+ hooks::input.Set(g_IInput);
+ hooks::input.HookMethod((void*)GetUserCmd_hook, offsets::GetUserCmd());
+ hooks::input.Apply();
+ hooks::modelrender.Set(g_IVModelRender);
+ hooks::modelrender.HookMethod((void*)DrawModelExecute_hook, offsets::DrawModelExecute());
+ hooks::modelrender.Apply();
+ hooks::steamfriends.Set(g_ISteamFriends);
+ hooks::steamfriends.HookMethod((void*)GetFriendPersonaName_hook, offsets::GetFriendPersonaName());
+ hooks::steamfriends.Apply();
//logging::Info("After hacking: %s", g_ISteamFriends->GetPersonaName());
// Sadly, it doesn't work as expected :(
/*hooks::hkBaseClientState = new hooks::VMTHook();
@@ -181,6 +171,8 @@ void hack::Initialize() {
//hooks::hkBaseClientState8->HookMethod((void*)ProcessSetConVar_hook, hooks::offProcessSetConVar);
//hooks::hkBaseClientState8->HookMethod((void*)ProcessGetCvarValue_hook, hooks::offProcessGetCvarValue);
//hooks::hkBaseClientState8->Apply();
+
+ // FIXME [MP]
if (TF2) g_GlowObjectManager = *reinterpret_cast(gSignatures.GetClientSignature("C1 E0 05 03 05") + 5);
InitStrings();
hacks::shared::killsay::Init();
@@ -211,18 +203,6 @@ void hack::Shutdown() {
if (hack::shutdown) return;
hack::shutdown = true;
playerlist::Save();
- logging::Info("Killing hooks..");
- if (hooks::hkPanel) hooks::hkPanel->Kill();
- if (hooks::hkClientMode) hooks::hkClientMode->Kill();
- if (hooks::hkClient) hooks::hkClient->Kill();
- if (hooks::hkMatSurface) hooks::hkMatSurface->Kill();
- if (hooks::hkNetChannel) hooks::hkNetChannel->Kill();
- if (hooks::hkStudioRender) hooks::hkStudioRender->Kill();
- if (hooks::hkInput) hooks::hkInput->Kill();
- if (hooks::hkIVModelRender) hooks::hkIVModelRender->Kill();
- if (hooks::hkBaseClientState) hooks::hkBaseClientState->Kill();
- if (hooks::hkBaseClientState8) hooks::hkBaseClientState8->Kill();
- //if (hooks::hkCTFPlayer) hooks::hkCTFPlayer->Kill();
logging::Info("Unregistering convars..");
ConVar_Unregister();
logging::Info("Shutting down killsay...");
diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp
index aac0f9f0..9120bd00 100644
--- a/src/hacks/Aimbot.cpp
+++ b/src/hacks/Aimbot.cpp
@@ -517,11 +517,15 @@ bool ShouldAim(CUserCmd* cmd) {
if (!HasCondition(g_pLocalPlayer->entity, TFCond_Slowed)) {
return false;
}
+ // syntax gymnastics
+#ifdef IPC_ENABLED
if (hacks::shared::followbot::bot) {
CachedEntity* player = ENTITY(hacks::shared::followbot::following_idx);
if (CE_BAD(player)) return false;
if (!HasCondition(player, TFCond_Slowed)) return false;
- } else {
+ } else
+#endif
+ {
if (!(cmd->buttons & IN_ATTACK2)) {
return false;
}
diff --git a/src/hacks/AutoHeal.cpp b/src/hacks/AutoHeal.cpp
index 0da9d00c..57ba0a52 100644
--- a/src/hacks/AutoHeal.cpp
+++ b/src/hacks/AutoHeal.cpp
@@ -388,11 +388,13 @@ int HealingPriority(int idx) {
priority += 50 * (1 - healthp);
priority += 10 * (1 - overhealp);
}
+#ifdef IPC_ENABLED
if (ipc::peer) {
if (hacks::shared::followbot::bot && hacks::shared::followbot::following_idx == idx) {
priority *= 3.0f;
}
}
+#endif
return priority;
}
diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp
index 47fb43fa..05a6f442 100644
--- a/src/hacks/ESP.cpp
+++ b/src/hacks/ESP.cpp
@@ -418,6 +418,7 @@ void ProcessEntity(CachedEntity* ent) {
if (pclass > 0 && pclass < 10)
AddEntityString(ent, classes[pclass - 1]);
}
+#ifdef IPC_ENABLED
if (show_bot_id && ipc::peer && ent != LOCAL_E) {
for (unsigned i = 1; i < cat_ipc::max_peers; i++) {
if (!ipc::peer->memory->peer_data[i].free && ipc::peer->memory->peer_user_data[i].friendid == info.friendsID) {
@@ -426,6 +427,7 @@ void ProcessEntity(CachedEntity* ent) {
}
}
}
+#endif
if (show_health) {
AddEntityString(ent, format(ent->m_iHealth, '/', ent->m_iMaxHealth, " HP"), colors::Health(ent->m_iHealth, ent->m_iMaxHealth));
}
diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp
index 524b11f5..1a6828d9 100644
--- a/src/hacks/FollowBot.cpp
+++ b/src/hacks/FollowBot.cpp
@@ -5,10 +5,13 @@
* Author: nullifiedcat
*/
+
#include "FollowBot.h"
#include "../common.h"
+#ifdef IPC_ENABLED
+
namespace hacks { namespace shared { namespace followbot {
unsigned follow_steamid { 0 };
@@ -509,3 +512,5 @@ void DoWalking() {
}
}}}
+
+#endif
diff --git a/src/hacks/FollowBot.h b/src/hacks/FollowBot.h
index bf06cccb..a97cdfd8 100644
--- a/src/hacks/FollowBot.h
+++ b/src/hacks/FollowBot.h
@@ -5,6 +5,8 @@
* Author: nullifiedcat
*/
+#ifdef IPC_ENABLED
+
#ifndef HACKS_FOLLOWBOT_H_
#define HACKS_FOLLOWBOT_H_
@@ -33,3 +35,5 @@ void AfterCreateMove();
}}}
#endif /* HACKS_FOLLOWBOT_H_ */
+
+#endif
diff --git a/src/hacks/KillSay.cpp b/src/hacks/KillSay.cpp
index c2c147dd..71cb0397 100644
--- a/src/hacks/KillSay.cpp
+++ b/src/hacks/KillSay.cpp
@@ -130,6 +130,6 @@ void KillSayEventListener::FireGameEvent(IGameEvent* event) {
if (!hacks::shared::killsay::killsay_mode) return;
std::string message = hacks::shared::killsay::ComposeKillSay(event);
if (message.size()) {
- chat_stack::stack.push(message);
+ chat_stack::Say(message);
}
}
diff --git a/src/hacks/Misc.cpp b/src/hacks/Misc.cpp
index 3a33c915..ecde5b93 100644
--- a/src/hacks/Misc.cpp
+++ b/src/hacks/Misc.cpp
@@ -112,16 +112,15 @@ static int last_number = 0;
void CreateMove() {
static bool flswitch = false;
-
- // TODO FIXME HOOKING WITHOUT UNHOOKING = 100% SEGV ON UNINJECT.
+ // TODO FIXME this should be moved out of here
IClientEntity* localplayer = g_IEntityList->GetClientEntity(g_IEngine->GetLocalPlayer());
if (TF && render_zoomed && localplayer) {
void** vtable = *(void***)(localplayer);
- if (vtable[hooks::offShouldDraw] != C_TFPlayer__ShouldDraw_hook) {
- C_TFPlayer__ShouldDraw_original = vtable[hooks::offShouldDraw];
+ if (vtable[offsets::ShouldDraw()] != C_TFPlayer__ShouldDraw_hook) {
+ C_TFPlayer__ShouldDraw_original = vtable[offsets::ShouldDraw()];
void* page = (void*)((uintptr_t)vtable &~ 0xFFF);
mprotect(page, 0xFFF, PROT_READ | PROT_WRITE | PROT_EXEC);
- vtable[hooks::offShouldDraw] = (void*)C_TFPlayer__ShouldDraw_hook;
+ vtable[offsets::ShouldDraw()] = (void*)C_TFPlayer__ShouldDraw_hook;
mprotect(page, 0xFFF, PROT_READ | PROT_EXEC);
}
}
diff --git a/src/hacks/SkinChanger.cpp b/src/hacks/SkinChanger.cpp
new file mode 100644
index 00000000..98bb88ce
--- /dev/null
+++ b/src/hacks/SkinChanger.cpp
@@ -0,0 +1,183 @@
+/*
+ * SkinChanger.cpp
+ *
+ * Created on: May 4, 2017
+ * Author: nullifiedcat
+ */
+
+#include "SkinChanger.hpp"
+
+namespace hacks { namespace tf2 { namespace skinchanger {
+
+CAttribute::CAttribute(uint16_t iAttributeDefinitionIndex, float flValue) {
+ defidx = iAttributeDefinitionIndex;
+ value = flValue;
+}
+
+void CAttributeList::RemoveAttribute(int index) {
+ for (int i = 0; i < m_Attributes.Count(); i++) {
+ const auto& a = m_Attributes[i];
+ if (a.defidx == index) {
+ m_Attributes.Remove(i);
+ return;
+ }
+ }
+}
+
+CAttributeList::CAttributeList() {}
+
+void CAttributeList::SetAttribute(int index, float value) {
+ // Let's check if attribute exists already. We don't want dupes.
+ for (int i = 0; i < m_Attributes.Count(); i++) {
+ auto& a = m_Attributes[i];
+ if (a.defidx == index) {
+ a.value = value;
+ return;
+ }
+ }
+
+ if (m_Attributes.Count() > 14)
+ return;
+
+ //m_Attributes.m_Memory.m_nGrowSize = -1;
+ //logging::Info("0x%08x 0x%08x 0x%08x", m_Attributes.m_Memory.m_nAllocationCount, m_Attributes.m_Memory.m_nGrowSize, m_Attributes.m_Memory.m_pMemory);
+ //m_Attributes.m_Memory.SetExternalBuffer(m_Attributes.m_Memory.Base(), 15);
+ CAttribute attr( index, value );
+ m_Attributes.AddToTail(attr);
+}
+
+static CatVar enabled(CV_SWITCH, "skinchanger", "0", "Skin Changer");
+static CatCommand set_attr("skinchanger_set", "Set Attribute", [](const CCommand& args) {
+ unsigned attrid = strtoul(args.Arg(1), nullptr, 10);
+ unsigned attrv = strtoul(args.Arg(2), nullptr, 10);
+ GetModifier(CE_INT(LOCAL_W, netvar.iItemDefinitionIndex)).Set(attrid, attrv);
+ InvalidateCookies();
+});
+static CatCommand set_redirect("skinchanger_redirect", "Set Redirect", [](const CCommand& args) {
+ unsigned redirect = strtoul(args.Arg(1), nullptr, 10);
+ GetModifier(CE_INT(LOCAL_W, netvar.iItemDefinitionIndex)).defidx_redirect = redirect;
+ InvalidateCookies();
+});
+static CatCommand dump_attrs("skinchanger_debug_attrs", "Dump attributes", []() {
+ CAttributeList* list = CE_VAR(LOCAL_W, netvar.AttributeList, CAttributeList*);
+ logging::Info("ATTRIBUTE LIST: %i", list->m_Attributes.Size());
+ for (int i = 0; i < 15; i++) {
+ logging::Info("%i %.2f", list->m_Attributes[i].defidx, list->m_Attributes[i].value);
+ }
+});
+static CatCommand invalidate_cookies("skinchanger_invalidate_cookies", "Invalidate Cookies", InvalidateCookies);
+
+void FrameStageNotify(int stage) {
+ if (!enabled) return;
+ if (stage != FRAME_NET_UPDATE_POSTDATAUPDATE_START) return;
+ int handle = CE_INT(g_pLocalPlayer->entity, netvar.hActiveWeapon);
+ int eid = handle & 0xFFF;
+ IClientEntity* entity = g_IEntityList->GetClientEntity(eid);
+ GetModifier(NET_INT(entity, netvar.iItemDefinitionIndex)).Apply(eid);
+ /*if (!GetCookie(weapon->m_IDX).Check()) {
+ logging::Info("Cookie bad for %i", weapon->m_IDX); // FIXME DEBUG LOGS!
+ GetModifier(CE_INT(weapon, netvar.iItemDefinitionIndex)).Apply(weapon->m_IDX);
+ GetCookie(weapon->m_IDX).Update(weapon->m_IDX);
+ }*/
+}
+
+void PaintTraverse() {
+ if (!enabled) return;
+ if (CE_GOOD(LOCAL_W))
+ AddSideString(format("dIDX: ", CE_INT(LOCAL_W, netvar.iItemDefinitionIndex)));
+ // Debug info?
+}
+
+void def_attribute_modifier::Set(int id, float value) {
+ for (auto& i : modifiers) {
+ if (i.defidx == id) {
+ i.value = value;
+ return;
+ }
+ }
+ attribute_s& attr = modifiers.at(first_free_mod);
+ first_free_mod++;
+ attr.defidx = id;
+ attr.value = value;
+ logging::Info("new attr: %i %.2f %i", attr.defidx, attr.value, first_free_mod);
+}
+
+void InvalidateCookies() {
+ logging::Info("All cookies invalidated!"); // FIXME DEBUG LOGS!
+ for (auto& cookie : cookie_map) {
+ cookie.second.valid = false;
+ }
+}
+
+patched_weapon_cookie::patched_weapon_cookie(int entity) {
+ Update(entity);
+}
+
+void patched_weapon_cookie::Update(int entity) {
+ IClientEntity* ent = g_IEntityList->GetClientEntity(entity);
+ if (!ent || ent->IsDormant()) return;
+ logging::Info("Updating cookie for %i", entity); // FIXME DEBUG LOGS!
+ CAttributeList* list = NET_VAR(ent, 0x9c0, CAttributeList*);
+ attrs = list->m_Attributes.Size();
+ eidx = entity;
+ defidx = NET_INT(ent, netvar.iItemDefinitionIndex);
+ eclass = ent->GetClientClass()->m_ClassID;
+ valid = true;
+}
+
+bool patched_weapon_cookie::Check() {
+ if (!valid) return false;
+ IClientEntity* ent = g_IEntityList->GetClientEntity(eidx);
+ if (!ent || ent->IsDormant()) return false;
+ CAttributeList* list = NET_VAR(ent, 0x9c0, CAttributeList*);
+ if (attrs != list->m_Attributes.Size()) return false;
+ if (eclass != ent->GetClientClass()->m_ClassID) return false;
+ if (defidx != NET_INT(ent, netvar.iItemDefinitionIndex)) return false;
+ return true;
+}
+
+void def_attribute_modifier::Apply(int entity) {
+ IClientEntity* ent = g_IEntityList->GetClientEntity(entity);
+ if (!ent) return;
+ //logging::Info("Applying modifiers for %i %i %i", entity, NET_INT(ent, netvar.iItemDefinitionIndex), defidx_redirect);
+ if (defidx_redirect && NET_INT(ent, netvar.iItemDefinitionIndex) != defidx_redirect) {
+ NET_INT(ent, netvar.iItemDefinitionIndex) = defidx_redirect;
+ logging::Info("Updated DefIDX to %i", NET_INT(ent, netvar.iItemDefinitionIndex));
+ GetCookie(entity).valid = false;
+ return;
+ }
+ CAttributeList* list = NET_VAR(ent, netvar.AttributeList, CAttributeList*);
+ //::Info("Attribute list: 0x%08x 0x%08x 0x%08x 0x%08x", 0x9c0, ent, list, (uint32_t)list - (uint32_t)ent);
+ list->m_Attributes.m_Size = list->m_Attributes.Size();
+ //logging::Info("Length: %i", list->m_Attributes.m_Size);
+ //logging::Info("Base: 0x%08x", list->m_Attributes.Base());
+ for (const auto& mod : modifiers) {
+ if (mod.defidx) {
+ //logging::Info("Setting %i to %.2f", mod.defidx, mod.value); // FIXME DEBUG LOGS!
+ list->SetAttribute(mod.defidx, mod.value);
+ }
+ }
+}
+
+def_attribute_modifier& GetModifier(int idx) {
+ try {
+ return modifier_map.at(idx);
+ } catch (std::out_of_range& oor) {
+ modifier_map.emplace(idx, def_attribute_modifier{});
+ return modifier_map.at(idx);
+ }
+}
+
+patched_weapon_cookie& GetCookie(int idx) {
+ try {
+ return cookie_map.at(idx);
+ } catch (std::out_of_range& oor) {
+ cookie_map.emplace(idx, patched_weapon_cookie{idx});
+ return cookie_map.at(idx);
+ }
+}
+
+std::unordered_map modifier_map {};
+std::unordered_map cookie_map {};
+
+}}}
diff --git a/src/hacks/SkinChanger.hpp b/src/hacks/SkinChanger.hpp
new file mode 100644
index 00000000..d75481e9
--- /dev/null
+++ b/src/hacks/SkinChanger.hpp
@@ -0,0 +1,92 @@
+/*
+ * SkinChanger.hpp
+ *
+ * Created on: May 4, 2017
+ * Author: nullifiedcat
+ */
+
+#ifndef HACKS_SKINCHANGER_HPP_
+#define HACKS_SKINCHANGER_HPP_
+
+#include "../common.h"
+
+namespace hacks { namespace tf2 { namespace skinchanger {
+
+// TOTALLY NOT A PASTE.
+// Seriously tho, it's modified at least.
+// Credits: blackfire62
+
+struct attribute_s {
+ uint16_t defidx;
+ float value;
+};
+
+class CAttribute {
+public:
+ CAttribute(uint16_t iAttributeDefinitionIndex, float flValue);
+public:
+ void* vtable;
+ uint16_t defidx;
+ float value;
+ unsigned int pad01;
+};
+
+class CAttributeList {
+public:
+ CAttributeList();
+ void SetAttribute(int index, float value);
+ void RemoveAttribute(int index);
+public:
+ uint32_t unknown;
+ CUtlVector> m_Attributes;
+};
+
+enum class Attributes {
+ loot_rarity = 2022,
+ is_australium_item = 2027,
+ item_style_override = 542,
+ sheen = 2014,
+ killstreak_tier = 2025
+};
+
+enum class UnusualEffects {
+ HOT = 701,
+ ISOTOPE,
+ COOL,
+ ENERGY_ORB
+};
+
+struct patched_weapon_cookie {
+ patched_weapon_cookie(int entity);
+ void Update(int entity);
+ bool Check();
+public:
+ int eidx { 0 };
+ int defidx { 0 };
+ int eclass { 0 };
+ int attrs { 0 };
+ bool valid { false };
+};
+
+struct def_attribute_modifier {
+ void Apply(int entity);
+ void Set(int id, float value);
+ int defidx { 0 };
+ int defidx_redirect { 0 };
+ std::array modifiers { attribute_s{ 0, 0 } };
+ int first_free_mod { 0 };
+};
+
+extern std::unordered_map modifier_map;
+extern std::unordered_map cookie_map;
+
+def_attribute_modifier& GetModifier(int idx);
+patched_weapon_cookie& GetCookie(int idx);
+
+void InvalidateCookies();
+void FrameStageNotify(int stage);
+void PaintTraverse();
+
+}}}
+
+#endif /* HACKS_SKINCHANGER_HPP_ */
diff --git a/src/hacks/Spam.cpp b/src/hacks/Spam.cpp
index defc8fad..12d6e5d7 100644
--- a/src/hacks/Spam.cpp
+++ b/src/hacks/Spam.cpp
@@ -62,7 +62,7 @@ void CreateMove() {
if (random_order) current_index = rand() % source->size();
std::string spamString = source->at(current_index);
ReplaceString(spamString, "\\n", "\n");
- chat_stack::stack.push(spamString);
+ chat_stack::Say(spamString);
current_index++;
}
}
diff --git a/src/hacks/UberSpam.cpp b/src/hacks/UberSpam.cpp
index 962c9bfe..b76c0890 100644
--- a/src/hacks/UberSpam.cpp
+++ b/src/hacks/UberSpam.cpp
@@ -17,6 +17,7 @@ static CatVar on_ready(CV_SWITCH, "uberspam_ready", "1", "Uber Ready");
static CatVar on_used(CV_SWITCH, "uberspam_used", "1", "Uber Used");
static CatVar on_ended(CV_SWITCH, "uberspam_ended", "1", "Uber Ended");
static CatVar on_build(CV_INT, "uberspam_build", "25", "Uber Build", "Send a message every #% ubercharge. 0 = never send", 0, 100);
+static CatVar team_chat(CV_SWITCH, "uberspam_team", "1", "Uber Team Chat", "Send uberspam messages in team chat");
static CatVar custom_file(CV_STRING, "uberspam_file", "uberspam.txt", "Ubercharge Spam File", "Use cat_uberspam_file_reload! Same as spam/killsay files.");
static CatCommand custom_file_reload("uberspam_file_reload", "Reload Ubercharge Spam File", []() {
custom_lines.Load(std::string(custom_file.GetString()));
@@ -56,20 +57,22 @@ void CreateMove() {
bool release = CE_BYTE(LOCAL_W, netvar.bChargeRelease);
if (release_last_frame != release) {
if (release) {
- if (on_used) chat_stack::stack.push(GetSource()->at(1));
+ if (on_used) chat_stack::Say(GetSource()->at(1), !!team_chat);
} else {
- if (on_ended) chat_stack::stack.push(GetSource()->at(2));
+ if (on_ended) chat_stack::Say(GetSource()->at(2), !!team_chat);
}
}
if (!release && ((int)(100.0f * charge) != last_charge)) {
if (charge == 1.0f) {
- if (on_ready) chat_stack::stack.push(GetSource()->at(0));
+ if (on_ready) chat_stack::Say(GetSource()->at(0), !!team_chat);
} else {
if ((int)(charge * 100.0f) != 0 && on_build) {
- if (((int)(charge * 100.0f) % (int)on_build) == 0) {
+ int chargeperline = ((int)on_build >= 100) ? (100 / (GetSource()->size() - 2)) : (int)on_build;
+ if (chargeperline < 1) chargeperline = 1;
+ if ((int)(charge * 100.0f) % chargeperline == 0) {
std::string res = GetSource()->at(ChargePercentLineIndex(charge));
ReplaceString(res, "%i%", std::to_string((int)(charge * 100.0f)));
- chat_stack::stack.push(res);
+ chat_stack::Say(res, !!team_chat);
}
}
}
diff --git a/src/hacks/hacklist.h b/src/hacks/hacklist.h
index fe453563..0f8586a3 100644
--- a/src/hacks/hacklist.h
+++ b/src/hacks/hacklist.h
@@ -24,6 +24,7 @@
#include "Trigger.h"
#include "KillSay.h"
#include "UberSpam.hpp"
+#include "SkinChanger.hpp"
#include "Achievement.h"
#include "Spam.h"
#include "Noisemaker.h"
diff --git a/src/hooks.cpp b/src/hooks.cpp
index 1c3c0fce..6ee8013f 100644
--- a/src/hooks.cpp
+++ b/src/hooks.cpp
@@ -10,78 +10,79 @@
#include "logging.h"
#include
+#include
-unsigned int hooks::offCreateMove = 22;
-unsigned int hooks::offPaintTraverse = 42;
-unsigned int hooks::offOverrideView = 17;
-unsigned int hooks::offFrameStageNotify = 35;
-unsigned int hooks::offCanPacket = 57;
-unsigned int hooks::offSendNetMsg = 41;
-unsigned int hooks::offShutdown = 37;
-unsigned int hooks::offKeyEvent = 20;
-unsigned int hooks::offHandleInputEvent = 78;
-unsigned int hooks::offLevelInit = 23;
-unsigned int hooks::offLevelShutdown = 24;
-unsigned int hooks::offBeginFrame = 5;
+namespace hooks {
-// This thing had been copypasted from somewhere, maybe from F1Public.
-
-bool hooks::IsHooked(void* inst) {
- return hooks::GetVMT(inst, 0)[-2] == (void*)VMTHook::GUARD;
-}
-
-unsigned int hooks::CountMethods(void** vmt) {
+unsigned CountMethods(method_table_t table) {
unsigned int i = -1;
- do ++i; while (vmt[i]);
+ do ++i; while (table[i]);
return i;
}
-void**& hooks::GetVMT(void* inst, unsigned int offset) {
- return *reinterpret_cast((char*)inst + offset);
+table_ref_t GetVMT(ptr_t inst, uint32_t offset) {
+ return *reinterpret_cast((uint32_t)inst + offset);
}
-void hooks::VMTHook::Init(void* inst, unsigned int offset) {
- vmt = &GetVMT(inst, offset);
- oldvmt = *vmt;
- unsigned int cnt = CountMethods(oldvmt);
- void **arr = array = (void**)malloc((cnt + 4) * sizeof(void*));
- arr[0] = this;
- arr[1] = (void* )GUARD;
- (arr + 3)[cnt] = 0;
- unsigned int i = -1;
- do arr[i + 3] = oldvmt[i]; while (++i < cnt);
+bool IsHooked(ptr_t inst, uint32_t offset) {
+ return GetVMT(inst, offset)[-1] == (method_t)GUARD;
}
-void hooks::VMTHook::Kill() {
- if (vmt)
- *vmt = oldvmt;
- vmt = 0;
- free(array);
- array = 0;
+VMTHook::VMTHook() {
+ static_assert(ptr_size == 4, "Pointer size must be DWORD.");
+};
+
+VMTHook::~VMTHook() {
+ Release();
}
-void hooks::VMTHook::HookMethod(void* func, unsigned int idx) {
- array[idx + 3] = func;
+void VMTHook::Set(ptr_t inst, uint32_t offset) {
+ Release();
+ vtable_ptr = &GetVMT(inst, offset);
+ vtable_original = *vtable_ptr;
+ int mc = CountMethods(vtable_original);
+ vtable_hooked = static_cast(calloc(mc + 3, sizeof(ptr_t)));
+ memcpy(&vtable_hooked[2], vtable_original, sizeof(ptr_t) * mc);
+ vtable_hooked[0] = this;
+ vtable_hooked[1] = (void*)GUARD;
}
-void* hooks::VMTHook::GetMethod(unsigned int idx) const {
- return oldvmt[idx];
+void VMTHook::Release() {
+ if (vtable_ptr && *vtable_ptr == &vtable_hooked[2]) {
+ logging::Info("Un-hooking 0x%08x (vtable @ 0x%08x)", vtable_ptr, *vtable_ptr);
+ if ((*vtable_ptr)[-1] == (method_t)GUARD) {
+ *vtable_ptr = vtable_original;
+ }
+ free(vtable_hooked);
+ vtable_ptr = nullptr;
+ vtable_hooked = nullptr;
+ vtable_original = nullptr;
+ }
}
-void hooks::VMTHook::Apply() {
- *vmt = array + 3;
+void* VMTHook::GetMethod(uint32_t idx) const {
+ return vtable_original[idx];
}
-//hooks::VMTHook* hooks::hkCTFPlayer = nullptr;
-hooks::VMTHook* hooks::hkInput = nullptr;
-hooks::VMTHook* hooks::hkSteamFriends = nullptr;
-hooks::VMTHook* hooks::hkBaseClientState = nullptr;
-hooks::VMTHook* hooks::hkBaseClientState8 = nullptr;
-hooks::VMTHook* hooks::hkClientMode = 0;
-hooks::VMTHook* hooks::hkPanel = 0;
-hooks::VMTHook* hooks::hkClient = 0;
-hooks::VMTHook* hooks::hkNetChannel = 0;
-hooks::VMTHook* hooks::hkClientDLL = 0;
-hooks::VMTHook* hooks::hkMatSurface = 0;
-hooks::VMTHook* hooks::hkStudioRender = 0;
-hooks::VMTHook* hooks::hkIVModelRender = nullptr;
+void VMTHook::HookMethod(ptr_t func, uint32_t idx) {
+ vtable_hooked[2 + idx] = func;
+}
+
+void VMTHook::Apply() {
+ *vtable_ptr = &vtable_hooked[2];
+}
+
+VMTHook input {};
+VMTHook steamfriends {};
+VMTHook baseclientstate {};
+VMTHook baseclientstate8 {};
+VMTHook clientmode {};
+VMTHook panel {};
+VMTHook client {};
+VMTHook netchannel {};
+VMTHook clientdll {};
+VMTHook matsurface {};
+VMTHook studiorender {};
+VMTHook modelrender {};
+
+}
diff --git a/src/hooks.h b/src/hooks.h
index 1a75bfdb..74af6205 100644
--- a/src/hooks.h
+++ b/src/hooks.h
@@ -8,62 +8,56 @@
#ifndef HOOKS_H_
#define HOOKS_H_
-namespace hooks {
-
// Parts of copypasted code
// Credits: Casual_Hacker
-unsigned int CountMethods(void** vmt);
-void**& GetVMT(void* inst, unsigned int offset);
-bool IsHooked(void* inst);
+#include
+#include
+
+namespace hooks {
+
+typedef void* ptr_t;
+typedef void* method_t;
+typedef method_t* method_table_t;
+typedef method_table_t* table_ptr_t;
+typedef method_table_t& table_ref_t;
+
+constexpr size_t ptr_size = sizeof(ptr_t);
+
+unsigned CountMethods(method_table_t table);
+table_ref_t GetVMT(ptr_t inst, uint32_t offset = 0);
+bool IsHooked(ptr_t inst, uint32_t offset = 0);
+
+constexpr uint32_t GUARD = 0xD34DC477;
class VMTHook {
public:
- enum { GUARD = 0xD34DC477 };
- void Init(void* inst, unsigned int offset);
- void Kill();
- void HookMethod(void* func, unsigned int idx);
- void* GetMethod(unsigned int idx) const;
+ VMTHook();
+ ~VMTHook();
+ void Set(ptr_t inst, uint32_t offset = 0);
+ void Release();
+ void HookMethod(ptr_t func, uint32_t idx);
+ void* GetMethod(uint32_t idx) const;
void Apply();
-protected:
- void ***vmt;
- void **oldvmt;
- void **array;
+public:
+ ptr_t object { nullptr };
+ table_ptr_t vtable_ptr { nullptr };
+ method_table_t vtable_original { nullptr };
+ method_table_t vtable_hooked { nullptr };
};
-//extern VMTHook* hkCTFPlayer;
-extern VMTHook* hkPanel;
-extern VMTHook* hkClientMode;
-extern VMTHook* hkClient;
-extern VMTHook* hkNetChannel;
-extern VMTHook* hkClientDLL;
-extern VMTHook* hkMatSurface;
-extern VMTHook* hkStudioRender;
-extern VMTHook* hkInput;
-extern VMTHook* hkIVModelRender;
-extern VMTHook* hkBaseClientState;
-extern VMTHook* hkBaseClientState8;
-extern VMTHook* hkSteamFriends;
-
-constexpr unsigned int offGetUserCmd = 8;
-constexpr unsigned int offShouldDraw = 136;
-constexpr unsigned int offDrawModelExecute = 19;
-constexpr unsigned int offGetClientName = 44;
-constexpr unsigned int offProcessSetConVar = 4;
-constexpr unsigned int offProcessGetCvarValue = 29;
-constexpr unsigned int offGetFriendPersonaName = 7;
-extern unsigned int offHandleInputEvent;
-extern unsigned int offPaintTraverse;
-extern unsigned int offCreateMove;
-extern unsigned int offOverrideView;
-extern unsigned int offFrameStageNotify;
-extern unsigned int offCanPacket;
-extern unsigned int offSendNetMsg;
-extern unsigned int offShutdown;
-extern unsigned int offKeyEvent;
-extern unsigned int offLevelInit;
-extern unsigned int offLevelShutdown;
-extern unsigned int offBeginFrame;
+extern VMTHook panel;
+extern VMTHook clientmode;
+extern VMTHook client;
+extern VMTHook netchannel;
+extern VMTHook clientdll;
+extern VMTHook matsurface;
+extern VMTHook studiorender;
+extern VMTHook input;
+extern VMTHook modelrender;
+extern VMTHook baseclientstate;
+extern VMTHook baseclientstate8;
+extern VMTHook steamfriends;
}
diff --git a/src/hooks/BeginFrame.cpp b/src/hooks/BeginFrame.cpp
deleted file mode 100644
index 63a25206..00000000
--- a/src/hooks/BeginFrame.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * BeginFrame.cpp
- *
- * Created on: Feb 10, 2017
- * Author: nullifiedcat
- */
-
-#include "hookedmethods.h"
-#include "../common.h"
-#include "../sdk.h"
-
-void BeginFrame_hook(IStudioRender* _this) {
- ((BeginFrame_t*)hooks::hkStudioRender->GetMethod(hooks::offBeginFrame))(_this);
-}
diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp
index 7295211d..20da18c1 100644
--- a/src/hooks/CreateMove.cpp
+++ b/src/hooks/CreateMove.cpp
@@ -12,6 +12,7 @@
#include "../common.h"
#include "hookedmethods.h"
+// FIXME remove this temporary code already!
float AngleDiff( float destAngle, float srcAngle )
{
float delta;
@@ -28,7 +29,7 @@ float AngleDiff( float destAngle, float srcAngle )
delta += 360;
}
return delta;
-}//TODO temporary
+}
#include "../profiler.h"
@@ -70,7 +71,9 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) {
if (TF2C && CE_GOOD(LOCAL_W) && minigun_jump && LOCAL_W->m_iClassID == g_pClassID->CTFMinigun) {
CE_INT(LOCAL_W, netvar.iWeaponState) = 0;
}
- bool ret = ((CreateMove_t*)hooks::hkClientMode->GetMethod(hooks::offCreateMove))(thisptr, inputSample, cmd);
+
+ static CreateMove_t original_method = (CreateMove_t)hooks::clientmode.GetMethod(offsets::CreateMove());
+ bool ret = original_method(thisptr, inputSample, cmd);
PROF_SECTION(CreateMove);
@@ -90,13 +93,12 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) {
// PROF_BEGIN();
INetChannel* ch = (INetChannel*)g_IEngine->GetNetChannelInfo();
- if (ch && !hooks::IsHooked((void*)((uintptr_t)ch))) {
- hooks::hkNetChannel = new hooks::VMTHook();
- hooks::hkNetChannel->Init(ch, 0);
- hooks::hkNetChannel->HookMethod((void*)CanPacket_hook, hooks::offCanPacket);
- hooks::hkNetChannel->HookMethod((void*)SendNetMsg_hook, hooks::offSendNetMsg);
- hooks::hkNetChannel->HookMethod((void*)Shutdown_hook, hooks::offShutdown);
- hooks::hkNetChannel->Apply();
+ if (ch && !hooks::IsHooked((void*)ch)) {
+ hooks::netchannel.Set(ch);
+ hooks::netchannel.HookMethod((void*)CanPacket_hook, offsets::CanPacket());
+ hooks::netchannel.HookMethod((void*)SendNetMsg_hook, offsets::SendNetMsg());
+ hooks::netchannel.HookMethod((void*)Shutdown_hook, offsets::Shutdown());
+ hooks::netchannel.Apply();
}
//logging::Info("canpacket: %i", ch->CanPacket());
//if (!cmd) return ret;
@@ -120,7 +122,7 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) {
g_Settings.bInvalid = false;
// Disabled because this causes EXTREME aimbot inaccuracy
//if (!cmd->command_number) return ret;
-
+#ifdef IPC_ENABLED
if (hacks::shared::followbot::bot) {
static int team_joining_state = 0;
static float last_jointeam_try = 0;
@@ -170,6 +172,7 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) {
}
}
+#endif
if (CE_GOOD(g_pLocalPlayer->entity)) {
ResetCritHack();
if (TF2) SAFE_CALL(UpdateHoovyList());
@@ -207,7 +210,9 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) {
// TODO Auto Steam Friend
if (g_GlobalVars->framecount % 1000 == 0) {
playerlist::DoNotKillMe();
+#ifdef IPC_ENABLED
ipc::UpdatePlayerlist();
+#endif
}
if (CE_GOOD(g_pLocalPlayer->entity)) {
@@ -256,10 +261,11 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) {
ret = false;
}
-
+#ifdef IPC_ENABLED
if (CE_GOOD(g_pLocalPlayer->entity) && !g_pLocalPlayer->life_state) {
SAFE_CALL(hacks::shared::followbot::AfterCreateMove());
}
+#endif
if (cmd)
g_Settings.last_angles = cmd->viewangles;
}
diff --git a/src/hooks/PaintTraverse.cpp b/src/hooks/PaintTraverse.cpp
index bcfb49d0..91585815 100644
--- a/src/hooks/PaintTraverse.cpp
+++ b/src/hooks/PaintTraverse.cpp
@@ -26,7 +26,8 @@ void** pure_addr = nullptr;
CatEnum software_cursor_enum({"KEEP", "ALWAYS", "NEVER", "MENU ON", "MENU OFF"});
CatVar software_cursor_mode(software_cursor_enum, "software_cursor_mode", "1", "Software cursor", "Try to change this and see what works best for you");
-void PaintTraverse_hook(void* p, unsigned int vp, bool fr, bool ar) {
+void PaintTraverse_hook(void* _this, unsigned int vp, bool fr, bool ar) {
+ static const PaintTraverse_t original = (PaintTraverse_t)hooks::panel.GetMethod(offsets::PaintTraverse());
#if DEBUG_SEGV == true
if (!segvcatch::handler_fpe || !segvcatch::handler_segv) {
if (!segvcatch::handler_fpe) segvcatch::init_segv();
@@ -83,7 +84,7 @@ void PaintTraverse_hook(void* p, unsigned int vp, bool fr, bool ar) {
}
}
- if (call_default) SAFE_CALL(((PaintTraverse_t*)hooks::hkPanel->GetMethod(hooks::offPaintTraverse))(p, vp, fr, ar));
+ if (call_default) SAFE_CALL(original(_this, vp, fr, ar));
// To avoid threading problems.
PROF_SECTION(PaintTraverse);
@@ -156,6 +157,7 @@ void PaintTraverse_hook(void* p, unsigned int vp, bool fr, bool ar) {
SAFE_CALL(hacks::shared::esp::Draw());
if (TF) SAFE_CALL(hacks::tf::spyalert::Draw());
if (TF) SAFE_CALL(hacks::tf::radar::Draw());
+ if (TF2) SAFE_CALL(hacks::tf2::skinchanger::PaintTraverse());
}
diff --git a/src/hooks/hookedmethods.h b/src/hooks/hookedmethods.h
index c93787d4..85436c8b 100644
--- a/src/hooks/hookedmethods.h
+++ b/src/hooks/hookedmethods.h
@@ -10,36 +10,32 @@
#include "../common.h"
-typedef bool(CreateMove_t)(void*, float, CUserCmd*);
-typedef void(PaintTraverse_t)(void*, unsigned int, bool, bool);
-typedef bool(CanPacket_t)(void*);
-typedef int(IN_KeyEvent_t)(void*, int, int, const char*);
-typedef bool(SendNetMsg_t)(void*, INetMessage&, bool, bool);
-typedef void(Shutdown_t)(void*, const char*);
-typedef void(OverrideView_t)(void*, CViewSetup*);
-typedef bool(DispatchUserMessage_t)(void*, int, bf_read&);
-typedef void(FrameStageNotify_t)(void*, int);
-typedef void(LevelInit_t)(void*, const char*);
-typedef void(LevelShutdown_t)(void*);
-typedef void(BeginFrame_t)(IStudioRender*);
+typedef bool(*CreateMove_t)(void*, float, CUserCmd*);
+typedef void(*PaintTraverse_t)(void*, unsigned int, bool, bool);
+typedef bool(*CanPacket_t)(void*);
+typedef int(*IN_KeyEvent_t)(void*, int, int, const char*);
+typedef bool(*SendNetMsg_t)(void*, INetMessage&, bool, bool);
+typedef void(*Shutdown_t)(void*, const char*);
+typedef void(*OverrideView_t)(void*, CViewSetup*);
+typedef bool(*DispatchUserMessage_t)(void*, int, bf_read&);
+typedef void(*FrameStageNotify_t)(void*, int);
+typedef void(*LevelInit_t)(void*, const char*);
+typedef void(*LevelShutdown_t)(void*);
+typedef void(*BeginFrame_t)(IStudioRender*);
typedef bool(*CanInspect_t)(IClientEntity*);
typedef void(*DrawModelExecute_t)(IVModelRender*, const DrawModelState_t&, const ModelRenderInfo_t&, matrix3x4_t*);
-typedef CUserCmd*(GetUserCmd_t)(IInput*, int);
-typedef const char*(GetClientName_t)(CBaseClientState*);
-typedef bool(ProcessSetConVar_t)(CBaseClientState*, NET_SetConVar*);
-typedef bool(ProcessGetCvarValue_t)(CBaseClientState*, SVC_GetCvarValue*);
+typedef CUserCmd*(*GetUserCmd_t)(IInput*, int);
+typedef const char*(*GetClientName_t)(CBaseClientState*);
+typedef bool(*ProcessSetConVar_t)(CBaseClientState*, NET_SetConVar*);
+typedef bool(*ProcessGetCvarValue_t)(CBaseClientState*, SVC_GetCvarValue*);
const char* GetClientName_hook(CBaseClientState* _this);
bool ProcessSetConVar_hook(CBaseClientState* _this, NET_SetConVar* msg);
bool ProcessGetCvarValue_hook(CBaseClientState* _this, SVC_GetCvarValue* msg);
//typedef void(*CInput__CreateMove_t)(void*, int, float, bool);
//void CInput__CreateMove_hook(void*, int sequence_number, float input_sample_frametime, bool active);
-bool CanInspect_hook(IClientEntity*);
-const unsigned int offCanInspect = 512;
-
-typedef const char*(GetFriendPersonaName_t)(ISteamFriends*, CSteamID);
+typedef const char*(*GetFriendPersonaName_t)(ISteamFriends*, CSteamID);
const char* GetFriendPersonaName_hook(ISteamFriends* _this, CSteamID steamID);
-void BeginFrame_hook(IStudioRender*);
CUserCmd* GetUserCmd_hook(IInput*, int);
void DrawModelExecute_hook(IVModelRender* _this, const DrawModelState_t& state, const ModelRenderInfo_t& info, matrix3x4_t* matrix);
diff --git a/src/hooks/others.cpp b/src/hooks/others.cpp
index 603d6a9a..84331068 100644
--- a/src/hooks/others.cpp
+++ b/src/hooks/others.cpp
@@ -12,6 +12,7 @@
static CatVar no_invisibility(CV_SWITCH, "no_invis", "0", "Remove Invisibility", "Useful with chams!");
+// This hook isn't used yet!
int C_TFPlayer__DrawModel_hook(IClientEntity* _this, int flags) {
float old_invis = *(float*)((uintptr_t)_this + 79u);
if (no_invisibility) {
@@ -27,17 +28,9 @@ static CatVar no_arms(CV_SWITCH, "no_arms", "0", "No Arms", "Removes arms from f
static CatVar no_hats(CV_SWITCH, "no_hats", "0", "No Hats", "Removes non-stock hats");
void DrawModelExecute_hook(IVModelRender* _this, const DrawModelState_t& state, const ModelRenderInfo_t& info, matrix3x4_t* matrix) {
- /*IClientUnknown* unknown = info.pRenderable->GetIClientUnknown();
- if (unknown) {
- IClientEntity* entity = unknown->GetIClientEntity();
- if (entity && entity->entindex() != -1) {
- if (entity->GetClientClass()->m_ClassID == g_pClassID->C_Player) {
- //CMatRenderContextPtr ptr();
- }
- }
- }*/
+ static const DrawModelExecute_t original = (DrawModelExecute_t)hooks::modelrender.GetMethod(offsets::DrawModelExecute());
if (!cathook || !(no_arms || no_hats || (clean_screenshots && g_IEngine->IsTakingScreenshot()))) {
- ((DrawModelExecute_t)(hooks::hkIVModelRender->GetMethod(hooks::offDrawModelExecute)))(_this, state, info, matrix);
+ original(_this, state, info, matrix);
return;
}
@@ -63,18 +56,20 @@ void DrawModelExecute_hook(IVModelRender* _this, const DrawModelState_t& state,
}
}
- ((DrawModelExecute_t)(hooks::hkIVModelRender->GetMethod(hooks::offDrawModelExecute)))(_this, state, info, matrix);
+ original(_this, state, info, matrix);
}
-bool CanPacket_hook(void* thisptr) {
+bool CanPacket_hook(void* _this) {
+ const CanPacket_t original = (CanPacket_t)hooks::netchannel.GetMethod(offsets::CanPacket());
SEGV_BEGIN;
- return send_packets && ((CanPacket_t*)hooks::hkNetChannel->GetMethod(hooks::offCanPacket))(thisptr);
+ return send_packets && original(_this);
SEGV_END;
return false;
}
-CUserCmd* GetUserCmd_hook(IInput* thisptr, int sequence_number) {
- CUserCmd* def = ((GetUserCmd_t*)(hooks::hkInput->GetMethod(hooks::offGetUserCmd)))(thisptr, sequence_number);
+CUserCmd* GetUserCmd_hook(IInput* _this, int sequence_number) {
+ static const GetUserCmd_t original = (GetUserCmd_t)hooks::input.GetMethod(offsets::GetUserCmd());
+ CUserCmd* def = original(_this, sequence_number);
if (def && command_number_mod.find(def->command_number) != command_number_mod.end()) {
logging::Info("Replacing command %i with %i", def->command_number, command_number_mod[def->command_number]);
int oldcmd = def->command_number;
@@ -85,12 +80,13 @@ CUserCmd* GetUserCmd_hook(IInput* thisptr, int sequence_number) {
return def;
}
-int IN_KeyEvent_hook(void* thisptr, int eventcode, int keynum, const char* pszCurrentBinding) {
+int IN_KeyEvent_hook(void* _this, int eventcode, int keynum, const char* pszCurrentBinding) {
+ static const IN_KeyEvent_t original = (IN_KeyEvent_t)hooks::client.GetMethod(offsets::IN_KeyEvent());
SEGV_BEGIN;
if (g_pGUI->ConsumesKey((ButtonCode_t)keynum) && g_pGUI->Visible()) {
return 0;
}
- return ((IN_KeyEvent_t*)hooks::hkClient->GetMethod(hooks::offKeyEvent))(thisptr, eventcode, keynum, pszCurrentBinding);
+ return original(_this, eventcode, keynum, pszCurrentBinding);
SEGV_END;
return 0;
}
@@ -112,7 +108,9 @@ static CatVar newlines_msg(CV_INT, "chat_newlines", "0", "Prefix newlines", "Add
// TODO name \\n = \n
//static CatVar queue_messages(CV_SWITCH, "chat_queue", "0", "Queue messages", "Use this if you want to use spam/killsay and still be able to chat normally (without having your msgs eaten by valve cooldown)");
-bool SendNetMsg_hook(void* thisptr, INetMessage& msg, bool bForceReliable = false, bool bVoice = false) {
+bool SendNetMsg_hook(void* _this, INetMessage& msg, bool bForceReliable = false, bool bVoice = false) {
+ // This is a INetChannel hook - it SHOULDN'T be static because netchannel changes.
+ const SendNetMsg_t original = (SendNetMsg_t)hooks::netchannel.GetMethod(offsets::SendNetMsg());
SEGV_BEGIN;
// net_StringCmd
if (msg.GetType() == 4 && (newlines_msg)) {
@@ -128,7 +126,7 @@ bool SendNetMsg_hook(void* thisptr, INetMessage& msg, bool bForceReliable = fals
str = str.substr(16, str.length() - 17);
//if (queue_messages && !chat_stack::CanSend()) {
NET_StringCmd stringcmd(str.c_str());
- return ((SendNetMsg_t*)hooks::hkNetChannel->GetMethod(hooks::offSendNetMsg))(thisptr, stringcmd, bForceReliable, bVoice);
+ return original(_this, stringcmd, bForceReliable, bVoice);
//}
}
}
@@ -145,19 +143,21 @@ bool SendNetMsg_hook(void* thisptr, INetMessage& msg, bool bForceReliable = fals
}
logging::Info("%i bytes => %s", buffer.GetNumBytesWritten(), bytes.c_str());
}
- return ((SendNetMsg_t*)hooks::hkNetChannel->GetMethod(hooks::offSendNetMsg))(thisptr, msg, bForceReliable, bVoice);
+ return original(_this, msg, bForceReliable, bVoice);
SEGV_END;
return false;
}
CatVar disconnect_reason(CV_STRING, "disconnect_reason", "", "Disconnect reason", "A custom disconnect reason");
-void Shutdown_hook(void* thisptr, const char* reason) {
+void Shutdown_hook(void* _this, const char* reason) {
+ // This is a INetChannel hook - it SHOULDN'T be static because netchannel changes.
+ const Shutdown_t original = (Shutdown_t)hooks::netchannel.GetMethod(offsets::Shutdown());
SEGV_BEGIN;
if (cathook && (disconnect_reason.convar_parent->m_StringLength > 3) && strstr(reason, "user")) {
- ((Shutdown_t*)hooks::hkNetChannel->GetMethod(hooks::offShutdown))(thisptr, disconnect_reason.GetString());
+ original(_this, disconnect_reason.GetString());
} else {
- ((Shutdown_t*)hooks::hkNetChannel->GetMethod(hooks::offShutdown))(thisptr, reason);
+ original(_this, reason);
}
SEGV_END;
}
@@ -167,16 +167,19 @@ static CatVar glow_alpha(CV_FLOAT, "glow_old_alpha", "1", "Alpha", "Glow Transpa
static CatVar resolver(CV_SWITCH, "resolver", "0", "Resolve angles");
const char* GetFriendPersonaName_hook(ISteamFriends* _this, CSteamID steamID) {
+ static const GetFriendPersonaName_t original = (GetFriendPersonaName_t)hooks::steamfriends.GetMethod(offsets::GetFriendPersonaName());
if ((force_name.convar->m_StringLength > 2) && steamID == g_ISteamUser->GetSteamID()) {
return force_name.GetString();
}
- return ((GetFriendPersonaName_t*)(hooks::hkSteamFriends->GetMethod(hooks::offGetFriendPersonaName)))(_this, steamID);
+ return original(_this, steamID);
}
-void FrameStageNotify_hook(void* thisptr, int stage) {
+void FrameStageNotify_hook(void* _this, int stage) {
+ static const FrameStageNotify_t original = (FrameStageNotify_t)hooks::client.GetMethod(offsets::FrameStageNotify());
SEGV_BEGIN;
if (!g_IEngine->IsInGame()) g_Settings.bInvalid = true;
// TODO hack FSN hook
+ hacks::tf2::skinchanger::FrameStageNotify(stage);
if (resolver && cathook && !g_Settings.bInvalid && stage == FRAME_NET_UPDATE_POSTDATAUPDATE_START) {
for (int i = 1; i < 32 && i < HIGHEST_ENTITY; i++) {
if (i == g_IEngine->GetLocalPlayer()) continue;
@@ -255,16 +258,17 @@ void FrameStageNotify_hook(void* thisptr, int stage) {
}
}
}
- SAFE_CALL(((FrameStageNotify_t*)hooks::hkClient->GetMethod(hooks::offFrameStageNotify))(thisptr, stage));
+ SAFE_CALL(original(_this, stage));
SEGV_END;
}
CatVar override_fov_zoomed(CV_FLOAT, "fov_zoomed", "0", "FOV override (zoomed)", "Overrides FOV with this value when zoomed in (default FOV when zoomed is 20)");
CatVar override_fov(CV_FLOAT, "fov", "0", "FOV override", "Overrides FOV with this value");
-void OverrideView_hook(void* thisptr, CViewSetup* setup) {
+void OverrideView_hook(void* _this, CViewSetup* setup) {
+ static const OverrideView_t original = (OverrideView_t)hooks::clientmode.GetMethod(offsets::OverrideView());
SEGV_BEGIN;
- ((OverrideView_t*)hooks::hkClientMode->GetMethod(hooks::offOverrideView))(thisptr, setup);
+ original(_this, setup);
if (!cathook) return;
bool zoomed = g_pLocalPlayer->bZoomed;
if (zoomed && override_fov_zoomed) {
@@ -280,7 +284,8 @@ void OverrideView_hook(void* thisptr, CViewSetup* setup) {
static CatVar clean_chat(CV_SWITCH, "clean_chat", "0", "Clean chat", "Removes newlines from chat");
static CatVar dispatch_log(CV_SWITCH, "debug_log_usermessages", "0", "Log dispatched user messages");
-bool DispatchUserMessage_hook(void* thisptr, int type, bf_read& buf) {
+bool DispatchUserMessage_hook(void* _this, int type, bf_read& buf) {
+ static const DispatchUserMessage_t original = (DispatchUserMessage_t)hooks::client.GetMethod(offsets::DispatchUserMessage());
SEGV_BEGIN;
if (clean_chat) {
if (type == 4) {
@@ -301,31 +306,29 @@ bool DispatchUserMessage_hook(void* thisptr, int type, bf_read& buf) {
if (dispatch_log) {
logging::Info("D> %i", type);
}
- //if (type != net_Tick) logging::Info("Got message: %s", type);
- return ((DispatchUserMessage_t*)hooks::hkClient->GetMethod(hooks::offFrameStageNotify + 1))(thisptr, type, buf);
- SEGV_END; return false;
+ return original(_this, type, buf);
+ SEGV_END;
+ return false;
}
-void LevelInit_hook(void* thisptr, const char* newmap) {
+void LevelInit_hook(void* _this, const char* newmap) {
+ static const LevelInit_t original = (LevelInit_t)hooks::clientmode.GetMethod(offsets::LevelInit());
playerlist::Save();
- ((LevelInit_t*) hooks::hkClientMode->GetMethod(hooks::offLevelInit))(thisptr, newmap);
g_IEngine->ClientCmd_Unrestricted("exec cat_matchexec");
hacks::shared::aimbot::Reset();
-// LEVEL_SHUTDOWN(FollowBot);
- //if (TF) LEVEL_INIT(SpyAlert);
chat_stack::Reset();
hacks::shared::spam::Reset();
+ original(_this, newmap);
}
-bool CanInspect_hook(IClientEntity*) { return true; }
-
-void LevelShutdown_hook(void* thisptr) {
+void LevelShutdown_hook(void* _this) {
+ static const LevelShutdown_t original = (LevelShutdown_t)hooks::clientmode.GetMethod(offsets::LevelShutdown());
need_name_change = true;
playerlist::Save();
- ((LevelShutdown_t*) hooks::hkClientMode->GetMethod(hooks::offLevelShutdown))(thisptr);
g_Settings.bInvalid = true;
hacks::shared::aimbot::Reset();
chat_stack::Reset();
hacks::shared::spam::Reset();
+ original(_this);
}
diff --git a/src/ipc.cpp b/src/ipc.cpp
index 56b6ec8c..ce4bce6c 100644
--- a/src/ipc.cpp
+++ b/src/ipc.cpp
@@ -5,11 +5,14 @@
* Author: nullifiedcat
*/
+
#include "ipc.h"
#include "common.h"
#include "hack.h"
+#ifdef IPC_ENABLED
+
namespace ipc {
std::atomic thread_running(false);
@@ -138,3 +141,5 @@ void UpdatePlayerlist() {
}
}
+
+#endif
diff --git a/src/ipc.h b/src/ipc.h
index 8d8a0285..5f7da201 100644
--- a/src/ipc.h
+++ b/src/ipc.h
@@ -5,6 +5,8 @@
* Author: nullifiedcat
*/
+#ifdef IPC_ENABLED
+
#ifndef IPC_H_
#define IPC_H_
@@ -58,3 +60,5 @@ void UpdatePlayerlist();
}
#endif /* IPC_H_ */
+
+#endif
diff --git a/src/offsets.hpp b/src/offsets.hpp
new file mode 100644
index 00000000..61a90415
--- /dev/null
+++ b/src/offsets.hpp
@@ -0,0 +1,65 @@
+/*
+ * offsets.hpp
+ *
+ * Created on: May 4, 2017
+ * Author: nullifiedcat
+ */
+
+#ifndef OFFSETS_HPP_
+#define OFFSETS_HPP_
+
+#include
+#include
+
+enum class platform {
+ PLATFORM_LINUX,
+ PLATFORM_WINDOWS,
+ PLATFORM_OSX,
+ PLATFORM_UNSUPPORTED
+};
+
+#ifdef LINUX
+constexpr platform PLATFORM = platform::PLATFORM_LINUX;
+#else
+constexpr platform PLATFORM = platform::PLATFORM_UNSUPPORTED;
+#endif
+
+struct offsets {
+ static constexpr uint32_t PlatformOffset(uint32_t offset_linux, uint32_t offset_windows, uint32_t offset_osx) {
+ uint32_t result = -1;
+ switch (PLATFORM) {
+ case platform::PLATFORM_LINUX:
+ result = offset_linux; break;
+ case platform::PLATFORM_WINDOWS:
+ result = offset_windows; break;
+ case platform::PLATFORM_OSX:
+ result = offset_osx; break;
+ }
+ // pCompileError.
+ //static_assert(result != -1, "No offset defined for this platform!");
+ return result;
+ }
+ static constexpr uint32_t GetUserCmd() { return PlatformOffset(8, -1, -1); }
+ static constexpr uint32_t ShouldDraw() { return PlatformOffset(136, -1, -1); }
+ static constexpr uint32_t DrawModelExecute() { return PlatformOffset(19, -1, -1); }
+ static constexpr uint32_t GetClientName() { return PlatformOffset(44, -1, -1); }
+ static constexpr uint32_t ProcessSetConVar() { return PlatformOffset(4, -1, -1); }
+ static constexpr uint32_t ProcessGetCvarValue() { return PlatformOffset(29, -1, -1); }
+ static constexpr uint32_t GetFriendPersonaName() { return PlatformOffset(7, -1, -1); }
+ static constexpr uint32_t CreateMove() { return PlatformOffset(22, -1, -1); }
+ static constexpr uint32_t PaintTraverse() { return PlatformOffset(42, -1, -1); }
+ static constexpr uint32_t OverrideView() { return PlatformOffset(17, -1, -1); }
+ static constexpr uint32_t FrameStageNotify() { return PlatformOffset(35, -1, -1); }
+ static constexpr uint32_t DispatchUserMessage() { return PlatformOffset(36, -1, -1); }
+ static constexpr uint32_t CanPacket() { return PlatformOffset(57, -1, -1); }
+ static constexpr uint32_t SendNetMsg() { return PlatformOffset(41, -1, -1); }
+ static constexpr uint32_t Shutdown() { return PlatformOffset(37, -1, -1); }
+ static constexpr uint32_t IN_KeyEvent() { return PlatformOffset(20, -1, -1); }
+ static constexpr uint32_t HandleInputEvent() { return PlatformOffset(78, -1, -1); }
+ static constexpr uint32_t LevelInit() { return PlatformOffset(23, -1, -1); }
+ static constexpr uint32_t LevelShutdown() { return PlatformOffset(24, -1, -1); }
+ static constexpr uint32_t BeginFrame() { return PlatformOffset(5, -1, -1); }
+
+};
+
+#endif /* OFFSETS_HPP_ */
diff --git a/src/playerlist.cpp b/src/playerlist.cpp
index f3d11241..145222a8 100644
--- a/src/playerlist.cpp
+++ b/src/playerlist.cpp
@@ -8,6 +8,10 @@
#include "playerlist.hpp"
#include "common.h"
+#include
+#include
+#include
+
namespace playerlist {
std::unordered_map data {};