eliwarecs.com
-
Автор темы
- #1
Getting quite tired of people failing to shift through CL_Move despite having already spoonfeed it in multiple posts.
Thought I'd create the ultimate CL_Move spoonfeed that I can link people to when they have issues.
Note that fakelag will limit the shift window.
CL_Move Hook (for the actual shifting)
CreateMove Hook (for shift-tick handling and shift initiation)
Credits: KittenPopo
Thought I'd create the ultimate CL_Move spoonfeed that I can link people to when they have issues.
Note that fakelag will limit the shift window.
CL_Move Hook (for the actual shifting)
C++:
// Global Variables we will be using
int doubletapCharge = 0, // This is the amount of extra commands we are allowed for simulation on the server, which we can "charge" up by not sending any CMDs for a tick
ticksToShift = 0; // The amount of ticks we want to shift right now
bool isShifting = false; // To be used as an indicator to our CreateMove hook that we are currently creating a command that will be used for shifting
// Your CL_Move hook
// Signature: https://github.com/KittenPopo/csgo-signatures/blob/main/functions.cpp#L100
// Volvo Source: https://github.com/KittenPopo/CSGO-Source-Fixed-Search/blob/15ba38c4f02ad73674c750d7bbf159337dc042bc/engine/cl_main.cpp#L2736
void __cdecl hook_CLMove(float accumulatedExtraSamples, bool finalTick) {
// Recharge every other tick
// By not sending a command this tick, our commands allowed for simulation goes up so we can shift again
// Task for the reader: Automate this properly without preventing the second DT shot...
if (g_Globals->tickcount % 2 && doubletapCharge < 14) {
doubletapCharge++;
// Task for the reader: Tickbase still increases when recharging, but the client doesn't know that...
return;
}
oCLMove(accumulatedExtraSamples, finalTick);
//////// Shift if needed
// Every time we call original again, we create another command to send to the server
// All of these extra commands will be simulated by the server as long as we have a tick allowed for simulation
// Recharging "earns" us extra ticks allowed for simulation, which we can "spend" via sending multiple commands to shift
// Task for the reader: Fix tickbase (not required for shifting but will prevent pred errors and occasional failure to predict the third shot)
// Hint #1: Look where the game modifies m_nTickbase and do stuff there
// Hint #2: Print out your serverside tickbase and see how it changes when you shift
isShifting = true;
{
for (ticksToShift = min(doubletapCharge, ticksToShift); ticksToShift > 0; ticksToShift--, doubletapCharge--)
oCLMove(accumulatedExtraSamples, finalTick); // Create an extra movement command (will call CreateMove)
}
isShifting = false;
}
C++:
// Your CreateMove hook
bool __fastcall hook_CreateMove(...) {
...
// Before you do anything
if (isShifting) {
// Task for the reader: Maybe we want to do a few things during our teleport (i.e. bhop, autostrafe, etc.)
bSendPacket = ticksToShift == 1; // Only send on the last shifted
cmd->buttons &= ~(IN_ATTACK | IN_ATTACK2); // Prevent shooting mid-shift, will also give autofire for pistols when you DT
return;
}
...
// Example implementation for simple doubletap
auto weapon = gLocal->GetActiveWeapon();
if (weapon->IsValid()) {
int shiftAmount = 14;
float shiftTime = shiftAmount * g_Globals->interval_per_tick;
// Shift if we will shoot and have enough time to shift
if ((cmd->buttons & IN_ATTACK) && weapon->GetNextAttackTime() <= g_Globals->curtime - shiftTime)
ticksToShift = shiftAmount;
}
}