Merge remote-tracking branch 'origin/rf_improve' into octopus-merge
This commit is contained in:
commit
323ce3153b
@ -5,7 +5,10 @@
|
||||
<AutoVariable width="fill" target="warp.speed" label="Warp speed" tooltip="The discharge speed (0.5 = +50%, 2 = +200%. +2300% is the maximum possible)."/>
|
||||
<AutoVariable width="fill" target="warp.key" label="Warp key" tooltip="Pressing this key will use all stored ticks to accelerate you."/>
|
||||
<AutoVariable width="fill" target="warp.charge-key" label="Charge key" tooltip="Hold down this key to charge warp."/>
|
||||
<AutoVariable width="fill" target="warp.draw" label="Draw warp" tooltip="Draws a bar indicating your warp readiness."/>
|
||||
<AutoVariable width="fill" target="warp.draw" label="Draw warp text"/>
|
||||
<AutoVariable width="fill" target="warp.draw-info.x" label="Text x position"/>
|
||||
<AutoVariable width="fill" target="warp.draw-info.y" label="Text y position"/>
|
||||
<AutoVariable width="fill" target="warp.draw-bar" label="Draw warp bar" tooltip="Draws a bar indicating your warp readiness."/>
|
||||
<AutoVariable width="fill" target="warp.bar-size" label="Bar size"/>
|
||||
<AutoVariable width="fill" target="warp.bar-x" label="X position"/>
|
||||
<AutoVariable width="fill" target="warp.bar-y" label="Y position"/>
|
||||
@ -25,6 +28,8 @@
|
||||
<Box padding="12 6 6 6" width="content" height="content" name="Rapidfire" x="210">
|
||||
<List width="185">
|
||||
<AutoVariable width="fill" target="warp.rapidfire" label="Enable Rapidfire" tooltip="Allows you to shoot multiple shots at once or reduce time between shots."/>
|
||||
<AutoVariable width="fill" target="warp.rapidfire.distance" label="Minimum distance" tooltip="How close an enemy has to be to be able to rapidfire. 0 is off."/>
|
||||
<AutoVariable width="fill" target="warp.rapidfire.zoom" label="Enable Rapid zoom" tooltip="Allows you to instantly zoom in."/>
|
||||
<AutoVariable width="fill" target="warp.rapidfire.no-movement" label="Prevent movement in rapidfire" tooltip="Attempt to not move when Rapidfiring."/>
|
||||
<AutoVariable width="fill" target="warp.rapidfire.key" label="Rapidfire key" tooltip="Optional. If set you can use this key to control when to rapidfire."/>
|
||||
<LabeledObject width="fill" label="Rapidfire key mode" tooltip="Controls what the rapidfire key does.">
|
||||
@ -35,6 +40,14 @@
|
||||
<Option name="Toggle" value="3"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Disable Rapidfire on">
|
||||
<Select target="warp.rapidfire.disable-on">
|
||||
<Option name="None" value="0"/>
|
||||
<Option name="Projectile" value="1"/>
|
||||
<Option name="Melee" value="2"/>
|
||||
<Option name="Projectile + Melee" value="3"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
</List>
|
||||
</Box>
|
||||
</Tab>
|
||||
|
@ -17,6 +17,7 @@ class ISurface;
|
||||
class IPanel;
|
||||
} // namespace vgui
|
||||
|
||||
class IToolFrameworkInternal;
|
||||
class ISteamClient;
|
||||
class ISteamFriends;
|
||||
class IVEngineClient013;
|
||||
@ -95,6 +96,7 @@ extern IUniformRandomStream *g_pUniformStream;
|
||||
extern int *g_PredictionRandomSeed;
|
||||
extern IFileSystem *g_IFileSystem;
|
||||
extern IMDLCache *g_IMDLCache;
|
||||
extern IToolFrameworkInternal *g_IToolFramework;
|
||||
|
||||
void CreateInterfaces();
|
||||
void CreateEarlyInterfaces();
|
||||
|
@ -207,6 +207,7 @@ public:
|
||||
offset_t m_iPlayerIndex;
|
||||
offset_t m_hTargetPlayer;
|
||||
offset_t m_flResetTime;
|
||||
offset_t m_flMaxspeed;
|
||||
};
|
||||
|
||||
extern NetVars netvar;
|
||||
|
@ -228,4 +228,8 @@ struct offsets
|
||||
{
|
||||
return PlatformOffset(0x2fb8, undefined, undefined);
|
||||
}
|
||||
static constexpr uint32_t Think()
|
||||
{
|
||||
return PlatformOffset(27, undefined, undefined);
|
||||
}
|
||||
};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <gametrace.h>
|
||||
#include <engine/IEngineTrace.h>
|
||||
#include <materialsystem/imaterialvar.h>
|
||||
#include <toolframework/itoolframework.h>
|
||||
#include <globalvars_base.h>
|
||||
#include <materialsystem/itexture.h>
|
||||
#include <engine/ivmodelinfo.h>
|
||||
|
@ -3,6 +3,8 @@
|
||||
class INetMessage;
|
||||
namespace hacks::tf2::warp
|
||||
{
|
||||
extern bool in_rapidfire;
|
||||
extern bool in_warp;
|
||||
void SendNetMessage(INetMessage &msg);
|
||||
void CL_SendMove_hook();
|
||||
} // namespace hacks::tf2::warp
|
||||
|
@ -121,6 +121,7 @@ Vector getShootPos(Vector angle);
|
||||
Vector GetForwardVector(Vector origin, Vector viewangles, float distance, CachedEntity *punch_entity = nullptr);
|
||||
Vector GetForwardVector(float distance, CachedEntity *punch_entity = nullptr);
|
||||
CachedEntity *getClosestEntity(Vector vec);
|
||||
CachedEntity *getClosestNonlocalEntity(Vector vec);
|
||||
bool IsSentryBuster(CachedEntity *ent);
|
||||
std::unique_ptr<char[]> strfmt(const char *fmt, ...);
|
||||
// TODO move that to weaponid.h
|
||||
@ -218,7 +219,7 @@ template <typename T, typename... Targs> void format_internal(std::stringstream
|
||||
stream << value;
|
||||
format_internal(stream, args...);
|
||||
}
|
||||
template <typename... Args> std::string format(const Args &... args)
|
||||
template <typename... Args> std::string format(const Args &...args)
|
||||
{
|
||||
std::stringstream stream;
|
||||
format_internal(stream, args...);
|
||||
|
@ -75,4 +75,5 @@ extern VMTHook materialsystem;
|
||||
extern VMTHook enginevgui;
|
||||
extern VMTHook vstd;
|
||||
extern VMTHook eventmanager2;
|
||||
extern VMTHook toolbox;
|
||||
} // namespace hooks
|
||||
|
@ -15,10 +15,13 @@ enum ec_types
|
||||
CreateMoveLate,
|
||||
/* This kind of CreateMove will run earlier than "CreateMove" events
|
||||
* and guranteed to run before EnginePrediction
|
||||
* This is NEEDED for any kind of movement
|
||||
*/
|
||||
CreateMove_NoEnginePred,
|
||||
/* Note: this is still CreateMove, just ran before original is called, needed in some cases like changing tickcount before original gets called*/
|
||||
CreateMoveEarly,
|
||||
/* Note: This will replace the normal CreateMove when we are warping. Used for performance purposes. */
|
||||
CreateMoveWarp,
|
||||
#if ENABLE_VISUALS
|
||||
Draw,
|
||||
#endif
|
||||
|
@ -94,6 +94,8 @@ DECLARE_HOOKED_METHOD(EmitSound2, void, void *, IRecipientFilter &, int, int, co
|
||||
DECLARE_HOOKED_METHOD(EmitSound3, void, void *, IRecipientFilter &, int, int, int, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
|
||||
// g_IPrediction
|
||||
DECLARE_HOOKED_METHOD(RunCommand, void, IPrediction *, IClientEntity *, CUserCmd *, IMoveHelper *);
|
||||
// g_IToolFramework
|
||||
DECLARE_HOOKED_METHOD(Think, void, IToolFrameworkInternal *, bool);
|
||||
} // namespace hooked_methods
|
||||
|
||||
// TODO
|
||||
|
6
include/hooks/Think.hpp
Normal file
6
include/hooks/Think.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
namespace hooked_methods
|
||||
{
|
||||
// Update Prediction, Used by warp/Doubletap aswell
|
||||
void UpdatePred();
|
||||
} // namespace hooked_methods
|
@ -26,6 +26,8 @@ public:
|
||||
|
||||
// Start of CM
|
||||
void Update();
|
||||
// After prediction
|
||||
void UpdateEye();
|
||||
// End of CM
|
||||
void UpdateEnd();
|
||||
int team;
|
||||
|
@ -82,6 +82,13 @@ public:
|
||||
typedef bool (*fn_t)(IClientEntity *, bool, IClientEntity *);
|
||||
return vfunc<fn_t>(self, offsets::PlatformOffset(490, offsets::undefined, 490), 0)(self, unknown1, unknown2);
|
||||
}
|
||||
inline static float ApplyFireDelay(IClientEntity *self, float delay)
|
||||
{
|
||||
typedef float (*ApplyFireDelay_t)(IClientEntity *, float);
|
||||
static auto signature = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 6C C7 45 ? 00 00 00 00 A1 ? ? ? ? C7 45 ? 00 00 00 00 8B 5D ? 85 C0 0F 84 ? ? ? ? 8D 55 ? 89 04 24 31 F6 89 54 24 ? C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? C7 44 24 ? 6B 00 00 00 C7 44 24 ? ? ? ? ? C7 44 24 ? 00 00 00 00 C7 44 24 ? 00 00 00 00 C7 44 24 ? 00 00 00 00 C7 44 24 ? 00 00 00 00 FF 50 ? A1 ? ? ? ? 8B 0D ? ? ? ? 8B 55 ? 89 45 ? 8B 45 ? 85 C9 89 55 ? 89 45 ? 0F 85 ? ? ? ? 85 DB 0F 84 ? ? ? ? 8B 7B ? 85 FF 0F 84 ? ? ? ? C7 04 24 ? ? ? ? E8 ? ? ? ? 89 45 ? 8B 07 89 3C 24 FF 10 8B 7D ? 8B 10 C7 44 24 ? 00 00 00 00 89 5C 24 ? C7 44 24 ? ? ? ? ? 89 7C 24 ? 89 04 24 FF 52 ? D9 5D ? F3 0F 10 45 ? F3 0F 11 04 24 E8 ? ? ? ? D9 5D");
|
||||
static ApplyFireDelay_t ApplyFireDelay_fn = (ApplyFireDelay_t) signature;
|
||||
return ApplyFireDelay_fn(self, delay);
|
||||
}
|
||||
inline static void AddToCritBucket(IClientEntity *self, float value)
|
||||
{
|
||||
constexpr float max_bucket_capacity = 1000.0f;
|
||||
|
@ -18,44 +18,45 @@
|
||||
|
||||
// class ISteamFriends002;
|
||||
|
||||
IVModelRender *g_IVModelRender = nullptr;
|
||||
ISteamClient *g_ISteamClient = nullptr;
|
||||
ISteamFriends *g_ISteamFriends = nullptr;
|
||||
IVEngineClient013 *g_IEngine = nullptr;
|
||||
void *demoplayer = nullptr;
|
||||
IEngineSound *g_ISoundEngine = nullptr;
|
||||
vgui::ISurface *g_ISurface = nullptr;
|
||||
vgui::IPanel *g_IPanel = nullptr;
|
||||
IClientEntityList *g_IEntityList = nullptr;
|
||||
ICvar *g_ICvar = nullptr;
|
||||
IGameEventManager2 *g_IEventManager2 = nullptr;
|
||||
IBaseClientDLL *g_IBaseClient = nullptr;
|
||||
IEngineTrace *g_ITrace = nullptr;
|
||||
IVModelInfoClient *g_IModelInfo = nullptr;
|
||||
IInputSystem *g_IInputSystem = nullptr;
|
||||
CGlobalVarsBase **rg_GlobalVars = nullptr;
|
||||
IPrediction *g_IPrediction = nullptr;
|
||||
IGameMovement *g_IGameMovement = nullptr;
|
||||
IInput *g_IInput = nullptr;
|
||||
ISteamUser *g_ISteamUser = nullptr;
|
||||
IAchievementMgr *g_IAchievementMgr = nullptr;
|
||||
ISteamUserStats *g_ISteamUserStats = nullptr;
|
||||
IStudioRender *g_IStudioRender = nullptr;
|
||||
IVDebugOverlay *g_IVDebugOverlay = nullptr;
|
||||
IMaterialSystemFixed *g_IMaterialSystem = nullptr;
|
||||
IVRenderView *g_IVRenderView = nullptr;
|
||||
IMaterialSystem *g_IMaterialSystemHL = nullptr;
|
||||
IMoveHelperServer *g_IMoveHelperServer = nullptr;
|
||||
CBaseClientState *g_IBaseClientState = nullptr;
|
||||
IGameEventManager *g_IGameEventManager = nullptr;
|
||||
TFGCClientSystem *g_TFGCClientSystem = nullptr;
|
||||
CHud *g_CHUD = nullptr;
|
||||
CGameRules *g_pGameRules = nullptr;
|
||||
IEngineVGui *g_IEngineVGui = nullptr;
|
||||
IUniformRandomStream *g_pUniformStream = nullptr;
|
||||
int *g_PredictionRandomSeed = nullptr;
|
||||
IFileSystem *g_IFileSystem = nullptr;
|
||||
IMDLCache *g_IMDLCache = nullptr;
|
||||
IVModelRender *g_IVModelRender = nullptr;
|
||||
ISteamClient *g_ISteamClient = nullptr;
|
||||
ISteamFriends *g_ISteamFriends = nullptr;
|
||||
IVEngineClient013 *g_IEngine = nullptr;
|
||||
void *demoplayer = nullptr;
|
||||
IEngineSound *g_ISoundEngine = nullptr;
|
||||
vgui::ISurface *g_ISurface = nullptr;
|
||||
vgui::IPanel *g_IPanel = nullptr;
|
||||
IClientEntityList *g_IEntityList = nullptr;
|
||||
ICvar *g_ICvar = nullptr;
|
||||
IGameEventManager2 *g_IEventManager2 = nullptr;
|
||||
IBaseClientDLL *g_IBaseClient = nullptr;
|
||||
IEngineTrace *g_ITrace = nullptr;
|
||||
IVModelInfoClient *g_IModelInfo = nullptr;
|
||||
IInputSystem *g_IInputSystem = nullptr;
|
||||
CGlobalVarsBase **rg_GlobalVars = nullptr;
|
||||
IPrediction *g_IPrediction = nullptr;
|
||||
IGameMovement *g_IGameMovement = nullptr;
|
||||
IInput *g_IInput = nullptr;
|
||||
ISteamUser *g_ISteamUser = nullptr;
|
||||
IAchievementMgr *g_IAchievementMgr = nullptr;
|
||||
ISteamUserStats *g_ISteamUserStats = nullptr;
|
||||
IStudioRender *g_IStudioRender = nullptr;
|
||||
IVDebugOverlay *g_IVDebugOverlay = nullptr;
|
||||
IMaterialSystemFixed *g_IMaterialSystem = nullptr;
|
||||
IVRenderView *g_IVRenderView = nullptr;
|
||||
IMaterialSystem *g_IMaterialSystemHL = nullptr;
|
||||
IMoveHelperServer *g_IMoveHelperServer = nullptr;
|
||||
CBaseClientState *g_IBaseClientState = nullptr;
|
||||
IGameEventManager *g_IGameEventManager = nullptr;
|
||||
TFGCClientSystem *g_TFGCClientSystem = nullptr;
|
||||
CHud *g_CHUD = nullptr;
|
||||
CGameRules *g_pGameRules = nullptr;
|
||||
IEngineVGui *g_IEngineVGui = nullptr;
|
||||
IUniformRandomStream *g_pUniformStream = nullptr;
|
||||
int *g_PredictionRandomSeed = nullptr;
|
||||
IFileSystem *g_IFileSystem = nullptr;
|
||||
IMDLCache *g_IMDLCache = nullptr;
|
||||
IToolFrameworkInternal *g_IToolFramework = nullptr;
|
||||
|
||||
template <typename T> T *BruteforceInterface(std::string name, sharedobj::SharedObject &object, int start = 0)
|
||||
{
|
||||
@ -163,6 +164,7 @@ void CreateInterfaces()
|
||||
|
||||
g_IPanel = BruteforceInterface<vgui::IPanel>("VGUI_Panel", sharedobj::vgui2());
|
||||
g_pUniformStream = **(IUniformRandomStream ***) (gSignatures.GetVstdSignature("A3 ? ? ? ? C3 89 F6") + 0x1);
|
||||
g_IToolFramework = BruteforceInterface<IToolFrameworkInternal>("VTOOLFRAMEWORKVERSION", sharedobj::engine());
|
||||
#if ENABLE_VISUALS
|
||||
g_IVDebugOverlay = BruteforceInterface<IVDebugOverlay>("VDebugOverlay", sharedobj::engine());
|
||||
g_ISurface = BruteforceInterface<vgui::ISurface>("VGUI_Surface", sharedobj::vguimatsurface());
|
||||
|
@ -33,6 +33,7 @@ void NetVars::Init()
|
||||
|
||||
IF_GAME(IsTF2())
|
||||
{
|
||||
this->m_flMaxspeed = gNetvars.get_offset("DT_BasePlayer", "m_flMaxspeed");
|
||||
res_iTeam = gNetvars.get_offset("DT_TFPlayerResource", "baseclass", "m_iTeam");
|
||||
res_bAlive = gNetvars.get_offset("DT_TFPlayerResource", "baseclass", "m_bAlive");
|
||||
this->res_iMaxBuffedHealth = gNetvars.get_offset("DT_TFPlayerResource", "m_iMaxBuffedHealth");
|
||||
|
@ -257,6 +257,10 @@ void hack::Hook()
|
||||
hooks::prediction.HookMethod(HOOK_ARGS(RunCommand));
|
||||
hooks::prediction.Apply();
|
||||
|
||||
hooks::toolbox.Set(g_IToolFramework);
|
||||
hooks::toolbox.HookMethod(HOOK_ARGS(Think));
|
||||
hooks::toolbox.Apply();
|
||||
|
||||
#if ENABLE_VISUALS
|
||||
sdl_hooks::applySdlHooks();
|
||||
#endif
|
||||
|
@ -1594,6 +1594,7 @@ static InitRoutine EC([]() {
|
||||
EC::Register(EC::LevelInit, Reset, "INIT_Aimbot", EC::average);
|
||||
EC::Register(EC::LevelShutdown, Reset, "RESET_Aimbot", EC::average);
|
||||
EC::Register(EC::CreateMove, CreateMove, "CM_Aimbot", EC::late);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "CMW_Aimbot", EC::late);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, DrawText, "DRAW_Aimbot", EC::average);
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@ static settings::Boolean debug{ "anti-anti-aim.debug.enable", "false" };
|
||||
std::unordered_map<unsigned, brutedata> resolver_map;
|
||||
std::array<CachedEntity *, 32> sniperdot_array;
|
||||
|
||||
static inline void modifyAnlges()
|
||||
static inline void modifyAngles()
|
||||
{
|
||||
for (int i = 1; i <= g_IEngine->GetMaxClients(); i++)
|
||||
{
|
||||
@ -55,7 +55,7 @@ void frameStageNotify(ClientFrameStage_t stage)
|
||||
return;
|
||||
if (stage == FRAME_NET_UPDATE_POSTDATAUPDATE_START)
|
||||
{
|
||||
modifyAnlges();
|
||||
modifyAngles();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -259,8 +259,10 @@ static InitRoutine init([]() {
|
||||
hook();
|
||||
EC::Register(EC::Shutdown, shutdown, "antiantiaim_shutdown");
|
||||
EC::Register(EC::CreateMove, CreateMove, "cm_antiantiaim");
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_antiantiaim");
|
||||
#if ENABLE_TEXTMODE
|
||||
EC::Register(EC::CreateMove, modifyAnlges, "cm_textmodeantiantiaim");
|
||||
EC::Register(EC::CreateMove, modifyAngles, "cm_textmodeantiantiaim");
|
||||
EC::Register(EC::CreateMoveWarp, modifyAngles, "cmw_textmodeantiantiaim");
|
||||
#endif
|
||||
});
|
||||
} // namespace hacks::shared::anti_anti_aim
|
||||
|
@ -133,5 +133,8 @@ void CreateMove()
|
||||
noaa = false;
|
||||
}
|
||||
|
||||
static InitRoutine EC([]() { EC::Register(EC::CreateMove, CreateMove, "antibackstab", EC::late); });
|
||||
static InitRoutine EC([]() {
|
||||
EC::Register(EC::CreateMove, CreateMove, "antibackstab", EC::late);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "antibackstab_w", EC::late);
|
||||
});
|
||||
} // namespace hacks::tf2::antibackstab
|
||||
|
@ -35,5 +35,8 @@ void cm()
|
||||
}
|
||||
}
|
||||
}
|
||||
static InitRoutine EC([]() { EC::Register(EC::CreateMove, cm, "antidisguise", EC::average); });
|
||||
static InitRoutine EC([]() {
|
||||
EC::Register(EC::CreateMove, cm, "antidisguise", EC::average);
|
||||
EC::Register(EC::CreateMoveWarp, cm, "antidisguise_w", EC::average);
|
||||
});
|
||||
} // namespace hacks::tf2::antidisguise
|
||||
|
@ -356,5 +356,8 @@ void CreateMove()
|
||||
}
|
||||
}
|
||||
|
||||
static InitRoutine EC([]() { EC::Register(EC::CreateMove, CreateMove, "autobackstab", EC::average); });
|
||||
static InitRoutine EC([]() {
|
||||
EC::Register(EC::CreateMove, CreateMove, "autobackstab", EC::average);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "autobackstab_w", EC::average);
|
||||
});
|
||||
} // namespace hacks::tf2::autobackstab
|
||||
|
@ -238,6 +238,7 @@ void Draw()
|
||||
|
||||
static InitRoutine EC([]() {
|
||||
EC::Register(EC::CreateMove, CreateMove, "cm_auto_reflect", EC::average);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_auto_reflect", EC::average);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, Draw, "draw_auto_reflect", EC::average);
|
||||
#endif
|
||||
|
@ -549,7 +549,9 @@ std::optional<std::pair<CachedEntity *, BacktrackData>> getClosestTick(Vector ve
|
||||
|
||||
static InitRoutine init([]() {
|
||||
EC::Register(EC::CreateMove, CreateMove, "backtrack_cm", EC::early);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "backtrack_cmw", EC::early);
|
||||
EC::Register(EC::CreateMove, CreateMoveLate, "backtrack_cmlate", EC::very_late);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMoveLate, "backtrack_cmwlate", EC::very_late);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, Draw, "backtrack_draw");
|
||||
#endif
|
||||
|
@ -56,5 +56,5 @@ static void CreateMove()
|
||||
if (!jump)
|
||||
ticks_last_jump = 0;
|
||||
}
|
||||
static InitRoutine EC([]() { EC::Register(EC::CreateMove_NoEnginePred, CreateMove, "Bunnyhop", EC::average); });
|
||||
static InitRoutine EC([]() { EC::Register(EC::CreateMove_NoEnginePred, CreateMove, "Bunnyhop", EC::early); });
|
||||
} // namespace hacks::shared::bunnyhop
|
||||
|
@ -774,7 +774,7 @@ void rvarCallback(settings::VariableBase<int> &var, int after)
|
||||
}
|
||||
|
||||
static InitRoutine runinit([]() {
|
||||
EC::Register(EC::CreateMove, cm, "cm_followbot", EC::average);
|
||||
EC::Register(EC::CreateMove_NoEnginePred, cm, "cm_followbot", EC::average);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, draw, "draw_followbot", EC::average);
|
||||
#endif
|
||||
|
@ -960,6 +960,7 @@ static InitRoutine init([]() {
|
||||
teammatesPushaway = g_ICvar->FindVar("tf_avoidteammates_pushaway");
|
||||
EC::Register(EC::Shutdown, Shutdown, "draw_local_player", EC::average);
|
||||
EC::Register(EC::CreateMove, CreateMove, "cm_misc_hacks", EC::average);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_misc_hacks", EC::average);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, Draw, "draw_misc_hacks", EC::average);
|
||||
#if !ENFORCE_STREAM_SAFETY
|
||||
|
@ -589,6 +589,7 @@ float CAM_CapYaw_Hook(IInput *this_, float fVal)
|
||||
#define foffset(p, i) ((unsigned char *) &p)[i]
|
||||
static InitRoutine init([]() {
|
||||
EC::Register(EC::CreateMove, CreateMove, "cm_miscaimbot", EC::average);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_miscaimbot", EC::average);
|
||||
|
||||
static auto signature = gSignatures.GetClientSignature("55 89 E5 53 83 EC 14 E8 ? ? ? ? 85 C0 74 ? 8D 98 ? ? ? ? C7 44 24 ? 11 00 00 00");
|
||||
|
||||
|
@ -1395,6 +1395,7 @@ ObjectDestroyListener &listener()
|
||||
static InitRoutine runinit([]() {
|
||||
g_IEventManager2->AddListener(&listener(), "object_destroyed", false);
|
||||
EC::Register(EC::CreateMove, CreateMove, "navbot", EC::early);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "navbot_w", EC::early);
|
||||
EC::Register(
|
||||
EC::Shutdown, []() { g_IEventManager2->RemoveListener(&listener()); }, "navbot_shutdown");
|
||||
});
|
||||
|
@ -627,5 +627,8 @@ void Draw()
|
||||
{
|
||||
}
|
||||
|
||||
static InitRoutine EC([]() { EC::Register(EC::CreateMove, CreateMove, "triggerbot", EC::average); });
|
||||
static InitRoutine EC([]() {
|
||||
EC::Register(EC::CreateMove, CreateMove, "triggerbot", EC::average);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "triggerbot_w", EC::average);
|
||||
});
|
||||
} // namespace hacks::shared::triggerbot
|
||||
|
@ -1219,7 +1219,7 @@ static void cm()
|
||||
}
|
||||
|
||||
static InitRoutine init([]() {
|
||||
EC::Register(EC::CreateMove, cm, "cm_walkbot", EC::average);
|
||||
EC::Register(EC::CreateMove_NoEnginePred, cm, "cm_walkbot", EC::average);
|
||||
EC::Register(EC::LevelInit, OnLevelInit, "init_walkbot", EC::average);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, Draw, "draw_walkbot", EC::average);
|
||||
|
@ -14,17 +14,22 @@
|
||||
#include "DetourHook.hpp"
|
||||
#include "WeaponData.hpp"
|
||||
#include "MiscTemporary.hpp"
|
||||
#include "Think.hpp"
|
||||
|
||||
namespace hacks::tf2::warp
|
||||
{
|
||||
static settings::Boolean enabled{ "warp.enabled", "false" };
|
||||
static settings::Boolean no_movement{ "warp.rapidfire.no-movement", "true" };
|
||||
static settings::Boolean rapidfire{ "warp.rapidfire", "false" };
|
||||
static settings::Int distance{ "warp.rapidfire.distance", "0" };
|
||||
static settings::Boolean rapidfire_zoom{ "warp.rapidfire.zoom", "true" };
|
||||
static settings::Boolean wait_full{ "warp.rapidfire.wait-full", "true" };
|
||||
static settings::Button rapidfire_key{ "warp.rapidfire.key", "<null>" };
|
||||
static settings::Int rapidfire_key_mode{ "warp.rapidfire.key-mode", "1" };
|
||||
static settings::Int rf_disable_on{ "warp.rapidfire.disable-on", "0" };
|
||||
static settings::Float speed{ "warp.speed", "23" };
|
||||
static settings::Boolean draw{ "warp.draw", "false" };
|
||||
static settings::Boolean draw_bar{ "warp.draw-bar", "false" };
|
||||
static settings::Button warp_key{ "warp.key", "<null>" };
|
||||
static settings::Button charge_key{ "warp.charge-key", "<null>" };
|
||||
static settings::Boolean charge_passively{ "warp.charge-passively", "true" };
|
||||
@ -42,13 +47,16 @@ static settings::Boolean warp_right{ "warp.on-hit.right", "true" };
|
||||
// Hidden control rvars for communtiy servers
|
||||
static settings::Int maxusrcmdprocessticks("warp.maxusrcmdprocessticks", "24");
|
||||
|
||||
bool in_warp = false;
|
||||
bool in_rapidfire = false;
|
||||
bool in_warp = false;
|
||||
bool in_rapidfire = false;
|
||||
bool in_rapidfire_zoom = false;
|
||||
// Should we choke the packet or not? (in rapidfire)
|
||||
bool choke_packet = false;
|
||||
// Were we warping last tick?
|
||||
// why is this needed at all, why do i have to write this janky bs
|
||||
bool was_in_warp = false;
|
||||
// Is this the first warp tick?
|
||||
bool first_warp_tick = false;
|
||||
|
||||
// How many ticks we have to add to our CreateMove packet
|
||||
int ticks_to_add = 0;
|
||||
@ -60,6 +68,34 @@ void warpLogic();
|
||||
static settings::Int size{ "warp.bar-size", "100" };
|
||||
static settings::Int bar_x{ "warp.bar-x", "50" };
|
||||
static settings::Int bar_y{ "warp.bar-y", "200" };
|
||||
static settings::Int draw_string_x{ "warp.draw-info.x", "8" };
|
||||
static settings::Int draw_string_y{ "warp.draw-info.y", "800" };
|
||||
|
||||
// Need our own Text drawing
|
||||
static std::array<std::string, 32> warp_strings;
|
||||
static size_t warp_strings_count{ 0 };
|
||||
static std::array<rgba_t, 32> warp_strings_colors{ colors::empty };
|
||||
|
||||
void AddWarpString(const std::string &string, const rgba_t &color)
|
||||
{
|
||||
warp_strings[warp_strings_count] = string;
|
||||
warp_strings_colors[warp_strings_count] = color;
|
||||
++warp_strings_count;
|
||||
}
|
||||
|
||||
void DrawWarpStrings()
|
||||
{
|
||||
float x = *draw_string_x;
|
||||
float y = *draw_string_y;
|
||||
for (size_t i = 0; i < warp_strings_count; ++i)
|
||||
{
|
||||
float sx, sy;
|
||||
fonts::menu->stringSize(warp_strings[i], &sx, &sy);
|
||||
draw::String(x, y, warp_strings_colors[i], warp_strings[i].c_str(), *fonts::center_screen);
|
||||
y += fonts::center_screen->size + 1;
|
||||
}
|
||||
warp_strings_count = 0;
|
||||
}
|
||||
|
||||
static bool should_charge = false;
|
||||
static int warp_amount = 0;
|
||||
@ -109,6 +145,39 @@ bool UpdateRFKey()
|
||||
return allow_key;
|
||||
}
|
||||
|
||||
float getFireDelay()
|
||||
{
|
||||
auto weapon_data = GetWeaponData(RAW_ENT(LOCAL_W));
|
||||
return re::C_TFWeaponBase::ApplyFireDelay(RAW_ENT(LOCAL_W), weapon_data->m_flTimeFireDelay);
|
||||
}
|
||||
|
||||
bool canInstaZoom()
|
||||
{
|
||||
return in_rapidfire_zoom || (g_pLocalPlayer->holding_sniper_rifle && current_user_cmd->buttons & IN_ATTACK2 && !HasCondition<TFCond_Zoomed>(LOCAL_E) && CE_FLOAT(LOCAL_W, netvar.flNextSecondaryAttack) <= g_GlobalVars->curtime);
|
||||
}
|
||||
|
||||
// This is needed in order to make zoom/unzoom smooth even with insta zoom
|
||||
static int ignore_ticks = 0;
|
||||
|
||||
void handleSniper()
|
||||
{
|
||||
// Prevent unzooming
|
||||
if (in_rapidfire)
|
||||
{
|
||||
// Holding ready sniper rifle
|
||||
if (canInstaZoom())
|
||||
{
|
||||
current_user_cmd->buttons &= ~IN_ATTACK2;
|
||||
ignore_ticks = TIME_TO_TICKS(0.2f);
|
||||
}
|
||||
}
|
||||
else if (ignore_ticks)
|
||||
{
|
||||
ignore_ticks--;
|
||||
current_user_cmd->buttons &= ~IN_ATTACK2;
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldRapidfire()
|
||||
{
|
||||
if (!rapidfire)
|
||||
@ -138,9 +207,16 @@ bool shouldRapidfire()
|
||||
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFMinigun) && CE_INT(LOCAL_W, netvar.iWeaponState) != 3 && CE_INT(LOCAL_W, netvar.iWeaponState) != 2)
|
||||
return false;
|
||||
|
||||
// Check if enemies are close enough
|
||||
if (distance)
|
||||
{
|
||||
auto closest = getClosestNonlocalEntity(LOCAL_E->m_vecOrigin());
|
||||
if (!closest || closest->m_flDistance() > *distance)
|
||||
return false;
|
||||
}
|
||||
|
||||
// We do not have the amount of ticks needed, don't try it
|
||||
auto weapon_data = GetWeaponData(RAW_ENT(LOCAL_W));
|
||||
if (warp_amount < TIME_TO_TICKS(weapon_data->m_flTimeFireDelay) && (TIME_TO_TICKS(weapon_data->m_flTimeFireDelay) < *maxusrcmdprocessticks - 1 || (wait_full && warp_amount != GetMaxWarpTicks())))
|
||||
if (warp_amount < TIME_TO_TICKS(getFireDelay()) && (TIME_TO_TICKS(getFireDelay()) < *maxusrcmdprocessticks - 1 || (wait_full && warp_amount != GetMaxWarpTicks())))
|
||||
return false;
|
||||
|
||||
// Mouse 1 is held, do it.
|
||||
@ -150,6 +226,33 @@ bool shouldRapidfire()
|
||||
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFFlameThrower))
|
||||
buttons_pressed = current_user_cmd && current_user_cmd->buttons & IN_ATTACK2;
|
||||
|
||||
if (g_pLocalPlayer->holding_sniper_rifle)
|
||||
{
|
||||
// Run if m2 is pressed and sniper rifle is ready
|
||||
buttons_pressed = rapidfire_zoom && current_user_cmd && current_user_cmd->buttons & IN_ATTACK2 && canInstaZoom();
|
||||
// Heatmaker is the only exception here, it can also run on m1
|
||||
if (!buttons_pressed && HasCondition<TFCond_FocusBuff>(LOCAL_E))
|
||||
buttons_pressed = current_user_cmd && current_user_cmd->buttons & IN_ATTACK;
|
||||
}
|
||||
|
||||
switch (*rf_disable_on)
|
||||
{
|
||||
case 0: // Always on
|
||||
return buttons_pressed;
|
||||
case 1: // Disable on projectile
|
||||
if (g_pLocalPlayer->weapon_mode == weapon_projectile)
|
||||
return false;
|
||||
break;
|
||||
case 2: // Disable on melee
|
||||
if (g_pLocalPlayer->weapon_mode == weapon_melee)
|
||||
return false;
|
||||
break;
|
||||
case 3: // Disable on projectile and melee
|
||||
if (g_pLocalPlayer->weapon_mode == weapon_projectile || g_pLocalPlayer->weapon_mode == weapon_melee)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return buttons_pressed;
|
||||
}
|
||||
|
||||
@ -175,9 +278,17 @@ int GetWarpAmount(bool finalTick)
|
||||
{
|
||||
int max_extra_ticks = *maxusrcmdprocessticks - 1;
|
||||
|
||||
// Rapidfire ignores speed
|
||||
// Rapidfire ignores speed, and we send 15 + 7, aka maximum new + backup commands
|
||||
if (in_rapidfire)
|
||||
return max_extra_ticks;
|
||||
{
|
||||
// Warp right before the next shot
|
||||
float shot_time = getFireDelay();
|
||||
// This is to prevent Minigun/Pistol from only shooting once
|
||||
if (TICKS_TO_TIME(22) / shot_time >= 2)
|
||||
shot_time = TICKS_TO_TIME(23);
|
||||
return std::min(22, TIME_TO_TICKS(shot_time) - 2);
|
||||
// return 22;
|
||||
}
|
||||
// No limit set
|
||||
if (!*maxusrcmdprocessticks)
|
||||
max_extra_ticks = INT_MAX;
|
||||
@ -214,6 +325,8 @@ void Warp(float accumulated_extra_samples, bool finalTick)
|
||||
return;
|
||||
}
|
||||
|
||||
PROF_SECTION(warp_profiler);
|
||||
|
||||
int warp_ticks = warp_amount;
|
||||
if (warp_amount_override)
|
||||
warp_ticks = warp_amount_override;
|
||||
@ -230,6 +343,10 @@ void Warp(float accumulated_extra_samples, bool finalTick)
|
||||
int packets_sent = 1;
|
||||
for (int i = 0; i < calls; i++)
|
||||
{
|
||||
if (!i)
|
||||
first_warp_tick = true;
|
||||
else
|
||||
first_warp_tick = false;
|
||||
// Choke unless we sent too many already
|
||||
choke_packet = true;
|
||||
|
||||
@ -239,6 +356,8 @@ void Warp(float accumulated_extra_samples, bool finalTick)
|
||||
choke_packet = false;
|
||||
packets_sent = -1;
|
||||
}
|
||||
else
|
||||
hooked_methods::UpdatePred();
|
||||
|
||||
original(accumulated_extra_samples, finalTick);
|
||||
// Only decrease ticks for the final CL_Move tick
|
||||
@ -346,11 +465,6 @@ static bool was_overridden = false;
|
||||
static int ticks_in_revved = 0;
|
||||
static bool replaced_last_tick = false;
|
||||
|
||||
// Original Player origin and velocity, needed to not break because our engine pred.
|
||||
// We adjust it as the ticks go.
|
||||
static Vector original_origin;
|
||||
static Vector original_velocity;
|
||||
|
||||
// Reset all the revv data
|
||||
void resetRevvstate()
|
||||
{
|
||||
@ -416,20 +530,17 @@ void CL_Move_hook(float accumulated_extra_samples, bool bFinalTick)
|
||||
if (shouldRapidfire())
|
||||
{
|
||||
in_rapidfire = true;
|
||||
// Store original info
|
||||
original_origin = LOCAL_E->m_vecOrigin();
|
||||
velocity::EstimateAbsVelocity(RAW_ENT(LOCAL_E), original_velocity);
|
||||
// Zero out non z movement, it will just get messy else
|
||||
original_velocity.x = 0.0f;
|
||||
original_velocity.y = 0.0f;
|
||||
if (canInstaZoom())
|
||||
in_rapidfire_zoom = true;
|
||||
}
|
||||
|
||||
Warp(accumulated_extra_samples, bFinalTick);
|
||||
if (warp_amount < GetMaxWarpTicks())
|
||||
charged = false;
|
||||
in_warp = false;
|
||||
in_rapidfire = false;
|
||||
was_in_warp = true;
|
||||
in_warp = false;
|
||||
in_rapidfire = false;
|
||||
in_rapidfire_zoom = false;
|
||||
was_in_warp = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,24 +560,28 @@ void CreateMoveEarly()
|
||||
}
|
||||
}
|
||||
|
||||
// Fix the player origin after engine prediction, as it tries to predict the local
|
||||
// player linearly and just breaks doubletap when falling/moving
|
||||
void CreateMoveFixPrediction()
|
||||
{
|
||||
if (hacks::tf2::warp::in_rapidfire && current_user_cmd)
|
||||
{
|
||||
// Run very simple gravity calculations to ensure we do not miss
|
||||
if (no_movement)
|
||||
{
|
||||
static ConVar *sv_gravity = g_ICvar->FindVar("sv_gravity");
|
||||
Vector gravity{ 0.0f, 0.0f, -sv_gravity->GetFloat() };
|
||||
static float original_curtime = 0.0f;
|
||||
|
||||
auto mins = RAW_ENT(LOCAL_E)->GetCollideable()->OBBMins();
|
||||
auto maxs = RAW_ENT(LOCAL_E)->GetCollideable()->OBBMaxs();
|
||||
std::pair<Vector, Vector> minmax{ mins, maxs };
|
||||
PredictStep(original_origin, original_velocity, gravity, &minmax);
|
||||
// Restore from the engine prediction
|
||||
const_cast<Vector &>(RAW_ENT(LOCAL_E)->GetAbsOrigin()) = original_origin;
|
||||
// Run before prediction so we can do Faststop logic
|
||||
void CreateMovePrePredict()
|
||||
{
|
||||
// Attempt to stop fast in place to make movement smoother
|
||||
if (in_rapidfire && no_movement)
|
||||
FastStop();
|
||||
if (in_rapidfire_zoom)
|
||||
{
|
||||
float adjusted_curtime = g_GlobalVars->curtime;
|
||||
// Original curtime we need to use while in here
|
||||
if (first_warp_tick)
|
||||
original_curtime = g_GlobalVars->curtime;
|
||||
|
||||
// Update the data
|
||||
g_pLocalPlayer->bZoomed = true;
|
||||
g_pLocalPlayer->flZoomBegin = adjusted_curtime;
|
||||
// Do not exceed headshot time, we can only hs next tick
|
||||
if (adjusted_curtime - original_curtime > 0.2f)
|
||||
{
|
||||
g_pLocalPlayer->flZoomBegin = original_curtime - 0.2f - TICKS_TO_TIME(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -490,10 +605,6 @@ void CreateMove()
|
||||
|
||||
was_in_warp = false;
|
||||
}
|
||||
|
||||
// Attempt to stop fast in place to make movement smoother
|
||||
if (in_rapidfire && no_movement)
|
||||
FastStop();
|
||||
}
|
||||
|
||||
// Does all the logic related to charging and mode/settings specific actions like peek warp
|
||||
@ -507,6 +618,8 @@ void warpLogic()
|
||||
|
||||
// Handle minigun in rapidfire
|
||||
handleMinigun();
|
||||
// Handle sniper in rapidfire
|
||||
handleSniper();
|
||||
|
||||
// Charge logic
|
||||
if (!shouldWarp(false))
|
||||
@ -859,25 +972,44 @@ void SendNetMessage(INetMessage &msg)
|
||||
#if ENABLE_VISUALS
|
||||
void Draw()
|
||||
{
|
||||
if (!enabled || !draw)
|
||||
if (!enabled)
|
||||
return;
|
||||
if (!draw && !draw_bar)
|
||||
return;
|
||||
if (!g_IEngine->IsInGame())
|
||||
return;
|
||||
if (CE_BAD(LOCAL_E))
|
||||
return;
|
||||
if (!LOCAL_E->m_bAlivePlayer())
|
||||
return;
|
||||
|
||||
float charge_percent = (float) warp_amount / (float) GetMaxWarpTicks();
|
||||
// Draw background
|
||||
static rgba_t background_color = colors::FromRGBA8(96, 96, 96, 150);
|
||||
float bar_bg_x_size = *size * 2.0f;
|
||||
float bar_bg_y_size = *size / 5.0f;
|
||||
draw::Rectangle(*bar_x - 5.0f, *bar_y - 5.0f, bar_bg_x_size + 10.0f, bar_bg_y_size + 10.0f, background_color);
|
||||
// Draw bar
|
||||
rgba_t color_bar = colors::orange;
|
||||
if (GetMaxWarpTicks() == warp_amount)
|
||||
color_bar = colors::green;
|
||||
color_bar.a = 100 / 255.0f;
|
||||
draw::Rectangle(*bar_x, *bar_y, *size * 2.0f * charge_percent, *size / 5.0f, color_bar);
|
||||
if (draw)
|
||||
{
|
||||
rgba_t color = colors::orange;
|
||||
if (warp_amount == 0)
|
||||
color = colors::FromRGBA8(128.0f, 128.0f, 128.0f, 255.0f);
|
||||
else if (GetMaxWarpTicks() == warp_amount)
|
||||
color = colors::green;
|
||||
AddWarpString("Shiftable ticks: " + std::to_string(warp_amount), color);
|
||||
}
|
||||
|
||||
if (draw_bar)
|
||||
{
|
||||
float charge_percent = (float) warp_amount / (float) GetMaxWarpTicks();
|
||||
// Draw background
|
||||
static rgba_t background_color = colors::FromRGBA8(96, 96, 96, 150);
|
||||
float bar_bg_x_size = *size * 2.0f;
|
||||
float bar_bg_y_size = *size / 5.0f;
|
||||
draw::Rectangle(*bar_x - 5.0f, *bar_y - 5.0f, bar_bg_x_size + 10.0f, bar_bg_y_size + 10.0f, background_color);
|
||||
// Draw bar
|
||||
rgba_t color_bar = colors::orange;
|
||||
if (GetMaxWarpTicks() == warp_amount)
|
||||
color_bar = colors::green;
|
||||
color_bar.a = 100 / 255.0f;
|
||||
draw::Rectangle(*bar_x, *bar_y, *size * 2.0f * charge_percent, *size / 5.0f, color_bar);
|
||||
}
|
||||
|
||||
DrawWarpStrings();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -948,8 +1080,9 @@ static InitRoutine init([]() {
|
||||
cl_move_detour.Init(cl_move_addr, (void *) CL_Move_hook);
|
||||
|
||||
EC::Register(EC::LevelShutdown, LevelShutdown, "warp_levelshutdown");
|
||||
EC::Register(EC::CreateMove, CreateMoveFixPrediction, "warp_createmove_fixpred", EC::very_early);
|
||||
EC::Register(EC::CreateMove, CreateMove, "warp_createmove", EC::very_late);
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove, "warp_createmovew", EC::very_late);
|
||||
EC::Register(EC::CreateMove_NoEnginePred, CreateMovePrePredict, "warp_prepredict");
|
||||
EC::Register(EC::CreateMoveEarly, CreateMoveEarly, "warp_createmove_early", EC::very_early);
|
||||
g_IEventManager2->AddListener(&listener, "player_hurt", false);
|
||||
EC::Register(
|
||||
|
@ -705,6 +705,22 @@ CachedEntity *getClosestEntity(Vector vec)
|
||||
return best_ent;
|
||||
}
|
||||
|
||||
CachedEntity *getClosestNonlocalEntity(Vector vec)
|
||||
{
|
||||
float distance = FLT_MAX;
|
||||
CachedEntity *best_ent = nullptr;
|
||||
for (int i = 1; i <= g_IEngine->GetMaxClients(); i++)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_VALID(ent) && ent->m_IDX != g_pLocalPlayer->entity_idx && ent->m_vecDormantOrigin() && ent->m_bAlivePlayer() && ent->m_bEnemy() && vec.DistTo(ent->m_vecOrigin()) < distance)
|
||||
{
|
||||
distance = vec.DistTo(*ent->m_vecDormantOrigin());
|
||||
best_ent = ent;
|
||||
}
|
||||
}
|
||||
return best_ent;
|
||||
}
|
||||
|
||||
void VectorTransform(const float *in1, const matrix3x4_t &in2, float *out)
|
||||
{
|
||||
out[0] = (in1[0] * in2[0][0] + in1[1] * in2[0][1] + in1[2] * in2[0][2]) + in2[0][3];
|
||||
@ -1621,28 +1637,40 @@ void AimAtHitbox(CachedEntity *ent, int hitbox, CUserCmd *cmd, bool compensate_p
|
||||
AimAt(g_pLocalPlayer->v_Eye, r, cmd, compensate_punch);
|
||||
}
|
||||
|
||||
// Thanks to "copypaste" on UnknownCheats, this really helped
|
||||
void FastStop()
|
||||
{
|
||||
// Get velocity
|
||||
Vector vel;
|
||||
velocity::EstimateAbsVelocity(RAW_ENT(LOCAL_E), vel);
|
||||
|
||||
Vector direction;
|
||||
VectorAngles(vel, direction);
|
||||
float speed = vel.Length();
|
||||
static auto sv_friction = g_ICvar->FindVar("sv_friction");
|
||||
static auto sv_stopspeed = g_ICvar->FindVar("sv_stopspeed");
|
||||
|
||||
// Prevent overshooting
|
||||
speed *= 0.5f;
|
||||
auto speed = vel.Length2D();
|
||||
auto friction = sv_friction->GetFloat() * CE_FLOAT(LOCAL_E, 0x12b8);
|
||||
auto control = (speed < sv_stopspeed->GetFloat()) ? sv_stopspeed->GetFloat() : speed;
|
||||
auto drop = control * friction * g_GlobalVars->interval_per_tick;
|
||||
|
||||
direction.y = current_user_cmd->viewangles.y - direction.y;
|
||||
if (speed > drop - 1.0f)
|
||||
{
|
||||
Vector velocity = vel;
|
||||
Vector direction;
|
||||
VectorAngles(vel, direction);
|
||||
float speed = velocity.Length();
|
||||
|
||||
Vector negated_direction;
|
||||
AngleVectors2(VectorToQAngle(direction), &negated_direction);
|
||||
negated_direction *= -speed;
|
||||
direction.y = current_user_cmd->viewangles.y - direction.y;
|
||||
|
||||
current_user_cmd->forwardmove = negated_direction.x;
|
||||
current_user_cmd->sidemove = negated_direction.y;
|
||||
Vector forward;
|
||||
AngleVectors2(VectorToQAngle(direction), &forward);
|
||||
Vector negated_direction = forward * -speed;
|
||||
|
||||
current_user_cmd->forwardmove = negated_direction.x;
|
||||
current_user_cmd->sidemove = negated_direction.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_user_cmd->forwardmove = current_user_cmd->sidemove = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsEntityVisiblePenetration(CachedEntity *entity, int hb)
|
||||
|
@ -118,4 +118,5 @@ VMTHook soundclient{};
|
||||
VMTHook enginevgui{};
|
||||
VMTHook vstd{};
|
||||
VMTHook eventmanager2{};
|
||||
VMTHook toolbox{};
|
||||
} // namespace hooks
|
||||
|
@ -15,6 +15,7 @@ set(files "${CMAKE_CURRENT_LIST_DIR}/CanPacket.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/RunCommand.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/SendNetMsg.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Shutdown.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Think.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/FireEvent.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/FireEventClientSide.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/IsPlayingTimeDemo.cpp"
|
||||
|
@ -23,7 +23,7 @@
|
||||
static settings::Boolean minigun_jump{ "misc.minigun-jump-tf2c", "false" };
|
||||
static settings::Boolean roll_speedhack{ "misc.roll-speedhack", "false" };
|
||||
static settings::Boolean forward_speedhack{ "misc.roll-speedhack.forward", "false" };
|
||||
static settings::Boolean engine_pred{ "misc.engine-prediction", "true" };
|
||||
settings::Boolean engine_pred{ "misc.engine-prediction", "true" };
|
||||
static settings::Boolean debug_projectiles{ "debug.projectiles", "false" };
|
||||
static settings::Int fullauto{ "misc.full-auto", "0" };
|
||||
static settings::Boolean fuckmode{ "misc.fuckmode", "false" };
|
||||
@ -31,6 +31,7 @@ static settings::Boolean fuckmode{ "misc.fuckmode", "false" };
|
||||
class CMoveData;
|
||||
namespace engine_prediction
|
||||
{
|
||||
static Vector original_origin;
|
||||
|
||||
void RunEnginePrediction(IClientEntity *ent, CUserCmd *ucmd)
|
||||
{
|
||||
@ -51,6 +52,8 @@ void RunEnginePrediction(IClientEntity *ent, CUserCmd *ucmd)
|
||||
// Backup
|
||||
float frameTime = g_GlobalVars->frametime;
|
||||
float curTime = g_GlobalVars->curtime;
|
||||
int tickcount = g_GlobalVars->tickcount;
|
||||
original_origin = ent->GetAbsOrigin();
|
||||
|
||||
CUserCmd defaultCmd{};
|
||||
if (ucmd == nullptr)
|
||||
@ -79,11 +82,19 @@ void RunEnginePrediction(IClientEntity *ent, CUserCmd *ucmd)
|
||||
|
||||
g_GlobalVars->frametime = frameTime;
|
||||
g_GlobalVars->curtime = curTime;
|
||||
g_GlobalVars->tickcount = tickcount;
|
||||
|
||||
// Adjust tickbase
|
||||
NET_INT(ent, netvar.nTickBase)++;
|
||||
|
||||
return;
|
||||
}
|
||||
// Restore Origin
|
||||
void FinishEnginePrediction(IClientEntity *ent, CUserCmd *ucmd)
|
||||
{
|
||||
const_cast<Vector &>(ent->GetAbsOrigin()) = original_origin;
|
||||
original_origin.Invalidate();
|
||||
}
|
||||
} // namespace engine_prediction
|
||||
|
||||
void PrecalculateCanShoot()
|
||||
@ -222,6 +233,8 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, CUs
|
||||
}
|
||||
|
||||
// PROF_BEGIN();
|
||||
// Do not update if in warp, since the entities will stay identical either way
|
||||
if (!hacks::tf2::warp::in_warp)
|
||||
{
|
||||
PROF_SECTION(EntityCache);
|
||||
entity_cache::Update();
|
||||
@ -317,10 +330,17 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, CUs
|
||||
{
|
||||
PROF_SECTION(CM_WRAPPER);
|
||||
EC::run(EC::CreateMove_NoEnginePred);
|
||||
if (engine_pred)
|
||||
engine_prediction::RunEnginePrediction(RAW_ENT(LOCAL_E), current_user_cmd);
|
||||
|
||||
EC::run(EC::CreateMove);
|
||||
if (engine_pred)
|
||||
{
|
||||
engine_prediction::RunEnginePrediction(RAW_ENT(LOCAL_E), current_user_cmd);
|
||||
g_pLocalPlayer->UpdateEye();
|
||||
}
|
||||
|
||||
if (hacks::tf2::warp::in_warp)
|
||||
EC::run(EC::CreateMoveWarp);
|
||||
else
|
||||
EC::run(EC::CreateMove);
|
||||
}
|
||||
if (time_replaced)
|
||||
g_GlobalVars->curtime = curtime_old;
|
||||
@ -464,6 +484,12 @@ DEFINE_HOOKED_METHOD(CreateMoveInput, void, IInput *this_, int sequence_nr, floa
|
||||
// Run EC
|
||||
EC::run(EC::CreateMoveLate);
|
||||
|
||||
if (CE_GOOD(LOCAL_E))
|
||||
{
|
||||
// Restore prediction
|
||||
if (engine_prediction::original_origin.IsValid())
|
||||
engine_prediction::FinishEnginePrediction(RAW_ENT(LOCAL_E), current_late_user_cmd);
|
||||
}
|
||||
// Write the usercmd
|
||||
WriteCmd(this_, current_late_user_cmd, sequence_nr);
|
||||
}
|
||||
|
28
src/hooks/Think.cpp
Normal file
28
src/hooks/Think.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "HookedMethods.hpp"
|
||||
|
||||
extern settings::Boolean engine_pred;
|
||||
namespace hooked_methods
|
||||
{
|
||||
// Update Prediction, Used by warp/Doubletap aswell
|
||||
void UpdatePred()
|
||||
{
|
||||
if (isHackActive() && g_IEngine->IsInGame() && CE_GOOD(LOCAL_E) && engine_pred)
|
||||
{
|
||||
int signon_state = *(int *) (*(unsigned *) &g_IBaseClientState + 304);
|
||||
int m_nDeltaTick = *(int *) (*(unsigned *) &g_IBaseClientState + 408);
|
||||
int lastoutgoingcommand = *(int *) (*(unsigned *) &g_IBaseClientState + offsets::lastoutgoingcommand());
|
||||
int chokedcommands = *(int *) (*(unsigned *) &g_IBaseClientState + offsets::lastoutgoingcommand() + 4);
|
||||
int last_command_ack = *(int *) (*(unsigned *) &g_IBaseClientState + offsets::lastoutgoingcommand() + 8);
|
||||
|
||||
// Only run if fully connected
|
||||
if (signon_state == 6 && m_nDeltaTick > 0)
|
||||
g_IPrediction->Update(m_nDeltaTick ? m_nDeltaTick + 1 : 0, m_nDeltaTick > 0, last_command_ack, lastoutgoingcommand + chokedcommands);
|
||||
}
|
||||
}
|
||||
DEFINE_HOOKED_METHOD(Think, void, IToolFrameworkInternal *_this, bool finaltick)
|
||||
{
|
||||
UpdatePred();
|
||||
return original::Think(_this, finaltick);
|
||||
}
|
||||
|
||||
} // namespace hooked_methods
|
@ -156,6 +156,11 @@ void LocalPlayer::Update()
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::UpdateEye()
|
||||
{
|
||||
v_Eye = entity->m_vecOrigin() + CE_VECTOR(entity, netvar.vViewOffset);
|
||||
}
|
||||
|
||||
void LocalPlayer::UpdateEnd()
|
||||
{
|
||||
if (!isFakeAngleCM)
|
||||
|
@ -807,7 +807,7 @@ static void drawcrumbs()
|
||||
#endif
|
||||
|
||||
static InitRoutine runinit([]() {
|
||||
EC::Register(EC::CreateMove, cm, "cm_navparser", EC::average);
|
||||
EC::Register(EC::CreateMove_NoEnginePred, cm, "cm_navparser", EC::average);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, drawcrumbs, "draw_navparser", EC::average);
|
||||
#endif
|
||||
|
@ -845,6 +845,41 @@ void FX_FireBullets_hook(IClientEntity *weapon, int player, Vector *origin, Vect
|
||||
}*/
|
||||
|
||||
static Timer update_nospread_timer{};
|
||||
void CreateMove2()
|
||||
{
|
||||
if (bullet)
|
||||
{
|
||||
static auto sv_usercmd_custom_random_seed = g_ICvar->FindVar("sv_usercmd_custom_random_seed");
|
||||
if (!sv_usercmd_custom_random_seed)
|
||||
sv_usercmd_custom_random_seed = g_ICvar->FindVar("sv_usercmd_custom_random_seed");
|
||||
|
||||
// Server owner decided it would be a great idea to give the user control over the random seed
|
||||
else if (!sv_usercmd_custom_random_seed->GetBool())
|
||||
{
|
||||
auto seed = MD5_PseudoRandom(current_user_cmd->command_number) & 0x7FFFFFFF;
|
||||
prediction_seed = *reinterpret_cast<float *>(&seed);
|
||||
use_usercmd_seed = true;
|
||||
}
|
||||
// Normal server
|
||||
else
|
||||
use_usercmd_seed = false;
|
||||
|
||||
// Synced, mark as such to other modules
|
||||
if (no_spread_synced == SYNCED)
|
||||
is_syncing = false;
|
||||
// Not synced currently, try to sync
|
||||
if (no_spread_synced == NOT_SYNCED && !bad_mantissa)
|
||||
{
|
||||
is_syncing = true;
|
||||
should_update_time = true;
|
||||
update_nospread_timer.update();
|
||||
}
|
||||
// Else if mantissa bad, update every 10 mins
|
||||
else if (no_spread_synced == NOT_SYNCED && update_nospread_timer.test_and_set(10 * 60 * 1000))
|
||||
no_spread_synced = CORRECTING;
|
||||
}
|
||||
}
|
||||
|
||||
static InitRoutine init_bulletnospread([]() {
|
||||
// Get our detour hooks running
|
||||
static auto writeusercmd_addr = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 2C 8B 45 ? 8B 7D ? 8B 5D ? 89 45 ? 8B 40");
|
||||
@ -855,42 +890,8 @@ static InitRoutine init_bulletnospread([]() {
|
||||
net_sendpacket_detour.Init(net_sendpacket_addr, (void *) NET_SendPacket_hook);*/
|
||||
|
||||
// Register Event callbacks
|
||||
EC::Register(
|
||||
EC::CreateMove,
|
||||
[]() {
|
||||
if (bullet)
|
||||
{
|
||||
static auto sv_usercmd_custom_random_seed = g_ICvar->FindVar("sv_usercmd_custom_random_seed");
|
||||
if (!sv_usercmd_custom_random_seed)
|
||||
sv_usercmd_custom_random_seed = g_ICvar->FindVar("sv_usercmd_custom_random_seed");
|
||||
|
||||
// Server owner decided it would be a great idea to give the user control over the random seed
|
||||
else if (!sv_usercmd_custom_random_seed->GetBool())
|
||||
{
|
||||
auto seed = MD5_PseudoRandom(current_user_cmd->command_number) & 0x7FFFFFFF;
|
||||
prediction_seed = *reinterpret_cast<float *>(&seed);
|
||||
use_usercmd_seed = true;
|
||||
}
|
||||
// Normal server
|
||||
else
|
||||
use_usercmd_seed = false;
|
||||
|
||||
// Synced, mark as such to other modules
|
||||
if (no_spread_synced == SYNCED)
|
||||
is_syncing = false;
|
||||
// Not synced currently, try to sync
|
||||
if (no_spread_synced == NOT_SYNCED && !bad_mantissa)
|
||||
{
|
||||
is_syncing = true;
|
||||
should_update_time = true;
|
||||
update_nospread_timer.update();
|
||||
}
|
||||
// Else if mantissa bad, update every 10 mins
|
||||
else if (no_spread_synced == NOT_SYNCED && update_nospread_timer.test_and_set(10 * 60 * 1000))
|
||||
no_spread_synced = CORRECTING;
|
||||
}
|
||||
},
|
||||
"nospread_createmove2");
|
||||
EC::Register(EC::CreateMove, CreateMove2, "nospread_createmove2");
|
||||
EC::Register(EC::CreateMoveWarp, CreateMove2, "nospread_createmove2w");
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(
|
||||
EC::Draw,
|
||||
|
Reference in New Issue
Block a user