@@ -233,6 +233,18 @@ local gravity = client.GetConVar("sv_gravity") or 800 -- Get the current gravity
233
233
local stepSize = 18
234
234
local tickCounteratack = 0
235
235
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
+
236
248
if pLocal then
237
249
stepSize = pLocal :GetPropFloat (" localdata" , " m_flStepSize" ) or 18
238
250
else
@@ -826,94 +838,65 @@ local function UpdateHomingMissile()
826
838
end
827
839
828
840
local hasNotified = false
829
- local function checkInRangeWithLatency (playerIndex , swingRange , pWeapon , cmd , OnGround , isCharging )
841
+ local function checkInRangeWithLatency (playerIndex , swingRange , pWeapon , cmd )
830
842
local inRange = false
831
843
local point = nil
832
- can_charge = false
833
844
local Backtrack = gui .GetValue (" Backtrack" )
834
845
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
846
847
847
848
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
850
851
if checkInRange (vPlayerOrigin , pLocalOrigin , Charge_Range ) then
851
852
inRange = true
852
853
point = vPlayerOrigin
853
- tick_count = tick_count + 1
854
+ can_charge = false -- Don't set can_charge yet, we'll track it separately
854
855
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 )
872
858
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 ))
877
864
end
878
865
elseif checkInRange (vPlayerFuture , pLocalFuture , Charge_Range ) then
879
866
inRange = true
880
867
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
887
869
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 )
892
872
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 ))
905
878
end
906
879
end
880
+
907
881
if inRange then
908
- return inRange , point , can_charge
882
+ return inRange , point , false -- Return inRange but not can_charge yet
909
883
end
910
884
elseif chargeLeft < 100 then
911
885
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
913
887
inRange = true
914
888
point = vPlayerOrigin
915
889
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
917
900
tick_count = 0
918
901
can_charge = true
919
902
end
@@ -955,8 +938,30 @@ local function checkInRangeWithLatency(playerIndex, swingRange, pWeapon, cmd, On
955
938
inRange = true
956
939
point = vPlayerOrigin
957
940
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
+
960
965
tick_count = 0
961
966
can_charge = true
962
967
end
@@ -976,15 +981,60 @@ local function checkInRangeWithLatency(playerIndex, swingRange, pWeapon, cmd, On
976
981
inRange = true
977
982
point = vPlayerOrigin
978
983
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
+
980
1008
tick_count = 0
981
1009
can_charge = true
982
1010
elseif checkInRange (vPlayerFuture , pLocalFuture , Charge_Range ) then
983
1011
inRange = true
984
1012
point = vPlayerFuture
985
1013
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
+
988
1038
tick_count = 0
989
1039
can_charge = true
990
1040
end
@@ -1409,11 +1459,12 @@ local function OnCreateMove(pCmd)
1409
1459
else
1410
1460
engine .SetViewAngles (EulerAngles (aim_angles .pitch , aim_angles .yaw , 0 ))
1411
1461
end
1412
- elseif pLocalClass == 4 then
1413
- -- Remove ChargeControl call from here
1414
1462
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
1417
1468
end
1418
1469
1419
1470
-- Only try instant attack when it's possible
@@ -1443,10 +1494,10 @@ local function OnCreateMove(pCmd)
1443
1494
Menu .Aimbot .MaxSwingTime = weaponSmackDelay
1444
1495
1445
1496
-- Display notification about the change with weapon name
1446
- local pWeaponName = " Unknown"
1497
+ pWeaponName = " Unknown"
1447
1498
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 )
1450
1501
pWeaponName = pWeaponDef and pWeaponDef :GetName () or " Unknown"
1451
1502
end )
1452
1503
@@ -1504,25 +1555,48 @@ local function OnCreateMove(pCmd)
1504
1555
else
1505
1556
-- Normal attack if instant attack is disabled or not enough ticks
1506
1557
-- 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
1509
1560
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
1511
1577
end
1512
- can_attack = false
1513
- end
1514
1578
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
1516
1582
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
1524
1599
end
1525
- can_charge = false
1526
1600
end
1527
1601
1528
1602
-- Update last variables
@@ -2487,4 +2561,4 @@ local function OnCreateMove_ChargeControl(cmd)
2487
2561
end
2488
2562
2489
2563
-- Register the callback for charge control
2490
- callbacks .Register (" CreateMove" , " ChargeControl" , OnCreateMove_ChargeControl )
2564
+ callbacks .Register (" CreateMove" , " ChargeControl" , OnCreateMove_ChargeControl )
0 commit comments