add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,275 @@
PLUGIN.name = "TFA Lean"
PLUGIN.author = "TFA (Портирован для Helix)"
PLUGIN.description = "Система наклонов влево/вправо с автоматическим наклоном при прицеливании"
ix.util.Include("cl_plugin.lua")
-- Конфигурация
ix.config.Add("leanEnabled", true, "Включить систему наклонов", nil, {
category = "Lean System"
})
ix.config.Add("leanOffset", 16, "Расстояние наклона (в юнитах)", nil, {
data = {min = 8, max = 32},
category = "Lean System"
})
ix.config.Add("leanAutomatic", true, "Автоматический наклон при прицеливании за укрытием", nil, {
category = "Lean System"
})
ix.config.Add("leanAutoDist", 20, "Дистанция для определения укрытия (автонаклон)", nil, {
data = {min = 10, max = 50},
category = "Lean System"
})
ix.config.Add("leanRollAngle", 15, "Угол наклона камеры и модели", nil, {
data = {min = 5, max = 30},
category = "Lean System"
})
-- Локальные переменные
local LeanOffset = ix.config.Get("leanOffset", 16)
--[[Shared]]
local function MetaInitLean()
local PlayerMeta = FindMetaTable("Player")
PlayerMeta.LeanGetShootPosOld = PlayerMeta.LeanGetShootPosOld or PlayerMeta.GetShootPos
PlayerMeta.LeanEyePosOld = PlayerMeta.LeanEyePosOld or PlayerMeta.GetShootPos
PlayerMeta.GetNW2Int = PlayerMeta.GetNW2Int or PlayerMeta.GetNWFloat
PlayerMeta.SetNW2Int = PlayerMeta.SetNW2Int or PlayerMeta.SetNWFloat
function PlayerMeta:GetShootPos()
if not IsValid(self) or not self.LeanGetShootPosOld then return end
local ply = self
local status = ply.TFALean or ply:GetNW2Int("TFALean")
local off = Vector(0, status * -LeanOffset, 0)
off:Rotate(self:EyeAngles())
local gud, ret = pcall(self.LeanGetShootPosOld, self)
if gud then
return ret + off
else
return off
end
end
function PlayerMeta:EyePos()
if not IsValid(self) then return end
local gud, pos, ang = pcall(self.GetShootPos, self)
if gud then
return pos, ang
else
return vector_origin, angle_zero
end
end
hook.Add("ShutDown", "TFALeanPMetaCleanup", function()
if PlayerMeta.LeanGetShootPosOld then
PlayerMeta.GetShootPos = PlayerMeta.LeanGetShootPosOld
PlayerMeta.LeanGetShootPosOld = nil
end
end)
MetaOverLean = true
end
pcall(MetaInitLean)
function PLUGIN:PlayerSpawn(ply)
ply:SetNW2Int("TFALean", 0)
ply.TFALean = 0
end
function PLUGIN:OnConfigChanged(key, oldValue, newValue)
if key == "leanOffset" then
LeanOffset = newValue
end
end
--[[Lean Calculations]]
local targ
local autoLeanDist = ix.config.Get("leanAutoDist", 20)
local traceRes, traceResLeft, traceResRight
local traceData = {
["mask"] = MASK_SOLID,
["collisiongroup"] = COLLISION_GROUP_DEBRIS,
["mins"] = Vector(-4, -4, -4),
["maxs"] = Vector(4, 4, 4)
}
local function AngleOffset(new, old)
local _, ang = WorldToLocal(vector_origin, new, vector_origin, old)
return ang
end
local function RollBone(ply, bone, roll)
ply:ManipulateBoneAngles(bone, angle_zero)
if CLIENT then
ply:SetupBones()
end
local boneMat = ply:GetBoneMatrix(bone)
local boneAngle = boneMat:GetAngles()
local boneAngleOG = boneMat:GetAngles()
boneAngle:RotateAroundAxis(ply:EyeAngles():Forward(), roll)
ply:ManipulateBoneAngles(bone, AngleOffset(boneAngle, boneAngleOG))
if CLIENT then
ply:SetupBones()
end
end
function TFALeanModel()
local rollAngle = ix.config.Get("leanRollAngle", 15)
for k, ply in ipairs(player.GetAll()) do
ply.TFALean = Lerp(FrameTime() * 10, ply.TFALean or 0, ply:GetNW2Int("TFALean"))
local lean = ply.TFALean
local bone = ply:LookupBone("ValveBiped.Bip01_Spine")
if bone then
RollBone(ply, bone, lean * rollAngle)
end
bone = ply:LookupBone("ValveBiped.Bip01_Spine1")
if bone then
RollBone(ply, bone, lean * rollAngle)
end
end
end
function PLUGIN:Move(ply)
if not ix.config.Get("leanEnabled", true) then return end
targ = (ply:KeyDown(IN_ALT1) and -1 or (ply:KeyDown(IN_ALT2) and 1 or 0))
autoLeanDist = ix.config.Get("leanAutoDist", 20)
-- Автонаклон
if targ == 0 and ix.config.Get("leanAutomatic", true) and ply:KeyDown(IN_ATTACK2) then
local headpos = ply.LeanGetShootPosOld and ply:LeanGetShootPosOld() or ply:GetShootPos()
traceData.start = headpos
traceData.endpos = traceData.start + ply:EyeAngles():Forward() * autoLeanDist
traceRes = util.TraceHull(traceData)
if traceRes.Hit and traceRes.Fraction < 1 then
traceData.start = headpos - ply:EyeAngles():Right() * LeanOffset
traceData.endpos = traceData.start + ply:EyeAngles():Forward() * autoLeanDist * 2
traceResLeft = util.TraceLine(traceData)
traceData.start = headpos + ply:EyeAngles():Right() * LeanOffset
traceData.endpos = traceData.start + ply:EyeAngles():Forward() * autoLeanDist * 2
traceResRight = util.TraceLine(traceData)
if traceResLeft.Fraction > 1 or not traceResLeft.Hit then
targ = -1
elseif traceResRight.Fraction > 1 or not traceResRight.Hit then
targ = 1
end
end
end
ply:SetNW2Int("TFALean", targ)
if SERVER then
for _, v in ipairs(player.GetAll()) do
v.TFALean = Lerp(FrameTime() * 10, v.TFALean or 0, v:GetNW2Int("TFALean"))
end
end
end
if SERVER and not game.SinglePlayer() then
timer.Create("TFALeanSynch", 0.2, 0, function()
if not ix.config.Get("leanEnabled", true) then return end
local rollAngle = ix.config.Get("leanRollAngle", 15)
for k, v in ipairs(player.GetAll()) do
local lean = v:GetNW2Int("TFALean")
v.OldLean = v.OldLean or lean
if lean ~= v.OldLean then
v.OldLean = lean
local bone = v:LookupBone("ValveBiped.Bip01_Spine")
if bone then
RollBone(v, bone, lean * rollAngle)
end
bone = v:LookupBone("ValveBiped.Bip01_Spine1")
if bone then
RollBone(v, bone, lean * rollAngle)
end
end
end
end)
end
--[[Projectile Redirection]]
local PlayerPosEntities = {
["rpg_missile"] = true,
["crossbow_bolt"] = true,
["npc_grenade_frag"] = true,
["apc_missile"] = true,
["viewmodel_predicted"] = true
}
function PLUGIN:OnEntityCreated(ent)
local ply = ent.Owner or ent:GetOwner()
if not IsValid(ply) or not ply:IsPlayer() then return end
if ent:IsPlayer() then return end
local headposold
local gud, ret = pcall(ply.LeanGetShootPosOld, ply)
if gud then
headposold = ret
else
headposold = ply:EyePos()
end
local entpos = ent:GetPos()
if PlayerPosEntities[ent:GetClass()] or (math.floor(entpos.x) == math.floor(headposold.x) and math.floor(entpos.y) == math.floor(headposold.y) and math.floor(entpos.z) == math.floor(headposold.z)) then
ent:SetPos(ply:EyePos())
end
end
local ISPATCHING = false
function PLUGIN:EntityFireBullets(ply, bul)
if ISPATCHING then return end
if not ix.config.Get("leanEnabled", true) then return end
local bak = table.Copy(bul)
ISPATCHING = true
local call = hook.Run("EntityFireBullets", ply, bul)
ISPATCHING = false
if call == false then
return false
elseif call == nil then
table.Empty(bul)
table.CopyFromTo(bak, bul)
end
if ply:IsWeapon() and ply.Owner then
ply = ply.Owner
end
if not ply:IsPlayer() then return end
if ply.LeanGetShootPosOld and bul.Src == ply:LeanGetShootPosOld() then
bul.Src = ply:GetShootPos()
end
return true
end
function PLUGIN:Initialize()
print("[TFA Lean] Система наклонов загружена!")
print("[TFA Lean] Управление: ALT1 (Q) - наклон влево, ALT2 (E) - наклон вправо")
end