mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
427 lines
9.9 KiB
Lua
427 lines
9.9 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.
|
|
|
|
local gas_cl_enabled = GetConVar("cl_tfa_fx_gasblur")
|
|
local oldshell_cl_enabled = GetConVar("cl_tfa_legacy_shells")
|
|
|
|
local ScrW, ScrH = ScrW, ScrH
|
|
|
|
local BindToKeyTBL = {
|
|
["ctrl"] = KEY_LCONTROL,
|
|
["rctrl"] = KEY_LCONTROL,
|
|
["alt"] = KEY_LALT,
|
|
["ralt"] = KEY_RALT,
|
|
["space"] = KEY_SPACE,
|
|
["caps"] = KEY_CAPSLOCK,
|
|
["capslock"] = KEY_CAPSLOCK,
|
|
["tab"] = KEY_TAB,
|
|
["back"] = KEY_BACKSPACE,
|
|
["backspace"] = KEY_BACKSPACE,
|
|
[0] = KEY_0,
|
|
[1] = KEY_1,
|
|
[2] = KEY_2,
|
|
[3] = KEY_3,
|
|
[4] = KEY_4,
|
|
[5] = KEY_5,
|
|
[6] = KEY_6,
|
|
[7] = KEY_7,
|
|
[8] = KEY_8,
|
|
[9] = KEY_9
|
|
}
|
|
|
|
local alphabet = "abcdefghijklmnopqrstuvwxyz"
|
|
|
|
for i = 1, string.len(alphabet) do
|
|
local sstr = string.sub( alphabet, i, i )
|
|
BindToKeyTBL[ sstr ] = string.byte( sstr ) - 86
|
|
end
|
|
|
|
|
|
local SoundChars = {
|
|
["*"] = "STREAM",--Streams from the disc and rapidly flushed; good on memory, useful for music or one-off sounds
|
|
["#"] = "DRYMIX",--Skip DSP, affected by music volume rather than sound volume
|
|
["@"] = "OMNI",--Play the sound audible everywhere, like a radio voiceover or surface.PlaySound
|
|
[">"] = "DOPPLER",--Left channel for heading towards the listener, Right channel for heading away
|
|
["<"] = "DIRECTIONAL",--Left channel = front facing, Right channel = read facing
|
|
["^"] = "DISTVARIANT",--Left channel = close, Right channel = far
|
|
["("] = "SPATIALSTEREO_LOOP",--Position a stereo sound in 3D space; broken
|
|
[")"] = "SPATIALSTEREO",--Same as above but actually useful
|
|
["}"] = "FASTPITCH",--Low quality pitch shift
|
|
["$"] = "CRITICAL",--Keep it around in memory
|
|
["!"] = "SENTENCE",--NPC dialogue
|
|
["?"] = "USERVOX"--Fake VOIP data; not that useful
|
|
}
|
|
local DefaultSoundChar = ")"
|
|
|
|
local SoundChannels = {
|
|
["shoot"] = CHAN_WEAPON,
|
|
["shootwrap"] = CHAN_STATIC,
|
|
["misc"] = CHAN_AUTO
|
|
}
|
|
|
|
|
|
--Scope
|
|
|
|
local cv_rt = GetConVar("cl_tfa_3dscope_quality")
|
|
|
|
function TFA.RTQuality()
|
|
if not cv_rt or cv_rt:GetInt() == -1 then
|
|
return 0
|
|
elseif cv_rt then
|
|
return math.Clamp(cv_rt:GetInt(), 0, 3)
|
|
end
|
|
end
|
|
|
|
--Sensitivity
|
|
|
|
local ss, fov_og, resrat, fov_cv
|
|
|
|
fov_cv = GetConVar("fov_desired")
|
|
function TFA.CalculateSensitivtyScale( fov_target, fov_src, screenscale )
|
|
if not LocalPlayer():IsValid() then return 1 end
|
|
resrat = ScrW() / ScrH()
|
|
fov_og = fov_src or TFADUSKFOV or fov_cv:GetFloat()
|
|
ss = screenscale or 1
|
|
return math.atan( resrat * math.tan(math.rad( fov_target / 2 ) ) ) / math.atan( resrat * math.tan( math.rad( fov_og / 2) ) ) / ss
|
|
end
|
|
|
|
--Ammo
|
|
|
|
local AmmoTypesByName = {}
|
|
local AmmoTypesAdded = {}
|
|
|
|
function TFA.AddAmmo(id, name)
|
|
if not AmmoTypesAdded[id] then
|
|
AmmoTypesAdded[id] = true
|
|
|
|
game.AddAmmoType({
|
|
name = id
|
|
})
|
|
end
|
|
|
|
if name and language then
|
|
language.Add(id .. "_ammo", name)
|
|
end
|
|
|
|
if name then
|
|
AmmoTypesByName[name] = AmmoTypesByName[name] or id
|
|
|
|
return AmmoTypesByName[name]
|
|
end
|
|
|
|
return id
|
|
end
|
|
|
|
--Particles
|
|
|
|
function TFA.ParticleTracer( name,startPos,endPos,doWhiz,ent,att)
|
|
if type(ent) ~= "number" and IsValid(ent) and ent.EntIndex then
|
|
ent = ent:EntIndex()
|
|
end
|
|
if ent then
|
|
att = att or -1
|
|
return util.ParticleTracerEx(name,startPos,endPos,doWhiz,ent,att)
|
|
else
|
|
return util.ParticleTracerEx(name,startPos,endPos,doWhiz,0,-1)
|
|
end
|
|
end
|
|
|
|
--Binds
|
|
|
|
function TFA.BindToKey( bind, default )
|
|
return BindToKeyTBL[ string.lower( bind ) ] or default or KEY_C
|
|
end
|
|
|
|
--Sounds
|
|
|
|
function TFA.PatchSound( path, kind )
|
|
local pathv
|
|
local c = string.sub(path,1,1)
|
|
|
|
if SoundChars[c] then
|
|
pathv = string.sub( path, 2, string.len(path) )
|
|
else
|
|
pathv = path
|
|
end
|
|
|
|
local kindstr = kind
|
|
if not kindstr then
|
|
kindstr = DefaultSoundChar
|
|
end
|
|
if string.len(kindstr) > 1 then
|
|
local found = false
|
|
for k,v in pairs( SoundChars ) do
|
|
if v == kind then
|
|
kindstr = k
|
|
found = true
|
|
break
|
|
end
|
|
end
|
|
if not found then
|
|
kindstr = DefaultSoundChar
|
|
end
|
|
end
|
|
|
|
return kindstr .. pathv
|
|
end
|
|
|
|
function TFA.AddSound( name, channel, volume, level, pitch, wave, char )
|
|
char = char or ""
|
|
|
|
local SoundData = {
|
|
name = name,
|
|
channel = channel or CHAN_AUTO,
|
|
volume = volume or 1,
|
|
level = level or 75,
|
|
pitch = pitch or 100
|
|
}
|
|
|
|
if char ~= "" then
|
|
if type(wave) == "string" then
|
|
wave = TFA.PatchSound(wave, char)
|
|
elseif type(wave) == "table" then
|
|
local patchWave = table.Copy(wave)
|
|
|
|
for k, v in pairs(patchWave) do
|
|
patchWave[k] = TFA.PatchSound(v, char)
|
|
end
|
|
|
|
wave = patchWave
|
|
end
|
|
end
|
|
|
|
SoundData.sound = wave
|
|
|
|
sound.Add(SoundData)
|
|
end
|
|
|
|
function TFA.AddFireSound( id, path, wrap, kindv )
|
|
kindv = kindv or ")"
|
|
|
|
TFA.AddSound(id, wrap and SoundChannels.shootwrap or SoundChannels.shoot, 1, 120, {97, 103}, path, kindv)
|
|
end
|
|
|
|
function TFA.AddWeaponSound( id, path, kindv )
|
|
kindv = kindv or ")"
|
|
|
|
TFA.AddSound(id, SoundChannels.misc, 1, 80, {97, 103}, path, kindv)
|
|
end
|
|
|
|
--Frametime
|
|
|
|
--CVar Mediators
|
|
function TFA.GetGasEnabled()
|
|
local enabled = false
|
|
|
|
if gas_cl_enabled then
|
|
enabled = gas_cl_enabled:GetBool()
|
|
end
|
|
|
|
return enabled
|
|
end
|
|
|
|
function TFA.GetLegacyShellsEnabled()
|
|
local enabled = false
|
|
|
|
if oldshell_cl_enabled then
|
|
enabled = oldshell_cl_enabled:GetBool()
|
|
end
|
|
|
|
return enabled
|
|
end
|
|
|
|
local ejectionsmoke_cl_enabled = GetConVar("cl_tfa_fx_ejectionsmoke")
|
|
local muzzlesmoke_cl_enabled = GetConVar("cl_tfa_fx_muzzlesmoke")
|
|
|
|
function TFA.GetMZSmokeEnabled()
|
|
local enabled = false
|
|
|
|
if muzzlesmoke_cl_enabled then
|
|
enabled = muzzlesmoke_cl_enabled:GetBool()
|
|
end
|
|
|
|
return enabled
|
|
end
|
|
|
|
function TFA.GetEJSmokeEnabled()
|
|
local enabled = false
|
|
|
|
if ejectionsmoke_cl_enabled then
|
|
enabled = ejectionsmoke_cl_enabled:GetBool()
|
|
end
|
|
|
|
return enabled
|
|
end
|
|
|
|
local muzzleflashsmoke_cl_enabled = GetConVar("cl_tfa_fx_muzzleflashsmoke")
|
|
|
|
function TFA.GetMZFSmokeEnabled()
|
|
local enabled = false
|
|
|
|
if muzzleflashsmoke_cl_enabled then
|
|
enabled = muzzleflashsmoke_cl_enabled:GetBool()
|
|
end
|
|
|
|
return enabled
|
|
end
|
|
|
|
local ricofx_cl_enabled = GetConVar("cl_tfa_fx_impact_ricochet_enabled")
|
|
|
|
function TFA.GetRicochetEnabled()
|
|
local enabled = false
|
|
|
|
if ricofx_cl_enabled then
|
|
enabled = ricofx_cl_enabled:GetBool()
|
|
end
|
|
|
|
return enabled
|
|
end
|
|
|
|
--Local function for detecting TFA Base weapons.
|
|
function TFA.PlayerCarryingTFAWeapon(ply)
|
|
if not ply then
|
|
if CLIENT then
|
|
if LocalPlayer():IsValid() then
|
|
ply = LocalPlayer()
|
|
else
|
|
return false, nil, nil
|
|
end
|
|
elseif game.SinglePlayer() then
|
|
ply = Entity(1)
|
|
else
|
|
return false, nil, nil
|
|
end
|
|
end
|
|
|
|
if not (IsValid(ply) and ply:IsPlayer() and ply:Alive()) then return end
|
|
local wep = ply:GetActiveWeapon()
|
|
|
|
if IsValid(wep) then
|
|
if (wep.IsTFAWeapon) then return true, ply, wep end
|
|
|
|
return false, ply, wep
|
|
end
|
|
|
|
return false, ply, nil
|
|
end
|
|
|
|
local cvar_scale = GetConVar("cl_tfa_hud_scale")
|
|
local sscache = {}
|
|
|
|
function TFA.ScaleH(num)
|
|
if not sscache[num] then
|
|
sscache[num] = num * (ScrH() / 1080) * cvar_scale:GetFloat()
|
|
end
|
|
|
|
return sscache[num]
|
|
end
|
|
|
|
local function EmptyCache()
|
|
sscache = {}
|
|
end
|
|
|
|
cvars.AddChangeCallback("cl_tfa_hud_scale", EmptyCache, "TFA_ClearSScaleCache")
|
|
hook.Add("OnScreenSizeChanged", "_TFA_DropSScaleCache", EmptyCache)
|
|
|
|
local sv_cheats = GetConVar("sv_cheats")
|
|
local host_timescale = GetConVar("host_timescale")
|
|
|
|
function TFA.FrameTime()
|
|
return engine.TickInterval() * game.GetTimeScale() * (sv_cheats:GetBool() and host_timescale:GetFloat() or 1)
|
|
end
|
|
|
|
local buffer = {}
|
|
|
|
function TFA.tbezier(t, values, amount)
|
|
if DLib then return math.tbezier(t, values) end
|
|
|
|
assert(isnumber(t), 't is not a number')
|
|
assert(t >= 0 and t <= 1, '0 <= t <= 1!')
|
|
assert(#values >= 2, 'at least two values must be provided')
|
|
amount = amount or #values
|
|
local a, b = values[1], values[2]
|
|
|
|
-- linear
|
|
if amount == 2 then
|
|
return a + (b - a) * t
|
|
-- square
|
|
elseif amount == 3 then
|
|
return (1 - t) * (1 - t) * a + 2 * t * (1 - t) * b + t * t * values[3]
|
|
-- cube
|
|
elseif amount == 4 then
|
|
return (1 - t) * (1 - t) * (1 - t) * a + 3 * t * (1 - t) * (1 - t) * b + 3 * t * t * (1 - t) * values[3] + t * t * t * values[4]
|
|
end
|
|
|
|
for point = 1, amount do
|
|
local point1 = values[point]
|
|
local point2 = values[point + 1]
|
|
if not point2 then break end
|
|
buffer[point] = point1 + (point2 - point1) * t
|
|
end
|
|
|
|
return TFA.tbezier(t, buffer, amount - 1)
|
|
end
|
|
|
|
function TFA.Quintic(t)
|
|
return t * t * t * (t * (t * 6 - 15) + 10)
|
|
end
|
|
|
|
function TFA.Cosine(t)
|
|
return (1 - math.cos(t * math.pi)) / 2
|
|
end
|
|
|
|
function TFA.Sinusine(t)
|
|
return (1 - math.sin(t * math.pi)) / 2
|
|
end
|
|
|
|
function TFA.Cubic(t)
|
|
return -2 * t * t * t + 3 * t * t
|
|
end
|
|
|
|
function TFA.UnfoldBaseClass(tableInput, tableOutput)
|
|
if tableOutput == nil then tableOutput = tableInput end
|
|
if not istable(tableInput) or not istable(tableOutput) then return tableOutput end
|
|
|
|
if tableInput ~= tableOutput then
|
|
for k, v in pairs(tableInput) do
|
|
if tableOutput[k] == nil then
|
|
tableOutput[k] = v
|
|
end
|
|
end
|
|
end
|
|
|
|
if istable(tableInput.BaseClass) then
|
|
TFA.UnfoldBaseClass(tableInput.BaseClass, tableOutput)
|
|
end
|
|
|
|
return tableOutput
|
|
end
|