Skip to content

Commit 80297b9

Browse files
fixed charge reach ig
1 parent 359a197 commit 80297b9

File tree

1 file changed

+163
-89
lines changed

1 file changed

+163
-89
lines changed

A_Swing_Prediction.lua

+163-89
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,18 @@ local gravity = client.GetConVar("sv_gravity") or 800 -- Get the current gravity
233233
local stepSize = 18
234234
local tickCounteratack = 0
235235

236+
-- Variables to track attack and charge state
237+
local attackStarted = false
238+
local attackTickCount = 0
239+
local lastChargeTime = 0
240+
241+
-- Add this function to reset the attack tracking when needed
242+
local function resetAttackTracking()
243+
attackStarted = false
244+
attackTickCount = 0
245+
end
246+
247+
236248
if pLocal then
237249
stepSize = pLocal:GetPropFloat("localdata", "m_flStepSize") or 18
238250
else
@@ -826,94 +838,65 @@ local function UpdateHomingMissile()
826838
end
827839

828840
local hasNotified = false
829-
local function checkInRangeWithLatency(playerIndex, swingRange, pWeapon, cmd, OnGround, isCharging)
841+
local function checkInRangeWithLatency(playerIndex, swingRange, pWeapon, cmd)
830842
local inRange = false
831843
local point = nil
832-
can_charge = false
833844
local Backtrack = gui.GetValue("Backtrack")
834845
local fakelatencyON = gui.GetValue("Fake Latency")
835-
836-
-- Check if instant attack is ready
837-
local dashKeyBound = gui.GetValue("dash move key") ~= 0
838-
local instantAttackReady = Menu.Misc.InstantAttack and warp.CanWarp() and
839-
warp.GetChargedTicks() >= Menu.Aimbot.SwingTime and
840-
dashKeyBound
841-
842-
-- Don't attempt prediction when charging without jump charge
843-
if isCharging and not Menu.Misc.ChargeJump then
844-
return false, nil, false
845-
end
846+
local smackDelay = Menu.Aimbot.MaxSwingTime
846847

847848
if Backtrack == 0 and fakelatencyON == 0 then
848-
-- Check for charge range bug - only if instant attack is NOT ready
849-
if pLocalClass == 4 and Menu.Misc.ChargeReach and chargeLeft == 100 and not instantAttackReady then -- charge meter is full
849+
-- Check for charge range bug
850+
if pLocalClass == 4 and Menu.Misc.ChargeReach and chargeLeft == 100 then -- charge meter is full
850851
if checkInRange(vPlayerOrigin, pLocalOrigin, Charge_Range) then
851852
inRange = true
852853
point = vPlayerOrigin
853-
tick_count = tick_count + 1
854+
can_charge = false -- Don't set can_charge yet, we'll track it separately
854855

855-
-- Calculate predicted target position one tick ahead to compensate for engine delay
856-
local vPlayerVelocity = CurrentTarget:EstimateAbsVelocity()
857-
local tickInterval = globals.TickInterval()
858-
local predictedTargetPos = vPlayerOrigin + (vPlayerVelocity * tickInterval)
859-
860-
-- Only set can_charge to true when we've reached the exact final tick
861-
if tick_count == (Menu.Aimbot.SwingTime - 1) then
862-
-- Create aim angles that compensate for the one-tick delay
863-
local aimAngles = Math.PositionAngles(pLocalOrigin, predictedTargetPos)
864-
865-
-- Set the view angles to the predicted position
866-
if Menu.Aimbot.Silent then
867-
cmd:SetViewAngles(aimAngles.pitch, aimAngles.yaw, 0)
868-
else
869-
-- Engine angles need the compensation
870-
engine.SetViewAngles(EulerAngles(aimAngles.pitch, aimAngles.yaw, 0))
871-
end
856+
-- Set the view angles to target
857+
local aimAngles = Math.PositionAngles(pLocalOrigin, vPlayerOrigin)
872858

873-
tick_count = 0
874-
can_charge = true
875-
elseif vdistance > TotalSwingRange and Menu.Misc.ChargeJump and tick_count >= (Menu.Aimbot.SwingTime - 2) then
876-
cmd:SetButtons(cmd:GetButtons() | IN_JUMP) -- jump at 2 ticks before attack
859+
-- Apply the aiming angles
860+
if Menu.Aimbot.Silent then
861+
cmd:SetViewAngles(aimAngles.pitch, aimAngles.yaw, 0)
862+
else
863+
engine.SetViewAngles(EulerAngles(aimAngles.pitch, aimAngles.yaw, 0))
877864
end
878865
elseif checkInRange(vPlayerFuture, pLocalFuture, Charge_Range) then
879866
inRange = true
880867
point = vPlayerFuture
881-
tick_count = tick_count + 1
882-
883-
-- Calculate predicted future target position one tick ahead
884-
local vPlayerVelocity = CurrentTarget:EstimateAbsVelocity()
885-
local tickInterval = globals.TickInterval()
886-
local predictedTargetPos = vPlayerFuture + (vPlayerVelocity * tickInterval)
868+
can_charge = false -- Don't set can_charge yet, we'll track it separately
887869

888-
-- Only set can_charge to true when we've reached the exact final tick
889-
if tick_count == (Menu.Aimbot.SwingTime - 1) then
890-
-- Create aim angles that compensate for the one-tick delay
891-
local aimAngles = Math.PositionAngles(pLocalFuture, predictedTargetPos)
870+
-- Set the view angles to target
871+
local aimAngles = Math.PositionAngles(pLocalFuture, vPlayerFuture)
892872

893-
-- Set the view angles to the predicted position
894-
if Menu.Aimbot.Silent then
895-
cmd:SetViewAngles(aimAngles.pitch, aimAngles.yaw, 0)
896-
else
897-
-- Engine angles need the compensation
898-
engine.SetViewAngles(EulerAngles(aimAngles.pitch, aimAngles.yaw, 0))
899-
end
900-
901-
tick_count = 0
902-
can_charge = true
903-
elseif vdistance > TotalSwingRange and Menu.Misc.ChargeJump and tick_count >= (Menu.Aimbot.SwingTime - 2) then
904-
cmd:SetButtons(cmd:GetButtons() | IN_JUMP) -- jump at 2 ticks before attack
873+
-- Apply the aiming angles
874+
if Menu.Aimbot.Silent then
875+
cmd:SetViewAngles(aimAngles.pitch, aimAngles.yaw, 0)
876+
else
877+
engine.SetViewAngles(EulerAngles(aimAngles.pitch, aimAngles.yaw, 0))
905878
end
906879
end
880+
907881
if inRange then
908-
return inRange, point, can_charge
882+
return inRange, point, false -- Return inRange but not can_charge yet
909883
end
910884
elseif chargeLeft < 100 then
911885
can_charge = false
912-
if checkInRange(vPlayerOrigin, pLocalOrigin, Charge_Range) then --or checkInRange(vPlayerFuture, pLocalFuture, swingRange) and not onGround then
886+
if checkInRange(vPlayerOrigin, pLocalOrigin, Charge_Range) then
913887
inRange = true
914888
point = vPlayerOrigin
915889
tick_count = tick_count + 1
916-
if tick_count == (Menu.Aimbot.SwingTime - 1) then
890+
891+
-- Calculate the exact tick to charge at based on ping
892+
local latOut = clientstate.GetLatencyOut() or 0
893+
local latIn = clientstate.GetLatencyIn() or 0
894+
local tickInterval = globals.TickInterval()
895+
local pingTicks = math.floor(((latOut + latIn) / tickInterval) + 1) -- Ping in ticks + 1 for safety
896+
local chargeAtTick = math.max(1, smackDelay - pingTicks) -- Ensure we don't go negative
897+
898+
-- Use a small range around the target tick to increase reliability
899+
if tick_count >= chargeAtTick and tick_count <= (chargeAtTick + 1) then
917900
tick_count = 0
918901
can_charge = true
919902
end
@@ -955,8 +938,30 @@ local function checkInRangeWithLatency(playerIndex, swingRange, pWeapon, cmd, On
955938
inRange = true
956939
point = vPlayerOrigin
957940
tick_count = tick_count + 1
958-
-- Only set can_charge to true when we've reached the exact final tick
959-
if tick_count == (Menu.Aimbot.SwingTime - 1) then
941+
942+
-- Calculate the exact tick to charge at based on ping
943+
local latOut = clientstate.GetLatencyOut() or 0
944+
local latIn = clientstate.GetLatencyIn() or 0
945+
local tickInterval = globals.TickInterval()
946+
local pingTicks = math.floor(((latOut + latIn) / tickInterval) + 1) -- Ping in ticks + 1 for safety
947+
local chargeAtTick = math.max(1, smackDelay - pingTicks) -- Ensure we don't go negative
948+
949+
-- Use a small range around the target tick to increase reliability
950+
if tick_count >= chargeAtTick and tick_count <= (chargeAtTick + 1) then
951+
-- Compensate for engine view angles being one tick behind
952+
local vPlayerVelocity = CurrentTarget:EstimateAbsVelocity()
953+
local predictedPos = vPlayerOrigin + (vPlayerVelocity * tickInterval)
954+
955+
-- Set the view angles to anticipate where the target will be in the next tick
956+
local aimAngles = Math.PositionAngles(pLocalOrigin, predictedPos)
957+
958+
-- Apply the compensated angles
959+
if Menu.Aimbot.Silent then
960+
cmd:SetViewAngles(aimAngles.pitch, aimAngles.yaw, 0)
961+
else
962+
engine.SetViewAngles(EulerAngles(aimAngles.pitch, aimAngles.yaw, 0))
963+
end
964+
960965
tick_count = 0
961966
can_charge = true
962967
end
@@ -976,15 +981,60 @@ local function checkInRangeWithLatency(playerIndex, swingRange, pWeapon, cmd, On
976981
inRange = true
977982
point = vPlayerOrigin
978983
tick_count = tick_count + 1
979-
if tick_count >= (Menu.Aimbot.SwingTime - 1) then
984+
985+
-- Calculate the exact tick to charge at based on ping
986+
local latOut = clientstate.GetLatencyOut() or 0
987+
local latIn = clientstate.GetLatencyIn() or 0
988+
local tickInterval = globals.TickInterval()
989+
local pingTicks = math.floor(((latOut + latIn) / tickInterval) + 1) -- Ping in ticks + 1 for safety
990+
local chargeAtTick = math.max(1, smackDelay - pingTicks) -- Ensure we don't go negative
991+
992+
-- Use a small range around the target tick to increase reliability
993+
if tick_count >= chargeAtTick and tick_count <= (chargeAtTick + 1) then
994+
-- Compensate for engine view angles being one tick behind
995+
local vPlayerVelocity = CurrentTarget:EstimateAbsVelocity()
996+
local predictedPos = vPlayerOrigin + (vPlayerVelocity * tickInterval)
997+
998+
-- Set the view angles to anticipate where the target will be in the next tick
999+
local aimAngles = Math.PositionAngles(pLocalOrigin, predictedPos)
1000+
1001+
-- Apply the compensated angles
1002+
if Menu.Aimbot.Silent then
1003+
cmd:SetViewAngles(aimAngles.pitch, aimAngles.yaw, 0)
1004+
else
1005+
engine.SetViewAngles(EulerAngles(aimAngles.pitch, aimAngles.yaw, 0))
1006+
end
1007+
9801008
tick_count = 0
9811009
can_charge = true
9821010
elseif checkInRange(vPlayerFuture, pLocalFuture, Charge_Range) then
9831011
inRange = true
9841012
point = vPlayerFuture
9851013
tick_count = tick_count + 1
986-
-- Only set can_charge to true when we've reached the exact final tick
987-
if tick_count == (Menu.Aimbot.SwingTime - 1) then
1014+
1015+
-- Calculate the exact tick to charge at based on ping
1016+
local latOut = clientstate.GetLatencyOut() or 0
1017+
local latIn = clientstate.GetLatencyIn() or 0
1018+
local tickInterval = globals.TickInterval()
1019+
local pingTicks = math.floor(((latOut + latIn) / tickInterval) + 1) -- Ping in ticks + 1 for safety
1020+
local chargeAtTick = math.max(1, smackDelay - pingTicks) -- Ensure we don't go negative
1021+
1022+
-- Use a small range around the target tick to increase reliability
1023+
if tick_count >= chargeAtTick and tick_count <= (chargeAtTick + 1) then
1024+
-- Compensate for engine view angles being one tick behind
1025+
local vPlayerVelocity = CurrentTarget:EstimateAbsVelocity()
1026+
local predictedPos = vPlayerFuture + (vPlayerVelocity * tickInterval)
1027+
1028+
-- Set the view angles to anticipate where the target will be in the next tick
1029+
local aimAngles = Math.PositionAngles(pLocalFuture, predictedPos)
1030+
1031+
-- Apply the compensated angles
1032+
if Menu.Aimbot.Silent then
1033+
cmd:SetViewAngles(aimAngles.pitch, aimAngles.yaw, 0)
1034+
else
1035+
engine.SetViewAngles(EulerAngles(aimAngles.pitch, aimAngles.yaw, 0))
1036+
end
1037+
9881038
tick_count = 0
9891039
can_charge = true
9901040
end
@@ -1409,11 +1459,12 @@ local function OnCreateMove(pCmd)
14091459
else
14101460
engine.SetViewAngles(EulerAngles(aim_angles.pitch, aim_angles.yaw, 0))
14111461
end
1412-
elseif pLocalClass == 4 then
1413-
-- Remove ChargeControl call from here
14141462
end
1415-
elseif Menu.Misc.ChargeControl and pLocal:InCond(17) then
1416-
-- Removed ChargeControl call from here
1463+
end
1464+
1465+
-- Initialize tick_count if it hasn't been set yet
1466+
if tick_count == nil then
1467+
tick_count = 0
14171468
end
14181469

14191470
-- Only try instant attack when it's possible
@@ -1443,10 +1494,10 @@ local function OnCreateMove(pCmd)
14431494
Menu.Aimbot.MaxSwingTime = weaponSmackDelay
14441495

14451496
-- Display notification about the change with weapon name
1446-
local pWeaponName = "Unknown"
1497+
pWeaponName = "Unknown"
14471498
pcall(function()
1448-
local pWeaponDefIndex = pWeapon:GetPropInt("m_iItemDefinitionIndex")
1449-
local pWeaponDef = itemschema.GetItemDefinitionByID(pWeaponDefIndex)
1499+
pWeaponDefIndex = pWeapon:GetPropInt("m_iItemDefinitionIndex")
1500+
pWeaponDef = itemschema.GetItemDefinitionByID(pWeaponDefIndex)
14501501
pWeaponName = pWeaponDef and pWeaponDef:GetName() or "Unknown"
14511502
end)
14521503

@@ -1504,25 +1555,48 @@ local function OnCreateMove(pCmd)
15041555
else
15051556
-- Normal attack if instant attack is disabled or not enough ticks
15061557
-- Use a higher value for normal attacks, but cap it for safety
1507-
local normalAttackTicks = math.min(math.ceil(weaponSmackDelay * 1.8), 24) -- 1.8x multiplier with safety cap
1508-
client.RemoveConVarProtection("sv_maxusrcmdprocessticks") --bypass security
1558+
local normalAttackTicks = math.min(math.floor(weaponSmackDelay), 24)
1559+
client.RemoveConVarProtection("sv_maxusrcmdprocessticks") --bypass security
15091560
client.SetConVar("sv_maxusrcmdprocessticks", normalAttackTicks)
1510-
pCmd:SetButtons(pCmd:GetButtons() | IN_ATTACK) -- attack
1561+
pCmd:SetButtons(pCmd:GetButtons() | IN_ATTACK) -- attack
1562+
1563+
-- Start tracking attack ticks if this is a Demoman with a full charge meter
1564+
-- AND attack tracking hasn't already started
1565+
if pLocalClass == 4 and Menu.Misc.ChargeReach and chargeLeft == 100 and not attackStarted then
1566+
attackStarted = true
1567+
attackTickCount = 0
1568+
-- Get exact weapon smack delay
1569+
weaponSmackDelay = Menu.Aimbot.MaxSwingTime
1570+
if pWeapon and pWeapon:GetWeaponData() and pWeapon:GetWeaponData().smackDelay then
1571+
weaponSmackDelay = math.floor(pWeapon:GetWeaponData().smackDelay / globals.TickInterval())
1572+
end
1573+
--client.ChatPrintf("[Debug] Attack started! Will charge at end of swing (tick " ..(weaponSmackDelay - 1) .. ")")
1574+
end
1575+
1576+
can_attack = false
15111577
end
1512-
can_attack = false
1513-
end
15141578

1515-
-- No need to restore any ChargeReach setting as we're not temporarily changing it
1579+
-- Track attack ticks and execute charge at right moment
1580+
if attackStarted then
1581+
attackTickCount = attackTickCount + 1
15161582

1517-
if can_charge then
1518-
if Menu.Misc.ChargeJump and input.IsButtonPressed(MOUSE_RIGHT) and OnGround then
1519-
pCmd:SetButtons(pCmd:GetButtons() & ~IN_JUMP) -- stop jump for moment
1520-
pCmd:SetButtons(pCmd:GetButtons() & ~IN_ATTACK2) -- stop charge for moment
1521-
pCmd:SetButtons(pCmd:GetButtons() | IN_JUMP) -- jump at 2 ticks before attack
1522-
else
1523-
pCmd:SetButtons(pCmd:GetButtons() | IN_ATTACK2) -- charge
1583+
-- Get weapon smack delay (when the weapon will hit)
1584+
local weaponSmackDelay = Menu.Aimbot.MaxSwingTime
1585+
if pWeapon and pWeapon:GetWeaponData() and pWeapon:GetWeaponData().smackDelay then
1586+
weaponSmackDelay = math.floor(pWeapon:GetWeaponData().smackDelay / globals.TickInterval())
1587+
end
1588+
1589+
-- Execute charge exactly at the end of the swing animation (1 tick before the hit registers)
1590+
if attackTickCount >= (weaponSmackDelay - 2) then
1591+
--client.ChatPrintf("[Debug] Executing charge at end of swing, tick: " .. attackTickCount)
1592+
pCmd:SetButtons(pCmd:GetButtons() | IN_ATTACK2) -- charge
1593+
1594+
-- Reset attack tracking
1595+
attackStarted = false
1596+
attackTickCount = 0
1597+
can_charge = false
1598+
end
15241599
end
1525-
can_charge = false
15261600
end
15271601

15281602
-- Update last variables
@@ -2487,4 +2561,4 @@ local function OnCreateMove_ChargeControl(cmd)
24872561
end
24882562

24892563
-- Register the callback for charge control
2490-
callbacks.Register("CreateMove", "ChargeControl", OnCreateMove_ChargeControl)
2564+
callbacks.Register("CreateMove", "ChargeControl", OnCreateMove_ChargeControl)

0 commit comments

Comments
 (0)