mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
358 lines
12 KiB
Lua
358 lines
12 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
|
|
-- Copyright (c) 2018-2020 TFA Base Devs
|
|
|
|
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
-- of this software and associated documentation files (the "Software"), to deal
|
|
-- in the Software without restriction, including without limitation the rights
|
|
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
-- copies of the Software, and to permit persons to whom the Software is
|
|
-- furnished to do so, subject to the following conditions:
|
|
|
|
-- The above copyright notice and this permission notice shall be included in all
|
|
-- copies or substantial portions of the Software.
|
|
|
|
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
-- SOFTWARE.
|
|
|
|
-- stencil functions
|
|
local useStencils = render.SupportsPixelShaders_2_0() and render.SupportsVertexShaders_2_0()
|
|
|
|
local function defineCanvas(ref)
|
|
render.UpdateScreenEffectTexture()
|
|
render.ClearStencil()
|
|
render.SetStencilEnable(true)
|
|
render.SetStencilCompareFunction(STENCIL_ALWAYS)
|
|
render.SetStencilPassOperation(STENCIL_REPLACE)
|
|
render.SetStencilFailOperation(STENCIL_KEEP)
|
|
render.SetStencilZFailOperation(STENCIL_REPLACE)
|
|
render.SetStencilWriteMask(255)
|
|
render.SetStencilTestMask(255)
|
|
render.SetStencilReferenceValue(ref or 54)
|
|
end
|
|
|
|
local function drawOn()
|
|
render.SetStencilCompareFunction(STENCIL_EQUAL)
|
|
end
|
|
|
|
local function stopCanvas()
|
|
render.SetStencilEnable(false)
|
|
end
|
|
|
|
-- main draw functions
|
|
local CachedMaterials = {}
|
|
|
|
local DrawFunctions = {}
|
|
|
|
do -- Flat reticle, stays at center or moves with recoil
|
|
local function ScreenScaleH(num)
|
|
return num * (ScrH() / 480)
|
|
end
|
|
|
|
DrawFunctions[TFA.Enum.RETICLE_FLAT] = function(vm, ply, wep, SightElementTable)
|
|
local ReticleMaterial = wep:GetStat("StencilSight_ReticleMaterial")
|
|
if not ReticleMaterial then return end
|
|
|
|
if type(ReticleMaterial) == "string" then
|
|
CachedMaterials[ReticleMaterial] = CachedMaterials[ReticleMaterial] or Material(ReticleMaterial, "noclamp nocull smooth")
|
|
ReticleMaterial = CachedMaterials[ReticleMaterial]
|
|
end
|
|
|
|
local ReticleSize = wep:GetStat("StencilSight_ReticleSize")
|
|
if not ReticleSize then return end
|
|
|
|
if wep:GetStat("StencilSight_ScaleReticleByScreenHeight", true) then
|
|
ReticleSize = ScreenScaleH(ReticleSize)
|
|
end
|
|
|
|
if wep:GetStat("StencilSight_ScaleReticleByProgress", true) then
|
|
ReticleSize = ReticleSize * wep.IronSightsProgress
|
|
end
|
|
|
|
local w, h = ScrW(), ScrH()
|
|
|
|
local x, y = w * .5, h * .5
|
|
if wep:GetStat("StencilSight_FollowRecoil", true) then
|
|
x, y = TFA.LastCrosshairPosX or x, TFA.LastCrosshairPosY or y
|
|
end
|
|
|
|
local TargetColor = wep:GetStat("StencilSight_ReticleTint", color_white)
|
|
|
|
if wep:GetStat("StencilSight_ReticleTintBySightColor", false) and IsValid(wep:GetOwner()) then
|
|
local Owner = wep:GetOwner()
|
|
|
|
local _GetNWVector = Owner.GetNW2Vector or Owner.GetNWVector
|
|
|
|
local ColorVec = _GetNWVector(Owner, "TFAReticuleColor")
|
|
|
|
if ColorVec then
|
|
TargetColor = Color(ColorVec.x, ColorVec.y, ColorVec.z)
|
|
end
|
|
end
|
|
|
|
if wep:GetStat("StencilSight_FadeReticleByProgress", false) then
|
|
TargetColor = ColorAlpha(TargetColor, wep.IronSightsProgress * 255)
|
|
end
|
|
|
|
cam.Start2D(0, 0, w, h)
|
|
surface.SetMaterial(ReticleMaterial)
|
|
surface.SetDrawColor(TargetColor)
|
|
surface.DrawTexturedRect(x - ReticleSize * .5, y - ReticleSize * .5, ReticleSize, ReticleSize)
|
|
cam.End2D()
|
|
end
|
|
end
|
|
|
|
do -- Model reticle, for when you don't have an attach point
|
|
if IsValid(TFA.SightReticleEnt) then
|
|
TFA.SightReticleEnt:Remove()
|
|
TFA.SightReticleEnt = nil
|
|
end
|
|
|
|
TFA.SightReticleEnt = ClientsideModel("models/error.mdl", RENDERGROUP_VIEWMODEL)
|
|
TFA.SightReticleEnt:SetNoDraw(true)
|
|
|
|
local SightReticleEnt = TFA.SightReticleEnt
|
|
|
|
DrawFunctions[TFA.Enum.RETICLE_MODEL] = function(vm, ply, wep, SightElementTable)
|
|
if not SightElementTable.reticle then return end
|
|
|
|
local SightElementModel = SightElementTable.curmodel
|
|
|
|
SightReticleEnt:SetModel(SightElementTable.reticle)
|
|
if SightReticleEnt:GetModel() == "models/error.mdl" then return end
|
|
|
|
local matrix = Matrix()
|
|
matrix:Scale(SightElementTable.size)
|
|
SightReticleEnt:EnableMatrix("RenderMultiply", matrix)
|
|
|
|
if SightReticleEnt:GetParent() ~= SightElementModel then
|
|
SightReticleEnt:SetParent(SightElementModel)
|
|
SightReticleEnt:SetPos(SightElementModel:GetPos())
|
|
SightReticleEnt:SetAngles(SightElementModel:GetAngles())
|
|
|
|
if not SightReticleEnt:IsEffectActive(EF_BONEMERGE) then
|
|
SightReticleEnt:AddEffects(EF_BONEMERGE)
|
|
SightReticleEnt:AddEffects(EF_BONEMERGE_FASTCULL)
|
|
end
|
|
end
|
|
|
|
if wep.ViewModelFlip then render.CullMode(MATERIAL_CULLMODE_CW) end
|
|
if wep:GetStat("StencilSight_FadeReticleByProgress", false) then
|
|
local oldBlend = render.GetBlend()
|
|
|
|
render.SetBlend(wep.IronSightsProgress)
|
|
SightReticleEnt:DrawModel()
|
|
render.SetBlend(oldBlend)
|
|
else
|
|
SightReticleEnt:DrawModel()
|
|
end
|
|
if wep.ViewModelFlip then render.CullMode(MATERIAL_CULLMODE_CCW) end
|
|
|
|
if wep:GetStat("StencilSight_EnableQuad") then
|
|
DrawFunctions[TFA.Enum.RETICLE_QUAD](vm, ply, wep, SightElementTable)
|
|
end
|
|
end
|
|
end
|
|
|
|
do -- Quad/Attach reticle, TFA INS2 method
|
|
local function GetTargetPosition(wep, SightElementTable)
|
|
local TargetEntity = SightElementTable.curmodel
|
|
if not IsValid(TargetEntity) then return end
|
|
|
|
local Type = wep:GetStat("StencilSight_PositionType", TFA.Enum.SIGHTSPOS_ATTACH)
|
|
|
|
local pos, ang
|
|
|
|
if Type == TFA.Enum.SIGHTSPOS_ATTACH then
|
|
local AttachmentID = wep:GetStat("StencilSight_ReticleAttachment")
|
|
if not AttachmentID then return end
|
|
|
|
if type(AttachmentID) == "string" then
|
|
AttachmentID = TargetEntity:LookupAttachment(AttachmentID)
|
|
end
|
|
|
|
if not AttachmentID or AttachmentID <= 0 then return end
|
|
|
|
local Attachment = TargetEntity:GetAttachment(AttachmentID)
|
|
if not Attachment.Pos or not Attachment.Ang then return end
|
|
|
|
pos, ang = Attachment.Pos, Attachment.Ang
|
|
elseif Type == TFA.Enum.SIGHTSPOS_BONE then
|
|
local BoneID = wep:GetStat("StencilSight_ReticleBone")
|
|
|
|
if type(BoneID) == "string" then
|
|
BoneID = TargetEntity:LookupBone(BoneID)
|
|
end
|
|
|
|
if not BoneID or BoneID < 0 then return end
|
|
|
|
pos, ang = TargetEntity:GetBonePosition(BoneID)
|
|
|
|
if pos == TargetEntity:GetPos() then
|
|
pos = TargetEntity:GetBoneMatrix(BoneID):GetTranslation()
|
|
ang = TargetEntity:GetBoneMatrix(BoneID):GetAngles()
|
|
end
|
|
else
|
|
return
|
|
end
|
|
|
|
local OffsetPos = wep:GetStat("StencilSight_ReticleOffsetPos")
|
|
if OffsetPos then
|
|
pos = pos + ang:Right() * OffsetPos.x + ang:Forward() * OffsetPos.y + ang:Up() * OffsetPos.z
|
|
end
|
|
|
|
local OffsetAng = wep:GetStat("StencilSight_ReticleOffsetAng")
|
|
if OffsetAng then
|
|
ang:RotateAroundAxis(ang:Right(), OffsetAng.p)
|
|
ang:RotateAroundAxis(ang:Up(), OffsetAng.y)
|
|
ang:RotateAroundAxis(ang:Forward(), OffsetAng.r)
|
|
end
|
|
|
|
return pos, ang
|
|
end
|
|
|
|
DrawFunctions[TFA.Enum.RETICLE_QUAD] = function(vm, ply, wep, SightElementTable)
|
|
local ReticleMaterial = wep:GetStat("StencilSight_ReticleMaterial")
|
|
if not ReticleMaterial then return end
|
|
|
|
if type(ReticleMaterial) == "string" then
|
|
CachedMaterials[ReticleMaterial] = CachedMaterials[ReticleMaterial] or Material(ReticleMaterial, "noclamp nocull smooth")
|
|
ReticleMaterial = CachedMaterials[ReticleMaterial]
|
|
end
|
|
|
|
local ReticleSize = wep:GetStat("StencilSight_ReticleSize")
|
|
if not ReticleSize then return end
|
|
|
|
if wep:GetStat("StencilSight_ScaleReticleByProgress", false) then
|
|
ReticleSize = ReticleSize * wep.IronSightsProgress
|
|
end
|
|
|
|
local TargetColor = wep:GetStat("StencilSight_ReticleTint", color_white)
|
|
|
|
if wep:GetStat("StencilSight_ReticleTintBySightColor", false) and IsValid(wep:GetOwner()) then
|
|
local Owner = wep:GetOwner()
|
|
|
|
local _GetNWVector = Owner.GetNW2Vector or Owner.GetNWVector
|
|
|
|
local ColorVec = _GetNWVector(Owner, "TFAReticuleColor")
|
|
|
|
if ColorVec then
|
|
TargetColor = Color(ColorVec.x, ColorVec.y, ColorVec.z)
|
|
end
|
|
end
|
|
|
|
if wep:GetStat("StencilSight_FadeReticleByProgress", false) then
|
|
TargetColor = ColorAlpha(TargetColor, wep.IronSightsProgress * 255)
|
|
end
|
|
|
|
local p, a = GetTargetPosition(wep, SightElementTable)
|
|
if not p or not a then return end
|
|
|
|
render.OverrideDepthEnable(true, true)
|
|
|
|
render.SetMaterial(ReticleMaterial)
|
|
render.DrawQuadEasy(p, a:Forward() * -1, ReticleSize, ReticleSize, TargetColor, 180 + a.r * (wep.ViewModelFlip and 1 or -1))
|
|
|
|
render.OverrideDepthEnable(false, false)
|
|
end
|
|
end
|
|
|
|
-- hook logic
|
|
if IsValid(TFA.SightMaskEnt) then
|
|
TFA.SightMaskEnt:Remove()
|
|
TFA.SightMaskEnt = nil
|
|
end
|
|
|
|
TFA.SightMaskEnt = ClientsideModel("models/error.mdl", RENDERGROUP_VIEWMODEL)
|
|
TFA.SightMaskEnt:SetNoDraw(true)
|
|
|
|
local SightMaskEnt = TFA.SightMaskEnt
|
|
|
|
local function DrawSight(vm, ply, wep)
|
|
if not IsValid(wep) or not wep.IsTFAWeapon then return end
|
|
|
|
local wep2 = wep:GetTable()
|
|
|
|
if wep2.TFA_IsDrawingStencilSights then return end
|
|
wep2.TFA_IsDrawingStencilSights = true
|
|
|
|
if not wep2.GetStat(wep, "StencilSight") then wep2.TFA_IsDrawingStencilSights = false return end
|
|
if wep2.IronSightsProgress < wep2.GetStat(wep, "StencilSight_MinPercent", 0.05) then wep2.TFA_IsDrawingStencilSights = false return end
|
|
|
|
local SightElementName = wep2.GetStat(wep, "StencilSight_VElement")
|
|
if not SightElementName or not wep2.GetStat(wep, "VElements." .. SightElementName .. ".active") then wep2.TFA_IsDrawingStencilSights = false return end
|
|
|
|
local SightElementTable = wep2.VElements[SightElementName]
|
|
if not SightElementTable then wep2.TFA_IsDrawingStencilSights = false return end
|
|
|
|
local SightElementModel = SightElementTable.curmodel
|
|
if not IsValid(SightElementModel) then wep2.TFA_IsDrawingStencilSights = false return end
|
|
|
|
if useStencils then
|
|
defineCanvas()
|
|
|
|
local SightMaskModel = SightElementModel
|
|
|
|
if wep2.GetStat(wep, "StencilSight_UseMask", false) and SightElementTable.mask then
|
|
SightMaskEnt:SetModel(SightElementTable.mask)
|
|
|
|
if SightMaskEnt:GetModel() ~= "models/error.mdl" then
|
|
SightMaskModel = SightMaskEnt
|
|
|
|
local matrix = Matrix()
|
|
matrix:Scale(SightElementTable.size)
|
|
SightMaskEnt:EnableMatrix("RenderMultiply", matrix)
|
|
|
|
if SightMaskEnt:GetParent() ~= SightElementModel then
|
|
SightMaskEnt:SetParent(SightElementModel)
|
|
SightMaskEnt:SetPos(SightElementModel:GetPos())
|
|
SightMaskEnt:SetAngles(SightElementModel:GetAngles())
|
|
|
|
if not SightMaskEnt:IsEffectActive(EF_BONEMERGE) then
|
|
SightMaskEnt:AddEffects(EF_BONEMERGE)
|
|
SightMaskEnt:AddEffects(EF_BONEMERGE_FASTCULL)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if wep.ViewModelFlip then render.CullMode(MATERIAL_CULLMODE_CW) end
|
|
local oldBlend = render.GetBlend()
|
|
render.SetBlend(0)
|
|
SightMaskModel:DrawModel()
|
|
render.SetBlend(oldBlend)
|
|
if wep.ViewModelFlip then render.CullMode(MATERIAL_CULLMODE_CCW) end
|
|
|
|
drawOn()
|
|
end
|
|
|
|
local funcType = wep2.GetStat(wep, "StencilSight_ReticleType", TFA.Enum.RETICLE_FLAT)
|
|
|
|
if DrawFunctions[funcType] then
|
|
ProtectedCall(function()
|
|
DrawFunctions[funcType](vm, ply, wep, SightElementTable)
|
|
end)
|
|
end
|
|
|
|
if useStencils then
|
|
stopCanvas()
|
|
end
|
|
|
|
wep2.TFA_IsDrawingStencilSights = false
|
|
end
|
|
|
|
hook.Add("PostDrawViewModel", "TFA_DrawStencilSight", DrawSight) |