Files
VnUtest/garrysmod/gamemodes/helix/plugins/thirdperson.lua
2026-03-31 10:27:04 +03:00

234 lines
7.2 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local PLUGIN = PLUGIN
PLUGIN.name = "Third Person"
PLUGIN.author = "Black Tea"
PLUGIN.description = "Enables third person camera usage."
-- Localization
ix.lang.AddTable("russian", {
optThirdPerson = "Вид от третьего лица",
optThirdPersonEnabled = "Включить вид от 3-го лица",
optThirdPersonEnabledDesc = "Использовать камеру от третьего лица",
optThirdPersonClassic = "Классический режим",
optThirdPersonClassicDesc = "Использовать классический вид камеры",
optThirdPersonVertical = "Вертикальное смещение",
optThirdPersonVerticalDesc = "Высота камеры над персонажем",
optThirdPersonHorizontal = "Горизонтальное смещение",
optThirdPersonHorizontalDesc = "Боковое смещение камеры",
optThirdPersonDistance = "Расстояние камеры",
optThirdPersonDistanceDesc = "Дистанция камеры от персонажа",
})
ix.lang.AddTable("english", {
optThirdPerson = "Third Person",
optThirdPersonEnabled = "Enable Third Person",
optThirdPersonEnabledDesc = "Use third person camera view",
optThirdPersonClassic = "Classic Mode",
optThirdPersonClassicDesc = "Use classic camera view",
optThirdPersonVertical = "Vertical Offset",
optThirdPersonVerticalDesc = "Camera height above character",
optThirdPersonHorizontal = "Horizontal Offset",
optThirdPersonHorizontalDesc = "Camera side offset",
optThirdPersonDistance = "Camera Distance",
optThirdPersonDistanceDesc = "Distance of camera from character",
})
ix.config.Add("thirdperson", false, "Allow Thirdperson in the server.", nil, {
category = "server"
})
if (CLIENT) then
local function isHidden()
return !ix.config.Get("thirdperson")
end
ix.option.Add("thirdpersonEnabled", ix.type.bool, false, {
category = "optThirdPerson",
name = "optThirdPersonEnabled",
description = "optThirdPersonEnabledDesc",
hidden = isHidden,
OnChanged = function(oldValue, value)
hook.Run("ThirdPersonToggled", oldValue, value)
end
})
ix.option.Add("thirdpersonClassic", ix.type.bool, false, {
category = "optThirdPerson",
name = "optThirdPersonClassic",
description = "optThirdPersonClassicDesc",
hidden = isHidden
})
ix.option.Add("thirdpersonVertical", ix.type.number, 10, {
category = "optThirdPerson",
name = "optThirdPersonVertical",
description = "optThirdPersonVerticalDesc",
min = 0, max = 30,
hidden = isHidden
})
ix.option.Add("thirdpersonHorizontal", ix.type.number, 0, {
category = "optThirdPerson",
name = "optThirdPersonHorizontal",
description = "optThirdPersonHorizontalDesc",
min = -30, max = 30,
hidden = isHidden
})
ix.option.Add("thirdpersonDistance", ix.type.number, 50, {
category = "optThirdPerson",
name = "optThirdPersonDistance",
description = "optThirdPersonDistanceDesc",
category = "thirdperson", min = 0, max = 100,
hidden = isHidden
})
concommand.Add("ix_togglethirdperson", function()
local bEnabled = !ix.option.Get("thirdpersonEnabled", false)
ix.option.Set("thirdpersonEnabled", bEnabled)
end)
local function isAllowed()
return ix.config.Get("thirdperson")
end
local playerMeta = FindMetaTable("Player")
local traceMin = Vector(-10, -10, -10)
local traceMax = Vector(10, 10, 10)
function playerMeta:CanOverrideView()
local entity = Entity(self:GetLocalVar("ragdoll", 0))
if (IsValid(ix.gui.characterMenu) and !ix.gui.characterMenu:IsClosing() and ix.gui.characterMenu:IsVisible()) then
return false
end
if (IsValid(ix.gui.menu) and ix.gui.menu:GetCharacterOverview()) then
return false
end
if (ix.option.Get("thirdpersonEnabled", false) and
!IsValid(self:GetVehicle()) and
isAllowed() and
IsValid(self) and
self:GetCharacter() and
!self:GetNetVar("actEnterAngle") and
!IsValid(entity) and
LocalPlayer():Alive()
) then
return true
end
end
local view, traceData, traceData2, aimOrigin, crouchFactor, ft, curAng, owner
local clmp = math.Clamp
crouchFactor = 0
function PLUGIN:CalcView(client, origin, angles, fov)
ft = FrameTime()
owner = client
if (client:CanOverrideView() and LocalPlayer():GetViewEntity() == LocalPlayer()) then
local bNoclip = LocalPlayer():GetMoveType() == MOVETYPE_NOCLIP
if ((client:OnGround() and client:KeyDown(IN_DUCK)) or client:Crouching()) then
crouchFactor = Lerp(ft*5, crouchFactor, 1)
else
crouchFactor = Lerp(ft*5, crouchFactor, 0)
end
curAng = owner.camAng or angle_zero
view = {}
local headPos = client:GetPos() + client:GetViewOffset()
local offset = curAng:Up() * ix.option.Get("thirdpersonVertical", 10) +
curAng:Right() * ix.option.Get("thirdpersonHorizontal", 0) -
client:GetViewOffsetDucked() * .5 * crouchFactor
local startTrace = util.TraceLine({
start = headPos,
endpos = headPos + offset,
filter = client
})
traceData = {}
traceData.start = startTrace.HitPos
traceData.endpos = traceData.start - curAng:Forward() * ix.option.Get("thirdpersonDistance", 50)
traceData.filter = client
traceData.ignoreworld = bNoclip
traceData.mins = traceMin
traceData.maxs = traceMax
view.origin = util.TraceHull(traceData).HitPos
aimOrigin = view.origin
view.angles = curAng + client:GetViewPunchAngles()
traceData2 = {}
traceData2.start = aimOrigin
traceData2.endpos = aimOrigin + curAng:Forward() * 65535
traceData2.filter = client
traceData2.ignoreworld = bNoclip
local bClassic = ix.option.Get("thirdpersonClassic", false)
if (bClassic or owner:IsWepRaised() or
(owner:KeyDown(bit.bor(IN_FORWARD, IN_BACK, IN_MOVELEFT, IN_MOVERIGHT)) and owner:GetVelocity():Length() >= 10)) then
client:SetEyeAngles((util.TraceLine(traceData2).HitPos - client:GetShootPos()):Angle())
else
local currentAngles = client:EyeAngles()
currentAngles.pitch = (util.TraceLine(traceData2).HitPos - client:GetShootPos()):Angle().pitch
client:SetEyeAngles(currentAngles)
end
return view
end
end
local diff, fm, sm
function PLUGIN:CreateMove(cmd)
owner = LocalPlayer()
if (owner:CanOverrideView() and owner:GetMoveType() != MOVETYPE_NOCLIP and
LocalPlayer():GetViewEntity() == LocalPlayer()) then
local fm = cmd:GetForwardMove()
local sm = cmd:GetSideMove()
local camAng = owner.camAng or owner:EyeAngles()
local eyeAng = owner:EyeAngles()
local wishDir = (camAng:Forward() * fm) + (camAng:Right() * sm)
wishDir.z = 0
local localMove = WorldToLocal(wishDir, angle_zero, vector_origin, Angle(0, eyeAng.y, 0))
cmd:SetForwardMove(localMove.x)
cmd:SetSideMove(-localMove.y)
return false
end
end
function PLUGIN:InputMouseApply(cmd, x, y, ang)
owner = LocalPlayer()
if (!owner.camAng) then
owner.camAng = Angle(0, 0, 0)
end
owner.camAng.p = clmp(math.NormalizeAngle(owner.camAng.p + y / 50), -85, 85)
owner.camAng.y = math.NormalizeAngle(owner.camAng.y - x / 50)
if (owner:CanOverrideView() and LocalPlayer():GetViewEntity() == LocalPlayer()) then
return true
end
end
function PLUGIN:ShouldDrawLocalPlayer()
if (LocalPlayer():GetViewEntity() == LocalPlayer() and !IsValid(LocalPlayer():GetVehicle())) then
return LocalPlayer():CanOverrideView()
end
end
end