Files
VnUtest/garrysmod/addons/tfa_base/lua/tfa/modules/tfa_functions.lua
2026-03-31 10:27:04 +03:00

416 lines
9.2 KiB
Lua

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
function TFA.RTQuality()
if not cv_rt then
cv_rt = GetConVar("cl_tfa_3dscope_quality")
end
return math.Clamp(cv_rt:GetInt(), cv_rt:GetMin(), cv_rt:GetMax())
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.Clamp(math.atan( resrat * math.tan(math.rad( fov_target / 2 ) ) ) / math.atan( resrat * math.tan( math.rad( fov_og / 2) ) ) / ss, 0, 1)
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 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)
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
if DLib and math.tbezier and isfunction(math.tbezier) then
TFA.tbezier = math.tbezier
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
if CLIENT then
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 color_black = Color(0, 0, 0, 255)
function TFA.DrawTextShadowed(text, font, x, y, color, shadowlength, shadowcolor)
shadowlength = shadowlength or 2
shadowcolor = shadowcolor or ColorAlpha(color_black, color.a)
surface.SetFont(font)
surface.SetTextPos(x + shadowlength, y + shadowlength)
surface.SetTextColor(shadowcolor.r, shadowcolor.g, shadowcolor.b, shadowcolor.a)
surface.DrawText(text)
surface.SetTextPos(x, y)
surface.SetTextColor(color.r, color.g, color.b, color.a)
surface.DrawText(text)
end
end