add sborka
This commit is contained in:
125
garrysmod/gamemodes/militaryrp/plugins/lean/cl_plugin.lua
Normal file
125
garrysmod/gamemodes/militaryrp/plugins/lean/cl_plugin.lua
Normal file
@@ -0,0 +1,125 @@
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
--[[CLIENT SIDE]]
|
||||
function PLUGIN:PreRender()
|
||||
if not ix.config.Get("leanEnabled", true) then return end
|
||||
TFALeanModel()
|
||||
end
|
||||
|
||||
local minvec = Vector(-6, -6, -6)
|
||||
local maxvec = Vector(6, 6, 6)
|
||||
|
||||
local function filterfunc(ent)
|
||||
if (ent:IsPlayer() or ent:IsNPC() or ent:IsWeapon() or ent:GetClass() == "rpg_missile" or ent:GetClass() == "crossbow_bolt" or ent:GetClass() == "npc_grenade_frag" or ent:GetClass() == "apc_missile" or ent:GetClass() == "viewmodel_predicted") then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function bestcase(pos, endpos, ply)
|
||||
local off = endpos - pos
|
||||
local trace = {}
|
||||
trace.start = pos
|
||||
trace.endpos = pos + off
|
||||
trace.mask = MASK_SOLID
|
||||
trace.filter = filterfunc
|
||||
trace.ignoreworld = false
|
||||
trace.maxs = maxvec
|
||||
trace.mins = minvec
|
||||
local traceres = util.TraceHull(trace)
|
||||
|
||||
return pos + off:GetNormalized() * math.Clamp(traceres.Fraction, 0, 1) * off:Length()
|
||||
end
|
||||
|
||||
function LeanCalcView(ply, pos, angles, fov)
|
||||
local view = {}
|
||||
view.origin = pos
|
||||
view.angles = angles
|
||||
view.fov = fov
|
||||
if not ply:Alive() or ply:Health() <= 0 then return view end
|
||||
|
||||
local status = ply.TFALean or 0
|
||||
local leanOffset = ix.config.Get("leanOffset", 16)
|
||||
local rollAngle = ix.config.Get("leanRollAngle", 15)
|
||||
local off = Vector(0, status * -leanOffset, 0)
|
||||
off:Rotate(angles)
|
||||
view.angles:RotateAroundAxis(view.angles:Forward(), status * rollAngle)
|
||||
view.origin = bestcase(view.origin, view.origin + off, ply)
|
||||
|
||||
return view
|
||||
end
|
||||
|
||||
local ISLEANINGCV = false
|
||||
|
||||
function PLUGIN:CalcView(ply, pos, angles, fov)
|
||||
if ISLEANINGCV then return end
|
||||
if not ix.config.Get("leanEnabled", true) then return end
|
||||
if GetViewEntity() ~= ply then return end
|
||||
if not ply:Alive() then return end
|
||||
if ply:InVehicle() then return end
|
||||
|
||||
ISLEANINGCV = true
|
||||
local preTableRaw = hook.Run("CalcView", ply, pos, angles, fov)
|
||||
ISLEANINGCV = false
|
||||
|
||||
local preOrigin, preAngles, preFov
|
||||
if type(preTableRaw) == "table" then
|
||||
preOrigin = rawget(preTableRaw, "origin") or pos
|
||||
preAngles = rawget(preTableRaw, "angles") or angles
|
||||
preFov = tonumber(rawget(preTableRaw, "fov")) or fov
|
||||
else
|
||||
preOrigin = pos
|
||||
preAngles = angles
|
||||
preFov = fov
|
||||
end
|
||||
local preTable = { origin = preOrigin, angles = preAngles, fov = preFov }
|
||||
|
||||
local finalTable = LeanCalcView(ply, preTable.origin, preTable.angles, preTable.fov)
|
||||
|
||||
for k, v in pairs(preTable) do
|
||||
if finalTable[k] == nil and (k == "origin" or k == "angles" or k == "fov" or k == "drawviewer" or k == "znear" or k == "zfar") then
|
||||
rawset(finalTable, k, v)
|
||||
end
|
||||
end
|
||||
|
||||
return finalTable
|
||||
end
|
||||
|
||||
local ISLEANINGCV_VM = false
|
||||
|
||||
function LeanCalcVMView(wep, vm, oldPos, oldAng, pos, ang)
|
||||
if ISLEANINGCV_VM then return end
|
||||
local ply = LocalPlayer()
|
||||
if GetViewEntity() ~= ply then return end
|
||||
|
||||
if not ply.tfacastoffset or ply.tfacastoffset <= 0.001 then
|
||||
local status = ply.TFALean or 0
|
||||
|
||||
if math.abs(status) > 0.001 then
|
||||
local leanOffset = ix.config.Get("leanOffset", 16)
|
||||
local off = Vector(0, status * -leanOffset, 0)
|
||||
off:Rotate(ang)
|
||||
ang:RotateAroundAxis(ang:Forward(), status * 12 * (wep.ViewModelFlip and -1 or 1))
|
||||
pos = bestcase(pos, pos + off, ply)
|
||||
ISLEANINGCV_VM = true
|
||||
local tpos, tang = hook.Run("CalcViewModelView", wep, vm, oldPos, oldAng, pos, ang)
|
||||
ISLEANINGCV_VM = false
|
||||
|
||||
if tpos then
|
||||
pos = tpos
|
||||
end
|
||||
|
||||
if tang then
|
||||
ang = tang
|
||||
end
|
||||
|
||||
return pos, ang
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:CalcViewModelView(wep, vm, oldPos, oldAng, pos, ang)
|
||||
if not ix.config.Get("leanEnabled", true) then return end
|
||||
return LeanCalcVMView(wep, vm, oldPos, oldAng, pos, ang)
|
||||
end
|
||||
275
garrysmod/gamemodes/militaryrp/plugins/lean/sh_plugin.lua
Normal file
275
garrysmod/gamemodes/militaryrp/plugins/lean/sh_plugin.lua
Normal 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
|
||||
Reference in New Issue
Block a user