add sborka
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
LeyHitreg.WeaponSpreads = {}
|
||||
|
||||
local vector_origin = vector_origin
|
||||
|
||||
function LeyHitreg:PlayerSwitchWeapon(ply, oldWep, newWep)
|
||||
if (not IsValid(newWep)) then
|
||||
return
|
||||
end
|
||||
|
||||
local classname = newWep:GetClass()
|
||||
|
||||
if (not classname or self.WeaponSpreads[classname]) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self:IsIgnoreWep(newWep)) then
|
||||
self.WeaponSpreads[classname] = vector_origin
|
||||
return
|
||||
end
|
||||
|
||||
ply.LeyHitreg_NeedsSpreadForce = newWep
|
||||
|
||||
timer.Simple(1, function()
|
||||
if (not IsValid(ply) or not IsValid(newWep)) then
|
||||
return
|
||||
end
|
||||
|
||||
ply.LeyHitreg_NeedsSpreadForce = nil
|
||||
|
||||
if (ply:GetActiveWeapon() != newWep) then
|
||||
return
|
||||
end
|
||||
|
||||
LeyHitreg.WeaponSpreads[classname] = LeyHitreg.WeaponSpreads[classname] or vector_origin
|
||||
end)
|
||||
|
||||
LeyHitreg:SetFittingValidClip(newWep)
|
||||
|
||||
if (newWep.PrimaryAttack) then
|
||||
newWep:PrimaryAttack()
|
||||
elseif (newWep.Primary and newWep.Primary.Attack) then
|
||||
newWep.Primary.Attack()
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("PlayerSwitchWeapon", "LeyHitreg:PlayerSwitchWeapon", function(...)
|
||||
-- process switch at next frame so FireBullets uses proper wep
|
||||
local t = {...}
|
||||
|
||||
timer.Simple(0, function()
|
||||
LeyHitreg:PlayerSwitchWeapon(unpack(t))
|
||||
end)
|
||||
end)
|
||||
|
||||
function LeyHitreg:FetchSpreadFireBullets(ply, wep, bullet)
|
||||
local spreadForceWep = ply.LeyHitreg_NeedsSpreadForce
|
||||
local validSpreadForceWep = spreadForceWep != nil and IsValid(spreadForceWep)
|
||||
|
||||
-- if (validSpreadForceWep) then
|
||||
-- wep = spreadForceWep
|
||||
-- end
|
||||
|
||||
local weaponSpread = LeyHitreg:GetWeaponSpread(ply, wep, bullet)
|
||||
self.WeaponSpreads[wep:GetClass()] = weaponSpread
|
||||
|
||||
if (validSpreadForceWep and wep == spreadForceWep) then
|
||||
bullet.Damage = 1
|
||||
bullet.Distance = 1
|
||||
bullet.Src = Vector(-100000, -10000, -10000)
|
||||
bullet.Dir = vector_origin
|
||||
|
||||
timer.Simple(0, function()
|
||||
if (not IsValid(ply)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (ply.LeyHitreg_NeedsSpreadForce == wep) then
|
||||
ply.LeyHitreg_NeedsSpreadForce = nil
|
||||
end
|
||||
end)
|
||||
|
||||
return bullet
|
||||
end
|
||||
end
|
||||
|
||||
function LeyHitreg:EntityEmitSoundSpreadPrefire(data)
|
||||
if (not data) then
|
||||
return
|
||||
end
|
||||
|
||||
local ent = data.Entity
|
||||
|
||||
if (not IsValid(ent)) then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if (ent:IsPlayer()) then
|
||||
if (ent.LeyHitreg_NeedsSpreadForce) then
|
||||
return false
|
||||
end
|
||||
|
||||
local wep = ent:GetActiveWeapon()
|
||||
|
||||
if (not IsValid(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (wep.LeyHitreg_NeedsSpreadForce) then
|
||||
return false
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if (not ent:IsWeapon()) then
|
||||
return
|
||||
end
|
||||
|
||||
local ply = ent:GetOwner()
|
||||
|
||||
if (IsValid(ply) and ply:IsPlayer() and ply.LeyHitreg_NeedsSpreadForce) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (ent.LeyHitreg_NeedsSpreadForce) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("EntityEmitSound", "LeyHitreg:EntityEmitSoundSpreadPrefire", function(data)
|
||||
local ret = LeyHitreg:EntityEmitSoundSpreadPrefire(data)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,213 @@
|
||||
|
||||
local IsValid = IsValid
|
||||
local inputIsMouseDown = input.IsMouseDown
|
||||
local vector_origin = vector_origin
|
||||
|
||||
IN_LEYHITREG1 = bit.lshift(1, 27)
|
||||
|
||||
function LeyHitreg:ShouldPrimaryAttack()
|
||||
return inputIsMouseDown(MOUSE_LEFT) or inputIsMouseDown(MOUSE_RIGHT)
|
||||
end
|
||||
|
||||
local lastPrim = nil
|
||||
function LeyHitreg:CanShoot(cmd, wep, primary)
|
||||
local canShoot = true
|
||||
|
||||
local nextPrim = wep:GetNextPrimaryFire()
|
||||
|
||||
if (primary) then
|
||||
if (nextPrim == lastPrim or wep:Clip1() == 0) then
|
||||
canShoot = false
|
||||
else
|
||||
lastPrim = nextPrim
|
||||
end
|
||||
end
|
||||
|
||||
return canShoot
|
||||
end
|
||||
|
||||
local bitbor = bit.bor
|
||||
local trace = {}
|
||||
local traceres = {}
|
||||
trace.filter = LocalPlayer()
|
||||
trace.mask = MASK_SHOT
|
||||
trace.output = traceres
|
||||
|
||||
local lply = nil
|
||||
|
||||
timer.Create("LeyHitreg.LocalPlayerGet", 0.1, 0, function()
|
||||
if (not lply and IsValid(LocalPlayer())) then
|
||||
lply = LocalPlayer()
|
||||
trace.filter = lply
|
||||
timer.Remove("LeyHitreg.LocalPlayerGet")
|
||||
end
|
||||
end)
|
||||
|
||||
LeyHitreg.WeaponSpreads = {}
|
||||
|
||||
function LeyHitreg:IsAutoWep(wep)
|
||||
if (wep.Primary) then
|
||||
return wep.Primary.Automatic
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local NeedsPrimReset = false
|
||||
|
||||
function LeyHitreg:CreateMove(cmd)
|
||||
if (not lply or LeyHitreg.Disabled or LeyHitreg.DisabledOnlyOnClient) then
|
||||
return
|
||||
end
|
||||
|
||||
local spreadWep = lply.LeyHitreg_NeedsSpreadForce
|
||||
|
||||
if (spreadWep and IsValid(spreadWep)) then
|
||||
LeyHitreg:SetFittingValidClip(spreadWep)
|
||||
end
|
||||
|
||||
if (cmd:CommandNumber() == 0) then
|
||||
return
|
||||
end
|
||||
|
||||
local cmdAttack1 = cmd:KeyDown(IN_ATTACK)
|
||||
|
||||
if (not cmdAttack1) then
|
||||
NeedsPrimReset = false
|
||||
return
|
||||
elseif (NeedsPrimReset and not cmdAttack1) then
|
||||
NeedsPrimReset = false
|
||||
end
|
||||
|
||||
local shouldPrimary = self:ShouldPrimaryAttack()
|
||||
|
||||
if (not shouldPrimary) then
|
||||
return
|
||||
end
|
||||
|
||||
local wep = lply:GetActiveWeapon()
|
||||
|
||||
if (not IsValid(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self:IsIgnoreWep(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (not self:CanShoot(cmd, wep, shouldPrimary)) then
|
||||
return
|
||||
end
|
||||
|
||||
local primAuto = self:IsAutoWep(wep)
|
||||
|
||||
if (NeedsPrimReset and shouldPrimary) then
|
||||
return
|
||||
end
|
||||
|
||||
if (not primAuto and shouldPrimary) then
|
||||
NeedsPrimReset = true
|
||||
end
|
||||
|
||||
if (shouldPrimary) then
|
||||
cmd:SetButtons(bitbor(cmd:GetButtons(), IN_LEYHITREG1))
|
||||
end
|
||||
|
||||
trace.start = lply:GetShootPos()
|
||||
local viewang = cmd:GetViewAngles()
|
||||
local dir = viewang:Forward()
|
||||
|
||||
local weaponSpread = self:GetWeaponSpread(lply, wep)
|
||||
|
||||
if (weaponSpread) then
|
||||
local applied, newDir = self:ApplyBulletSpread(lply, dir, weaponSpread)
|
||||
|
||||
if (applied) then
|
||||
dir = newDir
|
||||
end
|
||||
else
|
||||
-- LocalPlayer():ChatPrint("NO WEAPONSPREAD")
|
||||
end
|
||||
|
||||
trace.endpos = trace.start + (dir * (56756 * 8))
|
||||
traceres.Entity = nil
|
||||
traceres.HitGroup = nil
|
||||
traceres.HitBox = nil
|
||||
|
||||
util.TraceLine(trace)
|
||||
|
||||
local target = traceres.Entity
|
||||
|
||||
if (not IsValid(target) or not (target:IsNPC() or target:IsPlayer())) then
|
||||
cmd:SetUpMove(-1)
|
||||
if (LeyHitreg.AnnounceClientHits) then
|
||||
LocalPlayer():ChatPrint("It's a miss!")
|
||||
-- PrintTable(trace)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local hitgroup = traceres.HitGroup
|
||||
local hitbox = traceres.HitBox
|
||||
local hitbone = target:GetHitBoxBone(hitbox, 0)
|
||||
|
||||
if (not hitbone or not hitgroup) then
|
||||
print("[/LeyHitreg/] Bone not found")
|
||||
return
|
||||
end
|
||||
|
||||
cmd:SetUpMove(target:EntIndex())
|
||||
cmd:SetMouseWheel(hitbone)
|
||||
|
||||
if (LeyHitreg.AnnounceClientHits) then
|
||||
LocalPlayer():ChatPrint("It's a hit!")
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("CreateMove", "LeyHitreg:CreateMove", function(...)
|
||||
LeyHitreg:CreateMove(...)
|
||||
end)
|
||||
|
||||
function LeyHitreg:EntityFireBullets(plyorwep, bullet)
|
||||
if (LeyHitreg.Disabled or LeyHitreg.DisabledOnlyOnClient) then
|
||||
return
|
||||
end
|
||||
|
||||
if (bullet.Num >= 2) then
|
||||
return
|
||||
end
|
||||
|
||||
local ply, wep = self:GetPlayerFromPlyOrBullet(plyorwep, bullet)
|
||||
|
||||
if (not ply) then
|
||||
return
|
||||
end
|
||||
|
||||
if (not wep or self:IsIgnoreWep(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (not LeyHitreg.ShotDirForceDisabled) then
|
||||
bullet.Dir = ply:GetAimVector()
|
||||
end
|
||||
|
||||
local forcedShot = LeyHitreg:FetchSpreadFireBullets(ply, wep, bullet)
|
||||
|
||||
if (forcedShot != nil) then
|
||||
return forcedShot
|
||||
end
|
||||
|
||||
local ret = LeyHitreg:SpreadedEntityFireBullets(ply, wep, bullet)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("EntityFireBullets", "LeyHitreg:EntityFireBullets", function(plyorwep, bullet)
|
||||
local ret = LeyHitreg:EntityFireBullets(plyorwep, bullet)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,60 @@
|
||||
-- By just locking onto a specific bone, we don't always get a match. We might lock onto a bone pos
|
||||
-- and that bone pos just happens to be the center. Then, if we're looking through a edge
|
||||
-- it's possible that the bullet would miss
|
||||
-- so how do we fix this? well, hit scanning
|
||||
-- if a bullet which should hit locked onto a bone pos misses,
|
||||
-- then attempt to use a more expensive calculation to scan for the precise
|
||||
-- location which would hit
|
||||
-- if one is found -> fire bullet again but with that information
|
||||
-- alternatively, dont fire
|
||||
-- the calculation is done in bullet cb to make it less expensive
|
||||
-- because most of the time, just picking the bone pos should work
|
||||
|
||||
-- bullet missed even though it should not have, try hitscan
|
||||
function LeyHitreg:HitScan(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos)
|
||||
-- TODO: do hitscan here
|
||||
end
|
||||
|
||||
local IsValid = IsValid
|
||||
|
||||
function LeyHitreg:HitScanBulletCallback(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos, cbdata)
|
||||
local traceres = cbdata[2]
|
||||
|
||||
if (IsValid(traceres.Entity)) then
|
||||
return
|
||||
end
|
||||
|
||||
self:HitScan(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos)
|
||||
end
|
||||
|
||||
function LeyHitreg:HitScanBullet(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos)
|
||||
if (self.BulletOverwriteDisabled) then
|
||||
return
|
||||
end
|
||||
|
||||
local oldCallback = bullet.Callback or function() end
|
||||
|
||||
bullet.Callback = function(...)
|
||||
local cbdata = {...}
|
||||
|
||||
if (cbdata[1] != ply) then
|
||||
return oldCallback(...)
|
||||
end
|
||||
|
||||
local ignoreBullet = hook.Call("LeyHitreg.OnBulletCallback", cbdata[1], cbdata[2], cbdata[3])
|
||||
|
||||
if (ignoreBullet) then
|
||||
return
|
||||
end
|
||||
|
||||
if (LeyHitreg.HitScanDisabled) then
|
||||
return oldCallback(...)
|
||||
end
|
||||
|
||||
if (LeyHitreg:HitScanBulletCallback(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos, cbdata)) then
|
||||
return
|
||||
end
|
||||
|
||||
return oldCallback(...)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,322 @@
|
||||
local IsValid = IsValid
|
||||
local CurTime = CurTime
|
||||
local ipairs = ipairs
|
||||
local tableremove = table.remove
|
||||
|
||||
LeyHitreg.ForceHit = {}
|
||||
|
||||
local toRemove = {}
|
||||
|
||||
function LeyHitreg:CleanHits(ply, wep, tbl)
|
||||
local needsRemove = false
|
||||
local highestKey = nil
|
||||
|
||||
local curTime = CurTime()
|
||||
|
||||
for k,v in ipairs(tbl) do
|
||||
local target = v.target
|
||||
|
||||
if (not IsValid(target) or target:Health() < 0 or curTime > v.expireTime or v.weapon != wep) then
|
||||
toRemove[#toRemove + 1] = k
|
||||
|
||||
if (not highestKey or k > highestKey) then
|
||||
highestKey = k
|
||||
end
|
||||
|
||||
needsRemove = true
|
||||
end
|
||||
end
|
||||
|
||||
if (not needsRemove) then
|
||||
return tbl
|
||||
end
|
||||
|
||||
for i = #toRemove, 1, -1 do
|
||||
local key = toRemove[i]
|
||||
tableremove(tbl, key)
|
||||
toRemove[i] = nil
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
LeyHitreg.ScaleDamageBlockEntity = LeyHitreg.ScaleDamageBlockEntity or {}
|
||||
|
||||
local spread = vector_origin
|
||||
|
||||
function LeyHitreg:FallbackEntityFireBullets(ply, wep, bullet)
|
||||
local ret = LeyHitreg:SpreadedEntityFireBullets(ply, wep, bullet)
|
||||
if (LeyHitreg.ShowActualShotSpreadedHit) then
|
||||
LeyHitreg:DebugShowActualShotHit(bullet)
|
||||
end
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
function LeyHitreg:DebugShowActualShotHit(bullet)
|
||||
|
||||
local ocb = bullet.Callback or function() end
|
||||
|
||||
bullet.Callback = function(atk, tr, dmginfo, ...)
|
||||
util.Decal("Eye", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal)
|
||||
return ocb(atk, tr, dmginfo, ...)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function LeyHitreg:EntityTakeDamage(ent, dmg)
|
||||
if (not IsValid(ent)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (not ent.IsNPC or not ent.IsPlayer) then
|
||||
return
|
||||
end
|
||||
|
||||
if (not ent:IsNPC() and not ent:IsPlayer()) then
|
||||
return
|
||||
end
|
||||
|
||||
local atk = dmg:GetAttacker()
|
||||
|
||||
if (not IsValid(atk)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (atk.LeyHitreg_CurrentBullet) then
|
||||
atk.LeyHitreg_CurrentBullet = nil
|
||||
atk.LeyHitreg_LastShotMissed = nil
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("EntityTakeDamage","LeyHitreg:EntityTakeDamage", function(ent, dmg)
|
||||
local ret = LeyHitreg:EntityTakeDamage(ent, dmg)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end)
|
||||
|
||||
local tickCount = engine.TickCount
|
||||
function LeyHitreg:PlayerTick(ply)
|
||||
if (ply.LeyHitreg_CurrentBullet) then
|
||||
local curTick = tickCount()
|
||||
ply.LeyHitreg_CurrentBullet = nil
|
||||
ply.LeyHitreg_LastShotMissed = curTick
|
||||
|
||||
local hitTable = LeyHitreg.ForceHit[ply]
|
||||
|
||||
if (not hitTable) then
|
||||
return
|
||||
end
|
||||
|
||||
local shot = nil
|
||||
local bestDelta = nil
|
||||
|
||||
for k,v in ipairs(hitTable) do
|
||||
local delta = curTick - v.tickCount
|
||||
if (delta >= 0) then
|
||||
if (not bestDelta or bestDelta > delta) then
|
||||
bestDelta = delta
|
||||
shot = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (not shot) then
|
||||
return
|
||||
end
|
||||
|
||||
if (bestDelta > 6) then -- Ideally I'd probably assume it's the same tick
|
||||
return
|
||||
end
|
||||
|
||||
ply.LeyHitreg_LastBulletEnt:FireBullets(ply.LeyHitreg_LastBullet)
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("PlayerTick", "LeyHitreg:PlayerTick", function(ply)
|
||||
LeyHitreg:PlayerTick(ply)
|
||||
end)
|
||||
|
||||
function LeyHitreg:EntityFireBullets(plyorwep, bullet)
|
||||
local ocb = bullet.Callback or function() end
|
||||
|
||||
bullet.Callback = function(atk, tr, dmginfo, ...)
|
||||
atk.LeyHitreg_CurrentBullet = true
|
||||
atk.LeyHitreg_LastBullet = table.Copy(bullet)
|
||||
atk.LeyHitreg_LastBulletEnt = plyorwep
|
||||
return ocb(atk, tr, dmginfo, ...)
|
||||
end
|
||||
|
||||
if (LeyHitreg.ShowActualShotHit) then
|
||||
LeyHitreg:DebugShowActualShotHit(bullet)
|
||||
end
|
||||
|
||||
local ply, wep = self:GetPlayerFromPlyOrBullet(plyorwep, bullet)
|
||||
|
||||
if (not ply or not wep) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self:IsIgnoreWep(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (not LeyHitreg.ShotDirForceDisabled) then
|
||||
bullet.Dir = ply:GetAimVector()
|
||||
end
|
||||
|
||||
local hitTable = LeyHitreg.ForceHit[ply]
|
||||
|
||||
if (not hitTable) then
|
||||
return self:FallbackEntityFireBullets(ply, wep, bullet)
|
||||
end
|
||||
|
||||
local shot = self:CleanHits(ply, wep, hitTable)[1]
|
||||
|
||||
if (not shot) then
|
||||
return self:FallbackEntityFireBullets(ply, wep, bullet)
|
||||
end
|
||||
|
||||
tableremove(hitTable, 1)
|
||||
local target = shot.target
|
||||
|
||||
|
||||
-- print(canSee)
|
||||
-- print(target)
|
||||
-- PrintTable(shot)
|
||||
|
||||
local targetpos = target:GetBonePosition(shot.targetBone)
|
||||
|
||||
if (not targetpos) then
|
||||
ply:ChatPrint("[/LeyHitreg/] Bone not found")
|
||||
return self:FallbackEntityFireBullets(ply, wep, bullet)
|
||||
end
|
||||
|
||||
local newshootpos = ply:GetShootPos()
|
||||
local newdir = (targetpos - bullet.Src)
|
||||
|
||||
LeyHitreg:HitScanBullet(ply, target, bullet, shot, shot.targetBone, shot.targetHitGroup, newshootpos)
|
||||
|
||||
bullet.Src = newshootpos
|
||||
bullet.Dir = newdir
|
||||
bullet.Spread = vector_origin
|
||||
|
||||
self.ScaleDamageBlockEntity[ply] = true
|
||||
|
||||
ply.LeyHitReg_ShouldHit = shot.targetHitGroup
|
||||
|
||||
if (LeyHitreg.LogFixedBullets) then
|
||||
ply.LeyHitreg_Bullets = (ply.LeyHitreg_Bullets or 0) + 1
|
||||
|
||||
timer.Create("LeyHitreg." .. ply:SteamID64() .. ".LogFixedBullets", 1, 1, function()
|
||||
ply:ChatPrint("bullets hitregged: " .. tostring(ply.LeyHitreg_Bullets))
|
||||
ply.LeyHitreg_Bullets = 0
|
||||
end)
|
||||
end
|
||||
|
||||
if (LeyHitreg.BulletAimbot) then
|
||||
timer.Simple(0, function()
|
||||
ply:SetEyeAngles(newdir:Angle())
|
||||
end)
|
||||
end
|
||||
|
||||
if (LeyHitreg.LogTargetBone) then
|
||||
ply:ChatPrint("Target Bone: " .. tostring(shot.targetBone))
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function LeyHitreg:InsertPlayerData(ply, cmd, wep, shouldPrimary, target, targetBone, targetHitGroup)
|
||||
if (#self.ForceHit[ply] > 500) then
|
||||
ply:Kick("[/LeyHitreg/] No Exploiting, little boy.")
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(self.ForceHit[ply], {
|
||||
["shouldPrimary"] = shouldPrimary,
|
||||
["target"] = target,
|
||||
["targetPos"] = target:GetPos(),
|
||||
["targetBone"] = targetBone,
|
||||
["targetHitGroup"] = targetHitGroup,
|
||||
["shootPos"] = ply:GetShootPos(),
|
||||
["eyeAngles"] = cmd:GetViewAngles(),
|
||||
["aimVec"] = ply:GetAimVector(),
|
||||
["shootPos"] = ply:GetPos(),
|
||||
["weapon"] = wep,
|
||||
["expireTime"] = CurTime() + 0.8,
|
||||
["tickCount"] = engine.TickCount()
|
||||
})
|
||||
end
|
||||
|
||||
function LeyHitreg:CanPrimaryAttack(wep)
|
||||
local ply = wep:GetOwner()
|
||||
if (wep:Clip1() == 0) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (not self.IgnoreCanNextPrimaryAttack and wep.CanPrimaryAttack) then
|
||||
if (not wep:CanPrimaryAttack()) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local nextPrim = wep:GetNextPrimaryFire()
|
||||
|
||||
if (wep.LastNextPrim and wep.LastNextPrim == nextPrim) then
|
||||
return false
|
||||
end
|
||||
|
||||
wep.LastNextPrim = nextPrim
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function LeyHitreg:ProcessBullet(ply, cmd, wep, shouldPrimary, target, targetBone)
|
||||
self.ForceHit[ply] = self.ForceHit[ply] or {}
|
||||
|
||||
if (not target or target:Health() < 0) then
|
||||
return
|
||||
end
|
||||
|
||||
if (wep.LeyHitregIgnore) then
|
||||
return
|
||||
end
|
||||
|
||||
if (shouldPrimary and self:CanPrimaryAttack(wep)) then
|
||||
local targetHitGroup = HITGROUP_GENERIC
|
||||
|
||||
local hitboxsets = target.GetHitBoxSetCount and target:GetHitBoxSetCount() or 1
|
||||
for hitboxset = 0, hitboxsets - 1 do
|
||||
local hitboxes = target:GetHitBoxCount(hitboxset)
|
||||
|
||||
for hitbox = 0, hitboxes - 1 do
|
||||
local bone = target:GetHitBoxBone(hitbox, hitboxset)
|
||||
|
||||
if (bone == targetBone) then
|
||||
targetHitGroup = target:GetHitBoxHitGroup(hitbox, hitboxset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hookRet = hook.Call("LeyHitreg:ProcessBullet", nil, ply, cmd, wep, shouldPrimary, target, targetBone, targetHitGroup)
|
||||
if (hookRet == false) then
|
||||
return
|
||||
end
|
||||
|
||||
self:InsertPlayerData(ply, cmd, wep, shouldPrimary, target, targetBone, targetHitGroup)
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("EntityFireBullets", "LeyHitreg:EntityFireBullets", function(...)
|
||||
local ret = LeyHitreg:EntityFireBullets(...)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,133 @@
|
||||
function LeyHitreg:OriginalScaleDamage(ent, hitgroup, dmg, orighitgroup)
|
||||
if (not self.LogHitgroupMismatches) then
|
||||
return
|
||||
end
|
||||
|
||||
local atk = dmg:GetAttacker()
|
||||
|
||||
if (orighitgroup and IsValid(atk) and atk.IsPlayer and atk:IsPlayer()) then
|
||||
local shouldHit = hitgroup
|
||||
atk:ChatPrint("HITGROUP_HEAD: " .. tostring(hitgroup == HITGROUP_HEAD))
|
||||
atk:ChatPrint(shouldHit .. "==" .. orighitgroup)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("ScalePlayerDamage", "LeyHitreg.DamageLog", function(ent, hitgroup, dmg, orighitgroup)
|
||||
local ret = LeyHitreg:OriginalScaleDamage(ent, hitgroup, dmg, orighitgroup)
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("ScaleNPCDamage", "LeyHitreg.DamageLog", function(ent, hitgroup, dmg, orighitgroup)
|
||||
local ret = LeyHitreg:OriginalScaleDamage(ent, hitgroup, dmg, orighitgroup)
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end)
|
||||
|
||||
LeyHitreg.ScaleDamagePlayersHooks = {}
|
||||
LeyHitreg.ScaleDamageNPCsHooks = {}
|
||||
|
||||
function LeyHitreg:ScaleDamageCorrectly(target, hitgroup, dmg, targetisplayer)
|
||||
local atk = dmg:GetAttacker()
|
||||
local orighitgroup = hitgroup
|
||||
|
||||
if (IsValid(atk) and atk:IsPlayer()) then
|
||||
if (LeyHitreg.ScaleDamageBlockEntity[atk]) then
|
||||
LeyHitreg.ScaleDamageBlockEntity[atk] = false
|
||||
end
|
||||
|
||||
hitgroup = atk.LeyHitReg_ShouldHit or hitgroup
|
||||
atk.LeyHitReg_ShouldHit = nil
|
||||
end
|
||||
|
||||
local damageHooks = targetisplayer and self.ScaleDamagePlayersHooks or self.ScaleDamageNPCsHooks
|
||||
|
||||
for k,v in pairs(damageHooks) do
|
||||
local ret = v(target, hitgroup, dmg, orighitgroup)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
if (targetisplayer) then
|
||||
local ret = GAMEMODE:OldScalePlayerDamage(target, hitgroup, dmg, orighitgroup)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
else
|
||||
local ret = GAMEMODE:OldScaleNPCDamage(target, hitgroup, dmg, orighitgroup)
|
||||
|
||||
if (ret != nil) then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function LeyHitreg:ScalePlayerDamage(ply, hitgroup, dmg)
|
||||
return LeyHitreg:ScaleDamageCorrectly(ply, hitgroup, dmg, true)
|
||||
end
|
||||
|
||||
function LeyHitreg:ScaleNPCDamage(npc, hitgroup, dmg)
|
||||
return LeyHitreg:ScaleDamageCorrectly(npc, hitgroup, dmg, false)
|
||||
end
|
||||
|
||||
function LeyHitreg:AbsorbScaleDamageHooks()
|
||||
if (self.Disabled) then
|
||||
return
|
||||
end
|
||||
|
||||
GAMEMODE.OldScalePlayerDamage = GAMEMODE.OldScalePlayerDamage or GAMEMODE.ScalePlayerDamage
|
||||
GAMEMODE.OldScaleNPCDamage = GAMEMODE.OldScaleNPCDamage or GAMEMODE.ScaleNPCDamage
|
||||
|
||||
function GAMEMODE:ScalePlayerDamage(...)
|
||||
if (LeyHitreg.Disabled) then
|
||||
return self:OldScalePlayerDamage(...)
|
||||
end
|
||||
|
||||
local ret = LeyHitreg:ScalePlayerDamage(...)
|
||||
|
||||
if (ret) then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
function GAMEMODE:ScaleNPCDamage(...)
|
||||
if (LeyHitreg.Disabled) then
|
||||
return self:OldScaleNPCDamage(...)
|
||||
end
|
||||
|
||||
local ret = LeyHitreg:ScaleNPCDamage(...)
|
||||
|
||||
if (ret) then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
local allHooks = hook.GetTable()
|
||||
|
||||
local scalePlayers = allHooks["ScalePlayerDamage"] or {}
|
||||
local scaleNPCs = allHooks["ScaleNPCDamage"] or {}
|
||||
|
||||
for k,v in pairs(scalePlayers) do
|
||||
hook.Remove("ScalePlayerDamage", k)
|
||||
self.ScaleDamagePlayersHooks[k] = v
|
||||
end
|
||||
|
||||
for k,v in pairs(scaleNPCs) do
|
||||
hook.Remove("ScaleNPCDamage", k)
|
||||
self.ScaleDamageNPCsHooks[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
timer.Simple(1, function()
|
||||
LeyHitreg:AbsorbScaleDamageHooks()
|
||||
end)
|
||||
|
||||
timer.Create("LeyHitreg:AbsorbScaleDamageHooks", 5, 0, function()
|
||||
LeyHitreg:AbsorbScaleDamageHooks()
|
||||
end)
|
||||
@@ -0,0 +1,12 @@
|
||||
local meta = FindMetaTable("CTakeDamageInfo")
|
||||
|
||||
LeyHitreg.ScaleDamageBlockEntity = LeyHitreg.ScaleDamageBlockEntity or {}
|
||||
meta.OldScaleDamage = meta.OldScaleDamage or meta.ScaleDamage
|
||||
|
||||
function meta:ScaleDamage(scale)
|
||||
if (self:IsBulletDamage() and LeyHitreg and LeyHitreg.ScaleDamageBlockEntity[self:GetAttacker()]) then
|
||||
return
|
||||
end
|
||||
|
||||
return self:OldScaleDamage(scale)
|
||||
end
|
||||
@@ -0,0 +1,101 @@
|
||||
IN_LEYHITREG1 = bit.lshift(1, 27)
|
||||
|
||||
local Entity = Entity
|
||||
local IsValid = IsValid
|
||||
|
||||
local PlyNeedsPrimReset = {}
|
||||
|
||||
LeyHitreg.BulletCount = {}
|
||||
LeyHitreg.InvalidShots = {}
|
||||
|
||||
function LeyHitreg:StartCommand(ply, cmd)
|
||||
if (not ply:Alive() or LeyHitreg.Disabled) then
|
||||
return
|
||||
end
|
||||
|
||||
local shouldPrimary = cmd:KeyDown(IN_LEYHITREG1)
|
||||
|
||||
if (not shouldPrimary) then
|
||||
return
|
||||
end
|
||||
|
||||
local targetEntIndex = cmd:GetUpMove()
|
||||
local targetBone = cmd:GetMouseWheel()
|
||||
|
||||
cmd:SetUpMove(0)
|
||||
cmd:SetMouseWheel(0)
|
||||
|
||||
if (targetBone > 0xFF) then
|
||||
return
|
||||
end
|
||||
|
||||
local wep = ply:GetActiveWeapon()
|
||||
|
||||
if (not IsValid(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self:IsIgnoreWep(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
if ((LeyHitreg.BulletCount[ply] or 0) > 50) then
|
||||
return
|
||||
end
|
||||
|
||||
LeyHitreg.BulletCount[ply] = (LeyHitreg.BulletCount[ply] or 0) + 1
|
||||
|
||||
local target
|
||||
|
||||
if (targetEntIndex and targetEntIndex > 0) then
|
||||
target = Entity(targetEntIndex)
|
||||
|
||||
if (not IsValid(target) or not (target:IsNPC() or target:IsPlayer())) then
|
||||
target = nil
|
||||
end
|
||||
else
|
||||
targetEntIndex = 0
|
||||
end
|
||||
|
||||
if (target) then
|
||||
if (self:IsInvalidShot(ply, cmd, wep, shouldPrimary, target, targetBone)) then
|
||||
if (self.LogInvalidShots) then
|
||||
ply:ChatPrint("Invalid shot!")
|
||||
end
|
||||
|
||||
LeyHitreg.InvalidShots[ply] = (LeyHitreg.InvalidShots[ply] or 0) + 1
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
LeyHitreg:ProcessBullet(ply, cmd, wep, shouldPrimary, target, targetBone)
|
||||
end
|
||||
|
||||
timer.Create("LeyHitreg.BulletMax", 0.1, 0, function()
|
||||
for k, ply in ipairs(player.GetAll()) do
|
||||
LeyHitreg.BulletCount[ply] = 0
|
||||
end
|
||||
end)
|
||||
|
||||
timer.Create("LeyHitreg.KickInvalidShooters", 30, 0, function()
|
||||
for k, ply in ipairs(player.GetAll()) do
|
||||
if ((LeyHitreg.InvalidShots[ply] or 0) >= 10) then
|
||||
ply:Kick("[/LeyHitreg/] Too many invalid shots!")
|
||||
end
|
||||
|
||||
LeyHitreg.InvalidShots[ply] = 0
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("StartCommand", "LeyHitreg:StartCommand", function(ply, cmd)
|
||||
LeyHitreg:StartCommand(ply, cmd)
|
||||
end)
|
||||
|
||||
function LeyHitreg:PlayerSwitchWeapon(ply, oldWep, newWep)
|
||||
PlyNeedsPrimReset[ply] = nil
|
||||
end
|
||||
|
||||
hook.Add("PlayerSwitchWeapon", "LeyHitreg:PlayerSwitchWeapon", function(ply, oldWep, newWep)
|
||||
LeyHitreg:PlayerSwitchWeapon(ply, oldWep, newWep)
|
||||
end)
|
||||
@@ -0,0 +1,72 @@
|
||||
-- just ideas to make aimbot using this harder
|
||||
|
||||
-- if the angle which client supposedly used to hit target is more than MaxFOVDiffDeg degrees off of the target
|
||||
-- chances are it's not a information mismatch but a manipulation attempt
|
||||
|
||||
local mathacos = math.acos
|
||||
local mathdeg = math.deg
|
||||
|
||||
local FOVCheckCloseDist = 350 * 350
|
||||
local FOVCheckFarDist = 700 * 700
|
||||
|
||||
local MaxCloseFOVDiffDeg = 90
|
||||
local MaxFarFOVDiffDeg = 40
|
||||
|
||||
local MaxCloseFOVDiffRad = math.rad(MaxCloseFOVDiffDeg)
|
||||
local MaxFarFOVDiffRad = math.rad(MaxFarFOVDiffDeg)
|
||||
|
||||
|
||||
function LeyHitreg:IsInvalidShotOutOfFOV(ply, plyang, plypos, tarpos, distsqr)
|
||||
if (distsqr < FOVCheckCloseDist) then
|
||||
if (self.LogInvalidFOV) then
|
||||
ply:ChatPrint("FOV: Close, so no checking")
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local maxRad = distsqr > FOVCheckFarDist and MaxFarFOVDiffRad or MaxCloseFOVDiffRad
|
||||
|
||||
local targetdir = (tarpos - plypos)
|
||||
local curdir = plyang:Forward()
|
||||
local FOVDiff = mathacos(targetdir:Dot(curdir) / (targetdir:Length() * curdir:Length()))
|
||||
|
||||
if (self.LogInvalidFOV) then
|
||||
ply:ChatPrint("FOV: " .. tostring(mathdeg(FOVDiff)) .. " Max: " .. tostring(mathdeg(maxRad)))
|
||||
end
|
||||
|
||||
return FOVDiff > maxRad
|
||||
end
|
||||
|
||||
-- if the weapon has spread, and the client did not apply any spread, then reject the bullet
|
||||
-- this requires the unmodified va to be sent together in the usercmd somehow
|
||||
-- then can compare the two and if equal, yeet
|
||||
function LeyHitreg:IsSpreadNotApplied(ply, cmd, wep, shouldPrimary)
|
||||
if (self.NoSpread) then
|
||||
return false
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function LeyHitreg:IsInvalidShot(ply, cmd, wep, shouldPrimary, target, targetBone)
|
||||
if (LeyHitreg.DisableSecurityChecks) then
|
||||
return false
|
||||
end
|
||||
|
||||
local plyang = cmd:GetViewAngles()
|
||||
local plypos = ply:GetPos()
|
||||
local tarpos = target:GetPos()
|
||||
local distsqr = plypos:DistToSqr(tarpos)
|
||||
|
||||
if (self:IsInvalidShotOutOfFOV(ply, plyang, plypos, tarpos, distsqr)) then
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
if (self:IsSpreadNotApplied(ply, cmd, wep, shouldPrimary)) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
local meta = FindMetaTable("Player")
|
||||
meta.OldLagCompensation = meta.OldLagCompensation or meta.LagCompensation
|
||||
|
||||
function meta:LagCompensation(...)
|
||||
if (LeyHitreg.DisableLagComp and not LeyHitreg.Disabled) then
|
||||
return
|
||||
end
|
||||
|
||||
return self:OldLagCompensation(...)
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
local Vector = Vector
|
||||
local mathmodf = math.modf
|
||||
local mathrandomseed = math.randomseed
|
||||
local mathrandom = math.random
|
||||
local mathsqrt = math.sqrt
|
||||
local isnumber = isnumber
|
||||
local vector_origin = vector_origin
|
||||
|
||||
local timefn = function()
|
||||
return 1 -- os.date("%S")
|
||||
end
|
||||
|
||||
function LeyHitreg:ApplyBulletSpread(ply, dir, spread)
|
||||
if (LeyHitreg.NoSpread) then
|
||||
return true, dir, vector_origin
|
||||
end
|
||||
|
||||
if (not spread or spread == vector_origin or LeyHitreg.BrokenSpread) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (isnumber(spread)) then
|
||||
spread = Vector(spread, spread, spread)
|
||||
end
|
||||
|
||||
local add = (8969 * timefn())
|
||||
|
||||
mathrandomseed(add + CurTime())
|
||||
|
||||
local ang = dir:Angle()
|
||||
|
||||
local appliedSpread, rgt, up = Vector(), ang:Right(), ang:Up()
|
||||
|
||||
local x, y, z
|
||||
|
||||
repeat
|
||||
x = mathrandom() + mathrandom() - 1
|
||||
y = mathrandom() + mathrandom() - 1
|
||||
|
||||
z = x * x + y * y
|
||||
until z <= 1
|
||||
|
||||
for i = 1, 3 do
|
||||
appliedSpread[i] = x * spread.x * rgt[i] + y * spread.y * up[i]
|
||||
end
|
||||
|
||||
dir = dir + appliedSpread
|
||||
|
||||
return true, dir, appliedSpread
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
function LeyHitreg:SpreadedEntityFireBullets(ply, wep, bullet, spread)
|
||||
if (LeyHitreg.Disabled) then
|
||||
return
|
||||
end
|
||||
|
||||
if (LeyHitreg.BrokenDefaultSpread) then
|
||||
return
|
||||
end
|
||||
|
||||
local bulletSpread = spread or LeyHitreg:GetWeaponSpread(ply, wep, bullet)
|
||||
local appliedAny, newDir = self:ApplyBulletSpread(ply, bullet.Dir, bulletSpread)
|
||||
|
||||
if (not appliedAny) then
|
||||
return
|
||||
end
|
||||
|
||||
bullet.Spread = vector_origin
|
||||
bullet.Dir = newDir
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
function LeyHitreg:ConVarSet(name, val)
|
||||
if (GetConVar(name)) then
|
||||
RunConsoleCommand(name, val)
|
||||
end
|
||||
end
|
||||
|
||||
function LeyHitreg:SWEPConvars()
|
||||
self:ConVarSet("arccw_enable_penetration", "0")
|
||||
self:ConVarSet("sv_tfa_bullet_penetration", "0")
|
||||
self:ConVarSet("sv_tfa_bullet_randomseed", "0")
|
||||
end
|
||||
|
||||
timer.Simple(1, function()
|
||||
LeyHitreg:SWEPConvars()
|
||||
end)
|
||||
@@ -0,0 +1,205 @@
|
||||
local HL2Ignore = {}
|
||||
HL2Ignore["weapon_physcannon"] = true
|
||||
HL2Ignore["weapon_physgun"] = true
|
||||
HL2Ignore["weapon_frag"] = true
|
||||
HL2Ignore["weapon_rpg"] = true
|
||||
HL2Ignore["gmod_camera"] = true
|
||||
HL2Ignore["gmod_tool"] = true
|
||||
HL2Ignore["weapon_physcannon"] = true
|
||||
HL2Ignore["weapon_shotgun"] = true
|
||||
|
||||
local MeleeHoldType = {}
|
||||
MeleeHoldType["knife"] = true
|
||||
MeleeHoldType["melee"] = true
|
||||
MeleeHoldType["melee2"] = true
|
||||
|
||||
local ExtraIgnores = {}
|
||||
|
||||
function LeyHitreg:IsIgnoreWep(wep)
|
||||
if (HL2Ignore[wep:GetClass()]) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (ExtraIgnores[wep:GetClass()]) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Ignore all melees
|
||||
if (wep.IsMelee or wep.Melee or wep:Clip1() < 0) then
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
if (wep.GetHoldType) then
|
||||
local holdType = wep:GetHoldType()
|
||||
|
||||
if (MeleeHoldType[holdType]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- Ignore shotguns
|
||||
if (wep.Shotgun or wep.IsShotgun or wep.ShotgunReload or wep.ShotGun or wep.Primary and wep.Primary.NumShots and wep.Primary.NumShots > 1) then
|
||||
return true
|
||||
end
|
||||
-- Ignore modern day SWEP creators who are too busy reinventing the wheel to add a single wep.IsShotgun variable
|
||||
if (wep.ShotgunEmptyAnim or wep.ShotgunStartAnimShell) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (wep.Category and string.find(string.lower(wep.Category), "shotgun", 1, true)) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (wep.Purpose and string.find(string.lower(wep.Purpose), "shotgun", 1, true)) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (wep.PrintName and string.find(string.lower(wep.PrintName), "shotgun", 1, true)) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (ACT3_CAT_SHOTGUN and wep.ACT3Cat and wep.ACT3Cat == ACT3_CAT_SHOTGUN) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function LeyHitreg:AddIgnoreWeapon(weporclass)
|
||||
if (isstring(weporclass)) then
|
||||
ExtraIgnores[weporclass] = true
|
||||
else
|
||||
ExtraIgnores[weporclass:GetClass()] = true
|
||||
end
|
||||
end
|
||||
|
||||
function LeyHitreg:GetPlayerFromWeapon(wep)
|
||||
local ply = wep:GetOwner()
|
||||
|
||||
if (not IsValid(ply)) then
|
||||
return
|
||||
end
|
||||
|
||||
return ply
|
||||
end
|
||||
|
||||
local IsValid = IsValid
|
||||
function LeyHitreg:GetPlayerFromPlyOrBullet(plyorwep, bullet)
|
||||
if (not bullet or not IsValid(plyorwep)) then
|
||||
return
|
||||
end
|
||||
|
||||
local ply = bullet.Attacker
|
||||
|
||||
if (not IsValid(ply) or not ply:IsPlayer()) then
|
||||
ply = nil
|
||||
end
|
||||
|
||||
if (plyorwep:IsWeapon()) then
|
||||
if (ply) then
|
||||
return ply, plyorwep
|
||||
end
|
||||
|
||||
local owner = plyorwep:GetOwner()
|
||||
|
||||
if (not IsValid(owner) or not owner:IsPlayer()) then
|
||||
return
|
||||
end
|
||||
|
||||
return owner, plyorwep
|
||||
end
|
||||
|
||||
if (not ply) then
|
||||
ply = plyorwep
|
||||
|
||||
if (not ply:IsPlayer()) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local wep = ply:GetActiveWeapon()
|
||||
|
||||
if (not IsValid(wep)) then
|
||||
return
|
||||
end
|
||||
|
||||
return ply, wep
|
||||
end
|
||||
|
||||
local vector_origin = vector_origin
|
||||
|
||||
function LeyHitreg:GetWeaponSpread(ply, wep, bullet)
|
||||
-- MW Swep pack workaround
|
||||
if (wep.CalculateCone) then
|
||||
return wep:CalculateCone() * 0.1 * 0.7
|
||||
end
|
||||
|
||||
-- TFA workaround
|
||||
if (wep.CalculateConeRecoil) then
|
||||
return wep:CalculateConeRecoil()
|
||||
end
|
||||
|
||||
-- ARCCW workaround
|
||||
if (wep.GetBuff and wep.ApplyRandomSpread and wep.TryBustDoor and ArcCW) then
|
||||
return ArcCW.MOAToAcc * wep:GetBuff("AccuracyMOA") * 4.5
|
||||
end
|
||||
|
||||
|
||||
-- CW2 workaround
|
||||
|
||||
if (wep.AimSpread and wep.recalculateAimSpread and wep.getBaseCone) then
|
||||
return wep:getBaseCone()
|
||||
end
|
||||
|
||||
if (bullet) then
|
||||
local bulletSpread = bullet.Spread
|
||||
|
||||
if (bulletSpread and bulletSpread != vector_origin) then
|
||||
return bulletSpread
|
||||
end
|
||||
end
|
||||
|
||||
if (self.WeaponSpreads and self.WeaponSpreads[wep:GetClass()]) then
|
||||
return self.WeaponSpreads[wep:GetClass()]
|
||||
end
|
||||
|
||||
if (wep.PrimarySpread) then
|
||||
return wep.PrimarySpread
|
||||
end
|
||||
|
||||
if (wep.PrimaryCone) then
|
||||
return wep.PrimaryCone
|
||||
end
|
||||
|
||||
if (wep.Primary) then
|
||||
if (wep.Primary.Spread) then
|
||||
return wep.Primary.Spread
|
||||
end
|
||||
|
||||
if (wep.Primary.Cone) then
|
||||
return wep.Primary.Cone
|
||||
end
|
||||
|
||||
return bulletSpread
|
||||
end
|
||||
|
||||
return vector_origin
|
||||
end
|
||||
|
||||
function LeyHitreg:SetFittingValidClip(wep)
|
||||
local clip1 = wep:Clip1()
|
||||
|
||||
if (clip1 == -1 or clip1 > 0) then
|
||||
return
|
||||
end
|
||||
|
||||
local max = wep:GetMaxClip1()
|
||||
|
||||
if (max > 0) then
|
||||
wep:SetClip1(max)
|
||||
return
|
||||
end
|
||||
|
||||
wep:SetClip1(30)
|
||||
end
|
||||
142
garrysmod/gamemodes/militaryrp/plugins/leyhitreg/sh_plugin.lua
Normal file
142
garrysmod/gamemodes/militaryrp/plugins/leyhitreg/sh_plugin.lua
Normal file
@@ -0,0 +1,142 @@
|
||||
PLUGIN.name = "LeyHitReg"
|
||||
PLUGIN.author = "Ley (Портирован для Helix)"
|
||||
PLUGIN.description = "Улучшенная система регистрации попаданий для точной стрельбы"
|
||||
|
||||
-- Конфигурация системы
|
||||
LeyHitreg = LeyHitreg or {}
|
||||
|
||||
-- Настройки через ix.config
|
||||
ix.config.Add("leyHitregEnabled", true, "Включить систему улучшенной регистрации попаданий", nil, {
|
||||
category = "LeyHitReg"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregShotDirForceDisabled", false, "Принудительно отключить направление выстрела (для тестирования проблемных SWEP баз)", nil, {
|
||||
category = "LeyHitReg"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregDisableSecurityChecks", false, "Отключить проверки безопасности выстрелов", nil, {
|
||||
category = "LeyHitReg"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregIgnoreCanNextPrimaryAttack", true, "Игнорировать задержку между выстрелами (рекомендуется)", nil, {
|
||||
category = "LeyHitReg"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregNoSpread", false, "[DEBUG] Включить режим без разброса для всех", nil, {
|
||||
category = "LeyHitReg - Debug"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregShowActualHit", false, "[DEBUG] Показывать где на самом деле попала пуля (без разброса)", nil, {
|
||||
category = "LeyHitReg - Debug"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregShowSpreadedHit", false, "[DEBUG] Показывать где на самом деле попала пуля (с разбросом)", nil, {
|
||||
category = "LeyHitReg - Debug"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregLogFixedBullets", false, "[DEBUG] Логировать количество исправленных пуль", nil, {
|
||||
category = "LeyHitReg - Debug"
|
||||
})
|
||||
|
||||
ix.config.Add("leyHitregLogInvalidShots", false, "[DEBUG] Логировать невалидные выстрелы", nil, {
|
||||
category = "LeyHitReg - Debug"
|
||||
})
|
||||
|
||||
-- Применяем настройки к LeyHitreg
|
||||
LeyHitreg.ShotDirForceDisabled = ix.config.Get("leyHitregShotDirForceDisabled", false)
|
||||
LeyHitreg.DisableSecurityChecks = ix.config.Get("leyHitregDisableSecurityChecks", false)
|
||||
LeyHitreg.IgnoreCanNextPrimaryAttack = ix.config.Get("leyHitregIgnoreCanNextPrimaryAttack", true)
|
||||
|
||||
-- Debug настройки
|
||||
LeyHitreg.Disabled = not ix.config.Get("leyHitregEnabled", true)
|
||||
LeyHitreg.DisabledOnlyOnClient = false
|
||||
LeyHitreg.NoSpread = ix.config.Get("leyHitregNoSpread", false)
|
||||
LeyHitreg.ShowActualShotHit = ix.config.Get("leyHitregShowActualHit", false)
|
||||
LeyHitreg.ShowActualShotSpreadedHit = ix.config.Get("leyHitregShowSpreadedHit", false)
|
||||
LeyHitreg.BrokenDefaultSpread = false
|
||||
LeyHitreg.LogHitgroupMismatches = false
|
||||
LeyHitreg.LogFixedBullets = ix.config.Get("leyHitregLogFixedBullets", false)
|
||||
LeyHitreg.LogInvalidFOV = false
|
||||
LeyHitreg.LogInvalidShots = ix.config.Get("leyHitregLogInvalidShots", false)
|
||||
LeyHitreg.BulletAimbot = false
|
||||
LeyHitreg.LogTargetBone = false
|
||||
LeyHitreg.HitScanDisabled = false
|
||||
LeyHitreg.BulletOverwriteDisabled = false
|
||||
LeyHitreg.AnnounceClientHits = false
|
||||
LeyHitreg.DisableLagComp = false
|
||||
|
||||
if LeyHitreg.Disabled then
|
||||
print("[LeyHitReg] Отключен через настройки")
|
||||
return
|
||||
end
|
||||
|
||||
-- Отключение конфликтующих систем хитрега
|
||||
function LeyHitreg:DisableMoatHitreg()
|
||||
if MOAT_HITREG then
|
||||
MOAT_HITREG.MaxPing = 1
|
||||
end
|
||||
|
||||
if ConVarExists("moat_alt_hitreg") then
|
||||
RunConsoleCommand("moat_alt_hitreg", "0")
|
||||
end
|
||||
|
||||
if SHR then
|
||||
if SHR.Config then
|
||||
SHR.Config.Enabled = false
|
||||
SHR.Config.ClientDefault = 0
|
||||
end
|
||||
hook.Remove("EntityFireBullets", "SHR.FireBullets")
|
||||
hook.Remove("EntityFireBullets", "a")
|
||||
net.Receivers["shr"] = function() end
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:Initialize()
|
||||
print("[LeyHitReg] Загрузка системы регистрации попаданий...")
|
||||
|
||||
-- Отключаем конфликтующие системы
|
||||
LeyHitreg:DisableMoatHitreg()
|
||||
|
||||
print("[LeyHitReg] Система загружена!")
|
||||
end
|
||||
|
||||
-- Обновление настроек при изменении конфига
|
||||
function PLUGIN:OnConfigChanged(key, oldValue, newValue)
|
||||
if key == "leyHitregEnabled" then
|
||||
LeyHitreg.Disabled = not newValue
|
||||
print("[LeyHitReg] Система " .. (newValue and "включена" or "отключена"))
|
||||
elseif key == "leyHitregShotDirForceDisabled" then
|
||||
LeyHitreg.ShotDirForceDisabled = newValue
|
||||
elseif key == "leyHitregDisableSecurityChecks" then
|
||||
LeyHitreg.DisableSecurityChecks = newValue
|
||||
elseif key == "leyHitregIgnoreCanNextPrimaryAttack" then
|
||||
LeyHitreg.IgnoreCanNextPrimaryAttack = newValue
|
||||
elseif key == "leyHitregNoSpread" then
|
||||
LeyHitreg.NoSpread = newValue
|
||||
elseif key == "leyHitregShowActualHit" then
|
||||
LeyHitreg.ShowActualShotHit = newValue
|
||||
elseif key == "leyHitregShowSpreadedHit" then
|
||||
LeyHitreg.ShowActualShotSpreadedHit = newValue
|
||||
elseif key == "leyHitregLogFixedBullets" then
|
||||
LeyHitreg.LogFixedBullets = newValue
|
||||
elseif key == "leyHitregLogInvalidShots" then
|
||||
LeyHitreg.LogInvalidShots = newValue
|
||||
end
|
||||
end
|
||||
|
||||
-- Загрузка модулей
|
||||
ix.util.Include("leyhitreg/shared/spreadsystem/bulletspread.lua")
|
||||
ix.util.Include("leyhitreg/shared/spreadsystem/firebullets.lua")
|
||||
ix.util.Include("leyhitreg/shared/disablelagcomp/disablelagcomp.lua")
|
||||
ix.util.Include("leyhitreg/shared/workarounds/workarounds.lua")
|
||||
ix.util.Include("leyhitreg/shared/workarounds/swepbases.lua")
|
||||
|
||||
ix.util.Include("leyhitreg/client/sendshots/sendshots.lua")
|
||||
ix.util.Include("leyhitreg/client/sendshots/fetchspreads.lua")
|
||||
|
||||
ix.util.Include("leyhitreg/server/bulletprocessing/hitscan.lua")
|
||||
ix.util.Include("leyhitreg/server/bulletprocessing/processbullet.lua")
|
||||
ix.util.Include("leyhitreg/server/damageinfo/scaledamagehack.lua")
|
||||
ix.util.Include("leyhitreg/server/damageinfo/fixscaling.lua")
|
||||
ix.util.Include("leyhitreg/server/receiveshotinfo/receiveshotinfo.lua")
|
||||
ix.util.Include("leyhitreg/server/receiveshotinfo/shotvalidator.lua")
|
||||
Reference in New Issue
Block a user