399 lines
11 KiB
Lua
399 lines
11 KiB
Lua
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
|