local blur = Material("pp/blurscreen") local function drawBlurAt(x, y, w, h, amount, passes, reverse) -- Intensity of the blur. amount = amount or 5 surface.SetMaterial(blur) surface.SetDrawColor(color_white) local scrW, scrH = ScrW(), ScrH() local x2, y2 = x / scrW, y / scrH local w2, h2 = (x + w) / scrW, (y + h) / scrH for i = -(passes or 0.2), 1, 0.2 do if reverse then blur:SetFloat("$blur", i * -1 * amount) else blur:SetFloat("$blur", i * amount) end blur:Recompute() render.UpdateScreenEffectTexture() surface.DrawTexturedRectUV(x, y, w, h, x2, y2, w2, h2) end end local peekzoom = 1.2 function SWEP:ScopeToggle(setlevel) if (setlevel or 0) > 0 and (!self:GetValue("Scope") or self:GetPrimedGrenade()) then return end -- if setlevel and setlevel > 0 and self:GetAnimLockTime() > CurTime() or (!setlevel and self:GetAnimLockTime() > CurTime()) then return end -- if (setlevel and setlevel > 0 and self:GetReloading()) or (!setlevel and self:GetReloading()) then return end local level = self:GetScopeLevel() local oldlevel = level level = setlevel or (level + 1) if level > self:GetValue("ScopeLevels") then level = self:GetValue("ScopeLevels") end if self:GetCustomize() or self:GetLastMeleeTime() + 1 > CurTime() then -- self:SprintLock(true) level = 0 end if self:GetIsSprinting() and level > 0 then if self:GetOwner():GetInfoNum("tacrp_aim_cancels_sprint", 0) > 0 and self:CanStopSprinting() then self:GetOwner().TacRP_SprintBlock = true else level = 0 end end if self:DoOldSchoolScopeBehavior() then level = 0 end if level == self:GetScopeLevel() then return end self:SetScopeLevel(level) if level > 0 then self:ToggleBlindFire(TacRP.BLINDFIRE_NONE) end if oldlevel == 0 or level == 0 then self:SetLastScopeTime(CurTime()) end if self:GetValue("AlwaysPeek") then self:SetPeeking(true) end -- HACK: In singleplayer, SWEP:Think is called on client but IsFirstTimePredicted is NEVER true. -- This causes ScopeToggle to NOT be called on client in singleplayer... -- GenerateAutoSight needs to run clientside or scopes will break. Good old CallOnClient it is. if SERVER and game.SinglePlayer() then self:CallOnClient("GenerateAutoSight") elseif CLIENT and (IsFirstTimePredicted() or game.SinglePlayer()) then self:GenerateAutoSight() self.LastHintLife = CurTime() end self:EmitSound(self:GetValue("Sound_ScopeIn"), 75, 100, 1, CHAN_ITEM) self:SetShouldHoldType() self:RunHook("Hook_PostScopeToggle", setlevel) end function SWEP:GetShouldFOV(ignorepeek) local base = 90 if !ignorepeek and self:GetPeeking() then return base / peekzoom else return base / self:GetMagnification() end end function SWEP:IsInScope() local sightdelta = self:Curve(self:GetSightDelta()) return (SERVER or !self:GetPeeking()) and !self:GetSafe() and ((self:GetScopeLevel() > 0 and sightdelta > 0.5) or (sightdelta > 0.9)) end function SWEP:DoScope() local h = ScrH() local w = ScrW() if self:IsInScope() then local img = self:GetValue("ScopeOverlay") if img then -- assume players have a screen that is wider than it is tall because... that's stupid local pos = self:GetOwner():EyePos() pos = pos + self:GetShootDir():Forward() * 9000 local toscreen = pos:ToScreen() local x = toscreen.x local y = toscreen.y local ss = math.Round(h * (self:GetValue("ScopeOverlaySize") or 1)) local sx = x - (ss / 2) local sy = y - (ss / 2) -- local shakey = math.min(cross * 35, 3) -- sx = sx + math.Round(math.Rand(-shakey, shakey)) -- sy = sy + math.Round(math.Rand(-shakey, shakey)) -- local int = self:CheckFlashlightPointing() -- if int > 0 then -- surface.SetDrawColor(255, 255, 255, int * 250) -- surface.DrawRect(0, 0, w, h) -- end surface.SetMaterial(img) surface.SetDrawColor(255, 255, 255, 255) surface.DrawTexturedRect(sx, sy, ss, ss) surface.SetDrawColor(0, 0, 0) surface.DrawRect(0, 0, w, sy) surface.DrawRect(0, sy + ss, w, h - sy) surface.DrawRect(0, 0, sx, h) surface.DrawRect(sx + ss, 0, w - sx, h) if self:GetReloading() then drawBlurAt(0, 0, w, h, 1, 1) end -- if int > 0 then -- surface.SetDrawColor(255, 255, 255, int * 25) -- surface.DrawRect(0, 0, w, h) -- end if self:GetValue("ScopeDraw") then self:GetValue("ScopeDraw")(self) end end end local blur_hook = self:RunHook("Hook_BlurScope") if blur_hook then if !istable(blur_hook) then blur_hook = {1, 1} end drawBlurAt(0, 0, w, h, blur_hook[0], blur_hook[1]) end end function SWEP:GetSightDelta() return self:GetSightAmount() end function SWEP:SetSightDelta(d) self:SetSightAmount(d) end function SWEP:CanSight() if self:GetReloading() and !TacRP.ConVars["ads_reload"]:GetBool() then return false end return true end function SWEP:ThinkSights() if !IsValid(self:GetOwner()) then return end local ftp = IsFirstTimePredicted() local ftsp = IsFirstTimePredicted() or !game.SinglePlayer() if self:GetOwner():KeyDown(IN_USE) and self:GetOwner():KeyPressed(IN_ATTACK2) and ftsp then self:ToggleSafety() return end if ftp and self:GetValue("Bipod") and self:GetOwner():KeyPressed(IN_ATTACK2) and !self:GetInBipod() and self:CanBipod() and ftsp then self:EnterBipod() end local FT = FrameTime() local sighted = self:GetScopeLevel() > 0 local amt = self:GetSightAmount() local adst = self:GetAimDownSightsTime() if ftp or game.SinglePlayer() then if sighted then if self:GetSprintLockTime() > CurTime() then adst = adst + self:GetSprintToFireTime() end amt = math.Approach(amt, 1, FT / adst) else amt = math.Approach(amt, 0, FT / adst) end end self:SetSightDelta(amt) if self:GetSafe() then return end if CLIENT then self:ThinkPeek() end local toggle = self:GetOwner():GetInfoNum("tacrp_toggleaim", 0) == 1 local press, down = self:GetOwner():KeyPressed(IN_ATTACK2), self:GetOwner():KeyDown(IN_ATTACK2) if (!self:GetValue("Scope") or self:DoOldSchoolScopeBehavior()) and !self.NoSecondaryMelee and down then self:Melee() elseif sighted and ((toggle and press and ftp) or (!toggle and !down)) then self:ScopeToggle(0) elseif !sighted and ((toggle and press and ftp) or (!toggle and down)) and self:CanSight() then self:ScopeToggle(1) elseif sighted and !self:CanSight() then self:ScopeToggle(0) end end function SWEP:GetMagnification() local mag = 1 local level = self:GetScopeLevel() if level > 0 then if self:GetPeeking() then return peekzoom end mag = 90 / self:GetValue("ScopeFOV") mag = Lerp(level / self:GetValue("ScopeLevels"), 1, mag) mag = self:RunHook("Hook_ModifyMagnification") or mag end if (mag <= 0) then return 0.001 -- just in case end return mag end function SWEP:AdjustMouseSensitivity() local mag = self:GetMagnification() local sensmult = GetConVar("tacrp_aimsens"):GetFloat() -- local aa = GetConVar("tacrp_aimassist") -- local aac = GetConVar("tacrp_aimassist_cl") -- local aai = GetConVar("tacrp_aimassist_intensity") -- local aams = GetConVar("tacrp_aimassist_multsens") -- if self:GetOwner().tacrp_AATarget != nil and aa:GetBool() and aac:GetBool()) then -- aamult = aams:GetFloat() / aai:GetFloat() -- else -- aamult = 1 -- end if mag > 1 then return 1 / mag * math.Clamp(sensmult, 0.1, 1) end end function SWEP:ThinkPeek() end function SWEP:GetCCIP(pos, ang) -- get calculated point of impact local sp, sa = self:GetMuzzleOrigin(), self:GetShootDir() pos = pos or sp ang = ang or sa local v = self:GetValue("MuzzleVelocity") local g = Vector(0, 0, -600) local d = 1 local h = 0 if self:GetValue("ShootEnt") then v = self:GetValue("ShootEntForce") d = 0 g = physenv.GetGravity() h = 4 end local vel = ang:Forward() * v local maxiter = 100 local timestep = 1 / 15 local gravity = timestep * g local steps = {} for i = 1, maxiter do local dir = vel:GetNormalized() local spd = vel:Length() * timestep local drag = d * spd * spd * (1 / 150000) if spd <= 0.001 then return nil end local newpos = pos + (vel * timestep) local newvel = vel - (dir * drag) + gravity local tr if h > 0 then tr = util.TraceHull({ start = pos, endpos = newpos, filter = self:GetOwner(), mask = MASK_SHOT, mins = Vector(-h, -h, -h), maxs = Vector(h, h, h), }) else tr = util.TraceLine({ start = pos, endpos = newpos, filter = self:GetOwner(), mask = MASK_SHOT }) end table.insert(steps, 0, tr.HitPos) if tr.Hit then debugoverlay.Sphere(tr.HitPos, 8, 0.25, color_white, true) return tr, i * timestep, steps else pos = newpos vel = newvel end end return nil end function SWEP:GetCorVal() local vmfov = self.ViewModelFOV local fov = self:GetShouldFOV() return vmfov / (fov * 1.33333) end function SWEP:HasOptic() return self:GetValue("Scope") and (self:GetValue("ScopeOverlay") or self:GetValue("Holosight")) end function SWEP:DoOldSchoolScopeBehavior() return (TacRP.ConVars["oldschool"]:GetBool() or TacRP.GetBalanceMode() == TacRP.BALANCE_OLDSCHOOL) and !self:HasOptic() end function SWEP:GetAimDownSightsTime(base) if base then return self:GetBaseValue("AimDownSightsTime") * TacRP.ConVars["mult_aimdownsights"]:GetFloat() else return self:GetValue("AimDownSightsTime") * TacRP.ConVars["mult_aimdownsights"]:GetFloat() end end function SWEP:GetSprintToFireTime(base) if base then return self:GetBaseValue("SprintToFireTime") * TacRP.ConVars["mult_sprinttofire"]:GetFloat() else return self:GetValue("SprintToFireTime") * TacRP.ConVars["mult_sprinttofire"]:GetFloat() end end function SWEP:GetPeeking() return (!self.InversePeek and self:GetNWPeeking()) or (self.InversePeek and !self:GetNWPeeking()) end function SWEP:SetPeeking(b) if self.InversePeek then self:SetNWPeeking(!b) else self:SetNWPeeking(b) end end