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