Alot of warp related stuff (see description)

- Add a speed meter
- Smoothen Warp Drastically
- GIve full control while in warp (Especially useful for bots)
- Rewrite the peek mode
- Add 22 tick fakelag (as a sideeffect)
This commit is contained in:
BenCat07 2020-05-17 17:40:00 +02:00
parent ef59d93734
commit d259fbacd0
5 changed files with 217 additions and 69 deletions

View File

@ -5,7 +5,7 @@
<AutoVariable width="fill" target="antiaim.draw-fakes" label="Draw Fakes"/>
<AutoVariable width="fill" target="antiaim.crouch" label="Fake Crouch"/>
<AutoVariable width="fill" target="antiaim.no-clamp" label="No Clamping"/>
<AutoVariable width="fill" target="misc.fakelag" label="Fakelag" min="0" max="15"/>
<AutoVariable width="fill" target="misc.fakelag" label="Fakelag" min="0" max="22"/>
<AutoVariable width="fill" target="antiaim.spin-speed" label="Spin speed" min="-45" max="45" step="0.1"/>
<AutoVariable width="fill" target="antiaim.roll" label="Roll"/>
<AutoVariable width="fill" target="antiaim.pitch.static" label="Custom Pitch"/>

View File

@ -59,6 +59,7 @@
<Box padding="12 6 6 6" width="content" height="content" name="Warp" x="370" y="65">
<List width="180">
<AutoVariable width="fill" target="warp.enabled" label="Enable Warp" tooltip="Allows you to charge a burst of speed"/>
<AutoVariable width="fill" target="warp.speed" label="Warp speed" tooltip="The Discharge speed (0.5 = +50%, 2 = +200%, +1000% 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.draw" label="Draw Warp" tooltip="Draws a bar indicating your warp readyness"/>
<AutoVariable width="fill" target="warp.bar-size" label="Bar Size"/>

View File

@ -14,6 +14,7 @@
#include <inetmsghandler.h>
#include <KeyValues.h>
#include "bitvec.h"
#include "CSignature.h"
#define DECLARE_BASE_MESSAGE(msgtype) \
public: \
@ -98,6 +99,26 @@ public:
return false;
}; // no handler set
public:
// I don't get what it does but we need it
virtual bool BIncomingMessageForProcessing(double param_1, int param_2)
{
// Call original to be sure nothing breaks
typedef bool (*BIncomingMessageForProcessing_t)(CNetMessage *, double, int);
static auto addr = gSignatures.GetEngineSignature("55 89 E5 56 53 83 EC 10 8B 5D ? F2 0F 10 45");
BIncomingMessageForProcessing_t BIncomingMessageForProcessing_fn = (BIncomingMessageForProcessing_t)addr;
return BIncomingMessageForProcessing_fn(this, param_1, param_2);
};
// I don't get what it does but we need it
virtual void SetRatePolicy()
{
// Call original to be sure nothing breaks
typedef bool (*SetRatePolicy_t)(CNetMessage *);
static auto addr = gSignatures.GetEngineSignature("55 89 E5 83 EC 18 C7 04 24 2C 00 00 00");
SetRatePolicy_t SetRatePolicy_fn = (SetRatePolicy_t)addr;
SetRatePolicy_fn(this);
};
protected:
bool m_bReliable; // true if message should be send reliable
INetChannel *m_NetChannel; // netchannel this message is from/for
@ -177,7 +198,7 @@ protected:
#define MAX_OSPATH 260
#define NETMSG_TYPE_BITS 5
#define NETMSG_TYPE_BITS 6
typedef int QueryCvarCookie_t;
typedef enum
{

View File

@ -11,10 +11,12 @@
#endif
#include "MiscAimbot.hpp"
#include "PlayerTools.hpp"
#include "DetourHook.hpp"
namespace hacks::tf2::warp
{
static settings::Boolean enabled{ "warp.enabled", "false" };
static settings::Float speed{ "warp.speed", "10" };
static settings::Boolean draw{ "warp.draw", "false" };
static settings::Button warp_key{ "warp.key", "<null>" };
static settings::Boolean charge_passively{ "warp.charge-passively", "true" };
@ -34,63 +36,73 @@ 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 bool should_charge = false;
static int warp_amount = 0;
static int warp_amount_override = 0;
static int warp_override_one_tick = 0;
static bool charged = false;
// Taken from MrSteyk
class clc_move_proto
{
public:
int VTable;
char reliable;
int netchan;
int field_C;
int field_10;
int m_nBackupCommands;
int m_nNewCommands;
int m_nLength;
bf_write m_DataIn;
bf_write m_DataOut;
};
static bool should_charge = false;
static int warp_amount = 0;
static int warp_amount_override = 0;
static bool charged = false;
// How many ticks of excess we have (for decimal speeds)
float excess_ticks = 0.0f;
int GetWarpAmount()
{
static auto sv_max_dropped_packets_to_process = g_ICvar->FindVar("sv_max_dropped_packets_to_process");
return warp_override_one_tick ? warp_override_one_tick : sv_max_dropped_packets_to_process->GetInt();
float warp_amount_preprocessed = *speed;
// Store excess
excess_ticks += warp_amount_preprocessed - std::floor(warp_amount_preprocessed);
// How many ticks to warp, add excess too
int warp_amount_processed = std::floor(warp_amount_preprocessed) + std::floor(excess_ticks);
// Remove the used amount from excess
excess_ticks -= std::floor(excess_ticks);
// Return smallest of the two
return std::min(warp_amount_processed, sv_max_dropped_packets_to_process->GetInt());
}
static bool should_warp = true;
static bool was_hurt = false;
// Warping part
void Warp()
DetourHook cl_move_detour;
typedef void (*CL_Move_t)(float accumulated_extra_samples, bool bFinalTick);
// Warping part, uses CL_Move
void Warp(float accumulated_extra_samples, bool finalTick)
{
auto ch = g_IEngine->GetNetChannelInfo();
if (!ch)
return;
if (!should_warp)
{
should_warp = true;
if (finalTick)
should_warp = true;
return;
}
int &m_nOutSequenceNr = *(int *) ((uintptr_t) ch + offsets::m_nOutSequenceNr());
int warp_ticks = warp_amount;
if (warp_amount_override)
warp_ticks = warp_amount_override;
// Don' add more than the warp_ticks
m_nOutSequenceNr += std::min(warp_ticks, GetWarpAmount());
warp_amount -= std::min(warp_ticks, GetWarpAmount());
warp_ticks -= std::min(warp_ticks, GetWarpAmount());
CL_Move_t original = (CL_Move_t) cl_move_detour.GetOriginalFunc();
// Call CL_Move once for every warp tick
int warp_amnt = GetWarpAmount();
for (int i = 0; i <= std::min(warp_ticks, warp_amnt); i++)
{
original(accumulated_extra_samples, finalTick);
// Only decrease ticks for the final CL_Move tick
if (finalTick)
{
warp_amount--;
warp_ticks--;
}
}
cl_move_detour.RestorePatch();
if (warp_amount_override)
warp_amount_override = warp_ticks;
// Don't attack while warping
current_user_cmd->buttons &= ~IN_ATTACK;
if (warp_ticks <= 0)
{
was_hurt = false;
@ -122,7 +134,7 @@ void SendNetMessage(INetMessage &msg)
if (should_charge && !charged)
{
int ticks = GetMaxWarpTicks();
auto movemsg = (clc_move_proto *) &msg;
auto movemsg = (CLC_Move *) &msg;
// Just null it :shrug:
movemsg->m_nBackupCommands = 0;
movemsg->m_nNewCommands = 0;
@ -138,13 +150,6 @@ void SendNetMessage(INetMessage &msg)
charged = true;
}
}
// Warp
if ((warp_key.isKeyDown() || was_hurt) && warp_amount)
{
Warp();
if (warp_amount < GetMaxWarpTicks())
charged = false;
}
}
should_charge = false;
}
@ -165,7 +170,19 @@ enum charge_state
DONE
};
charge_state current_state = ATTACK;
enum peek_state
{
IDLE = 0,
MOVE_TOWARDS,
MOVE_BACK,
STOP
};
charge_state current_state = ATTACK;
peek_state current_peek_state = IDLE;
// Used to determine when we should start moving back with peek
static int charge_at_start = 0;
// Used to determine when demoknight warp should be over
static bool was_overridden = false;
@ -175,11 +192,11 @@ void CreateMove()
return;
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
return;
warp_override_one_tick = 0;
if (!warp_key.isKeyDown() && !was_hurt)
{
warp_last_tick = false;
current_state = ATTACK;
warp_last_tick = false;
current_state = ATTACK;
current_peek_state = IDLE;
Vector velocity{};
velocity::EstimateAbsVelocity(RAW_ENT(LOCAL_E), velocity);
@ -329,34 +346,59 @@ void CreateMove()
// Warp peaking
else if (warp_peek)
{
// We have Warp
if (warp_amount)
switch (current_peek_state)
{
// Warped last tick, time to reverse
if (warp_last_tick)
{
// Wait 1 tick before warping back
if (should_warp && !should_warp_last_tick)
{
should_warp_last_tick = true;
should_warp = false;
}
else
should_warp_last_tick = false;
case IDLE:
{
// Not doing anything, update warp amount
charge_at_start = warp_amount;
// Inverse direction
current_user_cmd->forwardmove = -current_user_cmd->forwardmove;
current_user_cmd->sidemove = -current_user_cmd->sidemove;
}
Vector vel;
velocity::EstimateAbsVelocity(RAW_ENT(LOCAL_E), vel);
// if we move more than 1.0 HU/s , go to move towards statement...
if (!vel.IsZero(1.0f))
current_peek_state = MOVE_TOWARDS;
// ...else don't warp
else
warp_override_one_tick = warp_amount / 2;
warp_last_tick = true;
{
should_warp = false;
break;
}
// No "break;" here is intentional :)
}
// Prevent movement so you don't overshoot when you don't want to
else
case MOVE_TOWARDS:
{
// Just wait until we used about half of our warp, then we can start going back
if (warp_amount <= charge_at_start / 2.0f)
current_peek_state = MOVE_BACK;
break;
}
case MOVE_BACK:
{
// Inverse direction if we still have warp left
if (warp_amount)
{
current_user_cmd->forwardmove *= -1.0f;
current_user_cmd->sidemove *= -1.0f;
break;
}
// ... Else we stop in our tracks
else
current_peek_state = STOP;
// Once again, intentionally missing "break;"
}
case STOP:
{
// Stop dead in our tracks while key is still held
current_user_cmd->forwardmove = 0.0f;
current_user_cmd->sidemove = 0.0f;
break;
}
default:
break;
}
}
was_hurt_last_tick = was_hurt;
@ -438,12 +480,93 @@ void rvarCallback(settings::VariableBase<bool> &, bool)
yaw_selections.push_back(90.0f);
}
DetourHook cl_sendmove_detour;
typedef void (*CL_SendMove_t)();
void CL_SendMove_hook()
{
byte data[4000];
// the +4 one is choked commands
int nextcommandnr = NET_INT(g_IBaseClientState, offsets::lastoutgoingcommand()) + NET_INT(g_IBaseClientState, offsets::lastoutgoingcommand() + 4) + 1;
// send the client update packet
CLC_Move moveMsg;
moveMsg.m_DataOut.StartWriting(data, sizeof(data));
// Determine number of backup commands to send along
int cl_cmdbackup = 2;
// How many real new commands have queued up
moveMsg.m_nNewCommands = 1 + NET_INT(g_IBaseClientState, offsets::lastoutgoingcommand() + 4);
moveMsg.m_nNewCommands = std::clamp(moveMsg.m_nNewCommands, 0, 15);
// Excessive commands (Used for longer fakelag, credits to https://www.unknowncheats.me/forum/source-engine/370916-23-tick-guwop-fakelag-break-lag-compensation-running.html)
int extra_commands = NET_INT(g_IBaseClientState, offsets::lastoutgoingcommand() + 4) + 1 - moveMsg.m_nNewCommands;
cl_cmdbackup = std::max(2, extra_commands);
moveMsg.m_nBackupCommands = std::clamp(cl_cmdbackup, 0, 7);
int numcmds = moveMsg.m_nNewCommands + moveMsg.m_nBackupCommands;
int from = -1; // first command is deltaed against zeros
bool bOK = true;
for (int to = nextcommandnr - numcmds + 1; to <= nextcommandnr; to++)
{
bool isnewcmd = to >= (nextcommandnr - moveMsg.m_nNewCommands + 1);
// Call the write to buffer
typedef bool (*WriteUsercmdDeltaToBuffer_t)(IBaseClientDLL *, bf_write *, int, int, bool);
// first valid command number is 1
bOK = bOK && vfunc<WriteUsercmdDeltaToBuffer_t>(g_IBaseClient, offsets::PlatformOffset(23, offsets::undefined, offsets::undefined), 0)(g_IBaseClient, &moveMsg.m_DataOut, from, to, isnewcmd);
from = to;
}
if (bOK)
{
// Make fakelag work as we want it to
if (extra_commands > 0)
((INetChannel *) g_IEngine->GetNetChannelInfo())->m_nChokedPackets -= extra_commands;
// only write message if all usercmds were written correctly, otherwise parsing would fail
((INetChannel *) g_IEngine->GetNetChannelInfo())->SendNetMsg(moveMsg);
}
}
void CL_Move_hook(float accumulated_extra_samples, bool bFinalTick)
{
CL_Move_t original = (CL_Move_t) cl_move_detour.GetOriginalFunc();
original(accumulated_extra_samples, bFinalTick);
cl_move_detour.RestorePatch();
// Should we warp?
if ((warp_key.isKeyDown() || was_hurt) && warp_amount)
{
Warp(accumulated_extra_samples, bFinalTick);
if (warp_amount < GetMaxWarpTicks())
charged = false;
}
}
static InitRoutine init([]() {
static auto cl_sendmove_addr = gSignatures.GetEngineSignature("55 89 E5 57 56 53 81 EC 2C 10 00 00 C6 85 ? ? ? ? 01");
cl_sendmove_detour.Init(cl_sendmove_addr, (void *) CL_SendMove_hook);
static auto cl_move_addr = gSignatures.GetEngineSignature("55 89 E5 57 56 53 81 EC 9C 00 00 00 83 3D ? ? ? ? 01");
cl_move_detour.Init(cl_move_addr, (void *) CL_Move_hook);
EC::Register(EC::LevelShutdown, LevelShutdown, "warp_levelshutdown");
EC::Register(EC::CreateMove, CreateMove, "warp_createmove", EC::very_late);
g_IEventManager2->AddListener(&listener, "player_hurt", false);
EC::Register(
EC::Shutdown, []() { g_IEventManager2->RemoveListener(&listener); }, "warp_shutdown");
EC::Shutdown,
[]() {
g_IEventManager2->RemoveListener(&listener);
cl_sendmove_detour.Shutdown();
},
"warp_shutdown");
warp_forward.installChangeCallback(rvarCallback);
warp_backwards.installChangeCallback(rvarCallback);
warp_left.installChangeCallback(rvarCallback);

View File

@ -20,6 +20,8 @@ bf_write::bf_write()
m_pDebugName = NULL;
}
static char s_text[1024];
unsigned long g_LittleBits[32];
// Precalculated bit masks for WriteUBitLong. Using these tables instead of
@ -498,7 +500,8 @@ const char *CLC_ListenEvents::ToString(void) const
const char *CLC_Move::ToString(void) const
{
return strfmt("%s: backup %i, new %i, bytes %i", GetName(), m_nNewCommands, m_nBackupCommands, Bits2Bytes(m_nLength)).release();
Q_snprintf(s_text, sizeof(s_text), "%s: backup %i, new %i, bytes %i", GetName(), m_nNewCommands, m_nBackupCommands, Bits2Bytes(m_nLength));
return s_text;
}
bool CLC_Move::WriteToBuffer(bf_write &buffer)