commit 724dde6df33d8bf764829e015ea0c799ef43e68e Author: Haodong Mo Date: Thu Jun 25 12:24:08 2020 +1000 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/lua/arccw/client/cl_autostats.lua b/lua/arccw/client/cl_autostats.lua new file mode 100644 index 00000000..15a8a9b4 --- /dev/null +++ b/lua/arccw/client/cl_autostats.lua @@ -0,0 +1,128 @@ +-- ["buff"] = {"desc", bool ismult, bool lowerbetter} +ArcCW.AutoStats = { + ["Mult_BipodRecoil"] = {"Recoil in bipod", true, true}, + ["Mult_BipodDispersion"] = {"Dispersion in bipod", true, true}, + ["Mult_Damage"] = {"Close range damage", true, false}, + ["Mult_DamageMin"] = {"Long range damage", true, false}, + ["Mult_Range"] = {"Range", true, false}, + ["Mult_Penetration"] = {"Penetration", true, false}, + ["Mult_MuzzleVelocity"] = {"Muzzle velocity", true, false}, + ["Mult_MeleeTime"] = {"Melee attack time", true, true}, + ["Mult_MeleeDamage"] = {"Melee damage", true, false}, + ["Add_MeleeRange"] = {"Melee range", false, false}, + ["Mult_Recoil"] = {"Recoil", true, true}, + ["Mult_RecoilSide"] = {"Horizontal recoil", true, true}, + ["Mult_RPM"] = {"Fire rate", true, false}, + ["Mult_AccuracyMOA"] = {"Imprecision", true, true}, + ["Mult_HipDispersion"] = {"Hip fire spread", true, true}, + ["Mult_SightsDispersion"] = {"Sighted spread", true, true}, + ["Mult_MoveDispersion"] = {"Moving spread", true, true}, + ["Mult_ShootVol"] = {"Weapon volume", true, true}, + ["Mult_SpeedMult"] = {"Movement speed", true, false}, + ["Mult_MoveSpeed"] = {"Movement speed", true, false}, + ["Mult_SightedSpeedMult"] = {"Sighted strafe speed", true, false}, + ["Mult_SightedMoveSpeed"] = {"Sighted strafe speed", true, false}, + ["Mult_ReloadTime"] = {"Reload time", true, true}, + ["Mult_DrawTime"] = {"Draw time", true, true}, + ["Mult_SightTime"] = {"Sight time", true, true}, + ["Mult_CycleTime"] = {"Cycle time", true, true} +} + +local function getsimpleamt(stat) + if stat > 1 then + if stat >= 2 then + return "++++ " + elseif stat >= 1.5 then + return "+++ " + elseif stat >= 1.25 then + return "++ " + else + return "+ " + end + elseif stat < 1 then + if stat <= 0.25 then + return "---- " + elseif stat <= 0.5 then + return "--- " + elseif stat <= 0.25 then + return "-- " + else + return "- " + end + end +end + +function ArcCW:GetProsCons(att) + local pros = {} + local cons = {} + + table.Add(pros, att.Desc_Pros or {}) + table.Add(cons, att.Desc_Cons or {}) + + if !att.AutoStats then + return pros, cons + end + + local simple = GetConVar("arccw_attinv_simpleproscons"):GetBool() + + for i, k in pairs(att) do + if ArcCW.AutoStats[i] then + local stat = ArcCW.AutoStats[i] + local txt = "" + + if stat[2] then + -- mult + if k > 1 then + if simple then + txt = getsimpleamt(k) .. stat[1] + else + txt = "+" .. tostring((k - 1) * 100) .. "% " .. stat[1] + end + if stat[3] then + table.insert(cons, txt) + else + table.insert(pros, txt) + end + elseif k < 1 then + if simple then + txt = getsimpleamt(k) .. stat[1] + else + txt = "-" .. tostring((1 - k) * 100) .. "% " .. stat[1] + end + if stat[3] then + table.insert(pros, txt) + else + table.insert(cons, txt) + end + end + else + -- add + if k > 0 then + if simple then + txt = "+ " .. stat[1] + else + txt = "+" .. tostring(k) .. " " .. stat[1] + end + if stat[3] then + table.insert(cons, txt) + else + table.insert(pros, txt) + end + elseif k < 0 then + if simple then + txt = "+ " .. stat[1] + else + txt = "-" .. tostring(-k) .. " " .. stat[1] + end + if stat[3] then + table.insert(pros, txt) + else + table.insert(cons, txt) + end + end + end + end + end + + return pros, cons +end \ No newline at end of file diff --git a/lua/arccw/client/cl_binds.lua b/lua/arccw/client/cl_binds.lua new file mode 100644 index 00000000..6621fd3d --- /dev/null +++ b/lua/arccw/client/cl_binds.lua @@ -0,0 +1,142 @@ +ArcCW.KEY_FIREMODE = "+zoom" +ArcCW.KEY_FIREMODE_ALT = "arccw_firemode" +ArcCW.KEY_ZOOMIN = "invnext" +ArcCW.KEY_ZOOMIN_ALT = "arccw_zoom_in" +ArcCW.KEY_ZOOMOUT = "invprev" +ArcCW.KEY_ZOOMOUT_ALT = "arccw_zoom_out" +ArcCW.KEY_TOGGLEINV = "+menu_context" +ArcCW.KEY_TOGGLEINV_ALT = "arccw_toggle_inv" +ArcCW.KEY_SWITCHSCOPE = "+use" +ArcCW.KEY_SWITCHSCOPE_ALT = "arccw_switch_scope" +ArcCW.KEY_TOGGLEUBGL_ALT = "arccw_toggle_ubgl" + +local lastpressZ = 0 +local lastpressE = 0 + +function ArcCW:GetBind(bind) + if ArcCW[bind] then return ArcCW[bind] end + + return input.LookupBinding(bind) +end + +local function ArcCW_PlayerBindPress(ply, bind, pressed) + if !pressed then return end + if !ply:IsValid() then return end + + local wpn = ply:GetActiveWeapon() + + if !wpn.ArcCW then return end + + local block = false + + if bind == ArcCW.KEY_FIREMODE then + if wpn:GetBuff_Override("UBGL") then + if lastpressZ >= CurTime() - 0.25 then + if wpn:GetNWBool("ubgl") then + net.Start("arccw_ubgl") + net.WriteBool(false) + net.SendToServer() + + wpn:DeselectUBGL() + else + net.Start("arccw_ubgl") + net.WriteBool(true) + net.SendToServer() + + wpn:SelectUBGL() + end + lastpressZ = 0 + + timer.Remove("ArcCW_doubletapZ") + else + lastpressZ = CurTime() + timer.Create("ArcCW_doubletapZ", 0.25, 1, function() + if !IsValid(ply) then return end + if !IsValid(wpn) then return end + if ply:GetActiveWeapon() != wpn then return end + if wpn:GetNWBool("ubgl") then return end + + net.Start("arccw_firemode") + net.SendToServer() + + wpn:ChangeFiremode() + end) + end + else + net.Start("arccw_firemode") + net.SendToServer() + + wpn:ChangeFiremode() + end + + block = true + elseif bind == ArcCW.KEY_TOGGLEINV then + local p = wpn:GetState() != ArcCW.STATE_CUSTOMIZE + wpn:ToggleCustomizeHUD(p) + + net.Start("arccw_togglecustomize") + net.WriteBool(p) + net.SendToServer() + + block = true + end + + if wpn:GetState() == ArcCW.STATE_SIGHTS then + if bind == ArcCW.KEY_ZOOMIN then + wpn:Scroll(1) + block = true + elseif bind == ArcCW.KEY_ZOOMOUT then + wpn:Scroll(-1) + block = true + elseif bind == ArcCW.KEY_SWITCHSCOPE then + if lastpressE >= CurTime() - 0.25 then + wpn:SwitchActiveSights() + lastpressE = 0 + else + lastpressE = CurTime() + end + end + end + + if block then return true end +end + +hook.Add("PlayerBindPress", "ArcCW_PlayerBindPress", ArcCW_PlayerBindPress) + +-- ArcCW.CaptureKeys = { +-- KEY_G +-- } +-- ArcCW.LastInputs = {} +-- ArcCW.Inputs = {} + +-- local function ArcCW_CustomInputs() +-- local inputs = {} + +-- for _, i in pairs(ArcCW.CaptureKeys) do +-- -- local conv = GetConVar(i) + +-- -- if !conv then continue end +-- -- if !IsValid(conv) then continue end + +-- local kc = i + +-- inputs[kc] = input.IsKeyDown(kc) +-- end + +-- ArcCW.LastInputs = ArcCW.Inputs +-- ArcCW.Inputs = inputs + +-- if ArcCW:KeyPressed(KEY_G) then +-- ArcCW:QuickNade("frag") +-- end +-- end + +-- hook.Add("Think", "ArcCW_CustomInputs", ArcCW_CustomInputs) + +-- function ArcCW:KeyPressed(key) +-- if !ArcCW.LastInputs[key] and ArcCW.Inputs[key] then +-- return true +-- end + +-- return false +-- end \ No newline at end of file diff --git a/lua/arccw/client/cl_convars.lua b/lua/arccw/client/cl_convars.lua new file mode 100644 index 00000000..9eb0065e --- /dev/null +++ b/lua/arccw/client/cl_convars.lua @@ -0,0 +1,37 @@ +-- CreateClientConVar("arccw_quicknade", KEY_G) + +CreateClientConVar("arccw_crosshair", "1") + +CreateClientConVar("arccw_attinv_simpleproscons", "0") +CreateClientConVar("arccw_attinv_onlyinspect", "0") +CreateClientConVar("arccw_attinv_hideunowned", "0") + +CreateClientConVar("arccw_cheapscopes", "1") +CreateClientConVar("arccw_cheapscopesautoconfig", "0") + +CreateClientConVar("arccw_shake", "1") + +CreateClientConVar("arccw_muzzleeffects", "1") +CreateClientConVar("arccw_shelleffects", "1") + +CreateClientConVar("arccw_att_showothers", "1") + +CreateClientConVar("arccw_2d3d", "1") + +CreateClientConVar("arccw_hud_3dfun", "0") + +CreateClientConVar("arccw_scope_r", "255") +CreateClientConVar("arccw_scope_g", "0") +CreateClientConVar("arccw_scope_b", "0") + +CreateClientConVar("arccw_blur", "1") + +CreateClientConVar("arccw_glare", "1") + +CreateClientConVar("arccw_autosave", "1") + +CreateClientConVar("arccw_vm_right", "0") +CreateClientConVar("arccw_vm_up", "0") +CreateClientConVar("arccw_vm_forward", "0") + +CreateClientConVar("arccw_toggleads", "0", true, true) \ No newline at end of file diff --git a/lua/arccw/client/cl_garbage.lua b/lua/arccw/client/cl_garbage.lua new file mode 100644 index 00000000..f3128e28 --- /dev/null +++ b/lua/arccw/client/cl_garbage.lua @@ -0,0 +1,60 @@ +ArcCW.CSModels = { + -- [entid] = { + -- Weapon = NULL, + -- WModels = {}, + -- VModels = {} + -- } +} +ArcCW.CSModelPile = {} +-- { +-- {Model = NULL, Weapon = NULL} +--} + +ArcCW.ReferenceModel = NULL + +local function ArcCW_CollectGarbage() + local removed = 0 + local removedents = {} + + for i, k in pairs(ArcCW.CSModels) do + if !IsValid(k.Weapon) then + removed = removed + 1 + table.insert(removedents, i) + + if k.WModels then + for _, m in pairs(k.WModels) do + SafeRemoveEntity(m.Model) + end + end + + if k.VModels then + for _, m in pairs(k.VModels) do + SafeRemoveEntity(m.Model) + end + end + end + end + + for _, i in pairs(removedents) do + ArcCW.CSModels[i] = nil + end + + local newpile = {} + + for i, k in pairs(ArcCW.CSModelPile) do + if !IsValid(k.Weapon) then + SafeRemoveEntity(k.Model) + removed = removed + 1 + else + table.insert(newpile, k) + end + end + + ArcCW.CSModelPile = newpile + + if GetConVar("developer"):GetBool() and removed > 0 then + print("Removed " .. tostring(removed) .. " CSModels") + end +end + +timer.Create("ArcCW CSModel Garbage Collector", 5, 0, ArcCW_CollectGarbage) \ No newline at end of file diff --git a/lua/arccw/client/cl_glint.lua b/lua/arccw/client/cl_glint.lua new file mode 100644 index 00000000..68a78bf5 --- /dev/null +++ b/lua/arccw/client/cl_glint.lua @@ -0,0 +1,54 @@ +local glintmat = Material("effects/blueflare1") + +hook.Add("PostDrawEffects", "ArcCW_ScopeGlint", function() + local e = player.GetAll() + + cam.Start3D() + + for _, ply in pairs(e) do + if !IsValid(ply) then continue end + if !ply:ShouldDrawLocalPlayer() then continue end + + local wpn = ply:GetActiveWeapon() + + if !IsValid(wpn) then continue end + + if !wpn.ArcCW then continue end + + if !wpn:GetBuff_Override("ScopeGlint") then continue end + + local v1 = (ply:EyePos() - EyePos()):GetNormalized() + local v2 = -ply:EyeAngles():Forward() + + local d = v1:Dot(v2) + + d = (d * d * 1.75) - 0.75 + + if d < 0 then continue end + + local pos = ply:EyePos() + (ply:EyeAngles():Forward() * 16) + (ply:EyeAngles():Right() * 8) + + local _, scope_i = wpn:GetBuff_Override("ScopeGlint") + + if scope_i then + local wme = (wpn.Attachments[scope_i].WElement or {}).Model + + if wme then + local att = wme:LookupAttachment("holosight") + + if !att then + att = wme:LookupAttachment("scope") + end + + if att then + pos = wme:GetAttachment(att).Pos + end + end + end + + render.SetMaterial(glintmat) + render.DrawSprite(pos, 64 * d, 64 * d, Color(255, 255, 255)) + end + + cam.End3D() +end) \ No newline at end of file diff --git a/lua/arccw/client/cl_hud.lua b/lua/arccw/client/cl_hud.lua new file mode 100644 index 00000000..2ae0e5ad --- /dev/null +++ b/lua/arccw/client/cl_hud.lua @@ -0,0 +1,156 @@ +local hide = { + ["CHudHealth"] = true, + ["CHudBattery"] = true, + ["CHudAmmo"] = true, + ["CHudSecondaryAmmo"] = true, +} + +ArcCW.HUDElementConVars = { + ["CHudHealth"] = CreateClientConVar("arccw_hud_showhealth", "1"), + ["CHudBattery"] = GetConVar("arccw_hud_showhealth"), + ["CHudAmmo"] = CreateClientConVar("arccw_hud_showammo", "1"), + ["CHudSecondaryAmmo"] = GetConVar("arccw_hud_showammo"), +} + +hook.Add("HUDShouldDraw", "ArcCW_HideHUD", function(name) + if !hide[name] then return end + if !LocalPlayer():IsValid() then return end + if !LocalPlayer():GetActiveWeapon().ArcCW then return end + if ArcCW.PollingDefaultHUDElements then return end + if ArcCW.HUDElementConVars[name] and ArcCW.HUDElementConVars[name]:GetBool() == false then return end + + return false +end) + +ArcCW.PollingDefaultHUDElements = false + +function ArcCW:ShouldDrawHUDElement(ele) + if !GetConVar("cl_drawhud"):GetBool() then return false end + + if ArcCW.HUDElementConVars[ele] and !ArcCW.HUDElementConVars[ele]:GetBool() then + return false + end + + ArcCW.PollingDefaultHUDElements = true + + if hook.Call("HUDShouldDraw", nil, ele) == false then + ArcCW.PollingDefaultHUDElements = false + return false + end + + ArcCW.PollingDefaultHUDElements = false + + return true +end + +local font = "Bahnschrift" + +local sizes_to_make = { + 6, + 8, + 12, + 16, + 20, + 24, + 26 +} + +local unscaled_sizes_to_make = { + 32, + 24 +} + +local function generatefonts() + + for _, i in pairs(sizes_to_make) do + + surface.CreateFont( "ArcCW_" .. tostring(i), { + font = font, + size = ScreenScale(i), + weight = 0, + antialias = true, + } ) + + surface.CreateFont( "ArcCW_" .. tostring(i) .. "_Glow", { + font = font, + size = ScreenScale(i), + weight = 0, + antialias = true, + blursize = 8, + } ) + + end + + for _, i in pairs(unscaled_sizes_to_make) do + + surface.CreateFont( "ArcCW_" .. tostring(i) .. "_Unscaled", { + font = font, + size = i, + weight = 0, + antialias = true, + } ) + + end + +end + +generatefonts() + +language.Add("SniperPenetratedRound_ammo", "Sniper Ammo") + +local lastScrH = ScrH() +local lastScrW = ScrW() + +hook.Add("HUDPaint", "ArcCW_FontRegen", function() + if (lastScrH != ScrH()) or (lastScrW != ScrW()) then + generatefonts() + end + + lastScrH = ScrH() + lastScrW = ScrW() +end) + +-- surface.CreateFont( "ArcCW_12", { +-- font = font, +-- size = ScreenScale(12), +-- weight = 0, +-- antialias = true, +-- } ) + +-- surface.CreateFont( "ArcCW_12_Glow", { +-- font = font, +-- size = ScreenScale(12), +-- weight = 0, +-- antialias = true, +-- blursize = 8, +-- } ) + +-- surface.CreateFont( "ArcCW_16", { +-- font = font, +-- size = ScreenScale(16), +-- weight = 0, +-- antialias = true, +-- } ) + +-- surface.CreateFont( "ArcCW_16_Glow", { +-- font = font, +-- size = ScreenScale(16), +-- weight = 0, +-- antialias = true, +-- blursize = 8, +-- } ) + +-- surface.CreateFont( "ArcCW_26", { +-- font = font, +-- size = ScreenScale(26), +-- weight = 0, +-- antialias = true, +-- } ) + +-- surface.CreateFont( "ArcCW_26_Glow", { +-- font = font, +-- size = ScreenScale(26), +-- weight = 0, +-- antialias = true, +-- blursize = 8, +-- } ) \ No newline at end of file diff --git a/lua/arccw/client/cl_menus.lua b/lua/arccw/client/cl_menus.lua new file mode 100644 index 00000000..a7a0c019 --- /dev/null +++ b/lua/arccw/client/cl_menus.lua @@ -0,0 +1,105 @@ +hook.Add( "PopulateToolMenu", "ArcCW_Options", function() + spawnmenu.AddToolMenuOption( "Options", "ArcCW", "ArcCW_Options_HUD", "HUD", "", "", ArcCW_Options_HUD) + spawnmenu.AddToolMenuOption( "Options", "ArcCW", "ArcCW_Options_Client", "Client", "", "", ArcCW_Options_Client) + spawnmenu.AddToolMenuOption( "Options", "ArcCW", "ArcCW_Options_Server", "Server", "", "", ArcCW_Options_Server) + spawnmenu.AddToolMenuOption( "Options", "ArcCW", "ArcCW_Options_Mults", "Multipliers", "", "", ArcCW_Options_Mults) + spawnmenu.AddToolMenuOption( "Options", "ArcCW", "ArcCW_Options_NPC", "NPCs", "", "", ArcCW_Options_NPC) + spawnmenu.AddToolMenuOption( "Options", "ArcCW", "ArcCW_Options_Atts", "Attachments", "", "", ArcCW_Options_Atts) + spawnmenu.AddToolMenuOption( "Options", "ArcCW", "ArcCW_Options_Ammo", "Ammo", "", "", ArcCW_Options_Ammo) +end ) + +function ArcCW_Options_Ammo( CPanel ) + CPanel:AddControl("Header", {Description = "These options require admin privileges to change."}) + CPanel:AddControl("Header", {Description = ""}) + CPanel:AddControl("Header", {Description = "-1 = don't explode, 0 = simple explosion, 1 = fragmentation, 2 = full"}) + CPanel:AddControl("Slider", {Label = "Detonation Mode", Command = "arccw_ammo_detonationmode", Min = -1, Max = 2, Type = "int" }) + CPanel:AddControl("Checkbox", {Label = "Auto Pickup", Command = "arccw_ammo_autopickup" }) + CPanel:AddControl("Checkbox", {Label = "Large Pickup Trigger", Command = "arccw_ammo_largetrigger" }) + CPanel:AddControl("Slider", {Label = "Rare Skin Chance", Command = "arccw_ammo_rareskin", Min = 0, Max = 1, Type = "float" }) + CPanel:AddControl("Checkbox", {Label = "Chain Detonation", Command = "arccw_ammo_chaindet" }) + CPanel:AddControl("Slider", {Label = "Ammo Health (-1 for indestructible)", Command = "arccw_mult_ammohealth", Min = -1, Max = 10, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Ammo Amount", Command = "arccw_mult_ammoamount", Min = 0.1, Max = 10, Type = "float" }) +end + +function ArcCW_Options_HUD( CPanel ) + CPanel:AddControl("Header", {Description = "All options in this menu can be customized by players, and do not need admin privileges."}) + CPanel:AddControl("Header", {Description = ""}) + CPanel:AddControl("Checkbox", {Label = "3D Alt HUD", Command = "arccw_hud_3dfun" }) + CPanel:AddControl("Checkbox", {Label = "Show Crosshair", Command = "arccw_crosshair" }) + CPanel:AddControl("Checkbox", {Label = "Show Health", Command = "arccw_hud_showhealth" }) + CPanel:AddControl("Checkbox", {Label = "Show Ammo", Command = "arccw_hud_showammo" }) + CPanel:AddControl("Checkbox", {Label = "Hide Unowned Attachments", Command = "arccw_attinv_hideunowned" }) + CPanel:AddControl("Checkbox", {Label = "Hide Customization UI", Command = "arccw_attinv_onlyinspect" }) + CPanel:AddControl("Checkbox", {Label = "Simple Pros And Cons", Command = "arccw_attinv_simpleproscons" }) +end + +function ArcCW_Options_Client( CPanel ) + CPanel:AddControl("Header", {Description = "All options in this menu can be customized by players, and do not need admin privileges."}) + CPanel:AddControl("Header", {Description = ""}) + CPanel:AddControl("Checkbox", {Label = "Toggle Aim", Command = "arccw_toggleads" }) + CPanel:AddControl("Checkbox", {Label = "Weapon Autosave", Command = "arccw_autosave" }) + CPanel:AddControl("Header", {Description = "Attempt to re-equip the last equipped set of attachments."}) + CPanel:AddControl("Checkbox", {Label = "Cheap Scopes", Command = "arccw_cheapscopes" }) + CPanel:AddControl("Header", {Description = "A cheaper PIP scope implementation that is very low quality but saves a significant amount of performance. Can be a little glitchy."}) + CPanel:AddControl("Checkbox", {Label = "Scope Glare", Command = "arccw_glare" }) + CPanel:AddControl("Header", {Description = "Glare visible on your scope lens when aiming."}) + CPanel:AddControl("Checkbox", {Label = "Customization Blur", Command = "arccw_blur" }) + CPanel:AddControl("Checkbox", {Label = "Screen Shake", Command = "arccw_shake" }) + CPanel:AddControl("Checkbox", {Label = "Floating Help Text", Command = "arccw_2d3d" }) + CPanel:AddControl("Checkbox", {Label = "Muzzle Effects (Others Only)", Command = "arccw_muzzleeffects" }) + CPanel:AddControl("Checkbox", {Label = "Case Effects (Others Only)", Command = "arccw_shelleffects" }) + CPanel:AddControl("Checkbox", {Label = "Show World Attachments (Others Only)", Command = "arccw_att_showothers" }) + CPanel:AddControl("Slider", {Label = "Viewmodel Right", Command = "arccw_vm_right", Min = -5, Max = 5, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Viewmodel Forward", Command = "arccw_vm_forward", Min = -5, Max = 5, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Viewmodel Up", Command = "arccw_vm_up", Min = -5, Max = 5, Type = "float" }) + CPanel:AddControl("Header", {Description = " Warning! Viewmodel offset settings may cause clipping or other undesired effects!"}) +end + +function ArcCW_Options_Mults( CPanel ) + CPanel:AddControl("Header", {Description = "These options require admin privileges to change."}) + CPanel:AddControl("Header", {Description = ""}) + CPanel:AddControl("Slider", {Label = "Damage", Command = "arccw_mult_damage", Min = 0, Max = 20, Type = "float" }) + CPanel:AddControl("Slider", {Label = "NPC Damage", Command = "arccw_mult_npcdamage", Min = 0, Max = 20, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Range", Command = "arccw_mult_range", Min = 0.01, Max = 20, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Recoil", Command = "arccw_mult_recoil", Min = 0, Max = 100, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Penetration", Command = "arccw_mult_penetration", Min = 0, Max = 25, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Hip Dispersion", Command = "arccw_mult_hipfire", Min = 0, Max = 100, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Move Dispersion", Command = "arccw_mult_movedisp", Min = 0, Max = 100, Type = "float" }) + CPanel:AddControl("Slider", {Label = "Reload Time", Command = "arccw_mult_reloadtime", Min = 0.01, Max = 10, Type = "float" }) + CPanel:AddControl("Slider", {Label = "ADS Time", Command = "arccw_mult_sighttime", Min = 0.1, Max = 10, Type = "float" }) +end + +function ArcCW_Options_NPC( CPanel ) + CPanel:AddControl("Header", {Description = "These options require admin privileges to change."}) + CPanel:AddControl("Header", {Description = ""}) + CPanel:AddControl("Checkbox", {Label = "Replace NPC Weapons", Command = "arccw_npc_replace" }) + CPanel:AddControl("Checkbox", {Label = "NPC Attachments", Command = "arccw_npc_atts" }) +end + +function ArcCW_Options_Atts( CPanel ) + CPanel:AddControl("Header", {Description = "These options require admin privileges to change."}) + CPanel:AddControl("Header", {Description = ""}) + CPanel:AddControl("Header", {Description = "ArcCW supports attachment inventory style behaviour (Like ACT3) as well as attachment locking style behaviour (Like CW2.0) as well as giving everyone all attachments for free (Like TFA Base)."}) + CPanel:AddControl("Header", {Description = "Leave all options off for ACT3 style attachment inventory behaviour."}) + CPanel:AddControl("Checkbox", {Label = "Free Attachments", Command = "arccw_attinv_free" }) + CPanel:AddControl("Checkbox", {Label = "Attachment Locking", Command = "arccw_attinv_lockmode" }) + CPanel:AddControl("Checkbox", {Label = "Lose Attachments on Death", Command = "arccw_attinv_loseondie" }) + CPanel:AddControl("Header", {Description = "Pick X behaviour allows you to set a limit on attachments that can be placed on any weapon. 0 = unlimited."}) + CPanel:AddControl("Slider", {Label = "Pick X", Command = "arccw_atts_pickx", Min = 0, Max = 25, Type = "int" }) + CPanel:AddControl("color", {Label = "Sight Color", + Red = "arccw_scope_r", + Green = "arccw_scope_g", + Blue = "arccw_scope_b", + }) +end + +function ArcCW_Options_Server( CPanel ) + CPanel:AddControl("Header", {Description = "These options require admin privileges to change."}) + CPanel:AddControl("Header", {Description = ""}) + CPanel:AddControl("Checkbox", {Label = "Enable Penetration", Command = "arccw_enable_penetration" }) + CPanel:AddControl("Checkbox", {Label = "Enable Customization", Command = "arccw_enable_customization" }) + CPanel:AddControl("Checkbox", {Label = "True Names (Requires Restart)", Command = "arccw_truenames" }) + CPanel:AddControl("Slider", {Label = "Equipment Self-Destruct Time", Command = "arccw_equipmenttime", Min = 15, Max = 3600, Type = "int" }) + CPanel:AddControl("Checkbox", {Label = "Enable Year Limit", Command = "arccw_limityear_enable" }) + CPanel:AddControl("Slider", {Label = "Year Limit", Command = "arccw_limityear", Min = 1800, Max = 2100, Type = "int" }) +end \ No newline at end of file diff --git a/lua/arccw/client/cl_npc.lua b/lua/arccw/client/cl_npc.lua new file mode 100644 index 00000000..6231f926 --- /dev/null +++ b/lua/arccw/client/cl_npc.lua @@ -0,0 +1,32 @@ +hook.Add("PopulateMenuBar", "ArcCW_NPCWeaponMenu", function ( menubar ) + local m = menubar:AddOrGetMenu("ArcCW Weapons") + local weaponlist = weapons.GetList() + + m:AddCVar("None", "gmod_npcweapon", "none") + m:AddSpacer() + + local cats = {} + + table.SortByMember( weaponlist, "PrintName", true ) + + for i, k in pairs(weaponlist) do + if weapons.IsBasedOn(k.ClassName, "arccw_base") and !k.PrimaryBash and k.Spawnable and !k.NotForNPCs then + local cat = k.Category or "Other" + if !cats[cat] then + cats[cat] = m:AddSubMenu(cat) + end + + cats[cat]:SetDeleteSelf(false) + + cats[cat]:AddCVar(k.PrintName, "gmod_npcweapon", k.ClassName) + end + end +end) + +net.Receive("arccw_npcgiverequest", function(len, ply) + local class = GetConVar("gmod_npcweapon"):GetString() + + net.Start("arccw_npcgivereturn") + net.WriteString(class) + net.SendToServer() +end) \ No newline at end of file diff --git a/lua/arccw/client/cl_singleplayer.lua b/lua/arccw/client/cl_singleplayer.lua new file mode 100644 index 00000000..383279a2 --- /dev/null +++ b/lua/arccw/client/cl_singleplayer.lua @@ -0,0 +1,53 @@ +net.Receive("arccw_sp_anim", function(len, ply) + local key = net.ReadString() + local mult = net.ReadFloat() + local sf = net.ReadFloat() + + local wpn = LocalPlayer():GetActiveWeapon() + + if !wpn.ArcCW then return end + + wpn:PlayAnimation(key, mult, false, sf) +end) + +net.Receive("arccw_sp_lhikanim", function(len, ply) + local key = net.ReadString() + local time = net.ReadFloat() + + local wpn = LocalPlayer():GetActiveWeapon() + + if !wpn.ArcCW then return end + + wpn:DoLHIKAnimation(key, time) +end) + +net.Receive("arccw_sp_health", function(len, ply) + local ent = net.ReadEntity() + + if !IsValid(ent) then return end + + ent:SetHealth(0) + ent.ArcCWCLHealth = 0 +end) + +concommand.Add("arccw_listvmanims", function() + local wpn = LocalPlayer():GetActiveWeapon() + + if !wpn then return end + + local vm = LocalPlayer():GetViewModel() + + if !vm then return end + + PrintTable(vm:GetSequenceList()) +end) + +net.Receive("arccw_sp_loadautosave", function(len, ply) + local wpn = LocalPlayer():GetActiveWeapon() + + if !wpn then return end + if !IsValid(wpn) then return end + if !wpn.ArcCW then return end + + wpn:LoadPreset() +end) \ No newline at end of file diff --git a/lua/arccw/documentation/content.lua b/lua/arccw/documentation/content.lua new file mode 100644 index 00000000..ac88418f --- /dev/null +++ b/lua/arccw/documentation/content.lua @@ -0,0 +1,78 @@ +/* + +People Other Than Arctic: +Fleshy Mammal +TankNut +Fesiug +Code_GS +Zeaga +Rubat +TheOnly8Z +Dynamic + +Audio - CS:GO +Models - CS:S +Editing Program - Blender +General Model Decompiler/Compiler/Extractor - Crowbar +Texture Editor - Paint.NET w/ VTF plugin + +Double Barrel - 586 Studios +https://gamebanana.com/skins/72959 + +Barrett M82 - ??? +https://gamebanana.com/skins/72430 + +"Docter Sight" - tenoyl/Street-you +https://gamebanana.com/models/4337 + +Pistol Foregrip from M93 - Destiny +https://gamebanana.com/skins/112837 + +Compact laser for pistols - Krycek +https://gamebanana.com/models/3743 + +EOTech sight - TheLama/flamshmizer +https://gamebanana.com/models/2957 + +Micro T-1 sight - kouoaeha +https://gamebanana.com/models/3241 + +Trijicon reflex sight - dav0r +https://gamebanana.com/models/21 + +Kobra sight - TheLama +https://gamebanana.com/skins/111299 + +AFG - MirzaMiftahulFadilla h +https://gamebanana.com/models/download/3382 + +PVS-4 - Rectus +https://gamebanana.com/models/download/3749 + +MRS - Outlaws +https://gamebanana.com/skins/162976 + +AK Mount Redux - Pete3D, Steelbeast +https://gamebanana.com/models/797 + +Mk. 3 - mantuna +https://gamebanana.com/skins/143829 + +Raging Bull - Millennia +http://gamebanana.com/css/skins/16585 + +M60 - Twinke Masta +http://gamebanana.com/css/skins/16849 + +M14 - General Tso +https://gamebanana.com/skins/110796 + +OKP-7 - StreetYou +https://gamebanana.com/models/4134 + +Delta - eNse7en +https://gamebanana.com/models/4075 + +Green Laser - TenoYL +https://gamebanana.com/models/2833 +*/ \ No newline at end of file diff --git a/lua/arccw/server/sv_defaultclip.lua b/lua/arccw/server/sv_defaultclip.lua new file mode 100644 index 00000000..c6889a89 --- /dev/null +++ b/lua/arccw/server/sv_defaultclip.lua @@ -0,0 +1,11 @@ +hook.Add( "OnEntityCreated", "ArcCW_DefaultClip", function(ent) + if !ent.ArcCW then return end + + if ent.Primary.DefaultClip <= 0 then return end + + ent.Primary.DefaultClip = ent.Primary.ClipSize * 3 + + if ent.Primary.ClipSize >= 100 then + ent.Primary.DefaultClip = ent.Primary.ClipSize * 2 + end +end) \ No newline at end of file diff --git a/lua/arccw/server/sv_net.lua b/lua/arccw/server/sv_net.lua new file mode 100644 index 00000000..17899d59 --- /dev/null +++ b/lua/arccw/server/sv_net.lua @@ -0,0 +1,22 @@ +if game.SinglePlayer() then + +util.AddNetworkString("arccw_sp_lhikanim") +util.AddNetworkString("arccw_sp_anim") +util.AddNetworkString("arccw_sp_health") +util.AddNetworkString("arccw_sp_loadautosave") + +end + +util.AddNetworkString("arccw_sendattinv") +util.AddNetworkString("arccw_slidepos") +util.AddNetworkString("arccw_colorindex") +util.AddNetworkString("arccw_asktoattach") +util.AddNetworkString("arccw_asktodetach") +util.AddNetworkString("arccw_networkatts") +util.AddNetworkString("arccw_firemode") +util.AddNetworkString("arccw_quicknade") +util.AddNetworkString("arccw_togglecustomize") +util.AddNetworkString("arccw_ubgl") +util.AddNetworkString("arccw_npcgiverequest") +util.AddNetworkString("arccw_npcgivereturn") +util.AddNetworkString("arccw_rqwpnnet") \ No newline at end of file diff --git a/lua/arccw/server/sv_npc.lua b/lua/arccw/server/sv_npc.lua new file mode 100644 index 00000000..b6b763bd --- /dev/null +++ b/lua/arccw/server/sv_npc.lua @@ -0,0 +1,150 @@ +hook.Add("PlayerSpawnedNPC", "ArcCW_PlayerSpawnedNPC", function( ply, ent ) + net.Start("arccw_npcgiverequest") + net.Send(ply) + + ply.ArcCW_LastSpawnedNPC = ent +end) + +net.Receive("arccw_npcgivereturn", function(len, ply) + local class = net.ReadString() + local ent = ply.ArcCW_LastSpawnedNPC + + if !ent then return end + if !IsValid(ent) then return end + if !ent:IsNPC() then return end + if !class then return end + + local wpn = weapons.Get(class) + + local cap = ent:CapabilitiesGet() + + if bit.band(cap, CAP_USE_WEAPONS) != CAP_USE_WEAPONS then return end + + if weapons.IsBasedOn(class, "arccw_base") and wpn.Spawnable and !wpn.NotForNPCs and (!wpn.AdminOnly or ply:IsAdmin()) then + ent:Give(class) + end +end) + +function ArcCW:GetRandomWeapon(wpn) + local tbl = {} + local wgt = 0 + + for i, k in pairs(weapons.GetList()) do + if !weapons.IsBasedOn(k.ClassName, "arccw_base") then continue end + if k.PrimaryBash then continue end + if !k.Spawnable then continue end + if k.NotForNPCs then continue end + + if GetConVar("arccw_limityear_enable"):GetBool() then + local year = GetConVar("arccw_limityear"):GetInt() + + if k.Trivia_Year and isnumber(k.Trivia_Year) then + if k.Trivia_Year > year then continue end + end + end + + if k.NPCWeaponType then + if isstring(k.NPCWeaponType) then + if k.NPCWeaponType != wpn then continue end + elseif istable(k.NPCWeaponType) then + if !table.HasValue(k.NPCWeaponType, wpn) then continue end + end + else + local og = weapons.Get(wpn) + + if og and og.ArcCW then continue end + end + + wgt = wgt + (k.NPCWeight or 100) + + table.insert(tbl, {k.ClassName, wgt}) + end + + local r = math.random(0, wgt) + + for _, i in pairs(tbl) do + if i[2] >= r then + return i[1] + end + end +end + +hook.Add( "OnEntityCreated", "ArcCW_NPCWeaponReplacement", function(ent) + if CLIENT then return end + if !GetConVar("arccw_npc_replace"):GetBool() then return end + timer.Simple(0, function() + if !ent:IsValid() then return end + if !ent:IsNPC() then return end + local cap = ent:CapabilitiesGet() + + if bit.band(cap, CAP_USE_WEAPONS) != CAP_USE_WEAPONS then return end + + local class + + if IsValid(ent:GetActiveWeapon()) then + class = ent:GetActiveWeapon():GetClass() + end + + if !class then return end + + local wpn = ArcCW:GetRandomWeapon(class) + + if wpn then + ent:Give(wpn) + end + end) + timer.Simple(0, function() + if !ent:IsValid() then return end + if !ent:IsWeapon() then return end + if ent:GetOwner() then return end + + local class = ent:GetClass() + + local wpn = ArcCW:GetRandomWeapon(class) + + if wpn then + local wpnent = ents.Create(wpn) + wpnent:SetPos(ent:GetPos()) + wpnent:SetAngles(ent:GetAngles()) + + wpnent:NPC_Initialize() + + wpnent:Spawn() + + timer.Simple(0, function() + if !ent:IsValid() then return end + wpnent:OnDrop(true) + ent:Remove() + end) + end + end) +end) + +hook.Add("PlayerCanPickupWeapon", "ArcCW_PlayerCanPickupWeapon", function(ply, wep) + if !wep.ArcCW then return end + if !ply:HasWeapon(wep:GetClass()) then return end + + for _, i in pairs(wep.Attachments) do + if i.Installed then + ArcCW:PlayerGiveAtt(ply, i.Installed) + end + + i.Installed = nil + end + + ArcCW:PlayerSendAttInv(ply) + wep:NetworkWeapon() +end) + +hook.Add("onDarkRPWeaponDropped", "ArcCW_DarkRP", function(ply, spawned_weapon, wep) + if wep.ArcCW and wep.Attachments then + for i, k in pairs(wep.Attachments) do + if k.Installed then + ArcCW:PlayerGiveAtt(ply, k.Installed, 1) + -- Has to be sent to client or desync will happen + end + end + + ArcCW:PlayerSendAttInv(ply) + end +end) \ No newline at end of file diff --git a/lua/arccw/server/sv_singleplayer.lua b/lua/arccw/server/sv_singleplayer.lua new file mode 100644 index 00000000..b69069bd --- /dev/null +++ b/lua/arccw/server/sv_singleplayer.lua @@ -0,0 +1,14 @@ +if game.SinglePlayer() then + +hook.Add("EntityTakeDamage", "ArcCW_ETD", function(npc, dmg) + timer.Simple(0, function() + if !IsValid(npc) then return end + if npc:Health() <= 0 then + net.Start("arccw_sp_health") + net.WriteEntity(npc) + net.Broadcast() + end + end) +end) + +end \ No newline at end of file diff --git a/lua/arccw/server/sv_year.lua b/lua/arccw/server/sv_year.lua new file mode 100644 index 00000000..de39d4fd --- /dev/null +++ b/lua/arccw/server/sv_year.lua @@ -0,0 +1,14 @@ +hook.Add( "PlayerGiveSWEP", "ArcCW_YearLimiter", function( ply, class, swep ) + local wep = weapons.Get(class) + if !wep then return end + if !wep.ArcCW then return end + + if !GetConVar("arccw_limityear_enable"):GetBool() then return end + + local year = GetConVar("arccw_limityear"):GetInt() + + if !wep.Trivia_Year then return end + if !isnumber(wep.Trivia_Year) then return end + + if wep.Trivia_Year > year then return false end +end ) \ No newline at end of file diff --git a/lua/arccw/shared/attachments/default.lua b/lua/arccw/shared/attachments/default.lua new file mode 100644 index 00000000..849c5f86 --- /dev/null +++ b/lua/arccw/shared/attachments/default.lua @@ -0,0 +1,297 @@ +att.PrintName = "" +att.Icon = nil +att.Description = "" +att.Desc_Pros = {} +att.Desc_Cons = {} +att.Slot = "" +att.TargetSpecificWeapon = "" -- ALWAYS make this attachment available on a specific weapon +att.TargetSpecificSlot = 0 -- on this specific slot + +att.SortOrder = 0 + +att.Spawnable = false -- generate entity +att.AdminOnly = false -- see above +att.Ignore = true +att.InvAtt = nil -- use this other attachment in inventory +att.Free = false -- attachment is always available, and does not need to be picked up or unlocked +att.Hidden = false + +att.AddPrefix = "" +att.AddSuffix = "" + +att.GivesFlags = {} +att.RequireFlags = {} +att.ExcludeFlags = {} + +att.Model = "" +att.HideModel = false +att.ModelBodygroups = "" +att.ModelSkin = 0 +att.ModelScale = 1 +att.ModelOffset = Vector(0, 0, 0) +att.ModelIsShield = false + +att.Breakable = false +att.Health = 0 -- for shields +att.ShieldCorrectAng = Angle(0, 0, 0) +att.ShieldCorrectPos = Vector(0, 0, 0) + +-- amount of damage done to this attachment +-- attachments which are even a bit damaged are not returned +att.DamageOnShoot = 0 +att.DamageOnReload = 0 +att.DamagePerSecond = 0 + +-- {slot = int, oldhp = float, dmg = float} +att.Hook_AttTakeDamage = function(wep, data) end + +-- {slot = int, dmg = float} +att.Hook_AttDestroyed = function(wep, data) end + +att.VMColor = Color(255, 255, 255) +att.WMColor = Color(255, 255, 255) +att.VMMaterial = "" +att.WMMaterial = "" + +att.DroppedModel = nil +att.LHIKHide = false -- use this to just hide the left hand +att.LHIK = false -- use this model for left hand IK +att.LHIK_Animation = false + +att.ActivateElements = {} + +att.MountPositionOverride = nil -- set between 0 to 1 to always mount in a certain position + +att.AdditionalSights = { + { + Pos = Vector(0, 0, 0), -- relative to where att.Model is placed + Ang = Angle(0, 0, 0), + ScrollFunc = ArcCW.SCROLL_ZOOM, + ZoomLevels = 6, + ZoomSound = "weapons/arccw/fiveseven/fiveseven_slideback.wav", + NVScope = nil, -- enables night vision effects for scope + NVScopeColor = Color(0, 255, 100), + NVFullColor = false, -- night vision scope is true full color + Thermal = true, + ThermalScopeColor = Color(255, 255, 255), + ThermalHighlightColor = Color(255, 255, 255), + ThermalScopeSimple = false, + ThermalNoCC = false, + ThermalBHOT = false, -- invert bright/dark + IgnoreExtra = false -- ignore gun-determined extra sight distance + } +} + +att.UBGL = false -- is underbarrel grenade launcher + +att.UBGL_Automatic = false +att.UBGL_ClipSize = 1 +att.UBGL_Ammo = "smg1_grenade" +att.UBGL_RPM = 300 + +-- wep: weapon +-- ubgl: UBGL attachment slot. +att.UBGL_Fire = function(wep, ubgl) end +att.UBGL_Reload = function(wep, ubgl) end + +att.Silencer = false + +att.Bipod = false +att.Mult_BipodRecoil = 0.25 +att.Mult_BipodDispersion = 0.1 + +att.MagExtender = false +att.MagReducer = false +att.OverrideClipSize = nil +att.Add_ClipSize = 0 + +att.Laser = false +att.LaserStrength = 1 +att.LaserBone = "laser" + +att.Holosight = false +att.HolosightReticle = nil +att.HolosightFlare = nil +att.HolosightSize = nil +att.HolosightBone = "holosight" +att.HolosightPiece = nil -- the lens of the holo sight, if applicable +att.HolosightMagnification = 1 -- magnify the lens by this much +att.HolosightBlackbox = false +att.HolosightNoHSP = false -- for this holosight ignore HSP +att.HolosightConstDist = nil -- constant holosight distance, mainly for scopes with range finder + +att.Colorable = false -- automatically use the player's color option +att.HolosightColor = Color(255, 255, 255) + +att.Override_Firemodes = {} + +-- all hooks will work when applied to the SWEP table as well +-- e.g. SWEP.Hook_FireBullets + +-- use A_Hook_[Add_Whatever] to hook into additive hooks. +-- {buff = string buff, add = num add} +-- return table + +-- use O_Hook_[Override_Whatever] to hook into override hooks. +-- {buff = string buff, current = any override, winningslot = int slot} + +-- use M_Hook_[Mult_Whatever] to hook into multiply hooks. +-- {buff = string buff, mult = num mult} + +-- all hooks, mults, and adds will work on fire modes + +-- done before playing an effect +-- return false to prevent playing +-- fx: {fx = EffectData()} +att.Hook_PreDoEffects = function(wep, fx) end + +-- return true = compatible +-- return false = incompatible +-- data = {slot = string or table, att = string} +att.Hook_Compatible = function(wep, data) end + +-- hook that lets you change the values of the bullet before it's fired. +att.Hook_FireBullets = function(wep, bullettable) end + +-- called after all other primary attack functions. Do stuff here. +att.Hook_PostFireBullets = function(wep) end + +-- return true to prevent fire +att.Hook_ShouldNotFire = function(wep) end + +-- return anything to select this reload animation. Bear in mind that not all guns have the same animations, so check first. +att.Hook_SelectReloadAnimation = function(wep, curanim) end + +-- return anything to multiply reload time by that much +att.Hook_MultReload = function(wep, mult) end + +-- data has entries: +-- number count, how much ammo to add with this insert +-- string anim, which animation to play +-- bool empty, whether we are reloading from empty +att.Hook_SelectInsertAnimation = function(wep, data) end + +-- return to override fire animation +att.Hook_SelectFireAnimation = function(wep, curanim) end + +-- return string to change played anim +-- string anim, animation we are attempting to play +-- return false to block animation +-- return nil to do nothing +att.Hook_TranslateAnimation = function(wep, anim) end + +att.Hook_LHIK_TranslateAnimation = function(wep, anim) end + +-- att.Hook_TranslateAnimation = function(wep, anim) +-- if anim == "reload" then +-- return "reload_soh" +-- elseif anim == "reload_empty" then +-- return "reload_empty_soh" +-- end +-- end + +-- data has entries: +-- number range, the distance the bullet had to travel +-- number damage, the calculated damage the bullet will do +-- number penleft, the amount of penetration the bullet still possesses +-- enum dmgtype, the DMG_ enum of the damagetype +-- table tr, the trace result +-- entity att, the attacker (?) +-- DamageInfo dmg, the damage info + +-- changes to dmg may be overwritten later, so set damage and dmgtype instead +att.Hook_BulletHit = function(wep, data) end + +-- return to set mag capacity +att.Hook_GetCapacity = function(wep, cap) end + +-- return false to suppress shoot sound +-- string sound = default sound +att.Hook_GetShootSound = function(wep, sound) end +att.Hook_GetDistantShootSound = function(wep, sound) end + +-- allows you to modify the weapon's rate of fire +att.Hook_ModifyRPM = function(wep, delay) end + +-- run in Think() +att.Hook_Think = function(wep) end + +-- thinking hook for att +att.DrawFunc = function(wep, element, wm) end + +att.Mult_Damage = 1 +att.Mult_DamageMin = 1 +att.Mult_DamageNPC = 1 -- damage WHEN USED BY NPCS not when used against them +att.Mult_Range = 1 +att.Mult_Penetration = 1 +att.Override_DamageType = nil +att.Override_ShootEntity = nil +att.Mult_MuzzleVelocity = 1 + +att.Override_ShotgunSpreadPattern = {} +att.Override_ShotgunSpreadPatternOverrun = {} + +att.Mult_MeleeTime = 1 +att.Mult_MeleeDamage = 1 +att.Add_MeleeRange = 0 +att.Mult_MeleeAttackTime = 1 + +att.Override_Tracer = nil -- tracer effect name +att.Override_TracerNum = nil +-- att.Override_TracerCol = nil +-- att.Mult_TracerWidth = 1 + +att.Override_ShotgunReload = nil +att.Override_HybridReload = nil + +att.Override_ManualAction = nil + +att.Override_CanFireUnderwater = nil + +att.Override_ChamberSize = nil + +att.Mult_Recoil = 1 +att.Mult_RecoilSide = 1 +att.Mult_VisualRecoilMult = 1 + +att.Override_ShootWhileSprint = nil + +att.Mult_RPM = 1 + +att.Override_Num = nil + +att.Mult_AccuracyMOA = 1 +att.Mult_HipDispersion = 1 +att.Mult_SightsDispersion = 1 + +att.Mult_ShootVol = 1 +att.Mult_ShootPitch = 1 + +att.Override_MuzzleEffect = nil + +att.Override_ShellMaterial = nil + +att.Override_MuzzleEffectAttachment = nil +att.Override_CaseEffectAttachment = nil + +att.Mult_SpeedMult = 1 +att.Mult_SightedSpeedMult = 1 + +att.Override_HoldtypeHolstered = nil +att.Override_HoldtypeActive = nil +att.Override_HoldtypeSights = nil + +att.Override_AnimShoot = nil + +att.Override_HolsterPos = nil +att.Override_HolsterAng = nil + +att.Add_BarrelLength = 0 + +att.Override_BarrelOffsetSighted = nil +att.Override_BarrelOffsetHip = nil + +att.Mult_ReloadTime = 1 +att.Mult_DrawTime = 1 +att.Mult_SightTime = 1 +att.Mult_CycleTime = 1 \ No newline at end of file diff --git a/lua/arccw/shared/sh_acwcommon.lua b/lua/arccw/shared/sh_acwcommon.lua new file mode 100644 index 00000000..3a8f99c6 --- /dev/null +++ b/lua/arccw/shared/sh_acwcommon.lua @@ -0,0 +1,107 @@ +ArcCW.HUToM = 1 / 12 * 0.3048 +ArcCW.MOAToAcc = 10 / 180 / 60 + +ArcCW.EnableCustomization = true + +ArcCW.STATE_IDLE = 0 +ArcCW.STATE_SIGHTS = 1 +ArcCW.STATE_SPRINT = 2 +ArcCW.STATE_DISABLE = 3 +ArcCW.STATE_CUSTOMIZE = 4 +ArcCW.STATE_BIPOD = 5 + +ArcCW.SCROLL_NONE = 0 +ArcCW.SCROLL_ZOOM = 1 + +ArcCW.ShellSoundsTable = { + "player/pl_shell1.wav", + "player/pl_shell2.wav", + "player/pl_shell3.wav" +} + +ArcCW.ShotgunShellSoundsTable = { + "weapons/fx/tink/shotgun_shell1.wav", + "weapons/fx/tink/shotgun_shell2.wav", + "weapons/fx/tink/shotgun_shell3.wav" +} + +ArcCW.ReloadTimeTable = { + [ACT_HL2MP_GESTURE_RELOAD_AR2] = 2, + [ACT_HL2MP_GESTURE_RELOAD_SMG1] = 2, + [ACT_HL2MP_GESTURE_RELOAD_PISTOL] = 1.5, + [ACT_HL2MP_GESTURE_RELOAD_REVOLVER] = 2.5, + [ACT_HL2MP_GESTURE_RELOAD_SHOTGUN] = 2.5, + [ACT_HL2MP_GESTURE_RELOAD_DUEL] = 3.25, +} + +ArcCW.ReplaceWeapons = { + ["weapon_pistol"] = true, + ["weapon_smg1"] = true, + ["weapon_ar2"] = true, + ["weapon_shotgun"] = true, + ["weapon_357"] = true, + ["weapon_alyxgun"] = true, + ["weapon_crossbow"] = true, + ["weapon_rpg"] = true, + ["weapon_annabelle"] = true, +} + +ArcCW.PenTable = { + [MAT_ANTLION] = 1, + [MAT_BLOODYFLESH] = 1, + [MAT_CONCRETE] = 1, + [MAT_DIRT] = 0.75, + [MAT_EGGSHELL] = 1, + [MAT_FLESH] = 0.25, + [MAT_GRATE] = 1, + [MAT_ALIENFLESH] = 0.25, + [MAT_CLIP] = 1000, + [MAT_SNOW] = 0.75, + [MAT_PLASTIC] = 2, + [MAT_METAL] = 5, + [MAT_SAND] = 1, + [MAT_FOLIAGE] = 0.5, + [MAT_COMPUTER] = 0.75, + [MAT_SLOSH] = 1, + [MAT_TILE] = 1, + [MAT_GRASS] = 1, + [MAT_VENT] = 1, + [MAT_WOOD] = 0.75, + [MAT_DEFAULT] = 1, + [MAT_GLASS] = 0.2, + [MAT_WARPSHIELD] = 5 +} + +ArcCW.Colors = { + POS = Color(25, 225, 25), + MINIPOS = Color(75, 225, 75), + NEU = Color(225, 225, 225), + MININEG = Color(225, 75, 75), + NEG = Color(225, 25, 25), + COSM = Color(100, 100, 225) +} + +ArcCW.LHIKBones = { + "ValveBiped.Bip01_L_UpperArm", + "ValveBiped.Bip01_L_Forearm", + "ValveBiped.Bip01_L_Hand", + "ValveBiped.Bip01_L_Finger4", + "ValveBiped.Bip01_L_Finger41", + "ValveBiped.Bip01_L_Finger42", + "ValveBiped.Bip01_L_Finger3", + "ValveBiped.Bip01_L_Finger31", + "ValveBiped.Bip01_L_Finger32", + "ValveBiped.Bip01_L_Finger2", + "ValveBiped.Bip01_L_Finger21", + "ValveBiped.Bip01_L_Finger22", + "ValveBiped.Bip01_L_Finger1", + "ValveBiped.Bip01_L_Finger11", + "ValveBiped.Bip01_L_Finger12", + "ValveBiped.Bip01_L_Finger0", + "ValveBiped.Bip01_L_Finger01", + "ValveBiped.Bip01_L_Finger02", +} + +ArcCW.NoDraw = true + +ArcCW.PresetPath = "arccw_presets/" \ No newline at end of file diff --git a/lua/arccw/shared/sh_attachments.lua b/lua/arccw/shared/sh_attachments.lua new file mode 100644 index 00000000..7efd1693 --- /dev/null +++ b/lua/arccw/shared/sh_attachments.lua @@ -0,0 +1,282 @@ +function ArcCW:GetAttsForSlot(slot, wep) + local ret = {} + + for id, _ in pairs(ArcCW.AttachmentTable) do + + if !ArcCW:SlotAcceptsAtt(slot, wep, id) then continue end + + table.insert(ret, id) + end + + return ret +end + +function ArcCW:SlotAcceptsAtt(slot, wep, att) + local slots = {} + + if isstring(slot) then + slots[slot] = true + elseif istable(slot) then + for _, i in pairs(slot) do + slots[i] = true + end + end + + local atttbl = ArcCW.AttachmentTable[att] + + if atttbl.Hidden then return false end + + if atttbl.NotForNPC and wep.Owner:IsNPC() then + return false + end + + if wep.RejectAttachments and wep.RejectAttachments[att] then return false end + + if wep and atttbl.Hook_Compatible then + local compat = atttbl.Hook_Compatible(wep, {slot = slot, att = att}) + if compat == true then + return true + elseif compat == false then + return false + end + end + + if isstring(atttbl.Slot) then + if !slots[atttbl.Slot] then return false end + elseif istable(atttbl.Slot) then + local yeah = false + + for _, i in pairs(atttbl.Slot) do + if slots[i] then + yeah = true + break + end + end + + if !yeah then + return false + end + end + + return true +end + +function ArcCW:PlayerGetAtts(ply, att) + if GetConVar("arccw_attinv_free"):GetBool() then return 999 end + + if att == "" then return 999 end + + local atttbl = ArcCW.AttachmentTable[att] + + if atttbl.Free then return 999 end + + if !IsValid(ply) then return 0 end + + if !ply:IsAdmin() then + if atttbl.AdminOnly then + return 0 + end + end + + if atttbl.InvAtt then att = atttbl.InvAtt end + + if !ply.ArcCW_AttInv then return 0 end + + if !ply.ArcCW_AttInv[att] then return 0 end + + return ply.ArcCW_AttInv[att] +end + +function ArcCW:PlayerGiveAtt(ply, att, amt) + amt = amt or 1 + + if !IsValid(ply) then return end + + if !ply.ArcCW_AttInv then + ply.ArcCW_AttInv = {} + end + + local atttbl = ArcCW.AttachmentTable[att] + + if atttbl.InvAtt then att = atttbl.InvAtt end + + if GetConVar("arccw_attinv_lockmode"):GetBool() then + if ply.ArcCW_AttInv[att] == 1 then return end + ply.ArcCW_AttInv[att] = 1 + else + ply.ArcCW_AttInv[att] = (ply.ArcCW_AttInv[att] or 0) + amt + end +end + +function ArcCW:PlayerTakeAtt(ply, att, amt) + amt = amt or 1 + + if GetConVar("arccw_attinv_lockmode"):GetBool() then return end + + if !IsValid(ply) then return end + + if !ply.ArcCW_AttInv then + ply.ArcCW_AttInv = {} + end + + local atttbl = ArcCW.AttachmentTable[att] + + if atttbl.InvAtt then att = atttbl.InvAtt end + + ply.ArcCW_AttInv[att] = ply.ArcCW_AttInv[att] or 0 + + if ply.ArcCW_AttInv[att] <= 0 then + return + end + + ply.ArcCW_AttInv[att] = (ply.ArcCW_AttInv[att] or 0) - amt + + if ply.ArcCW_AttInv[att] < 0 then + ply.ArcCW_AttInv[att] = 0 + end +end + +if CLIENT then + +local function postsetup(wpn) + if wpn.SetupModel then + wpn:SetupModel(true) + if wpn:GetOwner() == LocalPlayer() then + wpn:SetupModel(false) + end + else + timer.Simple(0.1, function() + postsetup(wpn) + end) + end +end + +net.Receive("arccw_networkatts", function(len, ply) + local wpn = net.ReadEntity() + + if !IsValid(wpn) then return end + + local attnum = net.ReadUInt(8) + + wpn.Attachments = wpn.Attachments or {} + + for i = 1, attnum do + local attid = net.ReadUInt(ArcCW.GetBitNecessity()) + + wpn.Attachments[i] = wpn.Attachments[i] or {} + + if attid == 0 then + wpn.Attachments[i].Installed = false + continue + end + + local att = ArcCW.AttachmentIDTable[attid] + + wpn.Attachments[i].Installed = att + + if wpn.Attachments[i].SlideAmount then + wpn.Attachments[i].SlidePos = net.ReadFloat() + end + end + + wpn.CertainAboutAtts = true + + postsetup(wpn) +end) + +net.Receive("arccw_sendattinv", function(len, ply) + LocalPlayer().ArcCW_AttInv = {} + + local count = net.ReadUInt(32) + + for i = 1, count do + local attid = net.ReadUInt(ArcCW.GetBitNecessity()) + local acount = net.ReadUInt(32) + + local att = ArcCW.AttachmentIDTable[attid] + + LocalPlayer().ArcCW_AttInv[att] = acount + end +end) + +elseif SERVER then + +hook.Add("PlayerSpawn", "ArcCW_SpawnAttInv", function(ply, trans) + if trans then return end + + if GetConVar("arccw_attinv_loseondie"):GetBool() then + ply.ArcCW_AttInv = {} + + ArcCW:PlayerSendAttInv(ply) + end +end) + +net.Receive("arccw_rqwpnnet", function(len, ply) + local wpn = net.ReadEntity() + + if !wpn.ArcCW then return end + + wpn:NetworkWeapon(ply) +end) + +net.Receive("arccw_slidepos", function(len, ply) + local wpn = ply:GetActiveWeapon() + + local slot = net.ReadUInt(8) + local pos = net.ReadFloat() + + if !wpn.ArcCW then return end + + if !wpn.Attachments[slot] then return end + + wpn.Attachments[slot].SlidePos = pos +end) + +net.Receive("arccw_asktoattach", function(len, ply) + local wpn = ply:GetActiveWeapon() + + local slot = net.ReadUInt(8) + local attid = net.ReadUInt(24) + + local att = ArcCW.AttachmentIDTable[attid] + + if !wpn.ArcCW then return end + if !wpn.Attachments[slot] then return end + if !att then return end + + wpn:Attach(slot, att) +end) + +net.Receive("arccw_asktodetach", function(len, ply) + local wpn = ply:GetActiveWeapon() + + local slot = net.ReadUInt(8) + + if !wpn.ArcCW then return end + if !wpn.Attachments[slot] then return end + + wpn:Detach(slot) +end) + +function ArcCW:PlayerSendAttInv(ply) + if GetConVar("arccw_attinv_free"):GetBool() then return end + + if !IsValid(ply) then return end + + if !ply.ArcCW_AttInv then return end + + net.Start("arccw_sendattinv") + + net.WriteUInt(table.Count(ply.ArcCW_AttInv), 32) + + for att, count in pairs(ply.ArcCW_AttInv) do + local atttbl = ArcCW.AttachmentTable[att] + local attid = atttbl.ID + net.WriteUInt(attid, ArcCW.GetBitNecessity()) + net.WriteUInt(count, 32) + end + + net.Send(ply) +end + +end \ No newline at end of file diff --git a/lua/arccw/shared/sh_controls.lua b/lua/arccw/shared/sh_controls.lua new file mode 100644 index 00000000..8df9bd1e --- /dev/null +++ b/lua/arccw/shared/sh_controls.lua @@ -0,0 +1,29 @@ +net.Receive("arccw_firemode", function(len, ply) + local wpn = ply:GetActiveWeapon() + + if !wpn.ArcCW then return end + + wpn:ChangeFiremode() +end) + +net.Receive("arccw_ubgl", function(len, ply) + local on = net.ReadBool() + local wpn = ply:GetActiveWeapon() + + if !wpn.ArcCW then return end + + if on then + wpn:SelectUBGL() + else + wpn:DeselectUBGL() + end +end) + +net.Receive("arccw_togglecustomize", function(len, ply) + local wpn = ply:GetActiveWeapon() + local onoff = net.ReadBool() + + if !wpn.ArcCW then return end + + wpn:ToggleCustomizeHUD(onoff) +end) \ No newline at end of file diff --git a/lua/arccw/shared/sh_convars.lua b/lua/arccw/shared/sh_convars.lua new file mode 100644 index 00000000..b27b795b --- /dev/null +++ b/lua/arccw/shared/sh_convars.lua @@ -0,0 +1,42 @@ +CreateConVar("arccw_enable_penetration", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "") +CreateConVar("arccw_enable_customization", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "") + +CreateConVar("arccw_attinv_lockmode", 0, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Once owned, players can use attachments as much as they like.") +CreateConVar("arccw_attinv_free", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "All attachments can always be used.") +CreateConVar("arccw_attinv_loseondie", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "All attachments reset on death.") + +CreateConVar("arccw_atts_pickx", 0, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Limit weapons to this many maximum attachments. 0 = disable system.", 0) + +CreateConVar("arccw_npc_replace", 0, FCVAR_ARCHIVE, "Replace NPC weapons with ArcCW weapons.") +CreateConVar("arccw_npc_atts", 1, FCVAR_ARCHIVE, "Randomly give NPC weapons attachments.") + +CreateConVar("arccw_truenames", 0, FCVAR_ARCHIVE, "Use true names instead of fake names, where applicable. Requires restart.") + +CreateConVar("arccw_equipmenttime", 180, FCVAR_ARCHIVE, "How long equipment such as Claymores will remain on the map before self-destructing.") + +CreateConVar("arccw_mult_damage", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for damage done by all ArcCW weapons.") +CreateConVar("arccw_mult_npcdamage", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for damage done by all ArcCW weapons used by NPCs.") +CreateConVar("arccw_mult_hipfire", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for hip fire spread for ArcCW.") +CreateConVar("arccw_mult_reloadtime", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for how long ArcCW weapons take to reload.", 0.01) +CreateConVar("arccw_mult_sighttime", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for how long ArcCW weapons take to enter sights.", 0.1) +CreateConVar("arccw_mult_range", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for range of all ArcCW weapons.") +CreateConVar("arccw_mult_recoil", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for recoil of all ArcCW weapons.") +CreateConVar("arccw_mult_movedisp", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for moving inaccuracy of ArcCW weapons.") +CreateConVar("arccw_mult_penetration", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for ArcCW penetration amount.") + +CreateConVar("arccw_reloadonrefresh", 1, FCVAR_ARCHIVE, "Whether to reload ArcCW attachments on admin clean up.") + +CreateConVar("arccw_override_crosshair_off", 0, FCVAR_ARCHIVE + FCVAR_REPLICATED, "") + +CreateConVar("arccw_ammo_detonationmode", 2, FCVAR_ARCHIVE + FCVAR_REPLICATED, "The type of ammo detonation to use. -1 = don't explode, 0 = simple explosion, 1 = fragmentation, 2 = full", -1, 2) +CreateConVar("arccw_ammo_autopickup", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Whether to pick up ammo when walking over in addition to pressing Use.", 0, 1) +CreateConVar("arccw_ammo_largetrigger", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Whether to use larger trigger boxes for ammo, similar to HL2. Only useful when autopickup is true.", 0, 1) +CreateConVar("arccw_ammo_rareskin", 0.08, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Chance for a rare skin to appear. Only specific models have these.", 0, 1) +CreateConVar("arccw_ammo_chaindet", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Whether to allow ammoboxes to detonate each other. If disabled, they will still be destroyed but not explode.", 0, 1) + + +CreateConVar("arccw_mult_ammohealth", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for how much health ammo boxes have. Set to -1 for indestructible boxes.", -1) +CreateConVar("arccw_mult_ammoamount", 1, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Multiplier for how much ammo are in ammo boxes.", 0) + +CreateConVar("arccw_limityear_enable", 0, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Limit the maximum year for weapons.") +CreateConVar("arccw_limityear", 0, FCVAR_ARCHIVE + FCVAR_REPLICATED, "Limit the maximum year for weapons.") \ No newline at end of file diff --git a/lua/arccw/shared/sh_effects.lua b/lua/arccw/shared/sh_effects.lua new file mode 100644 index 00000000..a0a38fbb --- /dev/null +++ b/lua/arccw/shared/sh_effects.lua @@ -0,0 +1,20 @@ +game.AddParticles( "particles/muzzleflashes_test.pcf" ) +game.AddParticles( "particles/muzzleflashes_test_b.pcf" ) +PrecacheParticleSystem( "muzzleflash_smg" ) +PrecacheParticleSystem( "muzzleflash_shotgun" ) +PrecacheParticleSystem( "muzzleflash_slug" ) +PrecacheParticleSystem( "muzzleflash_pistol" ) +PrecacheParticleSystem( "muzzleflash_pistol_deagle" ) +PrecacheParticleSystem( "muzzleflash_suppressed" ) +PrecacheParticleSystem( "muzzleflash_mp5" ) +PrecacheParticleSystem( "muzzleflash_MINIMI" ) +PrecacheParticleSystem( "muzzleflash_m79" ) +PrecacheParticleSystem( "muzzleflash_m14" ) +PrecacheParticleSystem( "muzzleflash_ak74" ) +PrecacheParticleSystem( "muzzleflash_m82" ) +PrecacheParticleSystem( "muzzleflash_m3" ) +PrecacheParticleSystem( "muzzleflash_1" ) +PrecacheParticleSystem( "muzzleflash_3" ) +PrecacheParticleSystem( "muzzleflash_4" ) +PrecacheParticleSystem( "muzzleflash_5" ) +PrecacheParticleSystem( "muzzleflash_6" ) diff --git a/lua/arccw/shared/sh_loadatts.lua b/lua/arccw/shared/sh_loadatts.lua new file mode 100644 index 00000000..5118f301 --- /dev/null +++ b/lua/arccw/shared/sh_loadatts.lua @@ -0,0 +1,96 @@ +ArcCW = ArcCW or {} +ArcCW.AttachmentTable = {} +ArcCW.AttachmentIDTable = {} +ArcCW.AttachmentSlotTable = {} +ArcCW.NumAttachments = 1 + +ArcCW.GenerateAttEntities = true + +shortname = "" + +function ArcCW.LoadAttachmentType(att) + if !att.Ignore then + ArcCW.AttachmentTable[shortname] = att + ArcCW.AttachmentIDTable[ArcCW.NumAttachments] = shortname + + att.ShortName = shortname + + if !ArcCW.AttachmentSlotTable[att.Slot] then + ArcCW.AttachmentSlotTable[att.Slot] = {} + end + table.insert(ArcCW.AttachmentSlotTable[att.Slot], ArcCW.NumAttachments) + + att.ID = ArcCW.NumAttachments + + if ArcCW.GenerateAttEntities then + if !att.DoNotRegister and !att.InvAtt and !att.Free and !att.Ignore then + local attent = {} + attent.Base = "arccw_att_base" + attent.Icon = att.Icon + attent.PrintName = att.PrintName or shortname + attent.Spawnable = att.Spawnable or true + attent.AdminOnly = att.AdminOnly or false + attent.Category = "ArcCW - Attachments" + attent.Model = att.DroppedModel or att.Model or "models/Items/BoxSRounds.mdl" + attent.GiveAttachments = { + [att.ShortName] = 1 + } + + for i, k in pairs(att) do + attent[i] = k + end + + scripted_ents.Register( attent, "acwatt_" .. shortname ) + end + end + + ArcCW.NumAttachments = ArcCW.NumAttachments + 1 + end +end + +local function ArcCW_LoadAtts() + ArcCW.AttachmentTable = {} + ArcCW.AttachmentIDTable = {} + ArcCW.AttachmentSlotTable = {} + ArcCW.NumAttachments = 1 + + for k, v in pairs(file.Find("arccw/shared/attachments/*", "LUA")) do + att = {} + shortname = string.sub(v, 1, -5) + + include("arccw/shared/attachments/" .. v) + AddCSLuaFile("arccw/shared/attachments/" .. v) + + ArcCW.LoadAttachmentType(att) + end + + print("Loaded " .. tostring(ArcCW.NumAttachments) .. " ArcCW attachments.") +end + +function ArcCW.GetBitNecessity() + local bits = 1 + + bits = math.ceil(math.sqrt(ArcCW.NumAttachments)) + + return bits +end + +ArcCW_LoadAtts() + +if CLIENT then + spawnmenu.AddCreationTab( "#spawnmenu.category.entities", function() + + local ctrl = vgui.Create( "SpawnmenuContentPanel" ) + ctrl:EnableSearch( "entities", "PopulateEntities" ) + ctrl:CallPopulateHook( "PopulateEntities" ) + + return ctrl + + end, "icon16/bricks.png", 20 ) +end + +hook.Add("PostCleanupMap", "ArcCW_ReloadAttsDebug", function() + if !GetConVar("arccw_reloadonrefresh"):GetBool() then return end + + ArcCW_LoadAtts() +end) \ No newline at end of file diff --git a/lua/arccw/shared/sh_move.lua b/lua/arccw/shared/sh_move.lua new file mode 100644 index 00000000..4e19bc6d --- /dev/null +++ b/lua/arccw/shared/sh_move.lua @@ -0,0 +1,26 @@ + +function ArcCW.Move(ply, mv, cmd) + local wpn = ply:GetActiveWeapon() + + if !wpn.ArcCW then return end + + local s = 1 + + -- look, basically I made a bit of an oopsy and uh this is the best way to fix that + s = s * math.Clamp(wpn.SpeedMult * wpn:GetBuff_Mult("Mult_SpeedMult") * wpn:GetBuff_Mult("Mult_MoveSpeed"), 0, 1) + + local basespd = (Vector(cmd:GetForwardMove(), cmd:GetUpMove(), cmd:GetSideMove())):Length() + basespd = math.min(basespd, mv:GetMaxClientSpeed()) + + if wpn:GetState() == ArcCW.STATE_SIGHTS or + wpn:GetState() == ArcCW.STATE_CUSTOMIZE then + basespd = math.min(basespd, ply:GetWalkSpeed()) + s = s * math.Clamp(wpn.SightedSpeedMult * wpn:GetBuff_Mult("Mult_SightedSpeedMult") * wpn:GetBuff_Mult("Mult_SightedMoveSpeed"), 0, 1) + end + + mv:SetMaxSpeed(basespd * s) + mv:SetMaxClientSpeed(basespd * s) + +end + +hook.Add("SetupMove", "ArcCW_SetupMove", ArcCW.Move) \ No newline at end of file diff --git a/lua/arccw/shared/sh_physbullet2.lua b/lua/arccw/shared/sh_physbullet2.lua new file mode 100644 index 00000000..de2beb2b --- /dev/null +++ b/lua/arccw/shared/sh_physbullet2.lua @@ -0,0 +1 @@ +ArcCW.PhysBullets = {} diff --git a/lua/arccw/shared/sh_quicknade.lua b/lua/arccw/shared/sh_quicknade.lua new file mode 100644 index 00000000..6fc5d5fe --- /dev/null +++ b/lua/arccw/shared/sh_quicknade.lua @@ -0,0 +1,19 @@ +-- ArcCW.QuickNadeTable = { +-- ["frag"] = { +-- ShortName = "FRAG", +-- ThrowEntity = "arccw_proj_frag", +-- ViewModel = "models/weapons/cstrike/c_eq_fraggrenade.mdl" +-- } +-- } + +-- if CLIENT then + +-- function ArcCW:QuickNade(index) +-- if !ArcCW.QuickNadeTable[index] then return end + +-- local wpn = LocalPlayer():GetActiveWeapon() + +-- if !wpn.ArcCW then return end +-- end + +-- end \ No newline at end of file diff --git a/lua/arccw/shared/sh_truenames.lua b/lua/arccw/shared/sh_truenames.lua new file mode 100644 index 00000000..e814bc9a --- /dev/null +++ b/lua/arccw/shared/sh_truenames.lua @@ -0,0 +1,11 @@ +hook.Add("CreateTeams", "ArcCW_TrueNames", function() + if !GetConVar("arccw_truenames"):GetBool() then return end + + for _, i in pairs(weapons.GetList()) do + local wpn = weapons.GetStored(i.ClassName) + + if wpn.TrueName then + wpn.PrintName = wpn.TrueName + end + end +end) \ No newline at end of file diff --git a/lua/autorun/arccw_autorun.lua b/lua/autorun/arccw_autorun.lua new file mode 100644 index 00000000..18af7c0e --- /dev/null +++ b/lua/autorun/arccw_autorun.lua @@ -0,0 +1,46 @@ +AddCSLuaFile() + +-- the main object +ArcCW = {} + +ArcCWInstalled = true + +ArcCW.GenerateAttEntities = true + +for _, v in pairs(file.Find("arccw/shared/*", "LUA")) do + include("arccw/shared/" .. v) + AddCSLuaFile("arccw/shared/" .. v) +end + +for _, v in pairs(file.Find("arccw/client/*", "LUA")) do + AddCSLuaFile("arccw/client/" .. v) + if CLIENT then + include("arccw/client/" .. v) + end +end + +if SERVER or game.SinglePlayer() then + for _, v in pairs(file.Find("arccw/server/*", "LUA")) do + include("arccw/server/" .. v) + end +end + +-- if you want to override arccw functions, put your override files in the arccw/mods directory so it will be guaranteed to override the base + +for _, v in pairs(file.Find("arccw/mods/shared/*", "LUA")) do + include("arccw/mods/shared/" .. v) + AddCSLuaFile("arccw/mods/shared/" .. v) +end + +for _, v in pairs(file.Find("arccw/mods/client/*", "LUA")) do + AddCSLuaFile("arccw/mods/client/" .. v) + if CLIENT then + include("arccw/mods/client/" .. v) + end +end + +if SERVER or game.SinglePlayer() then + for _, v in pairs(file.Find("arccw/mods/server/*", "LUA")) do + include("arccw/mods/server/" .. v) + end +end \ No newline at end of file diff --git a/lua/effects/arccw_flashexplosion.lua b/lua/effects/arccw_flashexplosion.lua new file mode 100644 index 00000000..91526f27 --- /dev/null +++ b/lua/effects/arccw_flashexplosion.lua @@ -0,0 +1,77 @@ +local images_smoke = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"} + +local function TableRandomChoice(tbl) + return tbl[math.random(#tbl)] +end + +function EFFECT:Init(data) + self.Origin = data:GetOrigin() + + util.Decal("FadingScorch", self.Origin, self.Origin - Vector(0, 0, 16)) + + local emitter = ParticleEmitter( self.Origin + Vector( 0, 0, 16 ) ) + + for i = 0,5 do + local particle = emitter:Add( TableRandomChoice(images_smoke) , self.Origin ) + local scol = math.Rand( 200, 225 ) + + particle:SetVelocity( 250 * VectorRand() ) + particle:SetDieTime( math.Rand(1.5, 5) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.Rand(100,200) ) + particle:SetEndSize( math.Rand(300,400) ) + particle:SetRoll( math.Rand(0,360) ) + particle:SetRollDelta( math.Rand(-1,1) ) + particle:SetColor( scol,scol,scol ) + particle:SetAirResistance( 100 ) + particle:SetGravity( Vector( math.Rand(-30,30) ,math.Rand(-30,30),math.Rand(10,40)) ) + particle:SetLighting( true ) + particle:SetCollide( true ) + particle:SetBounce( 0.5 ) + end + + local particle = emitter:Add( "sprites/heatwave", self.Origin ) + particle:SetAirResistance( 0 ) + particle:SetDieTime( 1.5 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 255 ) + particle:SetStartSize( 250 ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.Rand(180,480) ) + particle:SetRollDelta( math.Rand(-5,5) ) + particle:SetColor( 255, 255, 255 ) + + local fire = emitter:Add( "particle/fire", self.Origin ) + fire:SetAirResistance( 0 ) + fire:SetDieTime( 0.1 ) + fire:SetStartAlpha( 255 ) + fire:SetEndAlpha( 0 ) + fire:SetEndSize( 0 ) + fire:SetStartSize( 800 ) + fire:SetRoll( math.Rand(180,480) ) + fire:SetRollDelta( math.Rand(-1,1) ) + fire:SetColor( 255, 255, 255 ) + + local light = DynamicLight(self:EntIndex()) + if (light) then + light.Pos = self.Origin + light.r = 255 + light.g = 255 + light.b = 255 + light.Brightness = 9 + light.Decay = 2500 + light.Size = 512 + light.DieTime = CurTime() + 0.1 + end + + emitter:Finish() + +end + +function EFFECT:Think() + return false +end + +function EFFECT:Render() +end \ No newline at end of file diff --git a/lua/effects/arccw_incendiaryround.lua b/lua/effects/arccw_incendiaryround.lua new file mode 100644 index 00000000..9bd47f4c --- /dev/null +++ b/lua/effects/arccw_incendiaryround.lua @@ -0,0 +1,79 @@ +local images_muzzle = {"effects/muzzleflash1", "effects/muzzleflash2", "effects/muzzleflash3", "effects/muzzleflash4"} +local images_smoke = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"} + +local function TableRandomChoice(tbl) + return tbl[math.random(#tbl)] +end + +function EFFECT:Init(data) + self.Origin = data:GetOrigin() + + local emitter = ParticleEmitter( self.Origin + Vector( 0, 0, 16 ) ) + + for i = 0,3 do + local particle = emitter:Add( TableRandomChoice(images_smoke) , self.Origin ) + local scol = math.Rand( 200, 225 ) + + particle:SetVelocity( 50 * VectorRand() ) + particle:SetDieTime( math.Rand(0.2, 0.5) ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 0 ) + particle:SetStartSize( math.Rand(20,30) ) + particle:SetEndSize( math.Rand(50,75) ) + particle:SetRoll( math.Rand(0,360) ) + particle:SetRollDelta( math.Rand(-1,1) ) + particle:SetColor( scol,scol,scol ) + particle:SetAirResistance( 100 ) + particle:SetGravity( Vector( math.Rand(-30,30) ,math.Rand(-30,30),math.Rand(10,40)) ) + particle:SetLighting( true ) + particle:SetCollide( true ) + particle:SetBounce( 0.5 ) + end + + local particle = emitter:Add( "sprites/heatwave", self.Origin ) + particle:SetAirResistance( 0 ) + particle:SetDieTime( 0.5 ) + particle:SetStartAlpha( 255 ) + particle:SetEndAlpha( 255 ) + particle:SetStartSize( 100 ) + particle:SetEndSize( 0 ) + particle:SetRoll( math.Rand(180,480) ) + particle:SetRollDelta( math.Rand(-5,5) ) + particle:SetColor( 255, 255, 255 ) + + for i = 0, 2 do + local fire = emitter:Add( TableRandomChoice(images_muzzle), self.Origin ) + fire:SetVelocity(VectorRand() * 100) + fire:SetAirResistance( 0 ) + fire:SetDieTime( 0.25 ) + fire:SetStartAlpha( 255 ) + fire:SetEndAlpha( 0 ) + fire:SetEndSize( 0 ) + fire:SetStartSize( 50 ) + fire:SetRoll( math.Rand(180,480) ) + fire:SetRollDelta( math.Rand(-1,1) ) + fire:SetColor( 255, 255, 255 ) + end + + local light = DynamicLight(self:EntIndex()) + if (light) then + light.Pos = self.Origin + light.r = 255 + light.g = 206 + light.b = 122 + light.Brightness = 5 + light.Decay = 2500 + light.Size = 256 + light.DieTime = CurTime() + 0.1 + end + + emitter:Finish() + +end + +function EFFECT:Think() + return false +end + +function EFFECT:Render() +end \ No newline at end of file diff --git a/lua/effects/arccw_muzzleeffect.lua b/lua/effects/arccw_muzzleeffect.lua new file mode 100644 index 00000000..40050933 --- /dev/null +++ b/lua/effects/arccw_muzzleeffect.lua @@ -0,0 +1,57 @@ +function EFFECT:Init(data) + local pos = data:GetOrigin() + local wpn = data:GetEntity() + + if !IsValid(wpn) then return end + + local muzzle = wpn:GetBuff_Override("Override_MuzzleEffect") or wpn.MuzzleEffect + + if wpn:GetNWBool("ubgl", false) then + muzzle = wpn:GetBuff_Override("UBGL_MuzzleEffect") or muzzle + end + + local att = data:GetAttachment() or 1 + + if !muzzle then return end + + local wm = false + + if (LocalPlayer():ShouldDrawLocalPlayer() or wpn.Owner != LocalPlayer()) and !wpn.AlwaysWM then + wm = true + att = 1 + end + + if wpn.Owner != LocalPlayer() then + if !GetConVar("arccw_muzzleeffects"):GetBool() then return end + end + + local mdl = wpn:GetMuzzleDevice(wm) + + ParticleEffectAttach(muzzle, PATTACH_POINT_FOLLOW, mdl, att) + + pos = (mdl:GetAttachment(att) or {}).Pos + + if !pos then return end + + if !wpn:GetBuff_Override("Silencer") then + local light = DynamicLight(self:EntIndex()) + if (light) then + light.Pos = pos + light.r = 244 + light.g = 209 + light.b = 66 + light.Brightness = 2 + light.Decay = 2500 + light.Size = 256 + light.DieTime = CurTime() + 0.1 + end + end +end + +function EFFECT:Think() + return false +end + +function EFFECT:Render() + return false +end \ No newline at end of file diff --git a/lua/effects/arccw_shelleffect.lua b/lua/effects/arccw_shelleffect.lua new file mode 100644 index 00000000..e9e3ebd3 --- /dev/null +++ b/lua/effects/arccw_shelleffect.lua @@ -0,0 +1,141 @@ + +EFFECT.Sounds = {} +EFFECT.Pitch = 90 +EFFECT.Scale = 1.5 +EFFECT.PhysScale = 1 +EFFECT.Model = "models/shells/shell_57.mdl" +EFFECT.Material = nil +EFFECT.JustOnce = true +EFFECT.AlreadyPlayedSound = false +EFFECT.ShellTime = 1 + +EFFECT.SpawnTime = 0 + +function EFFECT:Init(data) + + local att = data:GetAttachment() + local ent = data:GetEntity() + local mag = data:GetMagnitude() + + local mdl = LocalPlayer():GetViewModel() + + if LocalPlayer():ShouldDrawLocalPlayer() then + mdl = ent + end + + if !IsValid(ent) then return end + + if ent.Owner != LocalPlayer() then + mdl = ent + end + + if ent.Owner != LocalPlayer() then + if !GetConVar("arccw_shelleffects"):GetBool() then self:Remove() return end + end + + if !mdl or !IsValid(mdl) then return end + + if !mdl:GetAttachment(att) then return end + + local origin, ang = mdl:GetAttachment(att).Pos, mdl:GetAttachment(att).Ang + + ang:RotateAroundAxis(ang:Right(), -90 + ent.ShellRotate) + + ang:RotateAroundAxis(ang:Right(), (ent.ShellRotateAngle or Angle(0, 0, 0))[1]) + ang:RotateAroundAxis(ang:Up(), (ent.ShellRotateAngle or Angle(0, 0, 0))[2]) + ang:RotateAroundAxis(ang:Forward(), (ent.ShellRotateAngle or Angle(0, 0, 0))[3]) + + local dir = ang:Up() + + if ent then + self.Model = ent.ShellModel + self.Material = ent.ShellMaterial + self.Scale = ent.ShellScale or 1 + self.PhysScale = ent.ShellPhysScale or 1 + self.Pitch = ent.ShellPitch or 100 + self.Sounds = ent.ShellSounds + self.ShellTime = ent.ShellTime + end + + self:SetPos(origin) + self:SetModel(self.Model) + self:SetModelScale(self.Scale) + self:DrawShadow(true) + self:SetAngles(ang) + + if self.Material then + self:SetMaterial(self.Material) + end + + local pb_vert = 2 * self.Scale * self.PhysScale + local pb_hor = 0.5 * self.Scale * self.PhysScale + + self:PhysicsInitBox(Vector(-pb_vert,-pb_hor,-pb_hor), Vector(pb_vert,pb_hor,pb_hor)) + + self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE_DEBRIS) + + local phys = self:GetPhysicsObject() + + local plyvel = Vector(0, 0, 0) + + if IsValid(ent.Owner) then + plyvel = ent.Owner:GetAbsVelocity() + end + + phys:Wake() + phys:SetDamping(0, 0) + phys:SetMass(1) + phys:SetMaterial("gmod_silent") + + phys:SetVelocity((dir * mag * math.Rand(1, 2)) + plyvel) + phys:AddAngleVelocity(VectorRand() * 400) + + self.HitPitch = self.Pitch + math.Rand(-5,5) + + local emitter = ParticleEmitter(origin) + + for i = 1, 3 do + local particle = emitter:Add("particles/smokey", origin + (dir * 2)) + + if (particle) then + particle:SetVelocity(VectorRand() * 10 + (dir * i * math.Rand(48, 64)) + plyvel) + particle:SetLifeTime(0) + particle:SetDieTime(math.Rand(0.05, 0.15)) + particle:SetStartAlpha(math.Rand(40, 60)) + particle:SetEndAlpha(0) + particle:SetStartSize(0) + particle:SetEndSize(math.Rand(18, 24)) + particle:SetRoll(math.rad(math.Rand(0, 360))) + particle:SetRollDelta(math.Rand(-1, 1)) + particle:SetLighting(true) + particle:SetAirResistance(96) + particle:SetGravity(Vector(-7, 3, 20)) + particle:SetColor(150, 150, 150) + end + end + + self.SpawnTime = CurTime() +end + +function EFFECT:PhysicsCollide() + if self.AlreadyPlayedSound and self.JustOnce then return end + + sound.Play(self.Sounds[math.random(#self.Sounds)], self:GetPos(), 65, self.HitPitch, 1) + + self.AlreadyPlayedSound = true +end + +function EFFECT:Think() + if (self.SpawnTime + self.ShellTime) <= CurTime() then + self:SetRenderFX( kRenderFxFadeFast ) + if (self.SpawnTime + self.ShellTime + 1) <= CurTime() then + return false + end + end + return true +end + +function EFFECT:Render() + if !IsValid(self) then return end + self:DrawModel() +end \ No newline at end of file diff --git a/lua/entities/arccw_ammo.lua b/lua/entities/arccw_ammo.lua new file mode 100644 index 00000000..b25ccfc6 --- /dev/null +++ b/lua/entities/arccw_ammo.lua @@ -0,0 +1,235 @@ +AddCSLuaFile() + +ENT.Type = "anim" +ENT.Base = "base_gmodentity" +ENT.RenderGroup = RENDERGROUP_TRANSLUCENT + +ENT.PrintName = "Base Ammo" +ENT.Category = "ArcCW - Ammo" +ENT.ArcCW_Ammo = true + +ENT.Spawnable = false +ENT.Model = "models/items/sniper_round_box.mdl" +ENT.MaxHealth = 40 +ENT.Scale = 1 + +ENT.AmmoType = "SniperPenetratedRound" +ENT.AmmoCount = 5 +ENT.DetonationDamage = 10 -- Per-round damage +ENT.DetonationRadius = 256 +ENT.DetonationSound = "weapons/arccw/glock18/glock18-1.wav" -- string or table + +ENT.ShellModel = "models/shells/shell_9mm.mdl" +ENT.ShellScale = 1.5 + +ENT.ResistanceMult = { + [DMG_BURN] = 5, + [DMG_BLAST] = 2, + [DMG_BULLET] = 0.5, + [DMG_BUCKSHOT] = 0.5, + [DMG_CLUB] = 0.25, + [DMG_SLASH] = 0.25, + [DMG_CRUSH] = 0.25, +} + +function ENT:Initialize() + self:SetModel(self.Model) + self:SetHealth(math.max(math.ceil(self.MaxHealth * GetConVar("arccw_mult_ammohealth"):GetFloat()), 1)) + self.AmmoCount = self.AmmoCount * GetConVar("arccw_mult_ammoamount"):GetFloat() + self.MaxAmmoCount = self.AmmoCount + + if self.Scale ~= 1 then + self:SetModelScale(self.Scale) + end + + if self:SkinCount() > 1 and math.random() <= GetConVar("arccw_ammo_rareskin"):GetFloat() then + self:SetSkin(math.random(1, self:SkinCount() - 1)) + end + + if SERVER then + + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetSolid(SOLID_VPHYSICS) + self:SetCollisionGroup(COLLISION_GROUP_WEAPON) + self:SetUseType(SIMPLE_USE) + self:PhysWake() + + self:SetTrigger(true) -- Enables Touch() to be called even when not colliding + if GetConVar("arccw_ammo_largetrigger"):GetBool() then + self:UseTriggerBounds(true, 24) + end + end +end + +function ENT:ApplyAmmo(ply) + if self.USED then return end + self.USED = true -- Prevent multiple uses + ply:GiveAmmo(self.AmmoCount, self.AmmoType) + self:Remove() +end + +function ENT:DetonateRound() + local count = math.Clamp(math.random(1, self.MaxAmmoCount / 5), 1, self.AmmoCount) + -- Default function + self:FireBullets({ + Attacker = self.Burner, + Damage = self.DetonationDamage, + Force = self.DetonationDamage / 5, + Num = count, + AmmoType = self.AmmoType, + Src = self:WorldSpaceCenter(), + Dir = self:GetUp(), + Spread = Vector(3, 3, 0), + IgnoreEntity = self + }) + self.AmmoCount = self.AmmoCount - count + + self:GetPhysicsObject():AddVelocity(VectorRand() * math.random(30, 50) * self:GetPhysicsObject():GetMass()) + self:GetPhysicsObject():AddAngleVelocity(VectorRand() * math.random(60, 300)) + + if self.DetonationSound then + self:EmitSound(istable(self.DetonationSound) and table.Random(self.DetonationSound) or self.DetonationSound) + end +end + +function ENT:Detonate(wet, attacker) + if wet then + self:FireBullets({ + Attacker = attacker, + Damage = self.DetonationDamage, + Force = self.DetonationDamage / 5, + Num = math.max(self.AmmoCount, 50), + AmmoType = self.AmmoType, + Src = self:WorldSpaceCenter(), + Dir = self:GetUp(), + Spread = Vector(3, 3, 0), + IgnoreEntity = self + }) + end + + local e = EffectData() + e:SetOrigin(self:GetPos()) + util.Effect("Explosion", e) + + util.BlastDamage(self, attacker, self:GetPos(), self.DetonationRadius, self.DetonationDamage * (wet and 0.5 or 1)) + self:Remove() +end + +if SERVER then + + function ENT:Use(ply) + if !ply:IsPlayer() then return end + self:ApplyAmmo(ply) + end + + + function ENT:Touch(ply) + if !ply:IsPlayer() or !GetConVar("arccw_ammo_autopickup"):GetBool() then return end + self:ApplyAmmo(ply) + end + + function ENT:Burn(attacker) + self.Burning = true + self.Burner = attacker + self:Ignite(30) + self:SetHealth(-1) + end + + function ENT:OnTakeDamage(dmginfo) + + if self:Health() <= 0 or self.USED then return end + + self:TakePhysicsDamage(dmginfo) + self:SetHealth(self:Health() - dmginfo:GetDamage()) + + if self:Health() <= 0 then + + self.USED = true + + local cvar = GetConVar("arccw_ammo_detonationmode"):GetInt() + + if cvar == -1 or (!GetConVar("arccw_ammo_chaindet"):GetBool() and dmginfo:GetInflictor().ArcCW_Ammo) then + -- Go quietly + local e = EffectData() + e:SetOrigin(self:GetPos()) + e:SetMagnitude(8) + e:SetScale(2) + util.Effect("Sparks", e) + self:EmitSound("physics/cardboard/cardboard_box_break2.wav", 80, 120) + self:Remove() + elseif cvar == 2 and (math.random() <= 0.25 or dmginfo:IsDamageType(DMG_BURN)) then + -- Fancy ammobox burning + self:Burn(dmginfo:GetAttacker()) + else + -- Plain old explosion + self:Detonate(cvar >= 1, dmginfo:GetAttacker()) + end + end + + end + + function ENT:Think() + if self.Burning then + + if self.AmmoCount <= 0 then + self:Detonate(false, IsValid(self.Burner) and self.Burner or self) + else + self:DetonateRound() + end + + self:NextThink(CurTime() + math.random() * 0.3 + 0.2) + return true + end + end + + -- Do it during the hook so that hit damage numbers show up properly (yes, I am _that_ pedantic) + hook.Add("EntityTakeDamage", "ArcCW_Ammo", function(ent, dmginfo) + if ent.ArcCW_Ammo then + if GetConVar("arccw_mult_ammohealth"):GetFloat() < 0 then + dmginfo:ScaleDamage(0) + elseif ent.ResistanceMult then + -- Only apply one multiplier, and prioritize larger ones + for k, v in SortedPairsByValue(ent.ResistanceMult, true) do if dmginfo:IsDamageType(k) then dmginfo:ScaleDamage(v) break end end + end + end + end) + +elseif CLIENT then + + function ENT:Draw() + self:DrawModel() + + if !GetConVar("arccw_2d3d"):GetBool() then return end + + if (EyePos() - self:GetPos()):LengthSqr() <= 262144 then -- 512^2 + local ang = LocalPlayer():EyeAngles() + + ang:RotateAroundAxis(ang:Forward(), 180) + ang:RotateAroundAxis(ang:Right(), 90) + ang:RotateAroundAxis(ang:Up(), 90) + + cam.Start3D2D(self:WorldSpaceCenter() + Vector(0, 0, (self:OBBMaxs().z - self:OBBMins().z) * 0.5 + 8) , ang, 0.1) + surface.SetFont("ArcCW_32_Unscaled") + + local w = surface.GetTextSize(self.PrintName) + + surface.SetTextPos(-w / 2, 0) + surface.SetTextColor(255, 255, 255, 255) + surface.DrawText(self.PrintName) + + if self.AmmoCount > 1 then + w = surface.GetTextSize("×" .. self.AmmoCount) + surface.SetTextPos(-w / 2, 25) + surface.DrawText("×" .. self.AmmoCount) + end + + --surface.SetDrawColor(255, 255, 255) + --surface.SetMaterial(self.Icon or defaulticon) + --local iw = 64 + --surface.DrawTexturedRect(-iw / 2, -iw - 8, iw, iw) + cam.End3D2D() + end + end + +end \ No newline at end of file diff --git a/lua/entities/arccw_ammo_357.lua b/lua/entities/arccw_ammo_357.lua new file mode 100644 index 00000000..c23cf5e1 --- /dev/null +++ b/lua/entities/arccw_ammo_357.lua @@ -0,0 +1,17 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" +ENT.RenderGroup = RENDERGROUP_TRANSLUCENT + +ENT.PrintName = "Magnum Ammo" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/magnum_ammo.mdl" + +ENT.AmmoType = "357" +ENT.AmmoCount = 12 + +ENT.DetonationDamage = 50 +ENT.DetonationRadius = 128 +ENT.DetonationSound = "weapons/arccw/deagle/deagle-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_357_large.lua b/lua/entities/arccw_ammo_357_large.lua new file mode 100644 index 00000000..6fd64c9f --- /dev/null +++ b/lua/entities/arccw_ammo_357_large.lua @@ -0,0 +1,18 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" +ENT.RenderGroup = RENDERGROUP_TRANSLUCENT + +ENT.PrintName = "Magnum Ammo (Large)" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/magnum_ammo.mdl" + +ENT.AmmoType = "357" +ENT.AmmoCount = 60 +ENT.Scale = 1.5 + +ENT.DetonationDamage = 50 +ENT.DetonationRadius = 128 +ENT.DetonationSound = "weapons/arccw/deagle/deagle-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_ar2.lua b/lua/entities/arccw_ammo_ar2.lua new file mode 100644 index 00000000..2324a1a7 --- /dev/null +++ b/lua/entities/arccw_ammo_ar2.lua @@ -0,0 +1,17 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" +ENT.RenderGroup = RENDERGROUP_TRANSLUCENT + +ENT.PrintName = "Rifle Ammo" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/rifle_ammo.mdl" + +ENT.AmmoType = "ar2" +ENT.AmmoCount = 30 + +ENT.DetonationDamage = 50 +ENT.DetonationRadius = 256 +ENT.DetonationSound = "weapons/arccw/ak47/ak47-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_ar2_large.lua b/lua/entities/arccw_ammo_ar2_large.lua new file mode 100644 index 00000000..b5447f3e --- /dev/null +++ b/lua/entities/arccw_ammo_ar2_large.lua @@ -0,0 +1,18 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" +ENT.RenderGroup = RENDERGROUP_TRANSLUCENT + +ENT.PrintName = "Rifle Ammo (Large)" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/rifle_ammo.mdl" +ENT.Scale = 1.5 + +ENT.AmmoType = "ar2" +ENT.AmmoCount = 150 + +ENT.DetonationDamage = 50 +ENT.DetonationRadius = 256 +ENT.DetonationSound = "weapons/arccw/ak47/ak47-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_buckshot.lua b/lua/entities/arccw_ammo_buckshot.lua new file mode 100644 index 00000000..dc0230f1 --- /dev/null +++ b/lua/entities/arccw_ammo_buckshot.lua @@ -0,0 +1,16 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Shotgun Ammo" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/shotgun_ammo.mdl" + +ENT.AmmoType = "buckshot" +ENT.AmmoCount = 20 + +ENT.DetonationDamage = 80 +ENT.DetonationRadius = 128 +ENT.DetonationSound = "weapons/shotgun/shotgun_fire6.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_buckshot_large.lua b/lua/entities/arccw_ammo_buckshot_large.lua new file mode 100644 index 00000000..450653a4 --- /dev/null +++ b/lua/entities/arccw_ammo_buckshot_large.lua @@ -0,0 +1,17 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Shotgun Ammo (Large)" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/shotgun_ammo.mdl" +ENT.Scale = 1.5 + +ENT.AmmoType = "buckshot" +ENT.AmmoCount = 100 + +ENT.DetonationDamage = 80 +ENT.DetonationRadius = 128 +ENT.DetonationSound = "weapons/shotgun/shotgun_fire6.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_pistol.lua b/lua/entities/arccw_ammo_pistol.lua new file mode 100644 index 00000000..7d3eed6c --- /dev/null +++ b/lua/entities/arccw_ammo_pistol.lua @@ -0,0 +1,16 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Pistol Ammo" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/pistol_ammo.mdl" + +ENT.AmmoType = "pistol" +ENT.AmmoCount = 40 + +ENT.DetonationDamage = 10 +ENT.DetonationRadius = 256 +ENT.DetonationSound = "weapons/arccw/glock18/glock18-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_pistol_large.lua b/lua/entities/arccw_ammo_pistol_large.lua new file mode 100644 index 00000000..1e2b07c8 --- /dev/null +++ b/lua/entities/arccw_ammo_pistol_large.lua @@ -0,0 +1,17 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Pistol Ammo (Large)" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/pistol_ammo.mdl" +ENT.Scale = 1.5 + +ENT.AmmoType = "pistol" +ENT.AmmoCount = 200 + +ENT.DetonationDamage = 10 +ENT.DetonationRadius = 256 +ENT.DetonationSound = "weapons/arccw/glock18/glock18-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_smg1.lua b/lua/entities/arccw_ammo_smg1.lua new file mode 100644 index 00000000..560557bb --- /dev/null +++ b/lua/entities/arccw_ammo_smg1.lua @@ -0,0 +1,16 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Carbine Ammo" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/smg_ammo.mdl" + +ENT.AmmoType = "smg1" +ENT.AmmoCount = 60 + +ENT.DetonationDamage = 30 +ENT.DetonationRadius = 256 +ENT.DetonationSound = "weapons/arccw/galilar/galil-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_smg1_grenade.lua b/lua/entities/arccw_ammo_smg1_grenade.lua new file mode 100644 index 00000000..db2bad73 --- /dev/null +++ b/lua/entities/arccw_ammo_smg1_grenade.lua @@ -0,0 +1,39 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Rifle Grenade" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/Items/AR2_Grenade.mdl" +ENT.Health = 15 + +ENT.AmmoType = "smg1_grenade" +ENT.AmmoCount = 1 + +ENT.DetonationDamage = 50 -- Per-round damage +ENT.DetonationRadius = 300 + +function ENT:DetonateRound(attacker) + local nade = ents.Create("arccw_gl_ammodet") + nade:SetPos(self:GetPos()) + nade:SetAngles(self:GetAngles() + AngleRand(-10, 10)) + nade:Spawn() + nade:GetPhysicsObject():AddVelocity(self:GetVelocity() + self:GetForward() * math.random(500, 2000)) + nade:SetOwner(attacker or self.Burner) + self:Remove() +end + +function ENT:Detonate(wet, attacker) + if wet then + self:DetonateRound(attacker) + else + local e = EffectData() + e:SetOrigin(self:GetPos()) + util.Effect("Explosion", e) + + util.BlastDamage(self, attacker, self:GetPos(), self.DetonationRadius, self.DetonationDamage) + self:Remove() + end +end \ No newline at end of file diff --git a/lua/entities/arccw_ammo_smg1_grenade_large.lua b/lua/entities/arccw_ammo_smg1_grenade_large.lua new file mode 100644 index 00000000..ebd918a1 --- /dev/null +++ b/lua/entities/arccw_ammo_smg1_grenade_large.lua @@ -0,0 +1,48 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Rifle Grenade Box" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/riflegrenade_ammo.mdl" +ENT.Health = 70 + +ENT.AmmoType = "smg1_grenade" +ENT.AmmoCount = 5 + +ENT.DetonationDamage = 100 -- Per-round damage +ENT.DetonationRadius = 300 + +function ENT:DetonateRound(attacker) + local nade = ents.Create("arccw_gl_ammodet") + nade:SetPos(self:GetPos()) + local v = self:GetUp():Angle() + AngleRand(-60, 60) + nade:SetAngles(v) + nade:Spawn() + nade:GetPhysicsObject():AddVelocity(self:GetVelocity() + self:GetForward() * math.random(2000, 3000)) + nade:SetOwner(attacker or self.Burner) + + self.AmmoCount = self.AmmoCount - 1 + + self:GetPhysicsObject():AddVelocity(VectorRand() * math.random(5, 10) * self:GetPhysicsObject():GetMass()) + self:GetPhysicsObject():AddAngleVelocity(VectorRand() * math.random(60, 300)) + + self:EmitSound("weapons/ar2/ar2_altfire.wav", 80, 150) +end + +function ENT:Detonate(wet, attacker) + if wet then + for i = 1, math.random(1, 3) do + self:DetonateRound(attacker) + end + end + + local e = EffectData() + e:SetOrigin(self:GetPos()) + util.Effect("Explosion", e) + + util.BlastDamage(self, attacker, self:GetPos(), self.DetonationRadius, self.DetonationDamage * (wet and 1 or 2)) + self:Remove() +end \ No newline at end of file diff --git a/lua/entities/arccw_ammo_smg1_large.lua b/lua/entities/arccw_ammo_smg1_large.lua new file mode 100644 index 00000000..deceaaa3 --- /dev/null +++ b/lua/entities/arccw_ammo_smg1_large.lua @@ -0,0 +1,17 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Carbine Ammo (Large)" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/smg_ammo.mdl" +ENT.Scale = 1.5 + +ENT.AmmoType = "smg1" +ENT.AmmoCount = 300 + +ENT.DetonationDamage = 30 +ENT.DetonationRadius = 256 +ENT.DetonationSound = "weapons/arccw/galilar/galil-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_sniper.lua b/lua/entities/arccw_ammo_sniper.lua new file mode 100644 index 00000000..a55dc737 --- /dev/null +++ b/lua/entities/arccw_ammo_sniper.lua @@ -0,0 +1,17 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Sniper Ammo" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/sniper_ammo.mdl" + +ENT.AmmoType = "SniperPenetratedRound" +ENT.AmmoCount = 10 +ENT.MaxHealth = 20 + +ENT.DetonationDamage = 80 +ENT.DetonationRadius = 128 +ENT.DetonationSound = "weapons/arccw/ssg08/ssg08-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_sniper/shared.lua b/lua/entities/arccw_ammo_sniper/shared.lua new file mode 100644 index 00000000..bda59d39 --- /dev/null +++ b/lua/entities/arccw_ammo_sniper/shared.lua @@ -0,0 +1,31 @@ +AddCSLuaFile() + +ENT.Type = "anim" +ENT.Base = "base_gmodentity" + +ENT.PrintName = "Sniper Ammo" + +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true + +ENT.Model = "models/items/sniper_round_box.mdl" + +function ENT:Initialize() + self:SetModel(self.Model) + self:UseTriggerBounds(true, 24) + + if SERVER then + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetSolid(SOLID_VPHYSICS) + end +end + +function ENT:Touch(ply) + if !ply:IsPlayer() then return end + + ply:GiveAmmo(5, "SniperPenetratedRound") + + self:Remove() +end \ No newline at end of file diff --git a/lua/entities/arccw_ammo_sniper_large.lua b/lua/entities/arccw_ammo_sniper_large.lua new file mode 100644 index 00000000..59c9d196 --- /dev/null +++ b/lua/entities/arccw_ammo_sniper_large.lua @@ -0,0 +1,18 @@ +AddCSLuaFile() + +ENT.Base = "arccw_ammo" + +ENT.PrintName = "Sniper Ammo (Large)" +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true +ENT.Model = "models/items/arccw/sniper_ammo.mdl" +ENT.Scale = 1.5 + +ENT.AmmoType = "SniperPenetratedRound" +ENT.AmmoCount = 50 +ENT.MaxHealth = 20 + +ENT.DetonationDamage = 80 +ENT.DetonationRadius = 128 +ENT.DetonationSound = "weapons/arccw/ssg08/ssg08-1.wav" \ No newline at end of file diff --git a/lua/entities/arccw_ammo_sniper_large/shared.lua b/lua/entities/arccw_ammo_sniper_large/shared.lua new file mode 100644 index 00000000..584f9af7 --- /dev/null +++ b/lua/entities/arccw_ammo_sniper_large/shared.lua @@ -0,0 +1,31 @@ +AddCSLuaFile() + +ENT.Type = "anim" +ENT.Base = "base_gmodentity" + +ENT.PrintName = "Sniper Ammo (Large)" + +ENT.Category = "ArcCW - Ammo" + +ENT.Spawnable = true + +ENT.Model = "models/items/sniper_round_box.mdl" + +function ENT:Initialize() + self:SetModel(self.Model) + self:UseTriggerBounds(true, 24) + + if SERVER then + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetSolid(SOLID_VPHYSICS) + end +end + +function ENT:Touch(ply) + if !ply:IsPlayer() then return end + + ply:GiveAmmo(20, "SniperPenetratedRound") + + self:Remove() +end \ No newline at end of file diff --git a/lua/entities/arccw_att_base/shared.lua b/lua/entities/arccw_att_base/shared.lua new file mode 100644 index 00000000..ae897c09 --- /dev/null +++ b/lua/entities/arccw_att_base/shared.lua @@ -0,0 +1,114 @@ +ENT.Type = "anim" +ENT.Base = "base_entity" +ENT.PrintName = "Base Dropped Attachment" +ENT.Author = "" +ENT.Information = "" + +ENT.Spawnable = false + +ENT.RenderGroup = RENDERGROUP_TRANSLUCENT + +ENT.Category = "ArcCW - Attachments" + +AddCSLuaFile() + +ENT.GiveAttachments = {} -- table of all the attachments to give, and in what quantity. {{["id"] = int quantity}} + +ENT.SoundImpact = "weapon.ImpactSoft" +ENT.Model = "" + +if SERVER then + +function ENT:Initialize() + if !self.Model then + self:Remove() + return + end + + self:SetModel(self.Model) + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetSolid(SOLID_VPHYSICS) + self:SetCollisionGroup(COLLISION_GROUP_WEAPON) + self:SetTrigger( true ) + self:SetPos(self:GetPos() + Vector(0, 0, 4)) + local phys = self:GetPhysicsObject() + if phys:IsValid() then + phys:Wake() + phys:SetBuoyancyRatio(0) + end +end + +function ENT:PhysicsCollide(colData, collider) + if colData.DeltaTime < 0.25 then return end + + self:EmitSound(self.SoundImpact) +end + +function ENT:Use(activator, caller) + if !caller:IsPlayer() then return end + + if GetConVar("arccw_attinv_free"):GetBool() then return end + + local take = false + + for i, k in pairs(self.GiveAttachments) do + if i == "BaseClass" then continue end + + if GetConVar("arccw_attinv_lockmode"):GetBool() then + if ArcCW:PlayerGetAtts(caller, i) > 0 then + continue + end + end + + ArcCW:PlayerGiveAtt(caller, i, k) + + take = true + end + + if take then + ArcCW:PlayerSendAttInv(caller) + + self:EmitSound("weapons/arccw/useatt.wav") + self:Remove() + end +end + +end + +local defaulticon = Material("hud/atts/default.png") + +function ENT:DrawTranslucent() + + self:Draw() + +end + +function ENT:Draw() + self:DrawModel() + + if !GetConVar("arccw_2d3d"):GetBool() then return end + + if (EyePos() - self:GetPos()):LengthSqr() <= 262144 then -- 512^2 + local ang = LocalPlayer():EyeAngles() + + ang:RotateAroundAxis(ang:Forward(), 180) + ang:RotateAroundAxis(ang:Right(), 90) + ang:RotateAroundAxis(ang:Up(), 90) + + cam.Start3D2D(self:GetPos() + Vector(0, 0, 16), ang, 0.1) + surface.SetFont("ArcCW_32_Unscaled") + + local w = surface.GetTextSize(self.PrintName) + + surface.SetTextPos(-w / 2, 0) + surface.SetTextColor(255, 255, 255, 255) + surface.DrawText(self.PrintName) + + surface.SetDrawColor(255, 255, 255) + surface.SetMaterial(self.Icon or defaulticon) + local iw = 64 + surface.DrawTexturedRect(-iw / 2, -iw - 8, iw, iw) + cam.End3D2D() + end +end \ No newline at end of file diff --git a/lua/entities/arccw_gl_ammodet.lua b/lua/entities/arccw_gl_ammodet.lua new file mode 100644 index 00000000..37be4104 --- /dev/null +++ b/lua/entities/arccw_gl_ammodet.lua @@ -0,0 +1,71 @@ +AddCSLuaFile() + +ENT.Base = "arccw_gl_he" +ENT.Model = "models/items/ar2_grenade.mdl" +ENT.Spawnable = false +ENT.Ticks = 0 + +function ENT:Detonate() + if !self:IsValid() then return end + local effectdata = EffectData() + effectdata:SetOrigin( self:GetPos() ) + + if self:WaterLevel() >= 1 then + util.Effect( "WaterSurfaceExplosion", effectdata ) + self:EmitSound("weapons/underwater_explode3.wav", 125, 100, 1, CHAN_AUTO) + else + util.Effect( "Explosion", effectdata) + self:EmitSound("phx/kaboom.wav", 125, 100, 1, CHAN_AUTO) + end + + local attacker = self + + if self:GetOwner():IsValid() then + attacker = self:GetOwner() + end + + util.BlastDamage(self, attacker, self:GetPos(), 300, 50) + + self:FireBullets({ + Attacker = attacker, + Damage = 0, + Tracer = 0, + Distance = 20000, + Dir = self:GetVelocity(), + Src = self:GetPos(), + Callback = function(att, tr, dmg) + util.Decal("Scorch", tr.StartPos, tr.HitPos - (tr.HitNormal * 16), self) + end + }) + + self:Remove() +end + +if CLIENT then + function ENT:Think() + if self.Ticks % 2 == 0 then + local emitter = ParticleEmitter(self:GetPos()) + + if !self:IsValid() or self:WaterLevel() > 2 then return end + if !IsValid(emitter) then return end + + local smoke = emitter:Add("particle/particle_smokegrenade", self:GetPos()) + smoke:SetVelocity( VectorRand() * 25 ) + smoke:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), math.Rand(-20, -25)) ) + smoke:SetDieTime( math.Rand(1.5, 2.0) ) + smoke:SetStartAlpha( 255 ) + smoke:SetEndAlpha( 0 ) + smoke:SetStartSize( 0 ) + smoke:SetEndSize( 100 ) + smoke:SetRoll( math.Rand(-180, 180) ) + smoke:SetRollDelta( math.Rand(-0.2,0.2) ) + smoke:SetColor( 20, 20, 20 ) + smoke:SetAirResistance( 5 ) + smoke:SetPos( self:GetPos() ) + smoke:SetLighting( false ) + emitter:Finish() + end + + self.Ticks = self.Ticks + 1 + end +end \ No newline at end of file diff --git a/lua/entities/arccw_smoke/shared.lua b/lua/entities/arccw_smoke/shared.lua new file mode 100644 index 00000000..821a00c1 --- /dev/null +++ b/lua/entities/arccw_smoke/shared.lua @@ -0,0 +1,116 @@ +ENT.Type = "anim" +ENT.Base = "base_entity" +ENT.PrintName = "Smoke Cloud" +ENT.Author = "" +ENT.Information = "" +ENT.Spawnable = false +ENT.AdminSpawnable = false + +local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"} + +local function GetSmokeImage() + return smokeimages[math.random(#smokeimages)] +end + +ENT.Particles = nil +ENT.SmokeRadius = 256 +ENT.SmokeColor = Color(150, 150, 150) +ENT.BillowTime = 1 +ENT.Life = 15 + +AddCSLuaFile() + +function ENT:Initialize() + if SERVER then + self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" ) + self:SetMoveType( MOVETYPE_NONE ) + self:SetSolid( SOLID_NONE ) + self:DrawShadow( false ) + else + local emitter = ParticleEmitter(self:GetPos()) + + self.Particles = {} + + local amt = 20 + + for i = 1, amt do + local smoke = emitter:Add(GetSmokeImage(), self:GetPos()) + smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 400) ) + smoke:SetDieTime( self.BillowTime ) + smoke:SetStartAlpha( 0 ) + smoke:SetEndAlpha( 255 ) + smoke:SetStartSize( 0 ) + smoke:SetEndSize( self.SmokeRadius ) + smoke:SetRoll( math.Rand(-180, 180) ) + smoke:SetRollDelta( math.Rand(-0.2,0.2) ) + smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b ) + smoke:SetAirResistance( 75 ) + smoke:SetPos( self:GetPos() ) + smoke:SetCollide( true ) + smoke:SetBounce( 0.2 ) + smoke:SetLighting( false ) + smoke:SetNextThink( CurTime() + FrameTime() ) + smoke:SetThinkFunction( function(pa) + if !pa then return end + + local d = pa:GetLifeTime() / pa:GetDieTime() + + local prog = (-d ^ 2) + (2 * d) + + pa:SetEndSize( self.SmokeRadius * prog ) + pa:SetStartSize( self.SmokeRadius * prog ) + pa:SetNextThink( CurTime() + FrameTime() ) + end ) + + table.insert(self.Particles, smoke) + end + + emitter:Finish() + end + + self.bt = CurTime() + self.BillowTime + self.billowed = false + self.dt = CurTime() + self.Life + self.BillowTime +end + +function ENT:Think() + + if SERVER then + local targets = ents.FindInSphere(self:GetPos(), 256) + for _, k in pairs(targets) do + if k:IsNPC() then + k:SetNPCState(NPC_STATE_PRONE) + end + end + end + + if self.bt < CurTime() and !self.billowed then + self.billowed = true + if CLIENT then + for i, k in pairs(self.Particles or {}) do + if !k then continue end + k:SetThinkFunction(nil) + k:SetLifeTime(0) + k:SetDieTime(self.Life) + k:SetStartAlpha(255) + end + end + end + + if self.dt < CurTime() then + if CLIENT then + for i, k in pairs(self.Particles or {}) do + if !k then continue end + k:SetLifeTime(0) + k:SetDieTime(math.Rand(2.5, 5)) + k:SetEndAlpha(0) + end + else + SafeRemoveEntity(self) + end + end +end + +function ENT:Draw() + return false +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_blur.lua b/lua/weapons/arccw_base/cl_blur.lua new file mode 100644 index 00000000..34983da3 --- /dev/null +++ b/lua/weapons/arccw_base/cl_blur.lua @@ -0,0 +1,84 @@ +local dofmat = Material("pp/dof") + +function SWEP:BlurWeapon() + if !GetConVar("arccw_blur"):GetBool() then return end + + local delta = self:GetSightDelta() + + if delta >= 1 then return end + + local vm = self:GetOwner():GetViewModel() + + 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(0xFF) + render.SetStencilTestMask(0xFF) + + render.SetBlend(1) + + render.SetStencilReferenceValue(55) + + ArcCW.Overdraw = true + vm:DrawModel() + + ArcCW.Overdraw = false + + render.SetBlend(0) + + render.SetStencilPassOperation(STENCIL_REPLACE) + render.SetStencilCompareFunction(STENCIL_EQUAL) + + -- render.SetColorMaterial() + + dofmat:SetFloat("bluramount", 0.1 * (1 - delta)) + + render.SetMaterial(dofmat) + render.DrawScreenQuad() + + render.SetStencilEnable( false ) +end + +function SWEP:BlurNotWeapon() + if !GetConVar("arccw_blur"):GetBool() then return end + local vm = self:GetOwner():GetViewModel() + + 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(0xFF) + render.SetStencilTestMask(0xFF) + + render.SetBlend(1) + + render.SetStencilReferenceValue(55) + + ArcCW.Overdraw = true + vm:DrawModel() + + ArcCW.Overdraw = false + + render.SetStencilReferenceValue(0) + + render.SetBlend(0) + + render.SetStencilPassOperation(STENCIL_REPLACE) + render.SetStencilCompareFunction(STENCIL_EQUAL) + + -- render.SetColorMaterial() + + dofmat:SetFloat("bluramount", 0.1) + + render.SetMaterial(dofmat) + render.DrawScreenQuad() + + render.SetStencilEnable( false ) +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_crosshair.lua b/lua/weapons/arccw_base/cl_crosshair.lua new file mode 100644 index 00000000..29d072a9 --- /dev/null +++ b/lua/weapons/arccw_base/cl_crosshair.lua @@ -0,0 +1,137 @@ +local delta = 0 +local size = 0 +local cw = nil + +function SWEP:ShouldDrawCrosshair() + if !GetConVar("arccw_override_crosshair_off") then return false end + if !GetConVar("arccw_crosshair"):GetBool() then return false end + if self:GetNWBool("reloading") then return false end + local asight = self:GetActiveSights() + if self:GetState() == ArcCW.STATE_SIGHTS and !asight.CrosshairInSights then return false end + if self:GetState() == ArcCW.STATE_SPRINT and !(self:GetBuff_Override("Override_ShootWhileSprint") or self.ShootWhileSprint) then return false end + if self:GetCurrentFiremode().Mode == 0 then return false end + if self:GetBuff_Hook("Hook_ShouldNotFire") then return false end + + return true +end + +function SWEP:DoDrawCrosshair(x, y) + local pos = EyePos() + local ang = EyeAngles() - LocalPlayer():GetViewPunchAngles() + local dot = true + local prong_top = true + local prong_left = true + local prong_right = true + local prong_down = true + + local gap = ScreenScale(24) * math.Clamp(self:GetDispersion() / 1000, 0.1, 100) + + gap = gap + ScreenScale(8) * math.Clamp(self.RecoilAmount, 0, 1) + + local prong = ScreenScale(4) + + cw = cw or self + + cam.Start3D() + local sp = (pos + (ang:Forward() * 3200)):ToScreen() + cam.End3D() + + x, y = sp.x, sp.y + + local st = self:GetSightTime() / 4 + + if self:ShouldDrawCrosshair() then + delta = math.Approach(delta, 1, RealFrameTime() * 1 / st) + else + delta = math.Approach(delta, 0, RealFrameTime() * 1 / st) + end + + local p_w = ScreenScale(1) + local p_w2 = p_w + 2 + + if self:GetBuff_Override("Override_ShootEntity") or self.ShootEntity then + gap = gap * 1.5 + prong = ScreenScale(1) + p_w = ScreenScale(1) + p_w2 = p_w + 2 + end + + if self.PrimaryBash then + dot = false + gap = gap * 2 + prong = ScreenScale(1) + p_w = ScreenScale(1) + p_w2 = p_w + 2 + end + + if dot then + + surface.SetDrawColor(0, 0, 0, 150 * delta) + surface.DrawRect(x - p_w2 / 2, y - p_w2 / 2, p_w2, p_w2) + + surface.SetDrawColor(255, 255, 255, 255 * delta) + surface.DrawRect(x - p_w / 2, y - p_w / 2, p_w, p_w) + + end + + local num = (self:GetBuff_Override("Override_Num") or self.Num) + self:GetBuff_Add("Add_Num") + + size = math.Approach(size, gap, RealFrameTime() * 32 * gap) + + if cw != self then + delta = 0 + size = gap + end + + cw = self + + gap = size + + if num > 1 then + dot = false + gap = gap * 2.5 + prong = ScreenScale(1) + p_w = ScreenScale(10) + p_w2 = p_w + 2 + end + + local prong2 = prong + 2 + + surface.SetDrawColor(0, 0, 0, 150 * delta) + + if prong_left then + surface.DrawRect(x - gap - prong2 + 1, y - p_w2 / 2, prong2, p_w2) + end + + if prong_right then + surface.DrawRect(x + gap - 1, y - p_w2 / 2, prong2, p_w2) + end + + if prong_top then + surface.DrawRect(x - p_w2 / 2, y - gap - prong2 + 1, p_w2, prong2) + end + + if prong_down then + surface.DrawRect(x - p_w2 / 2, y + gap - 1, p_w2, prong2) + end + + surface.SetDrawColor(255, 255, 255, 255 * delta) + + if prong_left then + surface.DrawRect(x - gap - prong, y - p_w / 2, prong, p_w) + end + + if prong_right then + surface.DrawRect(x + gap, y - p_w / 2, prong, p_w) + end + + if prong_top then + surface.DrawRect(x - p_w / 2, y - gap - prong, p_w, prong) + end + + if prong_down then + surface.DrawRect(x - p_w / 2, y + gap, p_w, prong) + end + + return true +end diff --git a/lua/weapons/arccw_base/cl_holosight.lua b/lua/weapons/arccw_base/cl_holosight.lua new file mode 100644 index 00000000..30aa1516 --- /dev/null +++ b/lua/weapons/arccw_base/cl_holosight.lua @@ -0,0 +1,651 @@ +function SWEP:DoHolosight() + local asight = self:GetActiveSights() + if !asight then return end + local aslot = self.Attachments[asight.Slot] or {} + + local atttbl = asight.HolosightData + + if !atttbl and aslot.Installed then + atttbl = ArcCW.AttachmentTable[aslot.Installed] + + if !atttbl.Holosight then return end + end + + if atttbl then + local hsp = asight.HolosightPiece or self.HSPElement + local hsm = asight.HolosightModel + + if !hsp and !hsm then + self:SetupActiveSights() + return + end + + self:DrawHolosight(atttbl, hsm, hsp) + end +end + +local rtsize = ScrH() + +local rtmat = GetRenderTarget("arccw_rtmat", rtsize, rtsize, false) +local rtmat_cheap = GetRenderTarget("arccw_rtmat_cheap", ScrW(), ScrH(), false) +local rtmat_spare = GetRenderTarget("arccw_rtmat_spare", ScrW(), ScrH(), false) + +-- local shadow = Material("hud/scopes/shadow.png") + +-- local thermal = Material("models/debug/debugwhite") +local colormod = Material("pp/colour") +-- local warp = Material("models/props_c17/fisheyelens2") +local coldtime = 30 + +-- shamelessly robbed from Jackarunda +local function IsWHOT(ent) + if !ent:IsValid() then return false end + if (ent:IsWorld()) then return false end + if (ent.Health and (ent:Health() <= 0)) then return false end + if ((ent:IsPlayer()) or (ent:IsOnFire())) then return true end + if ent:IsNextBot() then return true end + if (ent:IsNPC()) then + if ent.ArcCWCLHealth and ent.ArcCWCLHealth <= 0 then return false end + if (ent.Health and (ent:Health() > 0)) then return true end + elseif (ent:IsRagdoll()) then + local Time = CurTime() + if !ent.ArcCW_ColdTime then ent.ArcCW_ColdTime = Time + coldtime end + return ent.ArcCW_ColdTime > Time + elseif (ent:IsVehicle()) then + return ent:GetVelocity():Length() >= 100 + end + return false +end + +function SWEP:FormThermalImaging(tex) + if !tex then + tex = render.GetRenderTarget() + end + + render.PushRenderTarget(tex) + + cam.Start3D() + + if tex then + colormod:SetTexture("$fbtexture", tex) + else + colormod:SetTexture("$fbtexture", render.GetScreenEffectTexture()) + end + + local asight = self:GetActiveSights() + + local nvsc = asight.ThermalScopeColor or Color(255, 255, 255) + local tvsc = asight.ThermalHighlightColor or Color(255, 255, 255) + + local tab = ents.GetAll() + + -- table.Add(tab, player.GetAll()) + -- table.Add(tab, ents.FindByClass("npc_*")) + + render.SetStencilEnable(true) + render.SetStencilWriteMask(255) + render.SetStencilTestMask(255) + render.ClearStencil() + + local sw = ScrH() + local sh = sw + + local sx = (ScrW() - sw) / 2 + local sy = (ScrH() - sh) / 2 + + render.SetScissorRect( sx, sy, sx + sw, sy + sh, true ) + + render.SetStencilReferenceValue(64) + + render.SetStencilPassOperation(STENCIL_REPLACE) + render.SetStencilFailOperation(STENCIL_KEEP) + render.SetStencilZFailOperation(STENCIL_KEEP) + render.SetStencilCompareFunction(STENCIL_ALWAYS) + + for _, v in pairs(tab) do + + if !IsWHOT(v) then continue end + + local Br = 0.9 + if v.ArcCW_ColdTime then + Br = (0.75 * v.ArcCW_ColdTime - CurTime()) / coldtime + end + + if v:IsVehicle() then + Br = math.Clamp(v:GetVelocity():Length() / 400, 0, 1) + end + + if Br > 0 then + + if !asight.ThermalScopeSimple then + render.SetBlend(0.5) + render.SuppressEngineLighting(true) + + Br = Br * 250 + + -- render.MaterialOverride(thermal) + + render.SetColorModulation(Br, Br, Br) + end + + v:DrawModel() + + end + end + + render.SetColorModulation(1, 1, 1) + + render.SuppressEngineLighting(false) + + render.MaterialOverride() + + render.SetBlend(1) + + render.SetStencilCompareFunction(STENCIL_EQUAL) + + if asight.ThermalScopeSimple then + surface.SetDrawColor(tvsc) + surface.DrawRect(0, 0, ScrW(), ScrH()) + end + + if !asight.ThermalNoCC then + DrawColorModify({ + ["$pp_colour_addr"] = 0, + ["$pp_colour_addg"] = 0, + ["$pp_colour_addb"] = 0, + ["$pp_colour_brightness"] = 0, + ["$pp_colour_contrast"] = 1, + ["$pp_colour_colour"] = 0, + ["$pp_colour_mulr"] = 0, + ["$pp_colour_mulg"] = 0, + ["$pp_colour_mulb"] = 0 + }) + + DrawColorModify({ + ["$pp_colour_addr"] = tvsc.r - 255, + ["$pp_colour_addg"] = tvsc.g - 255, + ["$pp_colour_addb"] = tvsc.b - 255, + ["$pp_colour_brightness"] = 0, + ["$pp_colour_contrast"] = 1, + ["$pp_colour_colour"] = 0, + ["$pp_colour_mulr"] = 0, + ["$pp_colour_mulg"] = 0, + ["$pp_colour_mulb"] = 0 + }) + + render.SetStencilCompareFunction(STENCIL_NOTEQUAL) + + DrawColorModify({ + ["$pp_colour_addr"] = 0, + ["$pp_colour_addg"] = 0, + ["$pp_colour_addb"] = 0, + ["$pp_colour_brightness"] = 0.1, + ["$pp_colour_contrast"] = 0.5, + ["$pp_colour_colour"] = 0, + ["$pp_colour_mulr"] = 0, + ["$pp_colour_mulg"] = 0, + ["$pp_colour_mulb"] = 0 + }) + + DrawColorModify({ + ["$pp_colour_addr"] = nvsc.r - 255, + ["$pp_colour_addg"] = nvsc.g - 255, + ["$pp_colour_addb"] = nvsc.b - 255, + ["$pp_colour_brightness"] = 0, + ["$pp_colour_contrast"] = 1, + ["$pp_colour_colour"] = 0, + ["$pp_colour_mulr"] = 0, + ["$pp_colour_mulg"] = 0, + ["$pp_colour_mulb"] = 0 + }) + + end + + render.SetScissorRect( sx, sy, sx + sw, sy + sh, false ) + + render.SetStencilEnable(false) + + colormod:SetTexture("$fbtexture", render.GetScreenEffectTexture()) + + cam.End3D() + + render.PopRenderTarget() +end + +function SWEP:FormNightVision(tex) + local asight = self:GetActiveSights() + + local orig = colormod:GetTexture("$fbtexture") + + colormod:SetTexture("$fbtexture", tex) + + render.PushRenderTarget(tex) + + local nvsc = asight.NVScopeColor or Color(0, 255, 0) + + if !asight.NVFullColor then + DrawColorModify({ + ["$pp_colour_addr"] = 0, + ["$pp_colour_addg"] = 0, + ["$pp_colour_addb"] = 0, + ["$pp_colour_brightness"] = 0, + ["$pp_colour_contrast"] = 1, + ["$pp_colour_colour"] = 0, + ["$pp_colour_mulr"] = 0, + ["$pp_colour_mulg"] = 0, + ["$pp_colour_mulb"] = 0 + }) + end + + DrawColorModify({ + ["$pp_colour_addr"] = nvsc.r - 255, + ["$pp_colour_addg"] = nvsc.g - 255, + ["$pp_colour_addb"] = nvsc.b - 255, + ["$pp_colour_brightness"] = -0.05, + ["$pp_colour_contrast"] = 4, + ["$pp_colour_colour"] = 1, + ["$pp_colour_mulr"] = 0, + ["$pp_colour_mulg"] = 0, + ["$pp_colour_mulb"] = 0 + }) + + render.PopRenderTarget() + + colormod:SetTexture("$fbtexture", orig) +end + +function SWEP:FormCheapScope() + local screen = render.GetRenderTarget() + + render.CopyTexture( screen, rtmat_spare ) + + render.PushRenderTarget(screen) + cam.Start3D(EyePos(), EyeAngles(), nil, nil, nil, nil, nil, 0, nil) + ArcCW.LaserBehavior = true + self:DoLaser(false) + ArcCW.LaserBehavior = false + cam.End3D() + render.PopRenderTarget() + + -- so, in order to avoid the fact that copying RTs doesn't transfer depth buffer data, we just take the screen texture and... + -- redraw it to cover up the thermal scope stuff. Don't think too hard about this. You have plenty of VRAM. + + local asight = self:GetActiveSights() + + if asight.Thermal then + self:FormThermalImaging(screen) + end + + render.CopyTexture( screen, rtmat_cheap ) + + render.DrawTextureToScreen(rtmat_spare) + + render.UpdateFullScreenDepthTexture() +end + +function SWEP:FormRTScope() + local asight = self:GetActiveSights() + + if !asight then return end + + if !asight.MagnifiedOptic then return end + + local mag = asight.ScopeMagnification + + cam.Start3D() + + ArcCW.Overdraw = true + ArcCW.LaserBehavior = true + + local rt = { + w = rtsize, + h = rtsize, + angles = LocalPlayer():EyeAngles() + (self:GetOwner():GetViewPunchAngles() * 0.5), + origin = LocalPlayer():EyePos(), + drawviewmodel = false, + fov = self:GetOwner():GetFOV() / mag / 1.2, + } + + rtsize = ScrH() + + if ScrH() > ScrW() then rtsize = ScrW() end + + rtmat = GetRenderTarget("arccw_rtmat", rtsize, rtsize, false) + + render.PushRenderTarget(rtmat, 0, 0, rtsize, rtsize) + + render.ClearRenderTarget(rt, Color(0, 0, 0)) + + if self:GetSightDelta() < 1 then + render.RenderView(rt) + cam.Start3D(EyePos(), EyeAngles(), rt.fov, 0, 0, nil, nil, 0, nil) + self:DoLaser(false) + cam.End3D() + end + + ArcCW.Overdraw = false + ArcCW.LaserBehavior = false + + render.PopRenderTarget() + + cam.End3D() + + if asight.Thermal then + self:FormThermalImaging(rtmat) + end +end + +hook.Add("RenderScene", "ArcCW", function() + if GetConVar("arccw_cheapscopes"):GetBool() then return end + + local wpn = LocalPlayer():GetActiveWeapon() + + if !wpn.ArcCW then return end + + wpn:FormRTScope() +end) + +local black = Material("hud/black.png") +local defaultdot = Material("hud/scopes/dot.png") + +function SWEP:DrawHolosight(hs, hsm, hsp) + -- holosight structure + -- holosight model + + local asight = self:GetActiveSights() + local delta = self:GetSightDelta() + + if asight.HolosightData then + hs = asight.HolosightData + end + + if delta == 1 then return end + + if !hs then return end + + local hsc = Color(255, 255, 255) + + if hs.Colorable then + hsc.r = GetConVar("arccw_scope_r"):GetInt() + hsc.g = GetConVar("arccw_scope_g"):GetInt() + hsc.b = GetConVar("arccw_scope_b"):GetInt() + else + hsc = hs.HolosightColor or hsc + end + + local attid = 0 + + if hsm then + + attid = hsm:LookupAttachment(asight.HolosightBone or hs.HolosightBone or "holosight") + + if attid == 0 then + attid = hsm:LookupAttachment("holosight") + end + + end + + local ret, pos, ang + + if attid != 0 then + + ret = hsm:GetAttachment(attid) + pos = ret.Pos + ang = ret.Ang + + else + + pos = EyePos() + ang = EyeAngles() + + end + + local size = hs.HolosightSize or 1 + + local hsmag = asight.ScopeMagnification or 1 + + -- if asight.NightVision then + + if hsmag and hsmag > 1 and delta < 1 and asight.NVScope then + local screen = rtmat + + if GetConVar("arccw_cheapscopes"):GetBool() then + screen = rtmat_cheap + end + self:FormNightVision(screen) + end + + 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.SetBlend(0) + + render.SetStencilReferenceValue(55) + + ArcCW.Overdraw = true + + render.OverrideDepthEnable( true, true ) + + if !hsm then + hsp:DrawModel() + else + + if !hsp or hs.HolosightNoHSP then + hsm:DrawModel() + end + + render.MaterialOverride() + + render.SetStencilReferenceValue(0) + + hsm:SetBodygroup(1, 1) + -- hsm:SetSubMaterial(0, "dev/no_pixel_write") + hsm:DrawModel() + -- hsm:SetSubMaterial() + hsm:SetBodygroup(1, 0) + + -- local vm = self:GetOwner():GetViewModel() + + -- ArcCW.Overdraw = true + -- vm:DrawModel() + + -- ArcCW.Overdraw = false + + render.SetStencilReferenceValue(55) + + if hsp then + hsp:DrawModel() + end + end + + render.MaterialOverride() + + render.OverrideDepthEnable( false, true ) + + ArcCW.Overdraw = false + + render.SetBlend(1) + + render.SetStencilPassOperation(STENCIL_REPLACE) + render.SetStencilCompareFunction(STENCIL_EQUAL) + + -- local pos = EyePos() + -- local ang = EyeAngles() + + ang:RotateAroundAxis(ang:Forward(), -90) + + ang = ang + (self:GetOwner():GetViewPunchAngles() * 0.25) + + local dir = ang:Up() + + local pdiff = (pos - EyePos()):Length() + + pos = LerpVector(delta, EyePos(), pos) + + local eyeangs = self:GetOwner():EyeAngles() - (self:GetOwner():GetViewPunchAngles() * 0.25) + + -- local vm = hsm or hsp + + -- eyeangs = eyeangs + (eyeangs - vm:GetAngles()) + + dir = LerpVector(delta, eyeangs:Forward(), dir:GetNormalized()) + + pdiff = Lerp(delta, pdiff, 0) + + local d = (8 + pdiff) + + d = hs.HolosightConstDist or d + + local vmscale = (self.Attachments[asight.Slot] or {}).VMScale or Vector(1, 1, 1) + + if hs.HolosightConstDist then + vmscale = Vector(1, 1, 1) + end + + local hsx = vmscale[2] or 1 + local hsy = vmscale[3] or 1 + + pos = pos + (dir * d) + + -- local corner1, corner2, corner3, corner4 + + -- corner2 = pos + (ang:Right() * (-0.5 * size)) + (ang:Forward() * (0.5 * size)) + -- corner1 = pos + (ang:Right() * (-0.5 * size)) + (ang:Forward() * (-0.5 * size)) + -- corner4 = pos + (ang:Right() * (0.5 * size)) + (ang:Forward() * (-0.5 * size)) + -- corner3 = pos + (ang:Right() * (0.5 * size)) + (ang:Forward() * (0.5 * size)) + + -- render.SetColorMaterialIgnoreZ() + -- render.DrawScreenQuad() + + -- render.SetStencilEnable( false ) + -- local fovmag = asight.Magnification or 1 + + if hsmag and hsmag > 1 and delta < 1 then + local screen = rtmat + + -- local sw2 = ScrH() + -- local sh2 = sw2 + + -- local sx2 = (ScrW() - sw2) / 2 + -- local sy2 = (ScrH() - sh2) / 2 + + -- render.SetScissorRect( sx2, sy2, sx2 + sw2, sy2 + sh2, true ) + + if GetConVar("arccw_cheapscopes"):GetBool() then + + screen = rtmat_cheap + + local ssmag = hsmag + + local sw = ScrW() * ssmag + local sh = ScrH() * ssmag + + -- local sx = -(sw - ScrW()) / 2 + -- local sy = -(sh - ScrH()) / 2 + + local cpos = self.Owner:EyePos() + ((EyeAngles() + (self:GetOwner():GetViewPunchAngles() * 0.5)):Forward() * 2048) + + local ts = cpos:ToScreen() + + local sx = ts.x - (sw / 2) + local sy = ts.y - (sh / 2) + + render.SetMaterial(black) + render.DrawScreenQuad() + + render.DrawTextureToScreenRect(screen, sx, sy, sw, sh) + + else + + local sw = ScrH() + local sh = sw + + local sx = (ScrW() - sw) / 2 + local sy = (ScrH() - sh) / 2 + + render.SetMaterial(black) + render.DrawScreenQuad() + + render.DrawTextureToScreenRect(screen, sx, sy, sw, sh) + + end + + -- warp:SetFloat("$refractamount", -0.015) + -- render.UpdateRefractTexture() + -- render.SetMaterial(warp) + -- render.DrawScreenQuad() + + -- render.SetScissorRect( sx2, sy2, sx2 + sw2, sy2 + sh2, false ) + end + + cam.Start3D() + + -- render.SetColorMaterialIgnoreZ() + -- render.DrawScreenQuad() + + -- render.DrawQuad( corner1, corner2, corner3, corner4, hsc or hs.HolosightColor ) + cam.IgnoreZ( true ) + + if hs.HolosightBlackbox then + render.SetStencilPassOperation(STENCIL_ZERO) + render.SetStencilCompareFunction(STENCIL_EQUAL) + + render.SetStencilReferenceValue(55) + + render.SetMaterial(hs.HolosightReticle or defaultdot) + render.DrawSprite(pos, size * hsx, size * hsy, hsc or Color(255, 255, 255)) + + if !hs.HolosightNoFlare then + render.SetMaterial(hs.HolosightFlare or hs.HolosightReticle) + render.DrawSprite(pos, size * 0.5 * hsx, size * 0.5 * hsy, Color(255, 255, 255)) + end + + render.SetStencilPassOperation(STENCIL_REPLACE) + render.SetStencilCompareFunction(STENCIL_EQUAL) + + render.SetMaterial(black) + render.DrawScreenQuad() + else + render.SetStencilReferenceValue(55) + + render.SetMaterial(hs.HolosightReticle or defaultdot) + render.DrawSprite( pos, size * hsx, size * hsy, hsc or Color(255, 255, 255) ) + if !hs.HolosightNoFlare then + render.SetMaterial(hs.HolosightFlare or hs.HolosightReticle or defaultdot) + local hss = 0.75 + if hs.HolosightFlare then + hss = 1 + end + render.DrawSprite( pos, size * hss * hsx, size * hss * hsy, Color(255, 255, 255, 255) ) + end + end + + render.SetStencilEnable( false ) + + cam.IgnoreZ( false ) + + cam.End3D() + + if hsp then + + cam.IgnoreZ(true) + + if GetConVar("arccw_glare"):GetBool() then + render.SetBlend(delta + 0.1) + else + render.SetBlend(delta) + end + hsp:DrawModel() + render.SetBlend(1) + + cam.IgnoreZ( false ) + + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_hud.lua b/lua/weapons/arccw_base/cl_hud.lua new file mode 100644 index 00000000..12c96d1e --- /dev/null +++ b/lua/weapons/arccw_base/cl_hud.lua @@ -0,0 +1,400 @@ +local function MyDrawText(tbl) + local x = tbl.x + local y = tbl.y + surface.SetFont(tbl.font) + + if tbl.alpha then + tbl.col.a = tbl.alpha + end + + if tbl.align or tbl.yalign then + local w, h = surface.GetTextSize(tbl.text) + if tbl.align == 1 then + x = x - w + elseif tbl.align == 2 then + x = x - (w / 2) + end + if tbl.yalign == 1 then + y = y - h + elseif tbl.yalign == 2 then + y = y - h / 2 + end + end + + if tbl.shadow then + surface.SetTextColor(Color(0, 0, 0, tbl.alpha or 255)) + surface.SetTextPos(x, y) + surface.SetFont(tbl.font .. "_Glow") + surface.DrawText(tbl.text) + end + + surface.SetTextColor(tbl.col) + surface.SetTextPos(x, y) + surface.SetFont(tbl.font) + surface.DrawText(tbl.text) +end + +local vhp = 0 +local varmor = 0 +local vclip = 0 +local vreserve = 0 +local lastwpn = "" +local lastinfo = {ammo = 0, clip = 0, firemode = "", plus = 0} +local lastinfotime = 0 + +function SWEP:DrawHUD() + -- info panel + + local col1 = Color(0, 0, 0, 100) + local col2 = Color(255, 255, 255, 255) + local col3 = Color(255, 0, 0, 255) + + local airgap = ScreenScale(8) + + local apan_bg = { + w = ScreenScale(128), + h = ScreenScale(48), + } + + local bargap = ScreenScale(2) + + if self:CanBipod() then + local txt = "[" .. string.upper(ArcCW:GetBind("+use")) .. "]" + + if self:InBipod() then + txt = txt .. " Retract Bipod" + else + txt = txt .. " Deploy Bipod" + end + + local bip = { + shadow = true, + x = ScrW() / 2, + y = (ScrH() / 2) + ScreenScale(36), + font = "ArcCW_12", + text = txt, + col = col2, + align = 2 + } + + MyDrawText(bip) + end + + if ArcCW:ShouldDrawHUDElement("CHudAmmo") then + + local curTime = CurTime() + local ammo = math.Round(vreserve) + local clip = math.Round(vclip) + local plus = 0 + local mode = self:GetFiremodeName() + + if clip > self:GetCapacity() then + plus = clip - self:GetCapacity() + clip = clip - plus + end + + local muzz = self:GetBuff_Override("Override_MuzzleEffectAttachment") or self.MuzzleEffectAttachment or 1 + + local suckitYurie = GetConVar("arccw_hud_3dfun"):GetBool() + + local vm = self.Owner:GetViewModel() + + local angpos + + if vm and vm:IsValid() then + angpos = vm:GetAttachment(muzz) + end + + if suckitYurie and muzz and angpos then + + local visible = (lastinfotime + 4 > curTime or lastinfotime - 0.5 > curTime) + + -- Detect changes to stuff drawn in HUD + local curInfo = {ammo = ammo, clip = clip, plus = plus, firemode = mode} + for i, v in pairs(curInfo) do + if v != lastinfo[i] then + lastinfotime = visible and (curTime - 0.5) or curTime + lastinfo = curInfo + break + end + end + + -- TODO: There's an issue where this won't ping the HUD when switching in from non-ArcCW weapons + if LocalPlayer():KeyDown(IN_RELOAD) or lastwpn != self then lastinfotime = visible and (curTime - 0.5) or curTime end + + local alpha + if lastinfotime + 3 < curTime then + alpha = 255 - (curTime - lastinfotime - 3) * 255 + elseif lastinfotime + 0.5 > curTime then + alpha = 255 - (lastinfotime + 0.5 - curTime) * 255 + else + alpha = 255 + end + + if alpha > 0 then + + cam.Start3D() + local toscreen = angpos.Pos:ToScreen() + cam.End3D() + + apan_bg.x = toscreen.x - apan_bg.w - ScreenScale(8) + apan_bg.y = toscreen.y - apan_bg.h * 0.5 + + if self.PrimaryBash or self:Clip1() == -1 or self:GetCapacity() == 0 or self.Primary.ClipSize == -1 then + clip = "-" + end + + local wammo = { + x = apan_bg.x + apan_bg.w - airgap, + y = apan_bg.y, + text = tostring(clip), + font = "ArcCW_26", + col = col2, + align = 1, + shadow = true, + alpha = alpha, + } + + wammo.col = col2 + + if self:Clip1() == 0 then + wammo.col = col3 + end + + if self:GetNWBool("ubgl") then + wammo.col = col2 + wammo.text = self:Clip2() + end + + MyDrawText(wammo) + wammo.w, wammo.h = surface.GetTextSize(wammo.text) + + if plus > 0 and !self:GetNWBool("ubgl") then + local wplus = { + x = wammo.x, + y = wammo.y, + text = "+" .. tostring(plus), + font = "ArcCW_16", + col = col2, + shadow = true, + alpha = alpha, + } + + MyDrawText(wplus) + end + + + local wreserve = { + x = wammo.x - wammo.w - ScreenScale(4), + y = apan_bg.y + ScreenScale(26 - 12), + text = tostring(ammo) .. " /", + font = "ArcCW_12", + col = col2, + align = 1, + yalign = 2, + shadow = true, + alpha = alpha, + } + + if self:GetNWBool("ubgl") then + local ubglammo = self:GetBuff_Override("UBGL_Ammo") + + if ubglammo then + wreserve.text = tostring(self:GetOwner():GetAmmoCount(ubglammo)) .. " /" + end + end + + if self.PrimaryBash then + wreserve.text = "" + end + + MyDrawText(wreserve) + wreserve.w, wreserve.h = surface.GetTextSize(wreserve.text) + + local wmode = { + x = apan_bg.x + apan_bg.w - airgap, + y = wammo.y + wammo.h, + font = "ArcCW_12", + text = mode, + col = col2, + align = 1, + shadow = true, + alpha = alpha, + } + MyDrawText(wmode) + + end + else + + apan_bg.x = ScrW() - apan_bg.w - airgap + apan_bg.y = ScrH() - apan_bg.h - airgap + + surface.SetDrawColor(col1) + surface.DrawRect(apan_bg.x, apan_bg.y, apan_bg.w, apan_bg.h) + + local bar = { + w = (apan_bg.w - (6 * bargap)) / 5, + h = ScreenScale(3), + x = apan_bg.x + bargap, + y = apan_bg.y + ScreenScale(14) + } + + local bars = self:GetFiremodeBars() + + for i = 1, 5 do + local c = bars[i] + + surface.SetDrawColor(col2) + + if c == "-" then + surface.DrawRect(bar.x, bar.y, bar.w, bar.h) + else + surface.DrawOutlinedRect(bar.x, bar.y, bar.w, bar.h) + end + + bar.x = bar.x + bar.w + bargap + end + + local wname = { + x = apan_bg.x + ScreenScale(4), + y = apan_bg.y, + font = "ArcCW_12", + text = self.PrintName, + col = col2 + } + + MyDrawText(wname) + + local wmode = { + x = apan_bg.x + apan_bg.w - ScreenScale(4) - surface.GetTextSize(mode), + y = apan_bg.y, + font = "ArcCW_12", + text = mode, + col = col2 + } + + MyDrawText(wmode) + + if self.PrimaryBash or self:Clip1() == -1 or self:GetCapacity() == 0 or self.Primary.ClipSize == -1 then + clip = "-" + end + + local wammo = { + x = apan_bg.x + airgap, + y = bar.y + ScreenScale(4), + text = tostring(clip), + font = "ArcCW_26", + col = col2 + } + + wammo.col = col2 + + if self:Clip1() == 0 then + wammo.col = col3 + end + + if self:GetNWBool("ubgl") then + wammo.col = col2 + wammo.text = self:Clip2() + end + + MyDrawText(wammo) + + local wreserve = { + x = apan_bg.x + ScreenScale(64) - airgap, + y = bar.y + ScreenScale(4), + text = "/ " .. tostring(ammo), + font = "ArcCW_26", + col = col2, + } + + if self:GetNWBool("ubgl") then + local ubglammo = self:GetBuff_Override("UBGL_Ammo") + + if ubglammo then + wreserve.text = "/ " .. tostring(self:GetOwner():GetAmmoCount(ubglammo)) + end + end + + if self.PrimaryBash then + wreserve.text = "/ -" + end + + MyDrawText(wreserve) + + wammo.w = surface.GetTextSize(tostring(clip)) + + if plus > 0 and !self:GetNWBool("ubgl") then + local wplus = { + x = wammo.x + bargap + wammo.w, + y = wammo.y, + text = "+" .. tostring(plus), + font = "ArcCW_16", + col = col2 + } + + MyDrawText(wplus) + end + + end + + end + + -- health + armor + + if ArcCW:ShouldDrawHUDElement("CHudHealth") then + + local colhp = col2 + + if LocalPlayer():Health() <= 30 then + colhp = col3 + end + + local whp = { + x = airgap, + y = ScrH() - ScreenScale(26) - ScreenScale(16) - airgap, + font = "ArcCW_26", + text = "HP: " .. tostring(math.Round(vhp)), + col = colhp, + shadow = true + } + + MyDrawText(whp) + + if LocalPlayer():Armor() > 0 then + local war = { + x = airgap, + y = ScrH() - ScreenScale(16) - airgap, + font = "ArcCW_16", + text = "ARMOR: " .. tostring(math.Round(varmor)), + col = col2, + shadow = true + } + + MyDrawText(war) + end + + end + + vhp = math.Approach(vhp, self:GetOwner():Health(), RealFrameTime() * 100) + varmor = math.Approach(varmor, self:GetOwner():Armor(), RealFrameTime() * 100) + + local clipdiff = math.abs(vclip - self:Clip1()) + local reservediff = math.abs(vreserve - self:Ammo1()) + + if clipdiff == 1 then + vclip = self:Clip1() + end + + vclip = math.Approach(vclip, self:Clip1(), RealFrameTime() * 30 * clipdiff) + vreserve = math.Approach(vreserve, self:Ammo1(), RealFrameTime() * 30 * reservediff) + + if lastwpn != self then + vclip = self:Clip1() + vreserve = self:Ammo1() + vhp = self:GetOwner():Health() + varmor = self:GetOwner():Armor() + end + + lastwpn = self +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_laser.lua b/lua/weapons/arccw_base/cl_laser.lua new file mode 100644 index 00000000..12b04655 --- /dev/null +++ b/lua/weapons/arccw_base/cl_laser.lua @@ -0,0 +1,159 @@ +function SWEP:DoLaser(wm) + wm = wm or false + + for i, k in pairs(self.Attachments) do + if !k.Installed then continue end + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if atttbl.Laser then + if wm then + if !k.WElement then continue end + cam.Start3D() + self:DrawLaser(atttbl, k.WElement.Model, atttbl.ColorOptionsTable[k.ColorOptionIndex or 1], true) + cam.End3D() + else + if !k.VElement then continue end + self:DrawLaser(atttbl, k.VElement.Model, atttbl.ColorOptionsTable[k.ColorOptionIndex or 1]) + end + end + end +end + +-- hook.Add("PostDrawEffects", "ArcCW_ScopeLaser", function() +-- -- if !ArcCW.LaserBehavior then return end + +-- -- local wep = LocalPlayer():GetActiveWeapon() + +-- -- if !wep.ArcCW then return end + +-- -- wep:DoLaser(false) +-- end) + +local lasermat = Material("arccw/laser") +local laserflare = Material("effects/whiteflare") + +local delta = 1 + +function SWEP:DrawLaser(ls, lsm, lsc, wm) + if !self:GetOwner() then return end + if !IsValid(self:GetOwner()) then return end + + if !lsm then return end + if !IsValid(lsm) then return end + + local attid = lsm:LookupAttachment(ls.LaserBone or "laser") + + if attid == 0 then + attid = lsm:LookupAttachment("muzzle") + end + + if attid == 0 then return end + + local ret = lsm:GetAttachment(attid) + local pos = ret.Pos + local ang = ret.Ang + + local dir = -ang:Right() + + if wm then + if self:GetOwner():IsNPC() then + dir = -ang:Right() + else + dir = self:GetOwner():EyeAngles():Forward() + end + else + ang:RotateAroundAxis(ang:Up(), 90) + + dir = ang:Forward() + + local eang = self:GetOwner():EyeAngles() + (self:GetOwner():GetViewPunchAngles() * 0.5) + + if self:GetCurrentFiremode().Mode != 0 and !self:GetNWBool("reloading", 0) then + delta = math.Approach(delta, self:GetSightDelta(), RealFrameTime() * 1 / 0.15) + else + delta = math.Approach(delta, 1, RealFrameTime() * 1 / 0.15) + end + + dir = Lerp(delta, eang:Forward(), dir) + end + + local dir2 = dir + + if wm then + dir2 = -ang:Right() + end + + local tpos = pos + + -- if !wm then + -- tpos = EyePos() + -- end + + if ArcCW.LaserBehavior and !wm then + ang = EyeAngles() - (self:GetOwner():GetViewPunchAngles() * 0.5) + + if GetConVar("arccw_cheapscopes"):GetBool() then + ang = EyeAngles() - (self:GetOwner():GetViewPunchAngles()) + end + + tpos = EyePos() - Vector(0, 0, 1) + pos = tpos + dir = ang:Forward() + dir2 = dir + end + + local di = 128 + + local tr = util.TraceLine({ + start = tpos, + endpos = tpos + (dir * 40000), + filter = self:GetOwner() + }) + + local btr = util.TraceLine({ + start = tpos, + endpos = tpos + (dir2 * di), + filter = self:GetOwner() + }) + + local hit = tr.HitPos + local didhit = tr.Hit + local m = ls.LaserStrength or 1 + local col = lsc + + if tr.StartSolid then + hit = tr.StartPos + end + + hit = hit - (EyeAngles():Forward() * 1.5) + + -- local hte = (hit - EyePos()):Length() + -- local htl = (pos - EyePos()):Length() + + if tr.StartSolid then return end + + local width = math.Rand(0.05, 0.1) * m + + if !ArcCW.LaserBehavior or wm then + render.SetMaterial(lasermat) + render.DrawBeam(pos, btr.HitPos, width, 1, 0, col) + else + cam.IgnoreZ(true) + end + + if didhit then + local sd = (tr.HitPos - EyePos()):Length() + local mult = math.log10(sd) * m + + render.SetMaterial(laserflare) + local r1 = math.Rand(4, 6) * mult + local r2 = math.Rand(4, 6) * mult + + render.DrawSprite(hit, r1, r2, col) + render.DrawSprite(hit, r1 * 0.25, r2 * 0.25, Color(255, 255, 255)) + end + + if ArcCW.LaserBehavior and !wm then + cam.IgnoreZ(false) + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_lhik.lua b/lua/weapons/arccw_base/cl_lhik.lua new file mode 100644 index 00000000..2ef60a46 --- /dev/null +++ b/lua/weapons/arccw_base/cl_lhik.lua @@ -0,0 +1,243 @@ +local function qerp(delta, a, b) + local qdelta = -(delta ^ 2) + (delta * 2) + + qdelta = math.Clamp(qdelta, 0, 1) + + return Lerp(qdelta, a, b) +end + +SWEP.LHIKAnimation_IsIdle = false +SWEP.LHIKAnimation = nil +SWEP.LHIKAnimationStart = 0 +SWEP.LHIKAnimationTime = 0 + +function SWEP:DoLHIKAnimation(key, time) + local lhik_model + + local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key) + + key = tranim or key + + for _, k in pairs(self.Attachments) do + if !k.Installed then continue end + if !k.VElement then continue end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if atttbl.LHIK then + lhik_model = k.VElement.Model + end + end + + if !lhik_model then return false end + + local seq = lhik_model:LookupSequence(key) + + if !seq then return false end + if seq == -1 then return false end + + lhik_model:ResetSequence(seq) + + if !time then time = lhik_model:SequenceDuration(seq) end + + self.LHIKAnimation = seq + self.LHIKAnimationStart = CurTime() + self.LHIKAnimationTime = time + + self.LHIKAnimation_IsIdle = false + + -- lhik_model:SetCycle(0) + -- lhik_model:SetPlaybackRate(dur / time) + + return true +end + +SWEP.LHIKDelta = {} +SWEP.LHIKDeltaAng = {} +SWEP.ViewModel_Hit = Vector(0, 0, 0) + +function SWEP:GetLHIKAnim() + local cyc = (CurTime() - self.LHIKAnimationStart) / self.LHIKAnimationTime + + if cyc > 1 then return nil end + if self.LHIKAnimation_IsIdle then return nil end + + return self.LHIKAnimation +end + +function SWEP:DoLHIK() + local justhide = false + local lhik_model = nil + local delta = 1 + + local vm = self:GetOwner():GetViewModel() + + + for _, k in pairs(self.Attachments) do + if !k.Installed then continue end + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if atttbl.LHIKHide then + justhide = true + end + + if !k.VElement then continue end + + if atttbl.LHIK then + lhik_model = k.VElement.Model + end + end + + if self.LHIKTimeline then + local tl = self.LHIKTimeline + + if tl[4] <= CurTime() then + -- it's over + delta = 1 + elseif tl[3] <= CurTime() then + -- transition back to 1 + delta = (CurTime() - tl[3]) / (tl[4] - tl[3]) + delta = qerp(delta, 0, 1) + + if lhik_model and IsValid(lhik_model) then + local key = "out" + + local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key) + + key = tranim or key + + local seq = lhik_model:LookupSequence(key) + + if seq > 0 then + lhik_model:SetSequence(seq) + lhik_model:SetCycle(delta) + end + end + elseif tl[2] <= CurTime() then + -- hold 0 + delta = 0 + elseif tl[1] <= CurTime() then + -- transition to 0 + delta = (CurTime() - tl[1]) / (tl[2] - tl[1]) + delta = qerp(delta, 1, 0) + + if lhik_model and IsValid(lhik_model) then + local key = "in" + + local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key) + + key = tranim or key + + local seq = lhik_model:LookupSequence(key) + + if seq and seq > 0 then + lhik_model:SetSequence(seq) + lhik_model:SetCycle(delta) + end + end + else + -- hasn't started yet + delta = 1 + end + end + + if justhide then + for _, bone in pairs(ArcCW.LHIKBones) do + local vmbone = vm:LookupBone(bone) + + local vmtransform = vm:GetBoneMatrix(vmbone) + + if !vmtransform then return end -- something very bad has happened + + local vm_pos = vmtransform:GetTranslation() + local vm_ang = vmtransform:GetAngles() + + local newtransform = Matrix() + + newtransform:SetTranslation(LerpVector(delta, vm_pos, vm_pos - (EyeAngles():Up() * 64))) + newtransform:SetAngles(vm_ang) + + vm:SetBoneMatrix(vmbone, newtransform) + end + end + + if !lhik_model or !IsValid(lhik_model) then return end + if justhide then return end + + lhik_model:SetupBones() + + local cyc = (CurTime() - self.LHIKAnimationStart) / self.LHIKAnimationTime + + if self.LHIKAnimation and cyc < 1 then + lhik_model:SetSequence(self.LHIKAnimation) + lhik_model:SetCycle(cyc) + else + local key = "idle" + + local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key) + + key = tranim or key + + self:DoLHIKAnimation(key, 1) + + self.LHIKAnimation_IsIdle = true + end + + local cf_deltapos = Vector(0, 0, 0) + local cf = 0 + + for _, bone in pairs(ArcCW.LHIKBones) do + local vmbone = vm:LookupBone(bone) + local lhikbone = lhik_model:LookupBone(bone) + + if !vmbone then continue end + if !lhikbone then continue end + + local vmtransform = vm:GetBoneMatrix(vmbone) + local lhiktransform = lhik_model:GetBoneMatrix(lhikbone) + + if !vmtransform then continue end + if !lhiktransform then continue end + + local vm_pos = vmtransform:GetTranslation() + local vm_ang = vmtransform:GetAngles() + local lhik_pos = lhiktransform:GetTranslation() + local lhik_ang = lhiktransform:GetAngles() + + local newtransform = Matrix() + + newtransform:SetTranslation(LerpVector(delta, vm_pos, lhik_pos)) + newtransform:SetAngles(LerpAngle(delta, vm_ang, lhik_ang)) + + if self.LHIKDelta[lhikbone] and self.LHIKAnimation and cyc < 1 then + local deltapos = lhik_model:WorldToLocal(lhik_pos) - self.LHIKDelta[lhikbone] + + if !deltapos:IsZero() then + cf_deltapos = cf_deltapos + deltapos + cf = cf + 1 + end + end + + self.LHIKDelta[lhikbone] = lhik_model:WorldToLocal(lhik_pos) + + vm:SetBoneMatrix(vmbone, newtransform) + + -- local vm_pos, vm_ang = vm:GetBonePosition(vmbone) + -- local lhik_pos, lhik_ang = lhik_model:GetBonePosition(lhikbone) + + -- local pos = LerpVector(delta, vm_pos, lhik_pos) + -- local ang = LerpAngle(delta, vm_ang, lhik_ang) + + -- vm:SetBonePosition(vmbone, pos, ang) + end + + if !cf_deltapos:IsZero() and cf > 0 and self:GetBuff_Override("LHIK_Animation") then + local new = Vector(0, 0, 0) + + new[1] = cf_deltapos[2] + new[2] = cf_deltapos[1] + new[3] = cf_deltapos[3] + + self.ViewModel_Hit = LerpVector(0.25, self.ViewModel_Hit, new / cf) + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_presets.lua b/lua/weapons/arccw_base/cl_presets.lua new file mode 100644 index 00000000..7fb7dd20 --- /dev/null +++ b/lua/weapons/arccw_base/cl_presets.lua @@ -0,0 +1,292 @@ +-- atts are comma separated +-- optic_mrs,,,perk_quickdraw,ammo_match + +function SWEP:GetPresetBase() + return self.PresetBase or self:GetClass() +end + +function SWEP:GetPresets() + local path = ArcCW.PresetPath .. self:GetPresetBase() .. "/*.txt" + + local files = file.Find(path, "DATA") + + return files +end + +function SWEP:LoadPreset(filename) + filename = filename or "autosave" + if !GetConVar("arccw_autosave"):GetBool() then + if filename == "autosave" then return end + end + + if filename != "autosave" then + surface.PlaySound("weapons/arccw/install.wav") + end + + filename = ArcCW.PresetPath .. self:GetPresetBase() .. "/" .. filename .. ".txt" + + if !file.Exists(filename, "DATA") then return end + + local f = file.Open(filename, "r", "DATA") + + if !f then return end + + for i = 1, table.Count(self.Attachments) do + local att = f:ReadLine() + + if !att then continue end + + att = string.Trim(att, "\n") + + if !att then continue end + + if !self.Attachments[i] then continue end + if att == self.Attachments[i].Installed then continue end + + self:Detach(i, true) + + if !ArcCW.AttachmentTable[att] then continue end + + self:Attach(i, att, true) + end + + f:Close() + + self:SavePreset() +end + +function SWEP:SavePreset(filename) + filename = filename or "autosave" + + local str = "" + for i, k in pairs(self.Attachments) do + if k.Installed then + str = str .. k.Installed .. "\n" + else + str = str .. "\n" + end + end + + filename = ArcCW.PresetPath .. self:GetPresetBase() .. "/" .. filename .. ".txt" + + file.CreateDir(ArcCW.PresetPath .. self:GetPresetBase()) + file.Write(filename, str) +end + +function SWEP:CreatePresetSave() + if !IsValid(ArcCW.InvHUD) then return end + local bg = vgui.Create("DFrame", ArcCW.InvHUD) + bg:SetPos(0, 0) + bg:SetSize(ScrW(), ScrH()) + bg:SetText("") + bg:SetTitle("") + bg:SetDraggable(false) + bg:ShowCloseButton(false) + bg.Paint = function(span) + surface.SetDrawColor(0, 0, 0, 200) + surface.DrawRect(0, 0, ScrW(), ScrH()) + end + bg:MakePopup() + + local text = vgui.Create("DTextEntry", bg) + text:SetSize(ScreenScale(256), ScreenScale(26)) + text:Center() + text:RequestFocus() + text:SetFont("ArcCW_24") + text:SetText("") + + local accept = vgui.Create("DButton", bg) + accept:SetSize((ScreenScale(256) - ScreenScale(2)) / 2, ScreenScale(14)) + accept:SetText("") + accept:SetPos((ScrW() - ScreenScale(256)) / 2, ((ScrH() - ScreenScale(14)) / 2) + ScreenScale(26) + ScreenScale(2)) + + accept.OnMousePressed = function(spaa, kc) + local txt = text:GetText() + txt = string.sub(txt, 0, 36) + self:SavePreset(txt) + bg:Close() + bg:Remove() + end + + accept.Paint = function(spaa, w, h) + if !self:IsValid() then return end + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + + if spaa:IsHovered() then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + + local txt = "Save" + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(ScreenScale(2), ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + end + + local cancel = vgui.Create("DButton", bg) + cancel:SetSize((ScreenScale(256) - ScreenScale(2)) / 2, ScreenScale(14)) + cancel:SetText("") + cancel:SetPos(((ScrW() - ScreenScale(256)) / 2) + ScreenScale(128 + 1), ((ScrH() - ScreenScale(14)) / 2) + ScreenScale(26) + ScreenScale(2)) + + cancel.OnMousePressed = function(spaa, kc) + bg:Close() + bg:Remove() + end + + cancel.Paint = function(spaa, w, h) + if !self:IsValid() then return end + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + + if spaa:IsHovered() then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + + local txt = "Cancel" + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(ScreenScale(2), ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + end +end + +function SWEP:CreatePresetMenu() + if !IsValid(ArcCW.InvHUD) then return end + + if !IsValid(ArcCW.InvHUD) then return end + local bg = vgui.Create("DFrame", ArcCW.InvHUD) + bg:SetPos(0, 0) + bg:SetSize(ScrW(), ScrH()) + bg:SetText("") + bg:SetTitle("") + bg:SetDraggable(false) + bg:ShowCloseButton(false) + bg.Paint = function(span) + surface.SetDrawColor(0, 0, 0, 200) + surface.DrawRect(0, 0, ScrW(), ScrH()) + end + + local cancel = vgui.Create("DButton", bg) + cancel:SetSize(ScreenScale(128), ScreenScale(14)) + cancel:SetText("") + cancel:SetPos((ScrW() - ScreenScale(128)) / 2, ScrH() - ScreenScale(32)) + + cancel.OnMousePressed = function(spaa, kc) + bg:Close() + bg:Remove() + end + + cancel.Paint = function(spaa, w, h) + if !self:IsValid() then return end + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + + if spaa:IsHovered() then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + + local txt = "Cancel" + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(ScreenScale(2), ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + end + + local presetsmenu = vgui.Create("DScrollPanel", bg) + presetsmenu:SetText("") + presetsmenu:SetSize(ScreenScale(256), ScrH() - ScreenScale(64)) + presetsmenu:SetPos((ScrW() - ScreenScale(256)) / 2, ScreenScale(8)) + presetsmenu.Paint = function(span, w, h) + end + + local sbar = presetsmenu:GetVBar() + sbar.Paint = function() end + + sbar.btnUp.Paint = function(span, w, h) + end + + sbar.btnDown.Paint = function(span, w, h) + end + + sbar.btnGrip.Paint = function(span, w, h) + surface.SetDrawColor(255, 255, 255, 255) + surface.DrawRect(0, 0, w, h) + end + + local c = 0 + + for i, k in pairs(self:GetPresets()) do + if k == "autosave.txt" then continue end + local preset = vgui.Create("DButton", presetsmenu) + preset:SetSize(ScreenScale(254), ScreenScale(14)) + preset:SetText("") + preset:Dock(TOP) + preset:DockMargin( 0, 0, 0, ScreenScale(2) ) + + preset.PresetName = string.sub(k, 1, -5) + + preset.OnMousePressed = function(spaa, kc) + self:LoadPreset(spaa.PresetName) + bg:Close() + bg:Remove() + end + + preset.Paint = function(spaa, w, h) + if !self:IsValid() then return end + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + + if spaa:IsHovered() then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(ScreenScale(2), ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(string.upper(spaa.PresetName)) + end + c = c + 1 + end + + if c == 0 then + local label = vgui.Create("DLabel", presetsmenu) + label:SetSize(ScreenScale(254), ScreenScale(14)) + label:SetText("") + label:Dock(TOP) + label:DockMargin( 0, 0, 0, ScreenScale(2) ) + + label.Paint = function(spaa, w, h) + local Bfg_col = Color(255, 255, 255, 255) + + local txt = "No presets found! Go make some!" + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(ScreenScale(2), ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + end + end +end + +function SWEP:ClosePresetMenu() +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_scope.lua b/lua/weapons/arccw_base/cl_scope.lua new file mode 100644 index 00000000..b66832cc --- /dev/null +++ b/lua/weapons/arccw_base/cl_scope.lua @@ -0,0 +1,65 @@ +function SWEP:AdjustMouseSensitivity() + if self:GetState() != ArcCW.STATE_SIGHTS then return end + + local irons = self:GetActiveSights() + + return 1 / (irons.Magnification + (irons.ScopeMagnification or 0)) +end + +function SWEP:Scroll(var) + local irons = self:GetActiveSights() + + if irons.ScrollFunc == ArcCW.SCROLL_ZOOM then + if !irons.ScopeMagnificationMin then return end + if !irons.ScopeMagnificationMax then return end + + local old = irons.ScopeMagnification + + local minus = var < 0 + + var = math.abs(irons.ScopeMagnificationMax - irons.ScopeMagnificationMin) + + var = var / (irons.ZoomLevels or 5) + + if minus then + var = var * -1 + end + + irons.ScopeMagnification = irons.ScopeMagnification - var + + irons.ScopeMagnification = math.Clamp(irons.ScopeMagnification, irons.ScopeMagnificationMin, irons.ScopeMagnificationMax) + + self.SightMagnifications[irons.Slot or 0] = irons.ScopeMagnification + + if old != irons.ScopeMagnification then + self:EmitSound(irons.ZoomSound or "", 75, math.Rand(95, 105), 1, CHAN_ITEM) + end + + -- if !irons.MinZoom then return end + -- if !irons.MaxZoom then return end + + -- local old = irons.Magnification + + -- irons.Magnification = irons.Magnification - var + + -- irons.Magnification = math.Clamp(irons.Magnification, irons.MinZoom, irons.MaxZoom) + + -- if old != irons.Magnification then + -- self:EmitSound(irons.ZoomSound or "", 75, 100, 1, CHAN_ITEM) + -- end + end + +end + +function SWEP:CalcView(ply, pos, ang, fov) + if !GetConVar("arccw_shake"):GetBool() then return end + + return pos, ang + (AngleRand() * self.RecoilAmount * 0.008), fov +end + +function SWEP:ShouldGlint() + return self:GetBuff_Override("ScopeGlint") and self:GetNWBool("state") == ArcCW.STATE_SIGHTS +end + +function SWEP:DoScopeGlint() +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/cl_viewmodel.lua b/lua/weapons/arccw_base/cl_viewmodel.lua new file mode 100644 index 00000000..1a6cd961 --- /dev/null +++ b/lua/weapons/arccw_base/cl_viewmodel.lua @@ -0,0 +1,424 @@ +SWEP.ActualVMData = false + +local function ApproachVector(vec1, vec2, d) + local vec3 = Vector() + vec3[1] = math.Approach(vec1[1], vec2[1], d) + vec3[2] = math.Approach(vec1[2], vec2[2], d) + vec3[3] = math.Approach(vec1[3], vec2[3], d) + + return vec3 +end + +local function ApproachAngleA(vec1, vec2, d) + local vec3 = Angle() + vec3[1] = math.ApproachAngle(vec1[1], vec2[1], d) + vec3[2] = math.ApproachAngle(vec1[2], vec2[2], d) + vec3[3] = math.ApproachAngle(vec1[3], vec2[3], d) + + return vec3 +end + +function SWEP:GetViewModelPosition(pos, ang) + local oldpos = Vector() + local oldang = Angle() + + local ft = RealFrameTime() + + local asight = self:GetActiveSights() + + oldpos:Set(pos) + oldang:Set(ang) + + ang = ang - (self:GetOwner():GetViewPunchAngles() * 0.5) + + actual = self.ActualVMData or {pos = Vector(0, 0, 0), ang = Angle(0, 0, 0), down = 1, sway = 1, bob = 1} + + local target = { + pos = self:GetBuff_Override("Override_ActivePos") or self.ActivePos, + ang = self:GetBuff_Override("Override_ActiveAng") or self.ActiveAng, + down = 1, + sway = 2, + bob = 2, + } + + local vm_right = GetConVar("arccw_vm_right"):GetFloat() + local vm_up = GetConVar("arccw_vm_up"):GetFloat() + local vm_forward = GetConVar("arccw_vm_forward"):GetFloat() + + target.pos = target.pos + Vector(vm_right, vm_forward, vm_up) + + local state = self:GetState() + + if self:GetOwner():Crouching() then + target.down = 0 + if self.CrouchPos then + target.pos = self.CrouchPos + target.ang = self.CrouchAng + end + end + + if self:InBipod() then + target.pos = target.pos + ((self.BipodAngle - self:GetOwner():EyeAngles()):Right() * -4) + target.sway = 0.2 + end + + local sighted = self.Sighted or state == ArcCW.STATE_SIGHTS + if game.SinglePlayer() then + sighted = state == ArcCW.STATE_SIGHTS + end + + local sprinted = self.Sprinted or state == ArcCW.STATE_SPRINT + if game.SinglePlayer() then + sprinted = state == ArcCW.STATE_SPRINT + end + + if state == ArcCW.STATE_CUSTOMIZE then + target = { + pos = Vector(), + ang = Angle(), + down = 1, + sway = 3, + bob = 1, + } + + local mx, my = input.GetCursorPos() + + mx = 2 * mx / ScrW() + my = 2 * my / ScrH() + + target.pos:Set(self.CustomizePos) + target.ang:Set(self.CustomizeAng) + + target.pos = target.pos + Vector(mx, 0, my) + target.ang = target.ang + Angle(0, my * 2, mx * 2) + + if self.InAttMenu then + target.ang = target.ang + Angle(0, -5, 0) + end + + elseif (sprinted or (self:GetCurrentFiremode().Mode == 0 and !sighted)) and !(self:GetBuff_Override("Override_ShootWhileSprint") or self.ShootWhileSprint) then + target = { + pos = self.HolsterPos, + ang = Angle(), + down = 1, + sway = 4, + bob = 5, + } + + target.ang:Set(self.HolsterAng) + + if ang.p < -15 then + target.ang.p = target.ang.p + ang.p + 15 + end + + target.ang.p = math.Clamp(target.ang.p, -80, 80) + elseif sighted then + local irons = self:GetActiveSights() + + target = { + pos = irons.Pos, + ang = irons.Ang, + evpos = irons.EVPos or Vector(0, 0, 0), + evang = irons.EVAng or Angle(0, 0, 0), + down = 0, + sway = 0.1, + bob = 0.1, + } + + local sr = self:GetBuff_Override("Override_AddSightRoll") + + if sr then + target.ang = Angle() + + target.ang:Set(irons.Ang) + target.ang.r = sr + end + + -- local anchor = irons.AnchorBone + + -- if anchor then + -- local vm = self:GetOwner():GetViewModel() + -- local bone = vm:LookupBone(anchor) + -- local bpos, bang = vm:GetBonePosition(bone) + + -- print(bpos) + -- end + end + + local deg = self:BarrelHitWall() + + if deg > 0 then + target = { + pos = LerpVector(deg, target.pos, self.HolsterPos), + ang = LerpAngle(deg, target.ang, self.HolsterAng), + down = 2, + sway = 2, + bob = 2, + } + end + + if isangle(target.ang) then + target.ang = Angle(target.ang) + end + + if self.InProcDraw then + self.InProcHolster = false + local delta = math.Clamp((CurTime() - self.ProcDrawTime) / (0.25 * self:GetBuff_Mult("Mult_HolsterTime")), 0, 1) + target = { + pos = LerpVector(delta, Vector(0, -30, -30), target.pos), + ang = LerpAngle(delta, Angle(40, 30, 0), target.ang), + down = target.down, + sway = target.sway, + bob = target.bob, + } + + if delta == 1 then + self.InProcDraw = false + end + end + + if self.InProcHolster then + self.InProcDraw = false + local delta = 1 - math.Clamp((CurTime() - self.ProcHolsterTime) / 0.25, 0, 1) + target = { + pos = LerpVector(delta, Vector(0, -30, -30), target.pos), + ang = LerpAngle(delta, Angle(40, 30, 0), target.ang), + down = target.down, + sway = target.sway, + bob = target.bob, + } + + if delta == 0 then + self.InProcHolster = false + end + end + + if self.InProcBash then + self.InProcDraw = false + + local mult = self:GetBuff_Mult("Mult_MeleeTime") + local mt = self.MeleeTime * mult + + local delta = 1 - math.Clamp((CurTime() - self.ProcBashTime) / mt, 0, 1) + + local bp = self.BashPos + local ba = self.BashAng + + if delta > 0.3 then + bp = self.BashPreparePos + ba = self.BashPrepareAng + delta = (delta - 0.5) * 2 + else + delta = delta * 2 + end + + target = { + pos = LerpVector(delta, bp, target.pos), + ang = LerpAngle(delta, ba, target.ang), + down = target.down, + sway = target.sway, + bob = target.bob, + speed = 10 + } + + if delta == 0 then + self.InProcBash = false + end + end + + if self.ViewModel_Hit then + local nap = Vector() + + nap[1] = self.ViewModel_Hit[1] + nap[2] = self.ViewModel_Hit[2] + nap[3] = self.ViewModel_Hit[3] + + nap[1] = math.Clamp(nap[1], -1, 1) + nap[2] = math.Clamp(nap[2], -1, 1) + nap[3] = math.Clamp(nap[3], -1, 1) + + target.pos = target.pos + nap + + if !self.ViewModel_Hit:IsZero() then + local naa = Angle() + + naa[1] = self.ViewModel_Hit[1] + naa[2] = self.ViewModel_Hit[2] + naa[3] = self.ViewModel_Hit[3] + + naa[1] = math.Clamp(naa[1], -1, 1) + naa[2] = math.Clamp(naa[2], -1, 1) + naa[3] = math.Clamp(naa[3], -1, 1) + + target.ang = target.ang + (naa * 10) + end + + local nvmh = Vector(0, 0, 0) + + local spd = self.ViewModel_Hit:Length() + + nvmh[1] = math.Approach(self.ViewModel_Hit[1], 0, ft * 5 * spd) + nvmh[2] = math.Approach(self.ViewModel_Hit[2], 0, ft * 5 * spd) + nvmh[3] = math.Approach(self.ViewModel_Hit[3], 0, ft * 5 * spd) + + self.ViewModel_Hit = nvmh + + -- local nvma = Angle(0, 0, 0) + + -- local spd2 = 360 + + -- nvma[1] = math.ApproachAngle(self.ViewModel_HitAng[1], 0, ft * 5 * spd2) + -- nvma[2] = math.ApproachAngle(self.ViewModel_HitAng[2], 0, ft * 5 * spd2) + -- nvma[3] = math.ApproachAngle(self.ViewModel_HitAng[3], 0, ft * 5 * spd2) + + -- self.ViewModel_HitAng = nvma + end + + target.pos = target.pos + (VectorRand() * self.RecoilAmount * 0.2) + + local speed = target.speed or 3 + + speed = 1 / self:GetSightTime() * speed * ft + + actual.pos = LerpVector(speed, actual.pos, target.pos) + actual.ang = LerpAngle(speed, actual.ang, target.ang) + actual.down = Lerp(speed, actual.down, target.down) + actual.sway = Lerp(speed, actual.sway, target.sway) + actual.bob = Lerp(speed, actual.bob, target.bob) + actual.evpos = Lerp(speed, actual.evpos or Vector(0, 0, 0), target.evpos or Vector(0, 0, 0)) + actual.evang = Lerp(speed, actual.evang or Angle(0, 0, 0), target.evang or Angle(0, 0, 0)) + + actual.pos = ApproachVector(actual.pos, target.pos, speed * 0.1) + actual.ang = ApproachAngleA(actual.ang, target.ang, speed * 0.1) + actual.down = math.Approach(actual.down, target.down, speed * 0.1) + + self.SwayScale = actual.sway + self.BobScale = actual.bob + + pos = pos + self.RecoilPunchBack * -oldang:Forward() + pos = pos + self.RecoilPunchSide * oldang:Right() + pos = pos + self.RecoilPunchUp * -oldang:Up() + + ang:RotateAroundAxis( oldang:Right(), actual.ang.x ) + ang:RotateAroundAxis( oldang:Up(), actual.ang.y ) + ang:RotateAroundAxis( oldang:Forward(), actual.ang.z ) + + ang:RotateAroundAxis( oldang:Right(), actual.evang.x ) + ang:RotateAroundAxis( oldang:Up(), actual.evang.y ) + ang:RotateAroundAxis( oldang:Forward(), actual.evang.z ) + + pos = pos + (oldang:Right() * actual.evpos.x) + pos = pos + (oldang:Forward() * actual.evpos.y) + pos = pos + (oldang:Up() * actual.evpos.z) + + pos = pos + actual.pos.x * ang:Right() + pos = pos + actual.pos.y * ang:Forward() + pos = pos + actual.pos.z * ang:Up() + + pos = pos - Vector(0, 0, actual.down) + + if asight and asight.Holosight then + ang = ang - (self:GetOwner():GetViewPunchAngles() * 0.5) + end + + self.ActualVMData = actual + + return pos, ang +end + +local function ShouldCheapWorldModel() + return !GetConVar("arccw_att_showothers"):GetBool() +end + +function SWEP:DrawWorldModel() + if !IsValid(self:GetOwner()) and GetConVar("arccw_2d3d"):GetBool() then + if (EyePos() - self:GetPos()):LengthSqr() <= 262144 then -- 512^2 + local ang = LocalPlayer():EyeAngles() + + ang:RotateAroundAxis(ang:Forward(), 180) + ang:RotateAroundAxis(ang:Right(), 90) + ang:RotateAroundAxis(ang:Up(), 90) + + cam.Start3D2D(self:GetPos() + Vector(0, 0, 16), ang, 0.1) + surface.SetFont("ArcCW_32_Unscaled") + + local w = surface.GetTextSize(self.PrintName) + + surface.SetTextPos(-w / 2, 0) + surface.SetTextColor(255, 255, 255, 255) + surface.DrawText(self.PrintName) + + surface.SetFont("ArcCW_24_Unscaled") + + local t = tostring(self:CountAttachments()) .. " Attachments" + + w = surface.GetTextSize(t) + + surface.SetTextPos(-w / 2, 32) + surface.SetTextColor(255, 255, 255, 255) + surface.DrawText(t) + cam.End3D2D() + end + end + + if ShouldCheapWorldModel() then + self:DrawModel() + else + self:DrawCustomModel(true) + end + + self:DoLaser(true) + + if self:ShouldGlint() then + self:DoScopeGlint() + end + + if !self.CertainAboutAtts then + net.Start("arccw_rqwpnnet") + net.WriteEntity(self) + net.SendToServer() + end +end + +function SWEP:PreDrawViewModel(vm) + if !vm then return end + + if GetConVar("arccw_cheapscopesautoconfig"):GetBool() then + -- auto configure what the best option is likely to be + -- if you can't get more than 45fps you probably want cheap scopes + + local fps = 1 / RealFrameTime() + + if fps >= 45 then + GetConVar("arccw_cheapscopes"):SetBool(false) + else + GetConVar("arccw_cheapscopes"):SetBool(true) + end + + GetConVar("arccw_cheapscopesautoconfig"):SetBool(false) + end + + local asight = self:GetActiveSights() + + if GetConVar("arccw_cheapscopes"):GetBool() and self:GetSightDelta() < 1 and asight.MagnifiedOptic then + self:FormCheapScope() + end + + self:DrawCustomModel(false) + + self:DoLHIK() +end + +function SWEP:PostDrawViewModel() + + if ArcCW.Overdraw then + ArcCW.Overdraw = false + else + self:DoLaser() + self:DoHolosight() + + if self:GetState() == ArcCW.STATE_CUSTOMIZE then + self:BlurNotWeapon() + end + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_anim.lua b/lua/weapons/arccw_base/sh_anim.lua new file mode 100644 index 00000000..f7f8df32 --- /dev/null +++ b/lua/weapons/arccw_base/sh_anim.lua @@ -0,0 +1,273 @@ +if SERVER then + +function SWEP:DoLHIKAnimation(key, time) + if game.SinglePlayer() then + net.Start("arccw_sp_lhikanim") + net.WriteString(key) + net.WriteFloat(time) + net.Send(self:GetOwner()) + end +end + +end + +function SWEP:PlayAnimation(key, mult, pred, startfrom, tt, skipholster) + mult = mult or 1 + pred = pred or false + startfrom = startfrom or 0 + tt = tt or false + skipholster = skipholster or false + + if !self.Animations[key] then return end + + -- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + + -- print(key) + + local anim = self.Animations[key] + + local tranim = self:GetBuff_Hook("Hook_TranslateAnimation", key) + + if tranim == false then return end + + if self.Animations[tranim] then + anim = self.Animations[tranim] + end + + if anim.Mult then + mult = mult * anim.Mult + end + + if game.SinglePlayer() and SERVER and pred then + net.Start("arccw_sp_anim") + net.WriteString(key) + net.WriteFloat(mult) + net.WriteFloat(startfrom) + net.Send(self:GetOwner()) + end + + if anim.ProcHolster and !skipholster then + self:ProceduralHolster() + self:SetTimer(0.25, function() + self:PlayAnimation(anim, mult, true, startfrom, tt, true) + end) + if tt then + self:SetNextPrimaryFire(CurTime() + 0.25) + end + return + end + + if anim.ViewPunchTable then + for k, v in pairs(anim.ViewPunchTable) do + + if !v.t then continue end + + local st = (v.t * mult) - startfrom + + if isnumber(v.t) then + if st < 0 then continue end + if self:GetOwner():IsPlayer() then + self:SetTimer(st, function() if !game.SinglePlayer() and !IsFirstTimePredicted() then return end self:GetOwner():ViewPunch(v.p or Vector(0, 0, 0)) end, id) + end + end + end + end + + if isnumber(anim.ShellEjectAt) then + self:SetTimer(anim.ShellEjectAt, function() + self:DoShellEject() + end) + end + + local vm = self:GetOwner():GetViewModel() + + if !vm then return end + if !IsValid(vm) then return end + + self:KillTimer("idlereset") + + self:GetAnimTime(key) + + local ttime = (anim.Time * mult) - startfrom + + if startfrom > anim.Time then return end + + if tt then + self:SetNextPrimaryFire(CurTime() + ttime) + end + + if anim.LHIK then + self.LHIKTimeline = { + CurTime() - startfrom, + CurTime() - startfrom + (anim.LHIKIn or 0.1) * mult, + CurTime() - startfrom + ttime - (anim.LHIKOut or 0.1) * mult, + CurTime() - startfrom + ttime + } + + if !anim.LHIKIn or anim.LHIKIn == 0 then + self.LHIKTimeline[1] = 0 + self.LHIKTimeline[2] = 0 + end + + if !anim.LHIKOut or anim.LHIKOut == 0 then + self.LHIKTimeline[3] = math.huge + self.LHIKTimeline[4] = math.huge + end + end + + if anim.LastClip1OutTime then + self.LastClipOutTime = CurTime() + ((anim.LastClip1OutTime * mult) - startfrom) + end + + local seq = anim.Source + + if anim.RareSource and math.random(1, 100) <= 1 then + seq = anim.RareSource + end + + if istable(seq) then + seq["BaseClass"] = nil + + seq = table.Random(seq) + end + + if isstring(seq) then + seq = vm:LookupSequence(seq) + end + + vm:SendViewModelMatchingSequence(seq) + + local framestorealtime = 1 + + if anim.FrameRate then + framestorealtime = 1 / anim.FrameRate + end + + local dur = vm:SequenceDuration() + + vm:SetPlaybackRate(dur / (ttime + startfrom)) + + if anim.Checkpoints then + self.CheckpointAnimation = key + self.CheckpointTime = startfrom + + for i, k in pairs(anim.Checkpoints) do + if !k then continue end + if istable(k) then continue end + local realtime = k * framestorealtime + + if realtime > startfrom then + self:SetTimer((realtime * mult) - startfrom, function() + self.CheckpointAnimation = key + self.CheckpointTime = realtime + end) + end + end + end + + if CLIENT then + if startfrom >= 0 then + vm:SetAnimTime(CurTime() - startfrom) + end + end + + if anim.TPAnim then + if anim.TPAnimStartTime then + local aseq = self:GetOwner():SelectWeightedSequence(anim.TPAnim) + if aseq then + self:GetOwner():AddVCDSequenceToGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD, aseq, anim.TPAnimStartTime, true ) + end + else + self:GetOwner():DoAnimationEvent(anim.TPAnim) + end + end + + self:PlaySoundTable(anim.SoundTable or {}, 1 / mult, startfrom) + + self:SetTimer(ttime, function() + self:NextAnimation() + + if anim.Checkpoints then + self.CheckpointAnimation = nil + self.CheckpointTime = 0 + end + end, key) + if key != "idle" then + self:SetTimer(ttime, function() + if self:GetState() == ArcCW.STATE_SPRINT and self.Animations.idle_sprint then + if self:Clip1() == 0 and self.Animations.idle_sprint_empty then + self:PlayAnimation("idle_sprint_empty", 1, pred) + else + self:PlayAnimation("idle_sprint", 1, pred) + end + + return + end + + if self:InBipod() and self.Animations.idle_bipod then + if self:Clip1() == 0 and self.Animations.idle_bipod_empty then + self:PlayAnimation("idle_bipod_empty", 1, pred) + else + self:PlayAnimation("idle_bipod", 1, pred) + end + + return + end + + if self:GetState() == ArcCW.STATE_SIGHTS and self.Animations.idle_sights then + if self:Clip1() == 0 and self.Animations.idle_sights_empty then + self:PlayAnimation("idle_sights_empty", 1, pred) + else + self:PlayAnimation("idle_sights", 1, pred) + end + + return + end + + if self:Clip1() == 0 and self.Animations.idle_empty then + self:PlayAnimation("idle_empty", 1, pred) + else + self:PlayAnimation("idle", 1, pred) + end + end, "idlereset") + end +end + +function SWEP:GetAnimTime(key) + local anim = self.Animations[key] + + if !anim then return end + + if !anim.Time then + local tseq = anim.Source + + if istable(tseq) then + tseq["BaseClass"] = nil -- god I hate Lua inheritance + tseq = tseq[1] + end + + tseq = vm:LookupSequence(tseq) + + anim.Time = vm:SequenceDuration(tseq) or 1 + end + + return anim.Time +end + +function SWEP:QueueAnimation(key, mult, pred, sf) + pred = pred or false + sf = sf or false + table.insert(self.AnimQueue, {k = key, m = mult, p = pred, sf = sf}) + + if table.Count(self.AnimQueue) == 0 then + self:NextAnimation() + end +end + +function SWEP:NextAnimation() + if table.Count(self.AnimQueue) == 0 then return end + + local anim = table.remove(self.AnimQueue, 1) + + self:PlayAnimation(anim.k, anim.m, anim.p, 0, anim.sf) +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_attach.lua b/lua/weapons/arccw_base/sh_attach.lua new file mode 100644 index 00000000..55239d45 --- /dev/null +++ b/lua/weapons/arccw_base/sh_attach.lua @@ -0,0 +1,840 @@ +ArcCW.ConVar_BuffMults = { + ["Mult_Damage"] = "arccw_mult_damage", + ["Mult_DamageMin"] = "arccw_mult_damage", + ["Mult_DamageNPC"] = "arccw_mult_npcdamage", + ["Mult_HipDispersion"] = "arccw_mult_hipfire", + ["Mult_ReloadTime"] = "arccw_mult_reloadtime", + ["Mult_SightTime"] = "arccw_mult_sighttime", + ["Mult_Range"] = "arccw_mult_range", + ["Mult_Recoil"] = "arccw_mult_recoil", + ["Mult_MoveDispersion"] = "arccw_mult_movedisp", + ["Mult_Penetration"] = "arccw_mult_penetration" +} + +function SWEP:GetBuff_Hook(buff, data) + -- call through hook function, args = data. return nil to do nothing. return false to prevent thing from happening. + + for i, k in pairs(self.Attachments) do + if !k.Installed then continue end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if !atttbl then continue end + + if isfunction(atttbl[buff]) then + local ret = atttbl[buff](self, data) + + if ret == nil then continue end + + if ret == false then return end + + data = ret + end + end + + local cfm = self:GetCurrentFiremode() + + if cfm and isfunction(cfm[buff]) then + local ret = cfm[buff](self, data) + + if ret != nil then + + if ret == false then return end + + data = ret + + end + end + + for i, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if ele then + if ele[buff] then + local ret = ele[buff](self, data) + + if ret != nil then + + if ret == false then return end + + data = ret + end + end + end + end + + if isfunction(self:GetTable()[buff]) then + local ret = self:GetTable()[buff](self, data) + + if ret != nil then + + if ret == false then return end + + data = ret + + end + end + + hook.Call(buff, ArcCW, self, data) + + return data +end + +function SWEP:GetBuff_Override(buff) + local level = 0 + local current = nil + local winningslot = nil + + for i, k in pairs(self.Attachments) do + if !k.Installed then continue end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if !atttbl then continue end + + if atttbl[buff] != nil then + if level == 0 or (atttbl[buff .. "_Priority"] and atttbl[buff .. "_Priority"] > level) then + current = atttbl[buff] + level = atttbl[buff .. "_Priority"] or 1 + winningslot = i + end + end + end + + if !ArcCW.BuffStack then + + ArcCW.BuffStack = true + + local cfm = self:GetCurrentFiremode() + + if cfm and cfm[buff] != nil then + if level == 0 or (cfm[buff .. "_Priority"] and cfm[buff .. "_Priority"] > level) then + current = cfm[buff] + level = cfm[buff .. "_Priority"] or 1 + end + end + + ArcCW.BuffStack = false + + end + + for i, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if ele then + if ele[buff] != nil then + if level == 0 or (ele[buff .. "_Priority"] and ele[buff .. "_Priority"] > level) then + current = ele[buff] + level = ele[buff .. "_Priority"] or 1 + winningslot = i + end + end + end + end + + if self:GetTable()[buff] != nil then + if level == 0 or (self:GetTable()[buff .. "_Priority"] and self:GetTable()[buff .. "_Priority"] > level) then + current = self:GetTable()[buff] + level = self:GetTable()[buff .. "_Priority"] or 1 + end + end + + local data = { + buff = buff, + current = current, + winningslot = winningslot + } + + if !ArcCW.BuffStack then + + ArcCW.BuffStack = true + + current = (self:GetBuff_Hook("O_Hook_" .. buff, data) or {}).current or current + + ArcCW.BuffStack = false + + end + + return current, winningslot +end + +function SWEP:GetBuff_Mult(buff) + local mult = 1 + + for i, k in pairs(self.Attachments) do + if !k.Installed then continue end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if atttbl[buff] then + mult = mult * atttbl[buff] + end + end + + local cfm = self:GetCurrentFiremode() + + if cfm and cfm[buff] then + mult = mult * cfm[buff] + end + + if self:GetTable()[buff] then + mult = mult * self:GetTable()[buff] + end + + if ArcCW.ConVar_BuffMults[buff] then + mult = mult * GetConVar(ArcCW.ConVar_BuffMults[buff]):GetFloat() + end + + for i, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if ele then + if ele[buff] then + mult = mult * ele[buff] + end + end + end + + local data = { + buff = buff, + mult = mult + } + + if !ArcCW.BuffStack then + + ArcCW.BuffStack = true + + mult = (self:GetBuff_Hook("M_Hook_" .. buff, data) or {}).mult or mult + + ArcCW.BuffStack = false + + end + + return mult +end + +function SWEP:GetBuff_Add(buff) + local add = 0 + + for i, k in pairs(self.Attachments) do + if !k.Installed then continue end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if atttbl[buff] then + add = add + atttbl[buff] + end + end + + local cfm = self:GetCurrentFiremode() + + if cfm and cfm[buff] then + add = add + cfm[buff] + end + + for i, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if ele then + if ele[buff] then + add = add + ele[buff] + end + end + end + + local data = { + buff = buff, + add = add + } + + if !ArcCW.BuffStack then + + ArcCW.BuffStack = true + + add = (self:GetBuff_Hook("A_Hook_" .. buff, data) or {}).add or add + + ArcCW.BuffStack = false + + end + + return add +end + +SWEP.ActiveElementCache = nil + +function SWEP:GetActiveElements(recache) + if self.ActiveElementCache and !recache then return self.ActiveElementCache end + + local eles = {} + + for _, i in pairs(self.Attachments) do + if !i.Installed then continue end + + if i.InstalledEles then + table.Add(eles, i.InstalledEles) + end + + local atttbl = ArcCW.AttachmentTable[i.Installed] + + if atttbl.ActivateElements then + table.Add(eles, atttbl.ActivateElements) + end + + local slots = atttbl.Slot + + if isstring(slots) then + slots = {slots} + end + + table.Add(eles, slots or {}) + + table.insert(eles, i.Installed) + end + + table.Add(eles, self.DefaultElements) + + local eles2 = {} + + ArcCW.Overflow = true + + for f, i in pairs(eles) do + local e = self.AttachmentElements[i] + + if !e then continue end + + if !self:CheckFlags(e.ExcludeFlags, e.RequireFlags) then continue end + + local a = false + local c = 0 + + for g = f, table.Count(eles) do + if eles[g] == i then c = c + 1 end + + if c > 1 then a = true break end + end + + if a then continue end + + table.insert(eles2, i) + end + + ArcCW.Overflow = false + + self.ActiveElementCache = eles2 + + return eles2 +end + +function SWEP:GetMuzzleDevice(wm) + local model = self.WM + local muzz = self + + if !wm then + model = self.VM + muzz = self:GetOwner():GetViewModel() + end + + if model then + for _, ele in pairs(model) do + if ele.IsMuzzleDevice then + muzz = ele.Model or muzz + end + end + end + + if self:GetNWBool("ubgl") then + local _, slot = self:GetBuff_Override("UBGL") + + if wm then + muzz = (self.Attachments[slot].WMuzzleDeviceElement or {}).Model or muzz + else + muzz = (self.Attachments[slot].VMuzzleDeviceElement or {}).Model or muzz + end + end + + return muzz +end + +function SWEP:CheckFlags(reject, need) + local flags = self:GetWeaponFlags() + + reject = reject or {} + need = need or {} + + for _, i in pairs(reject) do + if table.HasValue(flags, i) then + return false + end + end + + for _, i in pairs(need) do + if !table.HasValue(flags, i) then + return false + end + end + + return true +end + +function SWEP:GetWeaponFlags() + local flags = {} + + for _, i in pairs(self.Attachments) do + if !i.Installed then continue end + + local atttbl = ArcCW.AttachmentTable[i.Installed] + + if atttbl.GivesFlags then + table.Add(flags, atttbl.GivesFlags) + end + + if i.GivesFlags then + table.Add(flags, i.GivesFlags) + end + + table.Add(flags, i.Installed) + end + + return flags +end + +function SWEP:PlayerOwnsAtt(att) + local qty = ArcCW:PlayerGetAtts(self:GetOwner(), att) + + return qty > 0 +end + +function SWEP:NetworkWeapon(sendto) + net.Start("arccw_networkatts") + net.WriteEntity(self) -- self entity + + net.WriteUInt(table.Count(self.Attachments), 8) + + for _, i in pairs(self.Attachments) do + if !i.Installed then net.WriteUInt(0, ArcCW.GetBitNecessity()) continue end + + local atttbl = ArcCW.AttachmentTable[i.Installed] + local id = atttbl.ID + + net.WriteUInt(id, ArcCW.GetBitNecessity()) + + if i.SlideAmount then + net.WriteFloat(i.SlidePos or 0.5) + end + + -- if atttbl.ColorOptionsTable then + -- net.WriteUInt(i.ColorOptionIndex or 1, 8) -- look if you want more than 256 fucking color options you're insane and stupid and just don't ok + -- end + end + + if sendto then + net.Send(sendto) + else + net.Broadcast() + end +end + +function SWEP:SendDetail_ColorIndex(slot) + net.Start("arccw_colorindex") + net.WriteUInt(slot, 8) + net.WriteUInt(self.Attachments[slot].ColorOptionIndex) + net.SendToServer() +end + +function SWEP:SendDetail_SlidePos(slot) + if !self.Attachments then return end + if !self.Attachments[slot].SlidePos then return end + + net.Start("arccw_slidepos") + net.WriteUInt(slot, 8) + net.WriteFloat(self.Attachments[slot].SlidePos or 0.5) + net.SendToServer() +end + +function SWEP:SendAllDetails() + for i, k in pairs(self.Attachments) do + self:SendDetail_SlidePos(i) + end +end + +function SWEP:CountAttachments() + local total = 0 + + for _, i in pairs(self.Attachments) do + if i.Installed and !i.FreeSlot then + total = total + 1 + end + end + + return total +end + +function SWEP:RefreshBGs() + local vm + + local vmm = self:GetBuff_Override("Override_VMMaterial") or "" + local wmm = self:GetBuff_Override("Override_WMMaterial") or "" + + local vmc = self:GetBuff_Override("Override_VMColor") or Color(255, 255, 255) + local wmc = self:GetBuff_Override("Override_WMColor") or Color(255, 255, 255) + + local vms = self:GetBuff_Override("Override_VMSkin") or self.DefaultSkin + local wms = self:GetBuff_Override("Override_WMSkin") or self.DefaultWMSkin + + if self:GetOwner():IsPlayer() then + vm = self:GetOwner():GetViewModel() + end + + if vm and vm:IsValid() then + vm:SetBodyGroups(self.DefaultBodygroups) + vm:SetMaterial(vmm) + vm:SetColor(vmc) + vm:SetSkin(vms) + end + + self:SetMaterial(wmm) + self:SetColor(wmc) + self:SetSkin(wms) + + if self.WMModel and self.WMModel:IsValid() then + self.WMModel:SetMaterial(wmm) + self.WMModel:SetColor(wmc) + self.WMModel:SetSkin(wms) + end + + for _, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if !ele then continue end + + if ele.VMSkin and vm and IsValid(vm) then + vm:SetSkin(ele.VMSkin) + end + + if self.WMModel and self.WMModel:IsValid() and ele.WMSkin then + self.WMModel:SetSkin(ele.WMSkin) + self:SetSkin(ele.WMSkin) + end + + if ele.VMColor and vm and IsValid(vm) then + vm:SetColor(ele.VMColor) + end + + if self.WMModel and self.WMModel:IsValid() and ele.WMColor then + self.WMModel:SetColor(ele.WMColor) + self:SetColor(ele.WMColor) + end + + if ele.VMMaterial and vm and IsValid(vm) then + vm:SetMaterial(ele.VMMaterial) + end + + if self.WMModel and self.WMModel:IsValid() and ele.WMMaterial then + self.WMModel:SetMaterial(ele.WMMaterial) + self:SetMaterial(ele.WMMaterial) + end + + if ele.VMBodygroups then + for _, i in pairs(ele.VMBodygroups) do + if !i.ind or !i.bg then continue end + + if vm and IsValid(vm) and vm:GetBodygroup(i.ind) != i.bg then + vm:SetBodygroup(i.ind, i.bg) + end + end + end + + if ele.WMBodygroups then + for _, i in pairs(ele.WMBodygroups) do + if !i.ind or !i.bg then continue end + + if self.WMModel and IsValid(self.WMModel) and self.WMModel:GetBodygroup(i.ind) != i.bg then + self.WMModel:SetBodygroup(i.ind, i.bg) + end + + if self:GetBodygroup(i.ind) != i.bg then + self:SetBodygroup(i.ind, i.bg) + end + end + end + + if ele.VMBoneMods then + for bone, i in pairs(ele.VMBoneMods) do + local boneind = vm:LookupBone(bone) + + if !boneind then continue end + + vm:ManipulateBonePosition(boneind, i) + end + end + + if ele.WMBoneMods then + for bone, i in pairs(ele.WMBoneMods) do + if !(self.WMModel and self.WMModel:IsValid()) then break end + local boneind = self:LookupBone(bone) + + if !boneind then continue end + + self:ManipulateBonePosition(boneind, i) + end + end + + if SERVER then + self:SetupShields() + end +end +end + +function SWEP:Attach(slot, attname, silent) + silent = silent or false + local attslot = self.Attachments[slot] + if !attslot then return end + if attslot.Installed == attname then return end + + if !ArcCW.EnableCustomization or !GetConVar("arccw_enable_customization"):GetBool() then + if CLIENT and !silent then + surface.PlaySound("items/medshotno1.wav") + end + return + end + + local pick = GetConVar("arccw_atts_pickx"):GetInt() + + if pick > 0 then + if self:CountAttachments() >= pick and !attslot.FreeSlot then + if CLIENT and !silent then + surface.PlaySound("items/medshotno1.wav") + end + return + end + end + + if !self:CheckFlags(attslot.ExcludeFlags, attslot.RequireFlags) then return end + + local atttbl = ArcCW.AttachmentTable[attname] + + if !ArcCW:SlotAcceptsAtt(attslot.Slot, self, attname) then return end + if !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then return end + if !self:PlayerOwnsAtt(attname) then return end + + if attslot.SlideAmount then + attslot.SlidePos = 0.5 + end + + if atttbl.MountPositionOverride then + attslot.SlidePos = atttbl.MountPositionOverride + end + + if atttbl.AdditionalSights then + self.SightMagnifications = {} + end + + if CLIENT then + -- we are asking to attach something + + self:SendAllDetails() + + net.Start("arccw_asktoattach") + net.WriteUInt(slot, 8) + net.WriteUInt(atttbl.ID, 24) + net.SendToServer() + + if !silent then + surface.PlaySound("weapons/arccw/install.wav") + end + else + self:DetachAllMergeSlots(slot) + end + + attslot.Installed = attname + + if atttbl.Breakable then + attslot.HP = self:GetAttachmentMaxHP(slot) + end + + if atttbl.ColorOptionsTable then + attslot.ColorOptionIndex = 1 + end + + ArcCW:PlayerTakeAtt(self:GetOwner(), attname) + + local fmt = self:GetBuff_Override("Override_Firemodes") or self.Firemodes + local fmi = self:GetNWInt("firemode", 1) + + if fmi > table.Count(fmt) then + self:SetNWInt("firemode", 1) + end + + self.UnReady = false + + if SERVER then + self:NetworkWeapon() + self:SetupModel(false) + self:SetupModel(true) + ArcCW:PlayerSendAttInv(self:GetOwner()) + else + self:SetupActiveSights() + + self.LHIKAnimation = 0 + self.LHIKAnimationStart = 0 + self.LHIKAnimationTime = 0 + + self.LHIKDelta = {} + self.LHIKDeltaAng = {} + + self.ViewModel_Hit = Vector(0, 0, 0) + + if !silent then + self:SavePreset("autosave") + end + end + + self:AdjustAtts() + + for s, i in pairs(self.Attachments) do + if !self:CheckFlags(i.ExcludeFlags, i.RequireFlags) then + self:Detach(s, true) + end + end + + self:RefreshBGs() +end + +function SWEP:DetachAllMergeSlots(slot, silent) + local slots = {slot} + + table.Add(slots, self.Attachments[slot].MergeSlots or {}) + + for _, i in pairs(slots) do + self:Detach(i, silent) + end +end + +function SWEP:Detach(slot, silent) + if !slot then return end + if !self.Attachments[slot] then return end + + if !ArcCW.EnableCustomization or !GetConVar("arccw_enable_customization"):GetBool() then + if CLIENT then + surface.PlaySound("items/medshotno1.wav") + end + return + end + + if !self.Attachments[slot].Installed then return end + + local previnstall = self.Attachments[slot].Installed + + local atttbl = ArcCW.AttachmentTable[previnstall] + + if atttbl.UBGL then + local clip = self:Clip2() + + local ammo = atttbl.UBGL_Ammo or "smg1_grenade" + + if SERVER then + self:GetOwner():GiveAmmo(clip, ammo, true) + end + + self:SetClip2(0) + + self:DeselectUBGL() + end + + self.Attachments[slot].Installed = nil + + if self:GetAttachmentHP(slot) >= self:GetAttachmentMaxHP(slot) then + ArcCW:PlayerGiveAtt(self:GetOwner(), previnstall) + end + + if CLIENT then + self:SendAllDetails() + + -- we are asking to detach something + net.Start("arccw_asktodetach") + net.WriteUInt(slot, 8) + net.SendToServer() + + if !silent then + surface.PlaySound("weapons/arccw/uninstall.wav") + end + + self:SetupActiveSights() + + self.LHIKAnimation = 0 + self.LHIKAnimationStart = 0 + self.LHIKAnimationTime = 0 + + if !silent then + self:SavePreset("autosave") + end + else + self:NetworkWeapon() + self:SetupModel(false) + self:SetupModel(true) + ArcCW:PlayerSendAttInv(self:GetOwner()) + end + + self:RefreshBGs() + + self:AdjustAtts() +end + +function SWEP:AdjustAtts() + if SERVER then + local cs = self:GetBuff_Override("Override_ChamberSize") or self.ChamberSize + + if self:Clip1() > self:GetCapacity() + cs then + local diff = self:Clip1() - (self:GetCapacity() + cs) + self:GetOwner():GiveAmmo(diff, self.Primary.Ammo, true) + self:SetClip1(self:GetCapacity() + cs) + end + end + + if self:GetBuff_Override("UBGL_Capacity") then + self.Secondary.ClipSize = self:GetBuff_Override("UBGL_Capacity") + else + self.Secondary.ClipSize = -1 + end + + if self:GetBuff_Override("UBGL_Ammo") then + self.Secondary.Ammo = self:GetBuff_Override("UBGL_Ammo") + else + self.Secondary.Ammo = "none" + end +end + +function SWEP:GetAttachmentMaxHP(slot) + if !self.Attachments[slot] then return 100 end + if !self.Attachments[slot].Installed then return 100 end + local maxhp = 100 + local atttbl = ArcCW.AttachmentTable[self.Attachments[slot].Installed] + + if atttbl.Health then + maxhp = atttbl.Health + end + + return maxhp +end + +function SWEP:GetAttachmentHP(slot) + if !self.Attachments[slot] then return 100 end + if !self.Attachments[slot].Installed then return 100 end + + if self.Attachments[slot].HP then return self.Attachments[slot].HP end + + self.Attachments[slot].HP = self:GetAttachmentMaxHP(slot) + + return self.Attachments[slot].HP +end + +function SWEP:DamageAttachment(slot, dmg) + if !self.Attachments[slot] then return end + if !self.Attachments[slot].Installed then return end + + self.Attachments[slot].HP = self:GetAttachmentHP(slot) - dmg + + if self:GetAttachmentHP(slot) <= 0 then + self:Detach(slot, true) + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_bash.lua b/lua/weapons/arccw_base/sh_bash.lua new file mode 100644 index 00000000..b60e34fe --- /dev/null +++ b/lua/weapons/arccw_base/sh_bash.lua @@ -0,0 +1,155 @@ +function SWEP:Bash(melee2) + melee2 = melee2 or false + if self:GetState() == ArcCW.STATE_SIGHTS then return end + if self:GetNextPrimaryFire() > CurTime() then return end + + self.Primary.Automatic = true + + local mult = self:GetBuff_Mult("Mult_MeleeTime") + local mt = self.MeleeTime * mult + + if melee2 then + mt = self.Melee2Time * mult + end + + if melee2 then + if self.Animations.bash2_empty and self:Clip1() == 0 then + self:PlayAnimation("bash2_empty", mult, true, 0, true) + else + self:PlayAnimation("bash2", mult, true, 0, true) + end + elseif self.Animations.bash then + if self.Animations.bash_empty and self:Clip1() == 0 then + self:PlayAnimation("bash_empty", mult, true, 0, true) + else + self:PlayAnimation("bash", mult, true, 0, true) + end + else + self:ProceduralBash() + + self:EmitSound(self.MeleeSwingSound, 75, 100, 1, CHAN_USER_BASE + 1) + end + + self:GetOwner():ViewPunch(-self.BashPrepareAng * 0.05) + self:SetNextPrimaryFire(CurTime() + mt) + + if melee2 then + if self.HoldtypeActive == "pistol" or self.HoldtypeActive == "revolver" then + self:GetOwner():DoAnimationEvent(self.Melee2Gesture or ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE) + else + self:GetOwner():DoAnimationEvent(self.Melee2Gesture or ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE2) + end + else + if self.HoldtypeActive == "pistol" or self.HoldtypeActive == "revolver" then + self:GetOwner():DoAnimationEvent(self.MeleeGesture or ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE) + else + self:GetOwner():DoAnimationEvent(self.MeleeGesture or ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE2) + end + end + + local mat = self.MeleeAttackTime + + if melee2 then + mat = self.Melee2AttackTime + end + + mat = mat * self:GetBuff_Mult("Mult_MeleeAttackTime") + + self:SetTimer(mat or (0.125 * mt), function() + if !IsValid(self) then return end + if !IsValid(self:GetOwner()) then return end + if self:GetOwner():GetActiveWeapon() != self then return end + + self:GetOwner():ViewPunch(-self.BashAng * 0.05) + + self:MeleeAttack(melee2) + end) +end + +function SWEP:MeleeAttack(melee2) + local reach = 32 + self:GetBuff_Add("Add_MeleeRange") + self.MeleeRange + local dmg = self:GetBuff_Override("Override_MeleeDamage") or self.MeleeDamage or 20 + + if melee2 then + reach = 32 + self:GetBuff_Add("Add_MeleeRange") + self.Melee2Range + dmg = self:GetBuff_Override("Override_MeleeDamage") or self.Melee2Damage or 20 + end + + dmg = dmg * self:GetBuff_Mult("Mult_MeleeDamage") + + self:GetOwner():LagCompensation(true) + + local tr = util.TraceLine({ + start = self:GetOwner():GetShootPos(), + endpos = self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * reach, + filter = self:GetOwner(), + mask = MASK_SHOT_HULL + }) + + if (!IsValid(tr.Entity)) then + tr = util.TraceHull({ + start = self:GetOwner():GetShootPos(), + endpos = self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * reach, + filter = self:GetOwner(), + mins = Vector(-16, -16, -8), + maxs = Vector(16, 16, 8), + mask = MASK_SHOT_HULL + }) + end + + -- We need the second part for single player because SWEP:Think is ran shared in SP + if !(game.SinglePlayer() and CLIENT) then + if tr.Hit then + if tr.Entity:IsNPC() or tr.Entity:IsPlayer() then + self:EmitSound(self.MeleeHitNPCSound, 75, 100, 1, CHAN_USER_BASE + 2) + else + self:EmitSound(self.MeleeHitSound, 75, 100, 1, CHAN_USER_BASE + 2) + end + + if tr.MatType == MAT_FLESH or tr.MatType == MAT_ALIENFLESH or tr.MatType == MAT_ANTLION or tr.MatType == MAT_BLOODYFLESH then + local fx = EffectData() + fx:SetOrigin(tr.HitPos) + + util.Effect("BloodImpact", fx) + end + else + self:EmitSound(self.MeleeMissSound or "weapons/iceaxe/iceaxe_swing1.wav", 75, 100, 1, CHAN_USER_BASE + 3) + end + end + + if SERVER and IsValid(tr.Entity) and (tr.Entity:IsNPC() or tr.Entity:IsPlayer() or tr.Entity:Health() > 0) then + local dmginfo = DamageInfo() + + local attacker = self:GetOwner() + if !IsValid(attacker) then attacker = self end + dmginfo:SetAttacker(attacker) + + local relspeed = (tr.Entity:GetVelocity() - self:GetOwner():GetAbsVelocity()):Length() + + relspeed = relspeed / 225 + + relspeed = math.Clamp(relspeed, 1, 1.5) + + dmginfo:SetInflictor(self) + dmginfo:SetDamage(dmg * relspeed) + dmginfo:SetDamageType(self.MeleeDamageType or DMG_CLUB) + + dmginfo:SetDamageForce(self:GetOwner():GetRight() * -4912 + self:GetOwner():GetForward() * 9989) + + SuppressHostEvents(NULL) + tr.Entity:TakeDamageInfo(dmginfo) + SuppressHostEvents(self:GetOwner()) + + end + + if SERVER and IsValid(tr.Entity) then + local phys = tr.Entity:GetPhysicsObject() + if IsValid(phys) then + phys:ApplyForceOffset(self:GetOwner():GetAimVector() * 80 * phys:GetMass(), tr.HitPos) + end + end + + self:GetBuff_Hook("Hook_PostBash", {tr = tr, dmg = dmg}) + + self:GetOwner():LagCompensation(false) +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_bipod.lua b/lua/weapons/arccw_base/sh_bipod.lua new file mode 100644 index 00000000..497699cc --- /dev/null +++ b/lua/weapons/arccw_base/sh_bipod.lua @@ -0,0 +1,114 @@ +function SWEP:InBipod() + local bip = self:GetNWBool("bipod", false) + + if !self:CanBipod() then + self:ExitBipod() + end + + if self.BipodPos != self:GetOwner():EyePos() then + self:ExitBipod() + end + + return bip +end + +SWEP.BipodAngle = Angle(0, 0, 0) +SWEP.CachedCanBipod = true +SWEP.CachedCanBipodTime = 0 + +function SWEP:CanBipod() + if !(self:GetBuff_Override("Bipod") or self.Bipod_Integral) then return false end + + if self.CachedCanBipodTime >= CurTime() then return self.CachedCanBipod end + + local maxs = Vector(2, 2, 2) + local mins = Vector(-2, -2, -2) + + local pos = self:GetOwner():EyePos() + local angle = self:GetOwner():EyeAngles() + + if self:GetOwner():GetVelocity():Length() > 0 then + return false + end + + local rangemult = 2 + + if self:IsProne() then + rangemult = 2.5 + end + + local tr = util.TraceLine({ + start = pos, + endpos = pos + (angle:Forward() * 48 * rangemult), + filter = self:GetOwner(), + mask = MASK_SOLID + }) + + if tr.Hit then -- check for stuff in front of us + return false + end + + maxs = Vector(8, 8, 0) + mins = Vector(-8, -8, -16) + + angle.p = angle.p + 15 + + tr = util.TraceHull({ + start = pos, + endpos = pos + (angle:Forward() * 24 * rangemult), + filter = self:GetOwner(), + maxs = maxs, + mins = mins, + mask = MASK_SOLID + }) + + self.CachedCanBipodTime = CurTime() + + if tr.Hit then + self.CachedCanBipod = true + return true + else + self.CachedCanBipod = false + return false + end +end + +function SWEP:EnterBipod() + if self:GetNWBool("bipod", false) then return end + if !self:CanBipod() then return end + if CurTime() < self:GetNextSecondaryFire() then return end + + if self.Bipod_Integral then + if self.Animations.enter_bipod then + self:PlayAnimation("enter_bipod") + end + else + self:EmitSound(self.EnterBipodSound) + self:DoLHIKAnimation("enter", 0.5) + end + + self.BipodPos = self:GetOwner():EyePos() + self.BipodAngle = self:GetOwner():EyeAngles() + + self:SetNextSecondaryFire(CurTime() + 0.075) + + self:SetNWBool("bipod", true) +end + +function SWEP:ExitBipod() + if !self:GetNWBool("bipod", false) then return end + if CurTime() < self:GetNextSecondaryFire() then return end + + if self.Bipod_Integral then + if self.Animations.exit_bipod then + self:PlayAnimation("exit_bipod") + end + else + self:EmitSound(self.ExitBipodSound) + self:DoLHIKAnimation("exit", 0.5) + end + + self:SetNextSecondaryFire(CurTime() + 0.075) + + self:SetNWBool("bipod", false) +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_customize.lua b/lua/weapons/arccw_base/sh_customize.lua new file mode 100644 index 00000000..e576f3a6 --- /dev/null +++ b/lua/weapons/arccw_base/sh_customize.lua @@ -0,0 +1,1199 @@ +function SWEP:ToggleCustomizeHUD(ic) + if ic and self:GetState() == ArcCW.STATE_SPRINT then return end + + if ic then + if (self:GetNextPrimaryFire() + 0.1) >= CurTime() then return end + + self:SetState(ArcCW.STATE_CUSTOMIZE) + self:ExitSights() + self:SetShouldHoldType() + self:ExitBipod() + if CLIENT then + self:OpenCustomizeHUD() + end + else + self:SetState(ArcCW.STATE_IDLE) + self.Sighted = false + self.Sprinted = false + self:SetShouldHoldType() + if CLIENT then + self:CloseCustomizeHUD() + self:SendAllDetails() + end + end +end + +if CLIENT then + +local function multlinetext(text, maxw, font) + local content = {} + local tline = "" + local x = 0 + surface.SetFont(font) + + local newlined = string.Split(text, "\n") + + for _, line in pairs(newlined) do + local words = string.Split(line, " ") + + for _, word in pairs(words) do + local tx = surface.GetTextSize(word) + + if x + tx >= maxw then + table.insert(content, tline) + tline = "" + x = surface.GetTextSize(word) + end + + tline = tline .. word .. " " + + x = x + surface.GetTextSize(word .. " ") + end + + table.insert(content, tline) + tline = "" + x = 0 + end + + -- local space_len = surface.GetTextSize(" ") + + -- for _, word in pairs(string.Split(text, " ")) do + -- if word == "\n" then + -- table.insert(content, line) + -- line = "" + -- x = 0 + -- else + -- x = x + surface.GetTextSize(word) + + -- if x >= limitx then + -- table.insert(content, line) + -- line = "" + -- x = 0 + -- x = x + surface.GetTextSize(word) + -- end + + -- line = line .. word .. " " + + -- x = x + space_len + + -- -- print(word .. " at " .. tostring(x)) + -- end + -- end + + -- table.insert(content, line) + + return content +end + +function SWEP:OpenCustomizeHUD() + if IsValid(ArcCW.InvHUD) then + ArcCW.InvHUD:Show() + else + self:CreateCustomizeHUD() + gui.SetMousePos(ScrW() / 2, ScrH() / 2) + end + + gui.EnableScreenClicker(true) + +end + +function SWEP:CloseCustomizeHUD() + if IsValid(ArcCW.InvHUD) then + ArcCW.InvHUD:Hide() + ArcCW.InvHUD:Clear() + ArcCW.InvHUD:Remove() + gui.EnableScreenClicker(false) + end +end + +local defaultatticon = Material("hud/atts/default.png") +local activeslot = nil + +SWEP.InAttMenu = false + +function SWEP:CreateCustomizeHUD() + local barsize = ScreenScale(160) + local airgap = ScreenScale(16) + local smallgap = ScreenScale(2) + local linesize = ScreenScale(1) + local buttonsize = ScreenScale(32) + local fg_col = Color(255, 255, 255, 255) + local bg_col = Color(0, 0, 0, 150) + + if !self:IsValid() then return end + + self.InAttMenu = false + activeslot = nil + + ArcCW.InvHUD = vgui.Create("DFrame") + + ArcCW.InvHUD:SetPos(0, 0) + ArcCW.InvHUD:SetSize(ScrW(), ScrH()) + ArcCW.InvHUD:SetText("") + ArcCW.InvHUD:SetTitle("") + ArcCW.InvHUD.Paint = function(span) + if !IsValid(self) then + gui.EnableScreenClicker(false) + span:Remove() + end + end + ArcCW.InvHUD.OnRemove = function() + if self:GetState() == ArcCW.STATE_CUSTOMIZE then + net.Start("arccw_togglecustomize") + net.WriteBool(false) + net.SendToServer() + + self:ToggleCustomizeHUD(false) + end + end + + if GetConVar("arccw_attinv_onlyinspect"):GetBool() then + return + end + + local loadpresets = vgui.Create("DButton", ArcCW.InvHUD) + loadpresets:SetSize((barsize - ScreenScale(2)) / 2, ScreenScale(14)) + loadpresets:SetText("") + loadpresets:SetPos(ScrW() - barsize - airgap, airgap) + + loadpresets.OnMousePressed = function(spaa, kc) + self:CreatePresetMenu() + end + + loadpresets.Paint = function(spaa, w, h) + if !self:IsValid() then return end + if !self.Attachments then return end + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + + if spaa:IsHovered() then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + + local txt = "Load Preset" + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(smallgap, ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + end + + local savepresets = vgui.Create("DButton", ArcCW.InvHUD) + savepresets:SetSize((barsize - ScreenScale(2)) / 2, ScreenScale(14)) + savepresets:SetText("") + savepresets:SetPos(ScrW() - (barsize / 2) + ScreenScale(1) - airgap, airgap) + + savepresets.OnMousePressed = function(spaa, kc) + self:CreatePresetSave() + end + + savepresets.Paint = function(spaa, w, h) + if !self:IsValid() then return end + if !self.Attachments then return end + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + + if spaa:IsHovered() then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + + local txt = "Save Preset" + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(smallgap, ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + end + + local attcatsy = ScrH() - ScreenScale(64) - airgap + + local attcats = vgui.Create("DScrollPanel", ArcCW.InvHUD) + attcats:SetText("") + attcats:SetSize(barsize, attcatsy) + attcats:SetPos(airgap, airgap) + attcats.Paint = function(span, w, h) + -- surface.SetDrawColor(bg_col) + -- surface.DrawRect(0, 0, w, h) + end + + local triviabox = vgui.Create("DScrollPanel", ArcCW.InvHUD) + triviabox:SetText("") + triviabox:SetSize(barsize, ScrH() - ScreenScale(64) - (3 * airgap)) + triviabox:SetPos(ScrW() - barsize - airgap, 2 * airgap) + triviabox.Paint = function(span, w, h) + surface.SetDrawColor(bg_col) + surface.DrawRect(0, 0, w, h) + end + + local sbar = attcats:GetVBar() + sbar.Paint = function() end + + sbar.btnUp.Paint = function(span, w, h) + end + + sbar.btnDown.Paint = function(span, w, h) + end + + sbar.btnGrip.Paint = function(span, w, h) + surface.SetDrawColor(fg_col) + surface.DrawRect(0, 0, w, h) + end + + local wpninfo = attcats:Add("DLabel") + wpninfo:SetSize(barsize, buttonsize) + wpninfo:SetText("") + wpninfo:Dock( TOP ) + wpninfo:DockMargin( 0, 0, 0, smallgap ) + + wpninfo.Paint = function(span, w, h) + if !IsValid(self) then return end + local Bfg_col = fg_col + local Bbg_col = bg_col + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + surface.DrawRect(0, 0, w, h / 2) + + surface.SetDrawColor(Bfg_col) + surface.DrawRect(0, (h - linesize) / 2, w, linesize) + + surface.SetTextColor(0, 0, 0) + surface.SetTextPos(smallgap, 0) + surface.SetFont("ArcCW_12_Glow") + surface.DrawText(self.PrintName) + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(smallgap, 0) + surface.SetFont("ArcCW_12") + surface.DrawText(self.PrintName) + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(smallgap * 2, (h - linesize) / 2 + smallgap) + surface.SetFont("ArcCW_12") + + local pick = GetConVar("arccw_atts_pickx"):GetInt() + + if pick <= 0 then + surface.DrawText(self.Trivia_Class) + else + local txt = self:CountAttachments() .. "/" .. pick .. " Attachments" + + surface.DrawText(txt) + end + end + + local attmenuh = ScrH() - (2 * airgap) + + local attmenu = vgui.Create("DScrollPanel", ArcCW.InvHUD) + attmenu:SetText("") + attmenu:SetSize(barsize + ScreenScale(12), attmenuh) + attmenu:SetPos(airgap + barsize + smallgap, airgap) + attmenu.Paint = function(span, w, h) + -- surface.SetDrawColor(bg_col) + -- surface.DrawRect(0, 0, w, h) + end + attmenu:Hide() + + local sbar3 = attmenu:GetVBar() + sbar3.Paint = function() end + + sbar3.btnUp.Paint = function(span, w, h) + end + + sbar3.btnDown.Paint = function(span, w, h) + end + + sbar3.btnGrip.Paint = function(span, w, h) + surface.SetDrawColor(fg_col) + surface.DrawRect(0, 0, w, h) + end + + local attslidebox = vgui.Create("DPanel", ArcCW.InvHUD) + attslidebox:SetSize(barsize, ScreenScale(20)) + attslidebox:SetPos(ScrW() - barsize - airgap, ScrH() - ScreenScale(64) - (1 * airgap)) + attslidebox.Paint = function(span, w, h) + surface.SetDrawColor(bg_col) + surface.DrawRect(0, 0, w, h) + + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + surface.SetTextPos(smallgap, smallgap) + surface.DrawText("POSITION") + end + + local attslider = vgui.Create("DSlider", attslidebox) + attslider:SetPos(ScreenScale(4), ScreenScale(12)) + attslider:SetSize(barsize - ScreenScale(4 * 2), ScreenScale(4)) + + attslider.Paint = function(span, w, h) + surface.SetDrawColor(fg_col) + surface.DrawRect(0, h / 2, w, ScreenScale(1)) + end + + local lastslidepos = 0 + local lastsoundtime = 0 + + attslider.Knob.Paint = function(span, w, h) + if !self:IsValid() then return end + if !self.Attachments then return end + + if span:IsHovered() or attslider:GetDragging() then + surface.SetDrawColor(fg_col) + surface.DrawRect((w - ScreenScale(2)) / 2, 0, ScreenScale(2), h) + else + surface.SetDrawColor(fg_col) + surface.DrawRect((w - ScreenScale(1)) / 2, 0, ScreenScale(1), h) + end + + if attslider:GetDragging() then + if activeslot then + local delta = attslider:GetSlideX() + if lastslidepos != delta and lastsoundtime <= CurTime() then + EmitSound("weapons/arccw/dragatt.wav", EyePos(), -2, CHAN_ITEM, 1,75, 0, math.Rand(95, 105)) + + lastsoundtime = CurTime() + 0.05 + end + + self.Attachments[activeslot].SlidePos = delta + lastslidepos = delta + end + end + + attslider:SetSlideX((self.Attachments[activeslot] or {}).SlidePos or 0.5) + end + + local og_attsliderknobmr = attslider.Knob.OnMouseReleased + + attslider.Knob.OnMouseReleased = function(span, kc) + og_attsliderknobmr(span, kc) + self:SendDetail_SlidePos(activeslot) + end + + attslidebox:Hide() + + local atttrivia = vgui.Create("DScrollPanel", ArcCW.InvHUD) + atttrivia:SetSize(barsize, ScrH() - ScreenScale(116)) + atttrivia:SetPos(ScrW() - barsize - airgap, 2 * airgap) + atttrivia.Paint = function(span, w, h) + surface.SetDrawColor(bg_col) + surface.DrawRect(0, 0, w, h) + end + atttrivia:Hide() + + local sbar4 = atttrivia:GetVBar() + sbar4.Paint = function() end + + sbar4.btnUp.Paint = function(span, w, h) + end + + sbar4.btnDown.Paint = function(span, w, h) + end + + sbar4.btnGrip.Paint = function(span, w, h) + surface.SetDrawColor(fg_col) + surface.DrawRect(0, 0, w, h) + end + + local last_atttrivia = nil + + local function atttrivia_do(att) + + if !att then + last_atttrivia = att + atttrivia:Hide() + atttrivia:Clear() + return + end + + if att == "" then + last_atttrivia = att + atttrivia:Hide() + atttrivia:Clear() + return + end + + if att == last_atttrivia then + last_atttrivia = att + return + end + + atttrivia:Clear() + + last_atttrivia = att + + local atttbl = ArcCW.AttachmentTable[att] + + atttrivia:Show() + + -- att name + + local triv_attname = vgui.Create("DLabel", atttrivia) + triv_attname:SetSize(barsize, ScreenScale(16)) + triv_attname:Dock(TOP) + triv_attname:DockMargin( 0, 0, 0, 0 ) + triv_attname:SetText("") + triv_attname.Paint = function(span, w, h) + local txt = multlinetext(atttbl.PrintName, w, "ArcCW_16") + + c = 0 + + for _, i in pairs(txt) do + surface.SetFont("ArcCW_16") + local tw = surface.GetTextSize(i) + + surface.SetFont("ArcCW_16_Glow") + surface.SetTextPos((smallgap + (w - tw)) / 2, c) + surface.SetTextColor(Color(0, 0, 0)) + surface.DrawText(i) + + surface.SetFont("ArcCW_16") + surface.SetTextPos((smallgap + (w - tw)) / 2, c) + surface.SetTextColor(fg_col) + surface.DrawText(i) + + c = c + ScreenScale(16) + end + + span:SetSize(barsize, c) + end + + -- att pic + + local triv_pic = vgui.Create("DLabel", atttrivia) + triv_pic:SetSize(barsize, barsize / 2) + triv_pic:Dock(TOP) + triv_pic:DockMargin( 0, 0, 0, smallgap ) + triv_pic:SetText("") + triv_pic.Paint = function(span, w, h) + local img = atttbl.Icon or defaultatticon + + surface.SetDrawColor(fg_col) + surface.SetMaterial(img) + surface.DrawTexturedRect(h / 2, 0, h, h) + end + + -- att desc + + desctext = multlinetext(atttbl.Description, barsize - smallgap * 2, "ArcCW_8") + + local triv_desc = vgui.Create("DLabel", atttrivia) + triv_desc:SetSize(barsize, ScreenScale(8) * (table.Count(desctext) + 1)) + triv_desc:SetText("") + triv_desc:DockMargin( 0, 0, 0, smallgap ) + triv_desc:Dock(TOP) + triv_desc.Paint = function(span, w, h) + local y = ScreenScale(8) + for i, line in pairs(desctext) do + surface.SetFont("ArcCW_8") + surface.SetTextPos(smallgap * 2, y) + surface.SetTextColor(fg_col) + surface.DrawText(line) + y = y + ScreenScale(8) + end + end + + local triv_pros = vgui.Create("DLabel", atttrivia) + triv_pros:SetSize(barsize, ScreenScale(10)) + triv_pros:SetText("") + triv_pros:Dock(TOP) + triv_pros.Paint = function(span, w, h) + surface.SetDrawColor(Color(0, 50, 0, 100)) + surface.DrawRect(0, 0, w, h) + + surface.SetTextColor(Color(125, 200, 125)) + surface.SetFont("ArcCW_8") + surface.SetTextPos(smallgap, 0) + surface.DrawText("POSITIVES:") + end + + local pros, cons = ArcCW:GetProsCons(atttbl) + + for _, i in pairs(pros) do + local triv_pro = vgui.Create("DLabel", atttrivia) + triv_pro:SetSize(barsize, ScreenScale(10)) + triv_pro:SetText("") + triv_pro:Dock(TOP) + triv_pro.Paint = function(span, w, h) + + surface.SetTextColor(Color(150, 225, 150)) + surface.SetFont("ArcCW_8") + surface.SetTextPos(smallgap, 0) + surface.DrawText(i) + end + end + + local triv_cons = vgui.Create("DLabel", atttrivia) + triv_cons:SetSize(barsize, ScreenScale(10)) + triv_cons:SetText("") + triv_cons:Dock(TOP) + triv_cons.Paint = function(span, w, h) + surface.SetDrawColor(Color(50, 0, 0, 100)) + surface.DrawRect(0, 0, w, h) + + surface.SetTextColor(Color(200, 125, 125)) + surface.SetFont("ArcCW_8") + surface.SetTextPos(smallgap, 0) + surface.DrawText("NEGATIVES:") + end + + for _, i in pairs(cons) do + local triv_con = vgui.Create("DLabel", atttrivia) + triv_con:SetSize(barsize, ScreenScale(10)) + triv_con:SetText("") + triv_con:Dock(TOP) + triv_con.Paint = function(span, w, h) + + surface.SetTextColor(Color(225, 150, 150)) + surface.SetFont("ArcCW_8") + surface.SetTextPos(smallgap, 0) + surface.DrawText(i) + end + end + end + + ArcCW.InvHUD.OnMousePressed = function(span, kc) + if kc == MOUSE_LEFT or kc == MOUSE_RIGHT then + activeslot = nil + triviabox:Show() + attmenu:Hide() + self.InAttMenu = false + atttrivia:Hide() + end + end + + for i, k in pairs(self.Attachments) do + if !k.PrintName then continue end + if i == "BaseClass" then continue end + if k.Hidden then continue end + if k.Integral then continue end + + local attcatb = attcats:Add("DButton") + attcatb:SetSize(barsize, buttonsize) + attcatb:SetText("") + attcatb:Dock( TOP ) + attcatb:DockMargin( 0, 0, 0, smallgap ) + + attcatb.AttIndex = i + attcatb.AttSlot = k + + local function attcatb_regen(span) + local catt = self.Attachments[span.AttIndex].Installed + local catttbl + if catt then + catttbl = ArcCW.AttachmentTable[catt] + end + + if self.Attachments[span.AttIndex].Installed and self.Attachments[span.AttIndex].SlideAmount and !catttbl.MountPositionOverride then + attslidebox:Show() + else + attslidebox:Hide() + end + + attmenu:Clear() + + local atts = {} + local slots = {i} + + table.Add(slots, k.MergeSlots or {}) + + for _, y in pairs(slots) do + for _, bruh in pairs(ArcCW:GetAttsForSlot((self.Attachments[y] or {}).Slot, self)) do + table.insert(atts, { + att = bruh, + slot = y + }) + end + end + + atts[0] = "" + + table.sort(atts, function(a, b) + a = a.att + b = b.att + local atttbl_a = ArcCW.AttachmentTable[a] + local atttbl_b = ArcCW.AttachmentTable[b] + + local order_a = 0 + local order_b = 0 + + order_a = atttbl_a.SortOrder or order_a + order_b = atttbl_b.SortOrder or order_b + + if order_a == order_b then + return atttbl_a.PrintName > atttbl_b.PrintName + end + + return order_a > order_b + end) + + local ca = 0 + + for _, att in pairs(atts) do + local aslot = att + if istable(att) then + aslot = aslot.slot + att = att.att + end + local owned = self:PlayerOwnsAtt(att) + + if !owned and GetConVar("arccw_attinv_hideunowned"):GetBool() then continue end + + local attbtn = attmenu:Add("DButton") + attbtn:SetSize(barsize + ScreenScale(12), ScreenScale(14)) + attbtn:SetText("") + attbtn:Dock( TOP ) + attbtn:DockMargin( 0, 0, 0, smallgap ) + + ca = ca + 1 + + attbtn.AttName = att + + attbtn.OnMousePressed = function(spaa, kc2) + if kc2 == MOUSE_LEFT then + if spaa.AttName == "" then + self:DetachAllMergeSlots(span.AttIndex) + else + self:DetachAllMergeSlots(span.AttIndex, true) + self:Attach(aslot, spaa.AttName) + end + else + self:DetachAllMergeSlots(span.AttIndex) + end + + attcatb_regen(span) + end + + attbtn.Paint = function(spaa, w, h) + if !self:IsValid() then return end + if !self.Attachments then return end + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + local atttbl = ArcCW.AttachmentTable[spaa.AttName] + local qty = ArcCW:PlayerGetAtts(self:GetOwner(), spaa.AttName) + local showqty = true + + owned = self:PlayerOwnsAtt(spaa.AttName) + + if !atttbl then + atttbl = { + PrintName = k.DefaultAttName or "No Attachment", + Icon = defaultatticon, + Free = true + } + end + + if atttbl.Free then + showqty = false + end + + if GetConVar("arccw_attinv_free"):GetBool() then + showqty = false + end + + if !owned then + showqty = false + end + + if GetConVar("arccw_attinv_lockmode"):GetBool() then + showqty = false + end + + local installed = false + + if span.AttSlot.Installed == spaa.AttName then + installed = true + end + + for _, slot in pairs(k.MergeSlots or {}) do + if !slot then continue end + if !self.Attachments[slot] then continue end + if self.Attachments[slot].Installed == spaa.AttName then + installed = true + break + end + end + + if spaa.AttName == "" and !span.AttSlot.Installed then + installed = true + + for _, slot in pairs(span.AttSlot.MergeSlots or {}) do + if self.Attachments[slot].Installed then + installed = false + break + end + end + end + + if spaa:IsHovered() or installed then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + if spaa:IsHovered() and installed then + Bbg_col = Color(255, 255, 255, 200) + Bfg_col = Color(0, 0, 0, 255) + end + + if spaa:IsHovered() then + atttrivia_do(spaa.AttName) + end + + if !owned or !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then + Bbg_col = Color(75, 0, 0, 150) + Bfg_col = Color(150, 50, 50, 255) + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + surface.DrawRect(0, 0, h * 1.5, h) + + surface.SetDrawColor(Bfg_col) + surface.DrawRect((h * 1.5) - (linesize / 2), 0, linesize, h) + + local txt = atttbl.PrintName + + if showqty then + txt = txt .. " (" .. tostring(qty) .. ")" + end + + surface.SetTextColor(Bfg_col) + surface.SetTextPos((h * 1.5) + smallgap, ScreenScale(1)) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + + surface.SetDrawColor(Bfg_col) + surface.SetMaterial(atttbl.Icon or defaultatticon) + surface.DrawTexturedRect(h / 4, 0, h, h) + end + end + + local specsize = ca * (ScreenScale(14) + smallgap) + + attmenu:SetSize(barsize + ScreenScale(12), math.min(specsize, attmenuh)) + end + + attcatb.OnMousePressed = function(span, kc) + if !self:CheckFlags(span.AttSlot.ExcludeFlags, span.AttSlot.RequireFlags) then + return + end + + if kc == MOUSE_LEFT then + if activeslot == span.AttIndex then + activeslot = nil + triviabox:Show() + attmenu:Hide() + self.InAttMenu = false + atttrivia:Hide() + attslidebox:Hide() + else + activeslot = span.AttIndex + triviabox:Hide() + attmenu:Show() + attslider:SetSlideX(self.Attachments[span.AttIndex].SlidePos) + lastslidepos = self.Attachments[span.AttIndex].SlidePos + self.InAttMenu = true + + if self.Attachments[span.AttIndex].Installed then + atttrivia_do(self.Attachments[span.AttIndex].Installed) + end + + attcatb_regen(span) + end + elseif kc == MOUSE_RIGHT then + self:DetachAllMergeSlots(span.AttIndex) + attcatb_regen(span) + end + end + + attcatb.Paint = function(span, w, h) + local Bfg_col = Color(255, 255, 255, 255) + local Bbg_col = Color(0, 0, 0, 100) + + if span:IsHovered() or activeslot == span.AttIndex then + Bbg_col = Color(255, 255, 255, 100) + Bfg_col = Color(0, 0, 0, 255) + end + + if span:IsHovered() and activeslot == span.AttIndex then + Bbg_col = Color(255, 255, 255, 200) + Bfg_col = Color(0, 0, 0, 255) + end + + if self.CheckFlags and !self:CheckFlags(span.AttSlot.ExcludeFlags, span.AttSlot.RequireFlags) then + Bbg_col = Color(75, 0, 0, 150) + Bfg_col = Color(150, 50, 50, 255) + end + + local txt = k.PrintName + + local att_txt = k.DefaultAttName or "No Attachment" + local att_icon = defaultatticon + + local installed = k.Installed + + if !installed then + (k.MergeSlots or {})["BaseClass"] = nil + for _, slot in pairs(k.MergeSlots or {}) do + if self.Attachments[slot] and self.Attachments[slot].Installed then + installed = self.Attachments[slot].Installed + break + elseif !self.Attachments[slot] then + print("ERROR! No attachment " .. tostring(slot)) + end + end + end + + if installed then + local atttbl = ArcCW.AttachmentTable[installed] + + if atttbl.Breakable then + local perc = self:GetAttachmentHP(slot) / self:GetAttachmentMaxHP(slot) + perc = math.Round(perc) + txt = txt .. " (" .. tostring(perc) .. "%)" + end + end + + surface.SetDrawColor(Bbg_col) + surface.DrawRect(0, 0, w, h) + surface.DrawRect(0, 0, w, h / 2) + surface.DrawRect(w - (1.5 * h), h / 2, 1.5 * h, h / 2) + + surface.SetDrawColor(Bfg_col) + surface.DrawRect(0, (h - linesize) / 2, w - (1.5 * h), linesize) + + surface.SetTextColor(0, 0, 0) + surface.SetTextPos(smallgap, 0) + surface.SetFont("ArcCW_12_Glow") + surface.DrawText(txt) + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(smallgap, 0) + surface.SetFont("ArcCW_12") + surface.DrawText(txt) + + if installed then + local atttbl = ArcCW.AttachmentTable[installed] + + att_txt = atttbl.PrintName + + if atttbl.Icon then + att_icon = atttbl.Icon + end + end + + surface.SetTextColor(Bfg_col) + surface.SetTextPos(smallgap * 2, (h - linesize) / 2 + smallgap) + surface.SetFont("ArcCW_12") + surface.DrawText(att_txt) + + surface.SetDrawColor(Bfg_col) + surface.DrawRect(w - (1.5 * h), 0, linesize, h) + + surface.SetDrawColor(Bfg_col) + surface.SetMaterial(att_icon) + surface.DrawTexturedRect(w - (1.25 * h), 0, h, h) + end + end + + local sbar2 = triviabox:GetVBar() + sbar2.Paint = function() end + + sbar2.btnUp.Paint = function(span, w, h) + end + + sbar2.btnDown.Paint = function(span, w, h) + end + + sbar2.btnGrip.Paint = function(span, w, h) + surface.SetDrawColor(fg_col) + surface.DrawRect(0, 0, w, h) + end + + local triv_wpnnamelabel = vgui.Create("DLabel", triviabox) + triv_wpnnamelabel:SetSize(barsize, buttonsize) + triv_wpnnamelabel:Dock(TOP) + triv_wpnnamelabel:DockMargin( 0, 0, 0, smallgap ) + triv_wpnnamelabel:SetText("") + triv_wpnnamelabel.Paint = function(span, w, h) + if !IsValid(self) then return end + local txt = self.PrintName + + surface.SetFont("ArcCW_20") + local tw, th = surface.GetTextSize(txt) + + surface.SetFont("ArcCW_20_Glow") + surface.SetTextPos((w - tw) / 2, th / 2) + surface.SetTextColor(Color(0, 0, 0)) + surface.DrawText(txt) + + surface.SetFont("ArcCW_20") + surface.SetTextPos((w - tw) / 2, th / 2) + surface.SetTextColor(fg_col) + surface.DrawText(txt) + end + + local year = tostring(self.Trivia_Year) + + if isnumber(self.Trivia_Year) and self.Trivia_Year < 0 then + year = tostring(math.abs(year)) .. "BC" + end + + local trivia = { + function() return "Class: " .. self.Trivia_Class or "Unknown" end, + function() return "Year: " .. tostring(self.Trivia_Year) or "Unknown" end, + function() return "Mechanism: " .. self.Trivia_Mechanism or "Unknown" end, + function() return "Calibre: " .. self.Trivia_Calibre or "Unknown" end, + function() return "Ammo Type: " .. language.GetPhrase(self.Primary.Ammo) end, + function() return "Country: " .. self.Trivia_Country or "Unknown" end, + function() return "Manufacturer: " .. self.Trivia_Manufacturer or "Unknown" end, + function() return "Magazine Capacity: " .. self:GetCapacity() end, + function() return "Precision: " .. self.AccuracyMOA * self:GetBuff_Mult("Mult_AccuracyMOA") .. " MOA" end, + function() return "Noise: " .. (self.ShootVol * self:GetBuff_Mult("Mult_ShootVol")) .. "dB" end, + function() return "Effective Recoil Momentum: " .. math.Truncate(self.Recoil * 41.4 * self:GetBuff_Mult("Mult_Recoil"), 1) .. " lb-fps" end, + function() return "Penetration: " .. math.Round(self.Penetration * self:GetBuff_Mult("Mult_Penetration"), 1) .. "mm" end, + } + + if !self.ManualAction and !self:GetBuff_Override("Override_ManualAction") then + table.insert(trivia, function() + local rpm = 60 / (self.Delay * (1 / self:GetBuff_Mult("Mult_RPM"))) + rpm = math.ceil(rpm / 25) * 25 + return "Firerate: " .. rpm .. "RPM" + end) + end + + if !self.Trivia_Class then + trivia[1] = nil + end + + if !self.Trivia_Year then + trivia[2] = nil + end + + if !self.Trivia_Mechanism then + trivia[3] = nil + end + + if !self.Trivia_Calibre then + trivia[4] = nil + end + + if !self.Trivia_Country then + trivia[6] = nil + end + + if !self.Trivia_Manufacturer then + trivia[7] = nil + end + + if self.PrimaryBash then + trivia[4] = nil + trivia[5] = nil + trivia[8] = nil + trivia[9] = nil + trivia[10] = nil + trivia[11] = nil + trivia[12] = nil + trivia[13] = nil + end + + if self.Throwing then + trivia[4] = nil + trivia[8] = nil + trivia[9] = nil + trivia[10] = nil + trivia[11] = nil + trivia[12] = nil + trivia[13] = nil + end + + if self.FuseTime then + table.insert(trivia, function() return "Fuse Time: " .. self.FuseTime end) + end + + for _, i in pairs(trivia) do + if !i then continue end + local triv_misc = vgui.Create("DLabel", triviabox) + triv_misc:SetSize(barsize, ScreenScale(8)) + triv_misc:Dock(TOP) + triv_misc:SetText("") + triv_misc:DockMargin( 0, 0, 0, 0 ) + triv_misc.Paint = function(span, w, h) + if !IsValid(self) then return end + local txt = i() + + surface.SetFont("ArcCW_8") + surface.SetTextPos(smallgap, 0) + surface.SetTextColor(fg_col) + surface.DrawText(txt) + end + end + + -- multlinetext(text, maxw, font) + + local adesctext = multlinetext(self.Trivia_Desc, barsize, "ArcCW_8") + + table.insert(adesctext, "") + + local triv_desc = vgui.Create("DLabel", triviabox) + triv_desc:SetSize(barsize, ScreenScale(8) * (table.Count(adesctext) + 1)) + triv_desc:SetText("") + triv_desc:Dock(TOP) + triv_desc.Paint = function(span, w, h) + local y = ScreenScale(8) + for _, line in pairs(adesctext) do + surface.SetFont("ArcCW_8") + surface.SetTextPos(smallgap, y) + surface.SetTextColor(fg_col) + surface.DrawText(line) + y = y + ScreenScale(8) + end + end + + if self.ShootEntity then return end + if self.PrimaryBash then return end + if self.Throwing then return end + if self.NoRangeGraph then return end + + local rangegraph = vgui.Create("DLabel", triviabox) + rangegraph:SetSize(barsize, ScreenScale(64)) + rangegraph:SetText("") + rangegraph:Dock(TOP) + rangegraph.Paint = function(span, w, h) + if !IsValid(self) then return end + local sidegap = 0 + local gx, gy = 0, smallgap + local gw, gh = w - (2 * sidegap), h - smallgap - ScreenScale(6) + + local dmgmax = math.Round(self:GetDamage(0)) + local dmgmin = math.Round(self:GetDamage(self.Range)) + + local grsh = math.max(dmgmax, dmgmin) + + grsh = math.ceil((grsh / 25) + 1) * 25 + + local maxgr = (self.Range * self:GetBuff_Mult("Mult_Range")) + + if dmgmax < dmgmin then + maxgr = (self.Range / self:GetBuff_Mult("Mult_Range")) + end + + maxgr = math.Round(maxgr) + + local grsw = math.ceil((maxgr / 50) + 1) * 50 + + local convw = gw / grsw + local convh = gh / grsh + + local starty = gh - (dmgmax * convh) + local endy = gh - (dmgmin * convh) + local startx = 0 + local endx = maxgr * convw + + surface.SetDrawColor(bg_col) + surface.DrawRect(gx, gy, gw, gh) + + surface.SetDrawColor(fg_col) + surface.DrawLine(gx + startx, gy + starty, gx + endx, gy + endy) + surface.DrawLine(gx + endx, gy + endy, gx + gw, gy + endy) + + -- start dmg + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + surface.SetTextPos(gx + startx, gy + starty - ScreenScale(7) - 1) + surface.DrawText(tostring(dmgmax) .. "DMG") + + -- end dmg + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + + local dtw = surface.GetTextSize(tostring(dmgmin) .. "DMG") + surface.SetTextPos(gx + gw - dtw, gy + endy - ScreenScale(7) - 1) + surface.DrawText(tostring(dmgmin) .. "DMG") + + -- start range + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + surface.SetTextPos(sidegap, smallgap + gh) + surface.DrawText("0m") + + -- mid range + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + local mtw = surface.GetTextSize(tostring(maxgr) .. "m") + surface.SetTextPos(gx + endx - (mtw / 2), smallgap + gh) + surface.DrawText(tostring(maxgr) .. "m") + + -- end range + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + local rtw = surface.GetTextSize(tostring(grsw) .. "m") + surface.SetTextPos(w - sidegap - rtw, smallgap + gh) + surface.DrawText(tostring(grsw) .. "m") + + local mousex, mousey = span:CursorPos() + + if mousex > gx and mousex < (gx + gw) and + (mousey > gy and mousey < (gy + gh)) then + local mouser = (mousex - gx) / convw + + local shy + local shdmg + + if mouser < maxgr then + local delta = mouser / maxgr + shy = Lerp(delta, starty, endy) + shdmg = Lerp(delta, dmgmax, dmgmin) + else + shy = endy + shdmg = dmgmin + end + + surface.SetDrawColor(Color(fg_col.r, fg_col.g, fg_col.b, 150)) + surface.DrawLine(gx, gy + shy, gw, gy + shy) + surface.DrawLine(mousex, gy, mousex, gh + gy) + + shy = shy + ScreenScale(4) + + mouser = math.Round(mouser) + shdmg = math.Round(shdmg) + + local alignleft = true + + surface.SetFont("ArcCW_6") + local twmr = surface.GetTextSize(tostring(mouser) .. "m") + local twmb = surface.GetTextSize(tostring(shdmg) .. "DMG") + + if mousex < math.max(twmr, twmb) + ScreenScale(2) then + alignleft = false + end + + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + if alignleft then + surface.SetTextPos(mousex - ScreenScale(2) - twmr, shy) + else + surface.SetTextPos(mousex + ScreenScale(2), shy) + end + surface.DrawText(tostring(mouser) .. "m") + + surface.SetTextColor(fg_col) + surface.SetFont("ArcCW_6") + if alignleft then + surface.SetTextPos(mousex - ScreenScale(2) - twmb, ScreenScale(2) + gy) + else + surface.SetTextPos(mousex + ScreenScale(2), ScreenScale(2) + gy) + end + surface.DrawText(tostring(shdmg) .. "DMG") + end + end +end + +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_deploy.lua b/lua/weapons/arccw_base/sh_deploy.lua new file mode 100644 index 00000000..283b7032 --- /dev/null +++ b/lua/weapons/arccw_base/sh_deploy.lua @@ -0,0 +1,256 @@ +function SWEP:Deploy() + if !IsValid(self:GetOwner()) or self:GetOwner():IsNPC() then + return + end + + self:InitTimers() + + self.FullyHolstered = false + + self:SetShouldHoldType() + + self:SetNWBool("reloading", false) + self:SetNWBool("incustomize", false) + self:SetState(0) + self:SetNWBool("ubgl", false) + + self.LHIKAnimation = nil + + self.BurstCount = 0 + + if self.CheckpointAnimation then + self:PlayAnimation(self.CheckpointAnimation, self:GetBuff_Mult("Mult_ReloadTime"), true, self.CheckpointTime, true) + self:ProceduralDraw() + self:SetNWBool("reloading", true) + + self:SetTimer((self:GetAnimTime(self.CheckpointAnimation) * self:GetBuff_Mult("Mult_ReloadTime")) - self.CheckpointTime, + function() + self:SetNWBool("reloading", false) + self.CheckpointAnimation = nil + end) + else + local prd = false + + if self.Animations.ready and self.UnReady then + self:PlayAnimation("ready", 1, true, 0, true) + self.UnReady = false + + self:SetNWBool("reloading", true) + + self:SetTimer(self:GetAnimTime("ready"), + function() + self:SetNWBool("reloading", false) + end) + + prd = self.Animations.ready.ProcDraw + + self:SetNWBool("reloading", true) + else + if self.Animations.draw_empty and self:Clip1() == 0 then + self:PlayAnimation("draw_empty", self:GetBuff_Mult("Mult_DrawTime"), true, 0, true) + + self:SetNWBool("reloading", true) + + self:SetTimer(self:GetAnimTime("draw_empty") * self:GetBuff_Mult("Mult_DrawTime"), + function() + self:SetNWBool("reloading", false) + end) + + prd = self.Animations.draw_empty.ProcDraw + else + self:PlayAnimation("draw", self:GetBuff_Mult("Mult_DrawTime"), true, 0, true) + + self:SetNWBool("reloading", true) + + self:SetTimer(self:GetAnimTime("draw") * self:GetBuff_Mult("Mult_DrawTime"), + function() + self:SetNWBool("reloading", false) + end) + + prd = self.Animations.draw.ProcDraw + end + end + + if prd then + self:ProceduralDraw() + end + end + + self.LHIKAnimation = nil + + self:SetupModel(false) + + if SERVER then + self:SetupShields() + self:NetworkWeapon() + end +end + +function SWEP:Initialize() + if (!IsValid(self:GetOwner()) or self:GetOwner():IsNPC()) and self:IsValid() and self.NPC_Initialize and SERVER then + self:NPC_Initialize() + end + + if game.SinglePlayer() and self:GetOwner():IsValid() and SERVER then + self:CallOnClient("Initialize") + end + + if CLIENT then + local class = self:GetClass() + + if self.KillIconAlias then + killicon.AddAlias(class, self.KillIconAlias) + class = self.KillIconAlias + end + + local path = "arccw/weaponicons/" .. class + local mat = Material(path) + + if !mat:IsError() then + + local tex = mat:GetTexture("$basetexture") + local texpath = tex:GetName() + killicon.Add(class, texpath, Color(255, 255, 255)) + self.WepSelectIcon = surface.GetTextureID(texpath) + + if self.ShootEntity then + killicon.Add(self.ShootEntity, texpath, Color(255, 255, 255)) + end + + end + end + + self:SetState(0) + self:SetClip2(0) + + self.Attachments["BaseClass"] = nil + + self.Primary.DefaultClip = self.Primary.ClipSize * 3 + + if self.Primary.ClipSize >= 100 then + self.Primary.DefaultClip = self.Primary.ClipSize * 2 + end + + self:SetHoldType(self.HoldtypeActive) + + local og = weapons.Get(self:GetClass()) + + self.RegularClipSize = og.Primary.ClipSize + + self.OldPrintName = self.PrintName + + self:InitTimers() +end + +SWEP.FullyHolstered = false +SWEP.HolsterSwitchTo = nil + +function SWEP:Holster(wep) + if self:GetOwner():IsNPC() then return end + if self.BurstCount > 0 and self:Clip1() > 0 then return false end + + -- if game.SinglePlayer() and self:GetOwner():IsValid() and SERVER then + -- self:CallOnClient("Holster") + -- end + + if self:GetNWBool("grenadeprimed") then + self:Throw() + end + + self.Sighted = false + self.Sprinted = false + + self.HolsterSwitchTo = wep + + local time = 0.25 + if self.Animations.holster then + self:PlayAnimation("holster", self:GetBuff_Mult("Mult_HolsterTime")) + time = self.Animations.holster.Time + else + if CLIENT then + self:ProceduralHolster() + end + end + + time = time * self:GetBuff_Mult("Mult_HolsterTime") + + -- if !self.FullyHolstered then + -- self:SetTimer(time, function() + self.ReqEnd = true + self:KillTimers() + + -- self.FullyHolstered = true + + -- self:Holster(self.HolsterSwitchTo) + + -- if CLIENT then + -- input.SelectWeapon(self.HolsterSwitchTo) + -- else + if SERVER then + if self:GetBuff_Override("UBGL_UnloadOnDequip") then + local clip = self:Clip2() + + local ammo = self:GetBuff_Override("UBGL_Ammo") or "smg1_grenade" + + if SERVER then + self:GetOwner():GiveAmmo(clip, ammo, true) + end + + self:SetClip2(0) + end + + self:KillShields() + + -- self:GetOwner():SelectWeapon(self.HolsterSwitchTo:GetClass()) + + local vm = self:GetOwner():GetViewModel() + + for i = 0, vm:GetNumBodyGroups() do + vm:SetBodygroup(i, 0) + end + + vm:SetSkin(0) + end + -- end + -- end) + -- end + + return true + + -- return self.FullyHolstered +end + +function SWEP:ProceduralDraw() + if game.SinglePlayer() and self:GetOwner():IsValid() then + self:CallOnClient("ProceduralDraw") + end + + self.InProcDraw = true + self.ProcDrawTime = CurTime() + self:SetTimer(0.25, function() + self.InProcDraw = false + end) +end + +function SWEP:ProceduralHolster() + self.InProcHolster = true + self.ProcHolsterTime = CurTime() + self:SetTimer(0.25 * self:GetBuff_Mult("Mult_HolsterTime"), function() + self.InProcHolster = false + end) +end + +function SWEP:ProceduralBash() + if game.SinglePlayer() and self:GetOwner():IsValid() then + self:CallOnClient("ProceduralBash") + end + + local mult = self:GetBuff_Mult("Mult_MeleeTime") + local mt = self.MeleeTime * mult + + self.InProcBash = true + self.ProcBashTime = CurTime() + self:SetTimer(mt, function() + self.InProcBash = false + end) +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_firemodes.lua b/lua/weapons/arccw_base/sh_firemodes.lua new file mode 100644 index 00000000..4e6d6c86 --- /dev/null +++ b/lua/weapons/arccw_base/sh_firemodes.lua @@ -0,0 +1,97 @@ +function SWEP:ChangeFiremode(pred) + pred = pred or true + local fmt = self:GetBuff_Override("Override_Firemodes") or self.Firemodes + + fmt["BaseClass"] = nil + + if table.Count(fmt) == 1 then return end + + local fmi = self:GetNWInt("firemode", 1) + local lastfmi = fmi + + fmi = fmi + 1 + + if fmi > table.Count(fmt) then + fmi = 1 + end + + if !fmt[fmi] then fmi = 1 end + + self:SetNWInt("firemode", fmi) + + if SERVER then + if pred then + SuppressHostEvents(self:GetOwner()) + end + self:EmitSound(self.FiremodeSound, 75, 100, 1, CHAN_ITEM + 2) + if pred then + SuppressHostEvents(NULL) + end + else + self:EmitSound(self.FiremodeSound, 75, 100, 1, CHAN_ITEM + 2) + end + + local a = tostring(lastfmi) .. "_to_" .. tostring(fmi) + + self:SetShouldHoldType() + + if CLIENT then + if !ArcCW:ShouldDrawHUDElement("CHudAmmo") then + self:GetOwner():ChatPrint(self:GetFiremodeName() .. "|" .. self:GetFiremodeBars()) + end + end + + if self.Animations[a] then + self:PlayAnimation(a) + elseif self.Animations.changefiremode then + self:PlayAnimation("changefiremode") + end +end + +function SWEP:GetCurrentFiremode() + local fmt = self:GetBuff_Override("Override_Firemodes") or self.Firemodes + + if self:GetNWInt("firemode", 1) > table.Count(fmt) then + self:SetNWInt("firemode", 1) + end + + return fmt[self:GetNWInt("firemode", 1)] +end + +function SWEP:GetFiremodeName() + if self:GetNWBool("ubgl", false) then + return self:GetBuff_Override("UBGL_PrintName") or "UBGL" + end + + local fm = self:GetCurrentFiremode() + + if fm.PrintName then return fm.PrintName end + + local mode = fm.Mode + + if mode == 0 then return "SAFE" end + if mode == 1 then return "SEMI" end + if mode >= 2 then return "AUTO" end + if mode < 0 then return tostring(-mode) .. "BST" end +end + +function SWEP:GetFiremodeBars() + if self:GetNWBool("ubgl", false) then + return "____-" + end + + local fm = self:GetCurrentFiremode() + + if fm.CustomBars then return fm.CustomBars end + + local mode = fm.Mode + + if mode == 0 then return "_____" end + if mode == 1 then return "-____" end + if mode >= 2 then return "-----" end + if mode == -2 then return "--___" end + if mode == -3 then return "---__" end + if mode == -4 then return "----_" end + + return "-----" +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_firing.lua b/lua/weapons/arccw_base/sh_firing.lua new file mode 100644 index 00000000..cb4feea6 --- /dev/null +++ b/lua/weapons/arccw_base/sh_firing.lua @@ -0,0 +1,688 @@ +function SWEP:PrimaryAttack() + if self:GetOwner():IsNPC() then + self:NPC_Shoot() + return + end + + if self:GetNextPrimaryFire() >= CurTime() then return end + + if self:GetState() == ArcCW.STATE_CUSTOMIZE then return end + + if self:GetState() != ArcCW.STATE_SIGHTS and self:GetOwner():KeyDown(IN_USE) or self.PrimaryBash then + self:Bash() + return + end + + if self.Throwing then + self:PreThrow() + return + end + + if self:BarrelHitWall() > 0 then return end + if self:GetState() == ArcCW.STATE_SPRINT and !(self:GetBuff_Override("Override_ShootWhileSprint") or self.ShootWhileSprint) then return end + + if self:GetNWBool("ubgl") then + self:ShootUBGL() + return + end + + if self:Clip1() <= 0 then self.BurstCount = 0 self:DryFire() return end + if self:GetNWBool("cycle", false) then return end + if self.BurstCount >= self:GetBurstLength() then return end + if self:GetCurrentFiremode().Mode == 0 then + self:ChangeFiremode(false) + self.Primary.Automatic = false + return + end + + if self:GetBuff_Hook("Hook_ShouldNotFire") then return end + + math.randomseed(self:GetOwner():GetCurrentCommand():CommandNumber() + (self:EntIndex() % 30241)) + + self.Primary.Automatic = self:ShouldBeAutomatic() + + local ss = self.ShootSound + + if self:GetBuff_Override("Silencer") then + ss = self.ShootSoundSilenced + end + + if self.BurstCount == 0 and self.FirstShootSound then + ss = self.FirstShootSound + + if self:GetBuff_Override("Silencer") then + if self.FirstShootSoundSilenced then + ss = self.FirstShootSoundSilenced + else + ss = self.ShootSoundSilenced + end + end + end + + if self:Clip1() == 1 and self.LastShootSound then + ss = self.LastShootSound + + if self:GetBuff_Override("Silencer") then + if self.LastShootSoundSilenced then + ss = self.LastShootSoundSilenced + else + ss = self.ShootSoundSilenced + end + end + end + + ss = self:GetBuff_Hook("Hook_GetShootSound", ss) + + local dss = self.DistantShootSound + + if self:GetBuff_Override("Silencer") then + dss = nil + end + + dss = self:GetBuff_Hook("Hook_GetDistantShootSound", dss) + + local dir = self:GetOwner():EyeAngles() + + local src = self:GetShootSrc() + + if bit.band( util.PointContents( src ), CONTENTS_WATER ) == CONTENTS_WATER and !(self.CanFireUnderwater or self:GetBuff_Override("Override_CanFireUnderwater")) then + self:DryFire() + return + end + + local spread = ArcCW.MOAToAcc * self.AccuracyMOA * self:GetBuff_Mult("Mult_AccuracyMOA") + + dir = dir + (AngleRand() * self:GetDispersion() / 360 / 60) + + local delay = (self.Delay * (1 / self:GetBuff_Mult("Mult_RPM"))) + + delay = self:GetBuff_Hook("Hook_ModifyRPM", delay) or delay + + self:SetNextPrimaryFire(CurTime() + delay) + + -- if IsFirstTimePredicted() then + + local num = self:GetBuff_Override("Override_Num") + + if !num then + num = self.Num + end + + num = num + self:GetBuff_Add("Add_Num") + + local btabl = { + Attacker = self:GetOwner(), + Damage = 0, + Force = 5 / num, + Distance = 33000, + Num = num, + Tracer = self:GetBuff_Override("Override_TracerNum") or self.TracerNum, + TracerName = self:GetBuff_Override("Override_Tracer") or self.Tracer, + AmmoType = self.Primary.Ammo, + Dir = dir:Forward(), + Src = src, + Spread = Vector(spread, spread, spread), + Callback = function(att, tr, dmg) + local dist = (tr.HitPos - src):Length() * ArcCW.HUToM + + local pen = self.Penetration * self:GetBuff_Mult("Mult_Penetration") + + -- local frags = math.random(1, self.Frangibility) + + -- for i = 1, frags do + -- self:DoPenetration(tr, (self.Penetration / frags) - 0.5, tr.Entity) + -- end + + local ret = self:GetBuff_Hook("Hook_BulletHit", { + range = dist, + damage = self:GetDamage(dist), + dmgtype = self:GetBuff_Override("Override_DamageType") or self.DamageType, + penleft = pen, + att = att, + tr = tr, + dmg = dmg + }) + + if !ret then return end + + dmg:SetDamageType(ret.dmgtype) + dmg:SetDamage(ret.damage) + + if dmg:GetDamageType() == DMG_BURN and ret.range <= self.Range then + if num == 1 then + dmg:SetDamageType(DMG_BULLET) + else + dmg:SetDamageType(DMG_BUCKSHOT) + end + local fx = EffectData() + fx:SetOrigin(tr.HitPos) + util.Effect("arccw_incendiaryround", fx) + + util.Decal("FadingScorch", tr.StartPos, tr.HitPos - (tr.HitNormal * 16), self:GetOwner()) + + if SERVER then + if vFireInstalled then + CreateVFire(tr.Entity, tr.HitPos, tr.HitNormal, ret.damage * 0.02) + else + tr.Entity:Ignite(1, 0) + end + end + end + + self:DoPenetration(tr, ret.penleft) + end + } + + local se = self:GetBuff_Override("Override_ShootEntity") or self.ShootEntity + + local sp = self:GetBuff_Override("Override_ShotgunSpreadPattern") or self.ShotgunSpreadPattern + local spo = self:GetBuff_Override("Override_ShotgunSpreadPatternOverrun") or self.ShotgunSpreadPatternOverrun + + if sp or spo then + btabl = self:GetBuff_Hook("Hook_FireBullets", btabl) + + if !btabl then return end + -- if btabl.Num == 0 then return end + + local spd = AngleRand() * self:GetDispersion() / 360 / 60 + + if btabl.Num > 0 then + for n = 1, btabl.Num do + btabl.Num = 1 + local ang + if self:GetBuff_Hook("Override_ShotgunSpreadDispersion") or self.ShotgunSpreadDispersion then + ang = self:GetOwner():EyeAngles() + (self:GetShotgunSpreadOffset(n) * self:GetDispersion() / 60) + else + ang = self:GetOwner():EyeAngles() + self:GetShotgunSpreadOffset(n) + spd + end + + ang = ang + AngleRand() * spread / 10 + + btabl.Dir = ang:Forward() + + self:GetOwner():LagCompensation(true) + + self:GetOwner():FireBullets(btabl) + + self:GetOwner():LagCompensation(false) + end + end + elseif se then + if num > 1 then + local spd = AngleRand() * self:GetDispersion() / 360 / 60 + + for n = 1, btabl.Num do + btabl.Num = 1 + local ang + if self:GetBuff_Hook("Override_ShotgunSpreadDispersion") or self.ShotgunSpreadDispersion then + ang = self:GetOwner():EyeAngles() + (self:GetShotgunSpreadOffset(n) * self:GetDispersion() / 360 / 60) + else + ang = self:GetOwner():EyeAngles() + self:GetShotgunSpreadOffset(n) + spd + end + + ang = ang + AngleRand() * spread / 10 + + self:FireRocket(se, self.MuzzleVelocity * ArcCW.HUToM * self:GetBuff_Mult("Mult_MuzzleVelocity"), ang) + end + elseif num > 0 then + self:FireRocket(se, self.MuzzleVelocity * ArcCW.HUToM * self:GetBuff_Mult("Mult_MuzzleVelocity")) + end + else + btabl = self:GetBuff_Hook("Hook_FireBullets", btabl) + + if !btabl then return end + if btabl.Num > 0 then + + self:GetOwner():LagCompensation(true) + + self:GetOwner():FireBullets(btabl) + + self:GetOwner():LagCompensation(false) + + end + end + + self:DoRecoil() + + self:GetOwner():DoAnimationEvent(self:GetBuff_Override("Override_AnimShoot") or self.AnimShoot) + + local svol = self.ShootVol * self:GetBuff_Mult("Mult_ShootVol") + local spitch = self.ShootPitch * math.Rand(0.95, 1.05) * self:GetBuff_Mult("Mult_ShootPitch") + + svol = math.Clamp(svol, 51, 149) + spitch = math.Clamp(spitch, 51, 149) + + if SERVER and !game.SinglePlayer() then + SuppressHostEvents(self:GetOwner()) + end + + self:DoEffects() + + if dss then + -- sound.Play(self.DistantShootSound, self:GetPos(), 149, self.ShootPitch * math.Rand(0.95, 1.05), 1) + self:EmitSound(dss, 149, spitch, 0.5, CHAN_WEAPON + 1) + end + + if ss then + self:EmitSound(ss, svol, spitch, 1, CzfHAN_WEAPON) + end + + if IsFirstTimePredicted() then + self.BurstCount = self.BurstCount + 1 + end + + self:TakePrimaryAmmo(1) + + local ret = "fire" + + if self:Clip1() == 0 and self.Animations.fire_iron_empty and self:GetState() == ArcCW.STATE_SIGHTS then + ret = "fire_iron_empty" + elseif self:Clip1() == 0 and self.Animations.fire_empty and self:GetState() != ArcCW.STATE_SIGHTS then + ret = "fire_empty" + else + if self:GetState() == ArcCW.STATE_SIGHTS and self.Animations.fire_iron then + ret = "fire_iron" + else + ret = "fire" + end + end + + if self.ProceduralIronFire and self:GetState() == ArcCW.STATE_SIGHTS then + ret = nil + elseif self.ProceduralRegularFire and self:GetState() != ArcCW.STATE_SIGHTS then + ret = nil + end + + + ret = ret or self:GetBuff_Hook("Hook_SelectFireAnimation", ret) + + if ret then + self:PlayAnimation(ret, 1, true, 0, false) + end + + if self.ManualAction or self:GetBuff_Override("Override_ManualAction") then + if !(self.NoLastCycle and self:Clip1() == 0) then + self:SetNWBool("cycle", true) + end + end + + if self:GetCurrentFiremode().Mode < 0 and self.BurstCount == -self:GetCurrentFiremode().Mode then + local postburst = self:GetCurrentFiremode().PostBurstDelay or 0 + + self:SetNextPrimaryFire(CurTime() + postburst) + end + + self:GetBuff_Hook("Hook_PostFireBullets") + + if SERVER and !game.SinglePlayer() then + SuppressHostEvents(nil) + end + -- end + + math.randomseed(CurTime() + (self:EntIndex() % 31259)) +end + +function SWEP:DoPenetration(tr, penleft) + if CLIENT then return end + if penleft <= 0 then return end + + if tr.HitSky then return end + + local penmult = ArcCW.PenTable[tr.MatType] or 1 + local pentracelen = 2 + + local curr_ent = tr.Entity + + if !tr.HitWorld then + penmult = penmult * 1.5 + end + + if tr.Entity.mmRHAe then + penmult = tr.Entity.mmRHAe + end + + penmult = penmult * math.random(0.9, 1.1) * math.random(0.9, 1.1) + + local dir = (tr.HitPos - tr.StartPos):GetNormalized() + local endpos = tr.HitPos + + local ptr = util.TraceLine({ + start = endpos, + endpos = endpos + (dir * pentracelen), + mask = MASK_SHOT + }) + + while penleft > 0 and (!ptr.StartSolid or ptr.AllSolid) and ptr.Fraction < 1 and ptr.Entity == curr_ent do + penleft = penleft - (pentracelen * penmult) + + ptr = util.TraceLine({ + start = endpos, + endpos = endpos + (dir * pentracelen), + mask = MASK_SHOT + }) + + if ptr.Entity != curr_ent then + curr_ent = ptr.Entity + + local dist = (ptr.HitPos - tr.StartPos):Length() * ArcCW.HUToM + local pdelta = penleft / (self.Penetration * self:GetBuff_Mult("Mult_Penetration")) + + local dmg = DamageInfo() + + dmg:SetDamageType(self:GetBuff_Override("Override_DamageType") or self.DamageType) + dmg:SetDamage(self:GetDamage(dist) * pdelta) + dmg:SetDamagePosition(ptr.HitPos) + + if IsValid(ptr.Entity) then + ptr.Entity:TakeDamageInfo(dmg) + end + + penmult = ArcCW.PenTable[ptr.MatType] or 1 + + if !ptr.HitWorld then + penmult = penmult * 1.5 + end + + if ptr.Entity.mmRHAe then + penmult = ptr.Entity.mmRHAe + end + + penmult = penmult * math.random(0.9, 1.1) * math.random(0.9, 1.1) + + debugoverlay.Line(endpos, endpos + (dir * pentracelen), 10, Color(0, 0, 255), true) + end + + if GetConVar("developer"):GetBool() then + local pdeltap = penleft / self.Penetration + + local c = Lerp(pdeltap, 0, 255) + + debugoverlay.Line(endpos, endpos + (dir * pentracelen), 10, Color(255,c, c), true) + end + + endpos = endpos + (dir * pentracelen) + + dir = dir + (VectorRand() * 0.025 * penmult) + end + + if penleft > 0 then + -- print("bullet penetrated with " .. penleft .. "mm pen left") + --print(vel) + if (dir:Length() == 0) then return end + + local pdelta = penleft / (self.Penetration * self:GetBuff_Mult("Mult_Penetration")) + + self:GetOwner():FireBullets( { + Attacker = self:GetOwner(), + Damage = self.Damage * pdelta, + Force = 0, + Distance = 33000, + Num = 1, + Tracer = 0, + AmmoType = self.Primary.Ammo, + Dir = dir, + Src = endpos, + Spread = Vector(spread, spread, spread), + Callback = function(att, btr, dmg) + local dist = (btr.HitPos - endpos):Length() * ArcCW.HUToM + + dmg:SetDamageType(self:GetBuff_Override("Override_DamageType") or self.DamageType) + dmg:SetDamage(self:GetDamage(dist) * pdelta) + + self:DoPenetration(btr, penleft) + end + } ) + + self:GetOwner():FireBullets({ + Damage = 0, + Src = endpos, + Dir = -dir, + Distance = 8, + Tracer = 0, + Force = 0 + }, true) + + -- debugoverlay.Line(endpos, endpos + (dir * 3), 10, Color(0, 255, 0), true) + --else + --print("bullet stopped") + end +end + +function SWEP:GetShootSrc() + if self:GetOwner():IsNPC() then return self:GetOwner():GetShootPos() end + + local dir = self:GetOwner():EyeAngles() + local offset = self:GetBuff_Override("Override_BarrelOffsetHip") or self.BarrelOffsetHip + + if self:GetState() == ArcCW.STATE_SIGHTS then + offset = self:GetBuff_Override("Override_BarrelOffsetSighted") or self.BarrelOffsetSighted + end + + local src = self:GetOwner():EyePos() + + src = src + dir:Right() * offset[1] + src = src + dir:Forward() * offset[2] + src = src + dir:Up() * offset[3] + + return src +end + +function SWEP:GetShotgunSpreadOffset(n) + local sp = self:GetBuff_Override("Override_ShotgunSpreadPattern") or self.ShotgunSpreadPattern or {} + local spo = self:GetBuff_Override("Override_ShotgunSpreadPatternOverrun") or self.ShotgunSpreadPatternOverrun or {Angle(0, 0, 0)} + + sp["BaseClass"] = nil + spo["BaseClass"] = nil + + if n > #sp then + if spo then + n = n - #sp + n = math.fmod(n, #spo) + 1 + return spo[n] + else + n = math.fmod(n, #sp) + 1 + return sp[n] + end + else + return sp[n] + end +end + +function SWEP:GetDispersion() + local delta = self:GetSightDelta() + + local hip = delta * self:GetBuff_Mult("Mult_HipDispersion") * self.HipDispersion + + if self:InBipod() then + hip = hip * (self:GetBuff_Mult("Mult_BipodDispersion") or 0.1) + end + + if self:GetState() == ArcCW.STATE_SIGHTS then + hip = self.SightsDispersion * self:GetBuff_Mult("Mult_SightsDispersion") + end + + local spd = self:GetOwner():GetAbsVelocity():Length() + + spd = spd / self:GetOwner():GetWalkSpeed() + + spd = math.Clamp(spd, 0, 2) + + hip = hip + (spd * self.MoveDispersion * self:GetBuff_Mult("Mult_MoveDispersion")) + + return hip +end + +function SWEP:DoShellEject() + -- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + + if !IsValid(self:GetOwner()) then return end + + local vm = self + + if !self:GetOwner():IsNPC() then + self:GetOwner():GetViewModel() + end + + local posang = vm:GetAttachment(self.CaseEffectAttachment) + + if !posang then return end + + local pos = posang.Pos + local ang = posang.Ang + + local fx = EffectData() + fx:SetOrigin(pos) + fx:SetAngles(ang) + fx:SetAttachment(self:GetBuff_Override("Override_CaseEffectAttachment") or self.CaseEffectAttachment or 2) + fx:SetScale(1) + fx:SetEntity(self) + fx:SetNormal(ang:Forward()) + fx:SetMagnitude(100) + + util.Effect("arccw_shelleffect", fx) +end + +function SWEP:DoEffects() + if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + + local fx = EffectData() + fx:SetScale(1) + fx:SetAttachment(self:GetBuff_Override("Override_MuzzleEffectAttachment") or self.MuzzleEffectAttachment or 1) + fx:SetEntity(self) + + if self:GetBuff_Hook("Hook_PreDoEffects", {fx = fx}) == false then return end + + util.Effect("arccw_muzzleeffect", fx) +end + +function SWEP:DryFire() + if self.Animations.fire_dry then + self:PlayAnimation("fire_dry", 1, true, 0, true) + return + end + + self.Primary.Automatic = false + + self:EmitSound("weapons/arccw/dryfire.wav", 75, 100, 1, CHAN_ITEM) + self:SetNextPrimaryFire(CurTime() + 0.25) +end + +function SWEP:DoRecoil() + if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + if game.SinglePlayer() and self:GetOwner():IsValid() and SERVER then + self:CallOnClient("DoRecoil") + end + + -- if !game.SinglePlayer() and SERVER then return end + + local r = math.Rand(-1, 1) + local ru = math.Rand(0.75, 1.25) + + local m = 1 * self:GetBuff_Mult("Mult_Recoil") + local rs = 1 * self:GetBuff_Mult("Mult_RecoilSide") + local vsm = 1 * self:GetBuff_Mult("Mult_VisualRecoilMult") + + if self:InBipod() then + m = m * (self:GetBuff_Mult("Mult_BipodRecoil") or 0.25) + rs = rs * (self:GetBuff_Mult("Mult_BipodRecoil") or 0.25) + end + + local vpa = Angle(0, 0, 0) + + vpa = vpa + ((self:GetBuff_Override("Override_RecoilDirection") or self.RecoilDirection) * self.Recoil * m * vsm) + + vpa = vpa + ((self:GetBuff_Override("Override_RecoilDirectionSide") or self.RecoilDirectionSide) * r * self.RecoilSide * m * vsm) + + vpa = vpa * (self.RecoilPunch or 1) * self:GetBuff_Mult("Mult_RecoilPunch") + + self:GetOwner():ViewPunch(vpa) + -- self:SetNWFloat("recoil", self.Recoil * m) + -- self:SetNWFloat("recoilside", r * self.RecoilSide * m) + + local ang = self:GetOwner():GetViewPunchAngles() + + ang[1] = math.Clamp(ang[1], -180, 180) + ang[2] = math.Clamp(ang[2], -180, 180) + ang[3] = math.Clamp(ang[3], -180, 180) + + self:GetOwner():SetViewPunchAngles(ang) + + if CLIENT or game.SinglePlayer() then + vsm = vsm * self.VisualRecoilMult + + self.RecoilAmount = self.RecoilAmount + (self.Recoil * m) + self.RecoilAmountSide = self.RecoilAmountSide + (r * self.RecoilSide * m * rs) + + self.RecoilPunchBack = self.Recoil * 2.5 * m + + if self.MaxRecoilBlowback > 0 then + self.RecoilPunchBack = math.Clamp(self.RecoilPunchBack, 0, self.MaxRecoilBlowback) + end + + self.RecoilPunchSide = r * self.RecoilSide * m * 0.1 * vsm + self.RecoilPunchUp = math.Clamp(ru * self.Recoil * m * 0.6 * vsm * self.RecoilRise, 0, 0.5) + end +end + +function SWEP:GetBurstLength() + local bl = self:GetCurrentFiremode().Mode + + if !self:GetCurrentFiremode().Mode then + return self.BurstCount + 10 + end + + local hsb = self:GetBuff_Hook("Hook_GetBurstLength", bl) + + if bl >= 2 then return self.BurstCount + 10 end + + if hsb != bl then return hsb end + + if bl < 0 then return -bl end + + return self.BurstCount + 10 +end + +function SWEP:ShouldBeAutomatic() + if self:GetCurrentFiremode().Mode == 1 then return false end + + if self:GetCurrentFiremode().RunawayBurst then return true end + + return true +end + +function SWEP:FireAnimationEvent( pos, ang, event, options ) + return true +end + +function SWEP:GetDamage(range) + local num = (self:GetBuff_Override("Override_Num") or self.Num) + self:GetBuff_Add("Add_Num") + local dmult = 1 + + if num then + dmult = self.Num / dmult + end + + local dmgmax = self.Damage * self:GetBuff_Mult("Mult_Damage") * dmult + local dmgmin = self.DamageMin * self:GetBuff_Mult("Mult_DamageMin") * dmult + + local delta = 1 + + if dmgmax < dmgmin then + delta = range / (self.Range / self:GetBuff_Mult("Mult_Range")) + else + delta = range / (self.Range * self:GetBuff_Mult("Mult_Range")) + end + + delta = math.Clamp(delta, 0, 1) + + local amt = Lerp(delta, dmgmax, dmgmin) + + return amt +end + +function SWEP:SecondaryAttack() + if self.Melee2 then + self:Bash(true) + return + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_grenade.lua b/lua/weapons/arccw_base/sh_grenade.lua new file mode 100644 index 00000000..6dd49d47 --- /dev/null +++ b/lua/weapons/arccw_base/sh_grenade.lua @@ -0,0 +1,65 @@ +SWEP.GrenadePrimeTime = 0 + +function SWEP:PreThrow() + if self:Clip1() == 0 then + if self:Ammo1() == 0 then + return + else + self:SetClip1(1) + self:GetOwner():SetAmmo(self:Ammo1() - 1, self.Primary.Ammo) + end + end + if self:GetNWBool("grenadeprimed") then return end + + self:PlayAnimation("pre_throw", 1, false, 0, true) + + self:SetNextPrimaryFire(CurTime() + self.PullPinTime) + + self:SetNWBool("grenadeprimed", true) + + self.GrenadePrimeTime = CurTime() +end + +function SWEP:Throw() + if self:GetNextPrimaryFire() > CurTime() then return end + + self:SetNWBool("grenadeprimed", false) + + self:PlayAnimation("throw", 1, false, 0, true) + + local heldtime = (CurTime() - self.GrenadePrimeTime) + + local windup = heldtime / 0.5 + + windup = math.Clamp(windup, 0, 1) + + local force = Lerp(windup, self.MuzzleVelocity * 0.25, self.MuzzleVelocity) + + self:SetTimer(0.25, function() + local rocket = self:FireRocket(self.ShootEntity, force) + + if !rocket then return end + + if self.FuseTime then + rocket.FuseTime = self.FuseTime - heldtime + end + + local phys = rocket:GetPhysicsObject() + + phys:AddAngleVelocity( Vector(0, 750, 0) ) + + self:TakePrimaryAmmo(1) + + if self:Clip1() == 0 and self:Ammo1() >= 1 then + self:SetClip1(1) + self:GetOwner():SetAmmo(self:Ammo1() - 1, self.Primary.Ammo) + else + self:GetOwner():StripWeapon(self:GetClass()) + end + end) + self:SetTimer(self:GetAnimTime("throw"), function() + self:PlayAnimation("draw") + end) + + self:SetNextPrimaryFire(CurTime() + 1) +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_model.lua b/lua/weapons/arccw_base/sh_model.lua new file mode 100644 index 00000000..2946b4b6 --- /dev/null +++ b/lua/weapons/arccw_base/sh_model.lua @@ -0,0 +1,703 @@ +function SWEP:KillModels() + self:KillModel(self.WM) + self.WM = nil + self:KillModel(self.VM) + self.VM = nil +end + +function SWEP:AddElement(elementname, wm) + local e = self.AttachmentElements[elementname] + + if !e then return end + if !wm and self:GetOwner():IsNPC() then return end + + if !self:CheckFlags(e.ExcludeFlags, e.RequireFlags) then return end + + if GetConVar("arccw_truenames"):GetBool() and e.TrueNameChange then + self.PrintName = e.TrueNameChange + end + + if !GetConVar("arccw_truenames"):GetBool() and e.NameChange then + self.PrintName = e.NameChange + end + + if e.AddPrefix then + self.PrintName = e.AddPrefix .. self.PrintName + end + + if e.AddSuffix then + self.PrintName = self.PrintName .. e.AddSuffix + end + + local og_weapon = weapons.GetStored(self:GetClass()) + + local og_vm = og_weapon.ViewModel + local og_wm = og_weapon.WorldModel + + self.ViewModel = og_vm + self.WorldModel = og_wm + + local parent = self + local elements = self.WM + + if !wm then + parent = self:GetOwner():GetViewModel() + elements = self.VM + end + + local eles = e.VMElements + + if wm then + eles = e.WMElements + + self.WorldModel = e.WMOverride or self.WorldModel + self:SetSkin(e.WMSkin or self.DefaultWMSkin) + else + self.ViewModel = e.VMOverride or self.ViewModel + self:GetOwner():GetViewModel():SetSkin(e.VMSkin or self.DefaultSkin) + end + + if SERVER then return end + + for _, i in pairs(eles or {}) do + local model = ClientsideModel(i.Model) + + if !model then continue end + + if i.BoneMerge then + model:SetParent(parent) + model:AddEffects(EF_BONEMERGE) + else + model:SetParent(self) + end + + local element = {} + + local scale = Matrix() + scale:Scale(i.Scale or Vector(1, 1, 1)) + + model:SetNoDraw(ArcCW.NoDraw) + model:DrawShadow(true) + model:SetPredictable(false) + model.Weapon = self + model:SetSkin(i.ModelSkin or 0) + model:SetBodyGroups(i.ModelBodygroups or "") + model:EnableMatrix("RenderMultiply", scale) + model:SetupBones() + element.Model = model + element.RenderFunc = i.RenderFunc + element.WM = wm or false + element.Bone = i.Bone + element.NoDraw = i.NoDraw or false + element.BoneMerge = i.BoneMerge or false + element.Bodygroups = i.ModelBodygroups + element.DrawFunc = i.DrawFunc + element.OffsetAng = Angle() + element.OffsetAng:Set(i.Offset.ang or Angle(0, 0, 0)) + element.OffsetPos = Vector() + element.OffsetPos:Set(i.Offset.pos or Vector(), 0, 0) + element.IsMuzzleDevice = i.IsMuzzleDevice + + table.insert(elements, element) + end + +end + +function SWEP:SetupModel(wm) + local elements = {} + + if !wm and !self:GetOwner():IsPlayer() then return end + + local og = weapons.Get(self:GetClass()) + + self.PrintName = self.OldPrintName or og.PrintName + + self:GetActiveElements(true) + + if CLIENT then + + if wm then + self:KillModel(self.WM) + self.WM = elements + + if !GetConVar("arccw_att_showothers"):GetBool() then + if LocalPlayer() != self:GetOwner() then + return + end + end + else + self:KillModel(self.VM) + self.VM = elements + + if !IsValid(self:GetOwner()) or self:GetOwner():IsNPC() then + return + end + + if !IsValid(self:GetOwner():GetViewModel()) then + self:SetTimer(0.5, function() + self:SetupModel(wm) + end) + return + end + + self:GetOwner():GetViewModel():SetupBones() + end + + render.OverrideDepthEnable( true, true ) + + end + + if wm and CLIENT then + local model = ClientsideModel(self.WorldModel) + + if !model then return end + if !IsValid(model) then return end + + model:SetNoDraw(ArcCW.NoDraw) + model:DrawShadow(true) + model:SetPredictable(false) + model:SetParent(self:GetOwner() or self) + model:AddEffects(EF_BONEMERGE) + model.Weapon = self + model:SetSkin(self.DefaultWMSkin or 0) + model:SetBodyGroups(self.DefaultWMBodygroups or "") + model:SetupBones() + local element = {} + element.Model = model + element.WM = true + element.OffsetAng = Angle(0, 0, 0) + element.IsBaseWM = true + element.BoneMerge = true + + self.WMModel = model + + table.insert(elements, element) + end + + for _, k in pairs(self.DefaultElements) do + self:AddElement(k, wm) + end + + for i, k in pairs(self.Attachments) do + if !k.Installed then continue end + + if k.InstalledEles then + for _, ele in pairs(k.InstalledEles or {}) do + self:AddElement(ele, wm) + end + end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + for _, ele in pairs(atttbl.ActivateElements or {}) do + self:AddElement(ele, wm) + end + + if self.AttachmentElements[k.Installed] then + self:AddElement(k.Installed, wm) + end + + local slots = atttbl.Slot + + if isstring(slots) then + slots = {slots} + end + + for _, ele in pairs(slots) do + self:AddElement(ele, wm) + end + + if atttbl.AddPrefix then + self.PrintName = atttbl.AddPrefix .. self.PrintName + end + + if atttbl.AddSuffix then + self.PrintName = self.PrintName .. atttbl.AddSuffix + end + + if SERVER then continue end + + if wm and k.NoWM then continue end + if !wm and k.NoVM then continue end + + if !atttbl.Model then continue end + if atttbl.HideModel then continue end + + if !k.Offset and !atttbl.BoneMerge then continue end + + local model = ClientsideModel(atttbl.Model) + + if !model then continue end + + if atttbl.BoneMerge then + local parent = self:GetOwner():GetViewModel() + + if wm then + parent = self:GetOwner() + end + + model:SetParent(parent) + model:AddEffects(EF_BONEMERGE) + else + model:SetParent(self) + end + + local repbone = nil + local repang = nil + + for _, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if !ele then continue end + + if ((ele.AttPosMods or {})[i] or {}).bone then + repbone = ele.AttPosMods.bone + end + + if wm then + if ((ele.AttPosMods or {})[i] or {}).wmang then + repang = ele.AttPosMods.wmang + end + else + if ((ele.AttPosMods or {})[i] or {}).vmang then + repang = ele.AttPosMods.vmang + end + end + end + + local element = {} + + local scale = Matrix() + + if wm then + scale:Scale((k.WMScale or Vector(1, 1, 1)) * (atttbl.ModelScale or 1)) + else + scale:Scale((k.VMScale or Vector(1, 1, 1)) * (atttbl.ModelScale or 1)) + end + + model:SetNoDraw(ArcCW.NoDraw) + model:DrawShadow(true) + model:SetPredictable(false) + model.Weapon = self + model:SetSkin(atttbl.ModelSkin or 0) + model:SetBodyGroups(atttbl.ModelBodygroups or "") + model:SetupBones() + model:EnableMatrix("RenderMultiply", scale) + element.Model = model + element.RenderFunc = atttbl.RenderFunc + element.WM = wm or false + element.Bone = repbone or k.Bone + element.NoDraw = atttbl.NoDraw or false + element.BoneMerge = k.BoneMerge or false + element.Bodygroups = atttbl.ModelBodygroups + element.DrawFunc = atttbl.DrawFunc + element.Slot = i + element.ModelOffset = atttbl.ModelOffset or Vector(0, 0, 0) + + if wm then + element.OffsetAng = Angle() + element.OffsetAng:Set(repang or k.Offset.wang or Angle(0, 0, 0)) + element.OffsetAng = element.OffsetAng + (atttbl.OffsetAng or Angle(0, 0, 0)) + k.WElement = element + else + element.OffsetAng = Angle() + element.OffsetAng:Set(repang or k.Offset.vang or Angle(0, 0, 0)) + element.OffsetAng = element.OffsetAng + (atttbl.OffsetAng or Angle(0, 0, 0)) + k.VMOffsetAng = element.OffsetAng + k.VElement = element + end + + table.insert(elements, element) + + if atttbl.IsMuzzleDevice or atttbl.UBGL then + local hspmodel = ClientsideModel(atttbl.Model) + + if k.BoneMerge then + local parent = self:GetOwner():GetViewModel() + + if wm then + parent = self:GetOwner() + end + + hspmodel:SetParent(parent) + hspmodel:AddEffects(EF_BONEMERGE) + else + hspmodel:SetParent(self) + end + + local hspelement = {} + hspmodel:SetNoDraw(true) + hspmodel:DrawShadow(true) + hspmodel:SetPredictable(false) + hspmodel.Weapon = self + + hspelement.Model = hspmodel + hspmodel:EnableMatrix("RenderMultiply", scale) + + hspelement.WM = wm or false + hspelement.Bone = repbone or k.Bone + hspelement.NoDraw = true + hspelement.BoneMerge = k.BoneMerge or false + hspelement.Slot = i + + hspelement.OffsetAng = element.OffsetAng + + if atttbl.IsMuzzleDevice then + hspelement.IsMuzzleDevice = true + end + + if wm then + k.WMuzzleDeviceElement = hspelement + else + k.VMuzzleDeviceElement = hspelement + end + + table.insert(elements, hspelement) + else + k.VMuzzleDeviceElement = nil + k.WMuzzleDeviceElement = nil + end + + if atttbl.HolosightPiece then + local hspmodel = ClientsideModel(atttbl.HolosightPiece) + + if k.BoneMerge then + local parent = self:GetOwner():GetViewModel() + + if wm then + parent = self:GetOwner() + end + + hspmodel:SetParent(parent) + hspmodel:AddEffects(EF_BONEMERGE) + else + hspmodel:SetParent(self) + end + + local hspelement = {} + hspmodel:SetNoDraw(true) + hspmodel:DrawShadow(true) + hspmodel:SetPredictable(false) + hspmodel:EnableMatrix("RenderMultiply", scale) + hspmodel.Weapon = self + + hspelement.Model = hspmodel + + hspelement.WM = wm or false + hspelement.Bone = repbone or k.Bone + hspelement.NoDraw = atttbl.NoDraw or false + hspelement.BoneMerge = k.BoneMerge or false + hspelement.Slot = i + + hspelement.OffsetAng = element.OffsetAng + + if !wm then + k.HSPElement = hspelement + end + + table.insert(elements, hspelement) + else + k.HSPElement = nil + end + end + + if CLIENT then + + if !wm and self.HolosightPiece then + local hspmodel = ClientsideModel(self.HolosightPiece) + + hspmodel:SetParent(parent) + hspmodel:AddEffects(EF_BONEMERGE) + + local hspelement = {} + hspmodel:SetNoDraw(true) + hspmodel:DrawShadow(true) + hspmodel:SetPredictable(false) + hspmodel.Weapon = self + + hspelement.Model = hspmodel + + hspelement.WM = wm or false + hspelement.BoneMerge = true + hspelement.NoDraw = false + + if !wm then + self.HSPElement = hspelement + end + + table.insert(elements, hspelement) + end + + local eid = self:EntIndex() + + for i, k in pairs(elements) do + local piletab = { + Model = k.Model, + Weapon = self + } + + table.insert(ArcCW.CSModelPile, piletab) + end + + if !ArcCW.CSModels[eid] then + ArcCW.CSModels[eid] = { + Weapon = self + } + end + + if wm then + self.WM = elements + self:KillModel(ArcCW.CSModels[eid].WModels) + ArcCW.CSModels[eid].WModels = elements + else + self.VM = elements + self:KillModel(ArcCW.CSModels[eid].VModels) + ArcCW.CSModels[eid].VModels = elements + end + + render.OverrideDepthEnable( false, true ) + + end + + self:SetupActiveSights() +end + +function SWEP:KillModel(models) + if !models then return end + if table.Count(models) == 0 then return end + + for _, i in pairs(models) do + if !isentity(i.Model) then continue end + SafeRemoveEntity(i.Model) + end +end + +function SWEP:DrawCustomModel(wm) + local models = self.VM + local vm + local selfmode = false + + -- self:KillModel(self.VM) + -- self:KillModel(self.WM) + -- self.VM = nil + -- self.WM = nil + + if wm then + if !self.WM then + self:SetupModel(wm) + end + + models = self.WM + + vm = self:GetOwner() + + if !IsValid(self:GetOwner()) then + vm = self + selfmode = true + end + else + if !self.VM then + self:SetupModel(wm) + end + + vm = self:GetOwner():GetViewModel() + + models = self.VM + + if self.HSPElement then + self.HSPElement.Model:DrawModel() + end + end + + for i, k in pairs(models) do + if !IsValid(k.Model) then + self:SetupModel(wm) + return + end + + -- local asight = self:GetActiveSights() + + -- if asight then + -- local activeslot = asight.Slot + -- if k.Slot == activeslot and ArcCW.Overdraw then + -- continue + -- end + -- end + + if k.IsBaseWM then + if self:GetOwner():IsValid() then + k.Model:SetParent(self:GetOwner()) + else + k.Model:SetParent(self) + end + end + + if k.BoneMerge and !k.NoDraw then + k.Model:DrawModel() + continue + end + + local bonename = k.Bone + + if wm then + bonename = k.WMBone or "ValveBiped.Bip01_R_Hand" + end + + if !bonename then continue end + + local bpos, bang + + local boneindex = vm:LookupBone(bonename) + + if selfmode then + boneindex = 0 + end + + if !boneindex then continue end + + bpos, bang = vm:GetBonePosition(boneindex) + + if bpos == vm:GetPos() then + bpos = vm:GetBoneMatrix(boneindex):GetTranslation() + end + + local offset = k.OffsetPos + + if k.Slot then + + local attslot = self.Attachments[k.Slot] + + local delta = attslot.SlidePos or 0.5 + + local vmelemod = nil + local wmelemod = nil + local slidemod = nil + + for _, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if !ele then continue end + + if ((ele.AttPosMods or {})[k.Slot] or {}).vpos then + vmelemod = ele.AttPosMods[k.Slot].vpos + end + + if ((ele.AttPosMods or {})[k.Slot] or {}).wpos then + wmelemod = ele.AttPosMods[k.Slot].wpos + end + + if ((ele.AttPosMods or {})[k.Slot] or {}).slide then + slidemod = ele.AttPosMods[k.Slot].slide + end + end + + if wm then + offset = wmelemod or (attslot.Offset or {}).wpos or Vector(0, 0, 0) + + if attslot.SlideAmount then + offset = LerpVector(delta, (slidemod or attslot.SlideAmount).wmin or Vector(0, 0, 0), (slidemod or attslot.SlideAmount).wmax or Vector(0, 0, 0)) + end + else + offset = vmelemod or (attslot.Offset or {}).vpos or Vector(0, 0, 0) + + if attslot.SlideAmount then + offset = LerpVector(delta, (slidemod or attslot.SlideAmount).vmin or Vector(0, 0, 0), (slidemod or attslot.SlideAmount).vmax or Vector(0, 0, 0)) + end + + attslot.VMOffsetPos = offset + end + + end + + local pos = offset or Vector(0, 0, 0) + local ang = k.OffsetAng or Angle(0, 0, 0) + + local moffset = (k.ModelOffset or Vector(0, 0, 0)) + + apos = bpos + bang:Forward() * pos.x + apos = apos + bang:Right() * pos.y + apos = apos + bang:Up() * pos.z + + local aang = Angle() + aang:Set(bang) + + aang:RotateAroundAxis(aang:Right(), ang.p) + aang:RotateAroundAxis(aang:Up(), ang.y) + aang:RotateAroundAxis(aang:Forward(), ang.r) + + apos = apos + aang:Forward() * moffset.x + apos = apos + aang:Right() * moffset.y + apos = apos + aang:Up() * moffset.z + + k.Model:SetPos(apos) + k.Model:SetAngles(aang) + k.Model:SetRenderOrigin(apos) + k.Model:SetRenderAngles(apos) + + if k.Bodygroups then + k.Model:SetBodyGroups(k.Bodygroups) + end + + if k.DrawFunc then + k.DrawFunc(self, k, wm) + end + + if !k.NoDraw then + k.Model:DrawModel() + end + + if activeslot then + if i != activeslot and ArcCW.Overdraw then + k.Model:SetBodygroup(1, 0) + end + end + end + + self:RefreshBGs() +end + +SWEP.ReferencePosCache = {} + +function SWEP:GetFromReference(boneid) + if !boneid then boneid = 1 end + if self.ReferencePosCache[boneid] then + return self.ReferencePosCache[boneid].Pos, self.ReferencePosCache[boneid].Ang + end + + SafeRemoveEntity(ArcCW.ReferenceModel) + + if !self.ViewModel then + -- uh oh panic + local og = weapons.Get(self:GetClass()) + self.ViewModel = og.ViewModel + end + + ArcCW.ReferenceModel = ClientsideModel(self.ViewModel) + + local pos = self:GetOwner():EyePos() + local ang = self:GetOwner():EyeAngles() + + ArcCW.ReferenceModel:SetPos(pos) + ArcCW.ReferenceModel:SetAngles(ang) + ArcCW.ReferenceModel:SetNoDraw(true) + ArcCW.ReferenceModel:SetupBones() + + local id = ArcCW.ReferenceModel:LookupSequence("idle") + + ArcCW.ReferenceModel:SetSequence(id) + ArcCW.ReferenceModel:SetCycle(0) + + -- local transform = ArcCW.ReferenceModel:GetBoneMatrix(boneid) + + -- local bpos, bang = transform:GetTranslation(), transform:GetAngles() + + local bpos, bang = ArcCW.ReferenceModel:GetBonePosition(boneid) + + -- SafeRemoveEntity(ArcCW.ReferenceModel) + + bpos, bang = WorldToLocal(pos, ang, bpos, bang) + + self.ReferencePosCache[boneid] = {Pos = bpos, Ang = bang} + + return bpos, bang +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_reload.lua b/lua/weapons/arccw_base/sh_reload.lua new file mode 100644 index 00000000..861f3759 --- /dev/null +++ b/lua/weapons/arccw_base/sh_reload.lua @@ -0,0 +1,247 @@ +function SWEP:Reload() + if self:GetOwner():IsNPC() then + return + end + + if self:GetNextPrimaryFire() >= CurTime() then return end + if self:GetNextSecondaryFire() > CurTime() then return end + + if self.Throwing then return end + if self.PrimaryBash then return end + + if self:GetNWBool("ubgl") then + self:ReloadUBGL() + return + end + + if self:Ammo1() <= 0 then return end + + self.LastClip1 = self:Clip1() + + local reserve = self:Ammo1() + + reserve = reserve + self:Clip1() + + local clip = self:GetCapacity() + + local chamber = math.Clamp(self:Clip1(), 0, self:GetBuff_Override("Override_ChamberSize") or self.ChamberSize) + + local load = math.Clamp(clip + chamber, 0, reserve) + + if load <= self:Clip1() then return end + + if !self.ReloadInSights then + self:ExitSights() + self.Sighted = false + end + + self:SetNWBool("reloading", true) + self:SetNWBool("reqend", false) + self.BurstCount = 0 + + local shouldshotgunreload = self.ShotgunReload + + if self:GetBuff_Override("Override_ShotgunReload") then + shouldshotgunreload = true + end + + if self:GetBuff_Override("Override_ShotgunReload") == false then + shouldshotgunreload = false + end + + if self.HybridReload or self:GetBuff_Override("Override_HybridReload") then + if self:Clip1() == 0 then + shouldshotgunreload = false + else + shouldshotgunreload = true + end + end + + local mult = self:GetBuff_Mult("Mult_ReloadTime") + + if shouldshotgunreload then + local anim = "sgreload_start" + local insertcount = 0 + + local empty = (self:Clip1() == 0) or self:GetNWBool("cycle", false) + + if self.Animations.sgreload_start_empty and empty then + anim = "sgreload_start_empty" + empty = false + + insertcount = (self.Animations.sgreload_start_empty or {}).RestoreAmmo or 1 + end + + anim = self:GetBuff_Hook("Hook_SelectReloadAnimation", anim) or anim + + self:GetOwner():SetAmmo(self:Ammo1() - insertcount, self.Primary.Ammo) + self:SetClip1(self:Clip1() + insertcount) + + self:PlayAnimation(anim, mult, true, 0, true) + + self:SetTimer(self:GetAnimTime(anim) * mult, + function() + self:ReloadInsert(empty) + end) + else + local anim = self:SelectReloadAnimation() + + if self:Clip1() == 0 then + self:SetNWBool("cycle", false) + end + + if !self.Animations[anim] then print("Invalid animation \"" .. anim .. "\"") return end + + self:PlayAnimation(anim, mult, true, 0, true) + self:SetTimer(self:GetAnimTime(anim) * mult, + function() + self:SetNWBool("reloading", false) + end) + self.CheckpointAnimation = anim + self.CheckpointTime = 0 + + if SERVER then + self:GetOwner():GiveAmmo(self:Clip1(), self.Primary.Ammo, true) + self:SetClip1(0) + self:TakePrimaryAmmo(load) + self:SetClip1(load) + end + + if self.RevolverReload then + self.LastClip1 = load + end + end + + self.Primary.Automatic = false +end + +local lastframeclip1 = 0 + +SWEP.LastClipOutTime = 0 + +function SWEP:GetVisualBullets() + if self.LastClipOutTime > CurTime() then + return self.LastClip1_B or self:Clip1() + else + self.LastClip1_B = self:Clip1() + + return self:Clip1() + end +end + +function SWEP:GetVisualClip() + if self.LastClipOutTime > CurTime() then + return self.LastClip1 or self:Clip1() + else + if !self.RevolverReload then + self.LastClip1 = self:Clip1() + else + if self:Clip1() > lastframeclip1 then + self.LastClip1 = self:Clip1() + end + + lastframeclip1 = self:Clip1() + end + + return self:Clip1() + end +end + +function SWEP:SelectReloadAnimation() + local ret + + if self.Animations.reload_empty and self:Clip1() == 0 then + ret = "reload_empty" + else + ret = "reload" + end + + ret = self:GetBuff_Hook("Hook_SelectReloadAnimation", ret) or ret + + return ret +end + +function SWEP:ReloadInsert(empty) + local total = self:GetCapacity() + + if !empty then + total = total + (self:GetBuff_Override("Override_ChamberSize") or self.ChamberSize) + end + + self:SetNWBool("reloading", true) + + local mult = self:GetBuff_Mult("Mult_ReloadTime") + + if self:Clip1() >= total or self:Ammo1() == 0 or self:GetNWBool("reqend", false) then + local ret = "sgreload_finish" + + if empty then + ret = "sgreload_finish_empty" + if self:GetNWBool("cycle") then + self:SetNWBool("cycle", false) + end + end + + ret = self:GetBuff_Hook("Hook_SelectReloadAnimation", ret) or ret + + self:PlayAnimation(ret, mult, true, 0, true) + self:SetTimer(self:GetAnimTime(ret) * mult, + function() + self:SetNWBool("reloading", false) + end) + + self:SetNWBool("reqend", false) + else + local insertcount = 1 + local insertanim = "sgreload_insert" + + local ret = self:GetBuff_Hook("Hook_SelectInsertAnimation", {count = insertcount, anim = insertanim, empty = empty}) + + if ret then + insertcount = ret.count + insertanim = ret.anim + end + + self:GetOwner():SetAmmo(self:Ammo1() - insertcount, self.Primary.Ammo) + self:SetClip1(self:Clip1() + insertcount) + + self:PlayAnimation(insertanim, mult, true, 0, true) + self:SetTimer(self:GetAnimTime(insertanim) * mult, + function() + self:ReloadInsert(empty) + end) + end +end + +function SWEP:GetCapacity() + local clip = self.RegularClipSize or self.Primary.ClipSize + local level = 1 + + if self:GetBuff_Override("MagExtender") then + level = level + 1 + end + + if self:GetBuff_Override("MagReducer") then + level = level - 1 + end + + if level == 0 then + clip = self.ReducedClipSize + elseif level == 2 then + clip = self.ExtendedClipSize + end + + clip = self:GetBuff_Override("Override_ClipSize") or clip + + clip = clip + self:GetBuff_Add("Add_ClipSize") + + local ret = self:GetBuff_Hook("Hook_GetCapacity", clip) + + clip = ret or clip + + clip = math.Clamp(clip, 0, math.huge) + + self.Primary.ClipSize = clip + + return clip +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_rocket.lua b/lua/weapons/arccw_base/sh_rocket.lua new file mode 100644 index 00000000..21d4a3a6 --- /dev/null +++ b/lua/weapons/arccw_base/sh_rocket.lua @@ -0,0 +1,30 @@ +function SWEP:FireRocket(ent, vel, ang) + if CLIENT then return end + + local rocket = ents.Create(ent) + + ang = ang or self:GetOwner():EyeAngles() + + local src = self:GetShootSrc() + + if !rocket:IsValid() then print("!!! INVALID ROUND " .. ent) return end + + rocket:SetAngles(ang) + rocket:SetPos(src) + rocket:Spawn() + rocket:Activate() + constraint.NoCollide(self:GetOwner(), rocket, 0, 0) + rocket:GetPhysicsObject():SetVelocity(self:GetOwner():GetAbsVelocity()) + rocket:GetPhysicsObject():SetVelocityInstantaneous(ang:Forward() * vel) + rocket:SetCollisionGroup(COLLISION_GROUP_PROJECTILE) + + rocket.Owner = self:GetOwner() + + if rocket.ArcCW_Killable == nil then + rocket.ArcCW_Killable = true + end + + rocket.ArcCWProjectile = true + + return rocket +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_sights.lua b/lua/weapons/arccw_base/sh_sights.lua new file mode 100644 index 00000000..6483548b --- /dev/null +++ b/lua/weapons/arccw_base/sh_sights.lua @@ -0,0 +1,424 @@ +SWEP.Sighted = false +SWEP.Sprinted = false + +function SWEP:GetSightTime() + return self.SightTime * self:GetBuff_Mult("Mult_SightTime") +end + +function SWEP:EnterSprint() + -- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + self:SetState(ArcCW.STATE_SPRINT) + self.Sighted = false + self.Sprinted = true + + -- self.SwayScale = 1 + -- self.BobScale = 5 + + self:SetShouldHoldType() + + local s = self:GetBuff_Override("Override_ShootWhileSprint") or self.ShootWhileSprint + + if !s and self:GetNextPrimaryFire() <= (CurTime() + self:GetSightTime()) then + self:SetNextPrimaryFire(CurTime() + self:GetSightTime()) + end + + if self.Animations.enter_sprint then + self:PlayAnimation("enter_sprint", self:GetSightTime()) + end +end + +function SWEP:ExitSprint() + -- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + self:SetState(ArcCW.STATE_IDLE) + self.Sighted = false + self.Sprinted = false + + -- self.SwayScale = 1 + -- self.BobScale = 1.5 + + self:SetShouldHoldType() + + local s = self:GetBuff_Override("Override_ShootWhileSprint") or self.ShootWhileSprint + + if !s and self:GetNextPrimaryFire() <= (CurTime() + self:GetSightTime()) then + self:SetNextPrimaryFire(CurTime() + self:GetSightTime()) + end + + if self:GetOwner():KeyDown(IN_ATTACK2) then + self:EnterSights() + end + + if self.Animations.exit_sprint then + self:PlayAnimation("exit_sprint", self:GetSightTime()) + end +end + +SWEP.LastEnterSightTime = 0 +SWEP.LastExitSightTime = 0 + +function SWEP:EnterSights() + -- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + local asight = self:GetActiveSights() + if !asight then return end + if self:GetState() != ArcCW.STATE_IDLE then return end + if !self.ReloadInSights and self:GetNWBool("reloading", false) then return end + + self:SetupActiveSights() + + self:SetState(ArcCW.STATE_SIGHTS) + self.Sighted = true + self.Sprinted = false + + self:SetShouldHoldType() + + -- self.SwayScale = 0.1 + -- self.BobScale = 0.1 + + if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + + self:EmitSound(asight.SwitchToSound or "weapons/arccw/movement1.wav", 75, math.Rand(95, 105), 0.5, CHAN_VOICE2) + + self.LastEnterSightTime = CurTime() + + if self.Animations.enter_sight then + self:PlayAnimation("enter_sight", self:GetSightTime()) + end +end + +function SWEP:ExitSights() + -- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + local asight = self:GetActiveSights() + if self:GetState() != ArcCW.STATE_SIGHTS then return end + + self:SetState(ArcCW.STATE_IDLE) + self.Sighted = false + self.Sprinted = false + + -- self.SwayScale = 1 + -- self.BobScale = 1.5 + + self:SetShouldHoldType() + + if self:InSprint() then + self:EnterSprint() + end + + if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + + self:EmitSound(asight.SwitchFromSound or "weapons/arccw/movement1.wav", 75, math.Rand(80, 90), 0.5, CHAN_VOICE2) + + self.LastExitSightTime = CurTime() + + if self.Animations.exit_sight then + self:PlayAnimation("exit_sight", self:GetSightTime()) + end +end + +function SWEP:GetSightDelta() + local lst = self.LastExitSightTime + local minus = 0 + + if self:GetState() == ArcCW.STATE_SIGHTS then + lst = self.LastEnterSightTime + minus = 1 + + if CurTime() - lst >= self:GetSightTime() then + return 0 + end + else + if CurTime() - lst >= self:GetSightTime() then + return 1 + end + end + + local delta = minus - math.Clamp((CurTime() - lst) / self:GetSightTime(), 0, 1) + + delta = math.abs(delta) + + return delta +end + +SWEP.SightTable = {} +SWEP.SightMagnifications = {} + +function SWEP:SetupActiveSights() + if !self.IronSightStruct then return end + + if !self:GetOwner():IsPlayer() then return end + + local sighttable = {} + local vm = self:GetOwner():GetViewModel() + + if !vm or !vm:IsValid() then return end + + local kbi = self.KeepBaseIrons or true + + for i, k in pairs(self.Attachments) do + if !k.Installed then continue end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if !atttbl.AdditionalSights then continue end + + if !k.KeepBaseIrons then kbi = false end + + for _, s in pairs(atttbl.AdditionalSights) do + local stab = table.Copy(s) + + stab.Slot = i + + if stab.HolosightData then atttbl = stab.HolosightData end + + stab.HolosightData = atttbl + + if atttbl.HolosightMagnification then + stab.MagnifiedOptic = true + stab.ScopeMagnification = atttbl.HolosightMagnification or 1 + + if atttbl.HolosightMagnificationMin then + stab.ScopeMagnificationMin = atttbl.HolosightMagnificationMin + stab.ScopeMagnificationMax = atttbl.HolosightMagnificationMax + + stab.ScopeMagnification = math.max(stab.ScopeMagnificationMax, stab.ScopeMagnificationMin) + + if !i and self.SightMagnifications[0] then + stab.ScopeMagnification = self.SightMagnifications[0] + elseif self.SightMagnifications[i] then + stab.ScopeMagnification = self.SightMagnifications[i] + end + else + stab.ScopeMagnification = atttbl.HolosightMagnification + end + end + + if atttbl.Holosight then + stab.Holosight = true + end + + local boneid = vm:LookupBone(k.Bone) + + if !boneid then return end + + if CLIENT then + + if atttbl.HolosightPiece then + stab.HolosightPiece = (k.HSPElement or {}).Model + end + + if atttbl.Holosight then + stab.HolosightModel = (k.VElement or {}).Model + end + + local bpos, bang = self:GetFromReference(boneid) + + local offset + local offset_ang + + local vmang = Angle() + + offset = k.Offset.vpos or Vector(0, 0, 0) + + local attslot = k + + local delta = attslot.SlidePos or 0.5 + + local vmelemod = nil + local slidemod = nil + + for _, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if !ele then continue end + + if ((ele.AttPosMods or {})[i] or {}).vpos then + vmelemod = ele.AttPosMods[i].vpos + end + + if ((ele.AttPosMods or {})[i] or {}).slide then + slidemod = ele.AttPosMods[i].slide + end + end + + offset = vmelemod or attslot.Offset.vpos + + if slidemod or attslot.SlideAmount then + offset = LerpVector(delta, (slidemod or attslot.SlideAmount).vmin, (slidemod or attslot.SlideAmount).vmax) + end + + offset_ang = k.Offset.vang or Angle(0, 0, 0) + offset_ang = offset_ang + (atttbl.OffsetAng or Angle(0, 0, 0)) + + offset_ang = k.VMOffsetAng or offset_ang + + bpos, bang = WorldToLocal(Vector(0, 0, 0), Angle(0, 0, 0), bpos, bang) + + bpos = bpos + bang:Forward() * offset.x + bpos = bpos + bang:Right() * offset.y + bpos = bpos + bang:Up() * offset.z + + bang:RotateAroundAxis(bang:Right(), offset_ang.p) + bang:RotateAroundAxis(bang:Up(), -offset_ang.y) + bang:RotateAroundAxis(bang:Forward(), offset_ang.r) + + local vpos = Vector() + + vpos.y = -bpos.x + vpos.x = bpos.y + vpos.z = -bpos.z + + local corpos = (k.CorrectivePos or Vector(0, 0, 0)) + + vpos = vpos + bang:Forward() * corpos.x + vpos = vpos + bang:Right() * corpos.y + vpos = vpos + bang:Up() * corpos.z + + -- vpos = vpos + (bang:Forward() * s.Pos.x) + -- vpos = vpos - (bang:Right() * s.Pos.y) + -- vpos = vpos + (bang:Up() * s.Pos.z) + + vmang:Set(-bang) + + bang.r = -bang.r + bang.p = -bang.p + bang.y = -bang.y + + corang = k.CorrectiveAng or Angle(0, 0, 0) + + bang:RotateAroundAxis(bang:Right(), corang.p) + bang:RotateAroundAxis(bang:Up(), corang.y) + bang:RotateAroundAxis(bang:Forward(), corang.r) + + -- vpos = LocalToWorld(s.Pos + Vector(0, self.ExtraSightDist or 0, 0), Angle(0, 0, 0), vpos, bang) + + -- local vmf = (vmang):Forward():GetNormalized() + -- local vmr = (vmang):Right():GetNormalized() + -- local vmu = (vmang):Up():GetNormalized() + + -- print(" ----- vmf, vmr, vmu") + -- print(vmf) + -- print(vmr) + -- print(vmu) + + -- vmf = -vmf + -- vmf.x = -vmf.x + + -- local r = vmf.y + -- vmf.y = vmf.z + -- vmf.z = r + + -- vmr = -vmr + -- vmr.y = -vmr.y + + -- -- local r = vmr.y + -- -- vmr.y = vmr.z + -- -- vmr.z = r + + -- vmu = -vmu + -- vmu.z = vmu.z + + -- local evpos = Vector(0, 0, 0) + + -- evpos = evpos + (vmf * (s.Pos.x + k.CorrectivePos.x)) + -- evpos = evpos - (vmr * (s.Pos.y + (self.ExtraSightDist or 0) + k.CorrectivePos.y)) + -- evpos = evpos + (vmu * (s.Pos.z + k.CorrectivePos.z)) + + -- print(vmang:Forward()) + + local evpos = s.Pos + + evpos = evpos * (k.VMScale or Vector(1, 1, 1)) + + if !s.IgnoreExtra then + evpos = evpos + Vector(0, k.ExtraSightDist or self.ExtraSightDist or 0, 0) + end + + evpos = evpos + (k.CorrectivePos or Vector(0, 0, 0)) + + stab.Pos, stab.Ang = vpos, bang + stab.EVPos = evpos + stab.EVAng = s.Ang + + end + + table.insert(sighttable, stab) + end + end + + if kbi then + table.insert(sighttable, table.Copy(self:GetBuff_Override("Override_IronSightStruct") or self.IronSightStruct)) + end + + self.SightTable = sighttable +end + +function SWEP:SwitchActiveSights() + if table.Count(self.SightTable) == 1 then return end + + self.ActiveSight = (self.ActiveSight or 1) + 1 + + if self.ActiveSight > table.Count(self.SightTable) then + self.ActiveSight = 1 + end + + if self:GetNextPrimaryFire() <= (CurTime() + self:GetSightTime()) then + self:SetNextPrimaryFire(CurTime() + self:GetSightTime()) + end + + local asight = self:GetActiveSights() + + if asight.SwitchToSound then + self:EmitSound(asight.SwitchToSound, 75, math.Rand(95, 105), 0.5, CHAN_VOICE2) + end + + self.LastEnterSightTime = CurTime() +end + +function SWEP:GetActiveSights() + if (self.ActiveSight or 1) > table.Count(self.SightTable) then + self.ActiveSight = 1 + end + + if table.Count(self.SightTable) == 0 then + return self.IronSightStruct + else + return self.SightTable[self.ActiveSight or 1] + end +end + +function SWEP:TranslateFOV(fov) + local irons = self:GetActiveSights() + if !irons then return end + if !irons.Magnification then return fov end + if irons.Magnification == 1 then return fov end + + self.ApproachFOV = self.ApproachFOV or fov + self.CurrentFOV = self.CurrentFOV or fov + + if self:GetState() != ArcCW.STATE_SIGHTS then + self.ApproachFOV = fov + else + self.ApproachFOV = fov / irons.Magnification + end + + self.CurrentFOV = math.Approach(self.CurrentFOV, self.ApproachFOV, FrameTime() * (self.CurrentFOV - self.ApproachFOV)) + return self.CurrentFOV +end + +function SWEP:SetShouldHoldType() + if self:GetCurrentFiremode().Mode == 0 then + self:SetHoldType(self.HoldtypeHolstered) + return + end + + if self:GetState() == ArcCW.STATE_SIGHTS then + self:SetHoldType(self:GetBuff_Override("Override_HoldtypeSights") or self.HoldtypeSights) + elseif self:GetState() == ArcCW.STATE_SPRINT then + self:SetHoldType(self:GetBuff_Override("Override_HoldtypeHolstered") or self.HoldtypeHolstered) + elseif self:GetState() == ArcCW.STATE_CUSTOMIZE then + self:SetHoldType(self:GetBuff_Override("Override_HoldtypeCustomize") or self.HoldtypeCustomize) + elseif self:GetCurrentFiremode().Mode == 0 then + self:SetHoldType(self:GetBuff_Override("Override_HoldtypeHolstered") or self.HoldtypeHolstered) + else + self:SetHoldType(self:GetBuff_Override("Override_HoldtypeActive") or self.HoldtypeActive) + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_think.lua b/lua/weapons/arccw_base/sh_think.lua new file mode 100644 index 00000000..c01c498f --- /dev/null +++ b/lua/weapons/arccw_base/sh_think.lua @@ -0,0 +1,243 @@ +if CLIENT then + +ArcCW.LastWeapon = nil + +end + +function SWEP:Think() + if !IsValid(self:GetOwner()) or self:GetOwner():IsNPC() then return end + + local vm = self:GetOwner():GetViewModel() + + if self:GetOwner():KeyPressed(IN_ATTACK) then + self:SetNWBool("reqend", true) + end + + if CLIENT then + if ArcCW.LastWeapon != self then + self:LoadPreset("autosave") + end + + ArcCW.LastWeapon = self + end + + self:InBipod() + + if (self:GetCurrentFiremode().Mode == 2 or !self:GetOwner():KeyDown(IN_ATTACK)) and self:GetNWBool("cycle", false) and !self:GetNWBool("reloading", false) then + local anim = "cycle" + if self:GetState() == ArcCW.STATE_SIGHTS and self.Animations.cycle_iron then + anim = "cycle_iron" + end + anim = self:GetBuff_Hook("Hook_SelectCycleAnimation", anim) or anim + local mult = self:GetBuff_Mult("Mult_CycleTime") + self:PlayAnimation(anim, mult, true, 0, true) + self:SetNWBool("cycle", false) + end + + if self:GetNWBool("grenadeprimed") and !self:GetOwner():KeyDown(IN_ATTACK) then + self:Throw() + end + + if self:GetNWBool("grenadeprimed") and self.GrenadePrimeTime > 0 then + local heldtime = (CurTime() - self.GrenadePrimeTime) + + if self.FuseTime and (heldtime >= self.FuseTime) then + self:Throw() + end + end + + if self:GetOwner():KeyPressed(IN_USE) then + if self:InBipod() then + self:ExitBipod() + else + self:EnterBipod() + end + end + + if self:GetCurrentFiremode().RunawayBurst and self:Clip1() > 0 then + if self.BurstCount > 0 then + self:PrimaryAttack() + end + + if self.BurstCount == self:GetBurstLength() then + self.Primary.Automatic = false + self.BurstCount = 0 + end + end + + if self:GetOwner():KeyReleased(IN_ATTACK) then + if !self:GetCurrentFiremode().RunawayBurst then + self.BurstCount = 0 + end + + if self:GetCurrentFiremode().Mode < 0 and !self:GetCurrentFiremode().RunawayBurst then + local postburst = self:GetCurrentFiremode().PostBurstDelay or 0 + + if (CurTime() + postburst) > self:GetNextPrimaryFire() then + self:SetNextPrimaryFire(CurTime() + postburst) + end + end + end + + if self:InSprint() and self:GetState() != ArcCW.STATE_SPRINT then + self:EnterSprint() + elseif !self:InSprint() and self:GetState() == ArcCW.STATE_SPRINT then + self:ExitSprint() + end + + if self:GetOwner():GetInfoNum("arccw_toggleads", 0) == 0 then + if self:GetOwner():KeyDown(IN_ATTACK2) and self:GetState() != ArcCW.STATE_SIGHTS then + self:EnterSights() + elseif !self:GetOwner():KeyDown(IN_ATTACK2) and self:GetState() == ArcCW.STATE_SIGHTS then + self:ExitSights() + end + else + if self:GetOwner():KeyPressed(IN_ATTACK2) then + if self:GetState() != ArcCW.STATE_SIGHTS then + self:EnterSights() + else + self:ExitSights() + end + end + end + + if (CLIENT or game.SinglePlayer()) and (IsFirstTimePredicted() or game.SinglePlayer()) then + local ft = FrameTime() + -- if CLIENT then + -- ft = RealFrameTime() + -- end + + local newang = self:GetOwner():EyeAngles() + local r = self.RecoilAmount -- self:GetNWFloat("recoil", 0) + local rs = self.RecoilAmountSide -- self:GetNWFloat("recoilside", 0) + + local ra = Angle(0, 0, 0) + + ra = ra + ((self:GetBuff_Override("Override_RecoilDirection") or self.RecoilDirection) * self.RecoilAmount * 0.5) + ra = ra + ((self:GetBuff_Override("Override_RecoilDirectionSide") or self.RecoilDirectionSide) * self.RecoilAmountSide * 0.5) + + newang = newang - ra + + self.RecoilAmount = r - (ft * r * 20) + self.RecoilAmountSide = rs - (ft * rs * 20) + + self.RecoilAmount = math.Approach(self.RecoilAmount, 0, ft * 0.1) + self.RecoilAmountSide = math.Approach(self.RecoilAmountSide, 0, ft * 0.1) + + -- self:SetNWFloat("recoil", r - (FrameTime() * r * 50)) + -- self:SetNWFloat("recoilside", rs - (FrameTime() * rs * 50)) + + self:GetOwner():SetEyeAngles(newang) + + for i = 1, vm:GetBoneCount() do + vm:ManipulateBoneScale(i, Vector(1, 1, 1) ) + end + + local rpb = self.RecoilPunchBack + local rps = self.RecoilPunchSide + local rpu = self.RecoilPunchUp + + if rpb != 0 then + self.RecoilPunchBack = math.Approach(rpb, 0, ft * rpb * 2.5) + end + + if rps != 0 then + self.RecoilPunchSide = math.Approach(rps, 0, ft * rps * 5) + end + + if rpu != 0 then + self.RecoilPunchUp = math.Approach(rpu, 0, ft * rpu * 5) + end + + local vec1 = Vector(1, 1, 1) + local vec0 = vec1 * 0 + + for i, k in pairs(self.CaseBones or {}) do + if !isnumber(i) then continue end + local bone = vm:LookupBone(k) + + if !bone then continue end + + vm:ManipulateBoneScale(bone, vec0) + end + + for i, k in pairs(self.BulletBones or {}) do + if !isnumber(i) then continue end + local bone = vm:LookupBone(k) + + if !bone then continue end + + vm:ManipulateBoneScale(bone, vec0) + end + + for i, k in pairs(self.CaseBones or {}) do + if !isnumber(i) then continue end + local bone = vm:LookupBone(k) + + if !bone then continue end + + if self:GetVisualClip() >= i then + vm:ManipulateBoneScale(bone, vec1) + end + end + + for i, k in pairs(self.BulletBones or {}) do + if !isnumber(i) then continue end + local bone = vm:LookupBone(k) + + if !bone then continue end + + if self:GetVisualBullets() >= i then + vm:ManipulateBoneScale(bone, vec1) + end + end + end + + if CLIENT then + if !IsValid(ArcCW.InvHUD) then + gui.EnableScreenClicker(false) + end + + if self:GetState() != ArcCW.STATE_CUSTOMIZE then + self:CloseCustomizeHUD() + else + self:OpenCustomizeHUD() + end + end + + if SERVER then + if self.Throwing then + if self:Clip1() == 0 then + if self:Ammo1() > 0 then + self:SetClip1(1) + self:GetOwner():SetAmmo(self:Ammo1() - 1, self.Primary.Ammo) + end + end + end + end + + -- self:RefreshBGs() + + self:GetBuff_Override("Hook_Think") + + if SERVER or !game.SinglePlayer() then + self:ProcessTimers() + end +end + +function SWEP:InSprint() + local sm = self.SpeedMult * self:GetBuff_Mult("Mult_SpeedMult") * self:GetBuff_Mult("Mult_MoveSpeed") + + sm = math.Clamp(sm, 0, 1) + + local sprintspeed = self:GetOwner():GetRunSpeed() * sm + local walkspeed = self:GetOwner():GetWalkSpeed() * sm + + local curspeed = self:GetOwner():GetVelocity():Length() + + if !self:GetOwner():KeyDown(IN_SPEED) then return false end + if curspeed < Lerp(0.5, walkspeed, sprintspeed) then return false end + if !self:GetOwner():OnGround() then return false end + + return true +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_timers.lua b/lua/weapons/arccw_base/sh_timers.lua new file mode 100644 index 00000000..73d70450 --- /dev/null +++ b/lua/weapons/arccw_base/sh_timers.lua @@ -0,0 +1,97 @@ +function SWEP:InitTimers() + self.ActiveTimers = {} -- {{time, callback}} +end + +function SWEP:SetTimer(time, callback, id) + -- if !IsFirstTimePredicted() then return end + -- if time < 0 then return end + id = id or "" + table.insert(self.ActiveTimers, {time + CurTime(), id, callback}) +end + +function SWEP:TimerExists(id) + for k, v in pairs(self.ActiveTimers) do + if v[2] == id then + return true + end + end + + return false +end + +function SWEP:KillTimer(id) + local keeptimers = {} + + for k, v in pairs(self.ActiveTimers) do + if v[2] != id then + table.insert(keeptimers, v) + end + end + + self.ActiveTimers = keeptimers +end + +function SWEP:KillTimers() + self.ActiveTimers = {} +end + +function SWEP:ProcessTimers() + local ct = CurTime() + + if !self.ActiveTimers then + self:InitTimers() + end + + for k, v in pairs(self.ActiveTimers) do + if v[1] <= ct then + v[3]() + end + end + + local keeptimers = {} + + for k, v in pairs(self.ActiveTimers) do + if v[1] > ct then + table.insert(keeptimers, v) + end + end + + self.ActiveTimers = keeptimers +end + +function SWEP:PlaySoundTable(soundtable, mult, startfrom) + if CLIENT and game.SinglePlayer() then return end + mult = mult or 1 + mult = 1 / mult + startfrom = startfrom or 0 + for k, v in pairs(soundtable) do + + if !v.t then continue end + + local pitch = 100 + local vol = 75 + + if v.p then + pitch = v.p + end + + if v.v then + vol = v.v + end + + local st = (v.t * mult) - startfrom + + if isnumber(v.t) then + if st < 0 then continue end + if self:GetOwner():IsNPC() then + timer.Simple(st, function() + if !IsValid(self) then return end + if !IsValid(self:GetOwner()) then return end + self:EmitSound(v.s, vol, pitch, 1, CHAN_AUTO) + end) + else + self:SetTimer(st, function() self:EmitSound(v.s, vol, pitch, 1, v.c or CHAN_AUTO) end, id) + end + end + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sh_ubgl.lua b/lua/weapons/arccw_base/sh_ubgl.lua new file mode 100644 index 00000000..7ab4457e --- /dev/null +++ b/lua/weapons/arccw_base/sh_ubgl.lua @@ -0,0 +1,116 @@ + +function SWEP:SelectUBGL() + self:SetNWBool("ubgl", true) + self:EmitSound(self.SelectUBGLSound) + self:SetNWInt("firemode", 1) + + if CLIENT then + if !ArcCW:ShouldDrawHUDElement("CHudAmmo") then + self:GetOwner():ChatPrint("Selected " .. self:GetBuff_Override("UBGL_PrintName") or "UBGL") + end + if !self:GetLHIKAnim() then + self:DoLHIKAnimation("enter") + end + end +end + +function SWEP:DeselectUBGL() + self:SetNWBool("ubgl", false) + self:EmitSound(self.ExitUBGLSound) + + if CLIENT then + if !ArcCW:ShouldDrawHUDElement("CHudAmmo") then + self:GetOwner():ChatPrint("Deselected " .. self:GetBuff_Override("UBGL_PrintName") or "UBGL") + end + if !self:GetLHIKAnim() then + self:DoLHIKAnimation("exit") + end + end +end + +function SWEP:RecoilUBGL() + if !game.SinglePlayer() and !IsFirstTimePredicted() then return end + if game.SinglePlayer() and self:GetOwner():IsValid() and SERVER then + self:CallOnClient("RecoilUBGL") + end + + local amt = self:GetBuff_Override("UBGL_Recoil") + + local r = math.Rand(-1, 1) + local ru = math.Rand(0.75, 1.25) + + local m = 1 * amt + local rs = 1 * amt * 0.1 + local vsm = 1 + + local vpa = Angle(0, 0, 0) + + vpa = vpa + (Angle(1, 0, 0) * amt * m * vsm) + + vpa = vpa + (Angle(0, 1, 0) * r * amt * m * vsm) + + self:GetOwner():ViewPunch(vpa) + -- self:SetNWFloat("recoil", self.Recoil * m) + -- self:SetNWFloat("recoilside", r * self.RecoilSide * m) + + local ang = self:GetOwner():GetViewPunchAngles() + + ang[1] = math.Clamp(ang[1], -180, 180) + ang[2] = math.Clamp(ang[2], -180, 180) + ang[3] = math.Clamp(ang[3], -180, 180) + + self:GetOwner():SetViewPunchAngles(ang) + + if CLIENT or game.SinglePlayer() then + + self.RecoilAmount = self.RecoilAmount + (amt * m) + self.RecoilAmountSide = self.RecoilAmountSide + (r * amt * m * rs) + + self.RecoilPunchBack = amt * 1 * m + + if self.MaxRecoilBlowback > 0 then + self.RecoilPunchBack = math.Clamp(self.RecoilPunchBack, 0, self.MaxRecoilBlowback) + end + + self.RecoilPunchSide = rs * rs * m * 0.1 * vsm + self.RecoilPunchUp = ru * amt * m * 0.3 * vsm + end +end + +function SWEP:ShootUBGL() + if self:GetNextSecondaryFire() > CurTime() then return end + + self.Primary.Automatic = self:GetBuff_Override("UBGL_Automatic") + + local ubglammo = self:GetBuff_Override("UBGL_Ammo") + + if self:Clip2() <= 0 and self:GetOwner():GetAmmoCount(ubglammo) <= 0 then + self.Primary.Automatic = false + self:DeselectUBGL() + return + end + + if self:Clip2() <= 0 then + return + end + + self:RecoilUBGL() + + local func, slot = self:GetBuff_Override("UBGL_Fire") + + if func then + func(self, self.Attachments[slot].VElement) + end + + self:SetNextSecondaryFire(CurTime() + (60 / self:GetBuff_Override("UBGL_RPM"))) +end + +function SWEP:ReloadUBGL() + if self:GetNextSecondaryFire() > CurTime() then return end + + local reloadfunc, slot = self:GetBuff_Override("UBGL_Reload") + + if reloadfunc then + reloadfunc(self, self.Attachments[slot].VElement) + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/shared.lua b/lua/weapons/arccw_base/shared.lua new file mode 100644 index 00000000..37865efe --- /dev/null +++ b/lua/weapons/arccw_base/shared.lua @@ -0,0 +1,542 @@ +AddCSLuaFile() + +SWEP.Spawnable = false -- this obviously has to be set to true +SWEP.Category = "ArcCW - Firearms" -- edit this if you like +SWEP.AdminOnly = false + +SWEP.PrintName = "MP-K1" +SWEP.Trivia_Class = nil -- "Submachine Gun" +SWEP.Trivia_Desc = nil -- "Ubiquitous 9mm SMG. Created as a response to the need for a faster-firing and more reliable submachine gun than existing options at the time." +SWEP.Trivia_Manufacturer = nil -- "Auschen Waffenfabrik" +SWEP.Trivia_Calibre = nil -- "9x21mm Jager" +SWEP.Trivia_Mechanism = nil -- "Roller-Delayed Blowback" +SWEP.Trivia_Country = nil -- "Austria" +SWEP.Trivia_Year = nil -- 1968 + +SWEP.UseHands = true + +SWEP.ViewModel = "" -- I mean, you probably have to edit these too +SWEP.WorldModel = "" + +SWEP.PresetBase = nil -- make this weapon share presets with this one. + +SWEP.KillIconAlias = nil -- set to other weapon class to share select and kill icons + +SWEP.DefaultBodygroups = "00000000" +SWEP.DefaultWMBodygroups = "00000000" +SWEP.DefaultSkin = 0 +SWEP.DefaultWMSkin = 0 + +SWEP.Damage = 26 +SWEP.DamageMin = 10 -- damage done at maximum range +SWEP.Range = 200 -- in METRES +SWEP.Penetration = 4 +SWEP.DamageType = DMG_BULLET +SWEP.ShootEntity = nil -- entity to fire, if any +SWEP.MuzzleVelocity = 400 -- projectile or phys bullet muzzle velocity +-- IN M/S + +SWEP.TracerNum = 1 -- tracer every X +SWEP.Tracer = nil -- override tracer effect +SWEP.TracerCol = Color(255, 255, 255) + +SWEP.ChamberSize = 1 -- how many rounds can be chambered. +SWEP.Primary.ClipSize = 25 -- DefaultClip is automatically set. +SWEP.ExtendedClipSize = 50 +SWEP.ReducedClipSize = 10 + +SWEP.ShotgunReload = false -- reloads like shotgun instead of magazines +SWEP.HybridReload = false -- reload normally when empty, reload like shotgun when part full + +SWEP.ManualAction = false -- pump/bolt action +SWEP.NoLastCycle = false -- do not cycle on last shot + +SWEP.RevolverReload = false -- cases all eject on reload + +SWEP.ReloadInSights = false + +SWEP.CanFireUnderwater = false + +SWEP.Recoil = 2 +SWEP.RecoilSide = 1 +SWEP.RecoilRise = 1 +SWEP.MaxRecoilBlowback = -1 +SWEP.VisualRecoilMult = 1.25 +SWEP.RecoilPunch = 1.5 + +SWEP.ShotgunSpreadDispersion = false -- dispersion will cause pattern to increase instead of shifting +SWEP.ShotgunSpreadPattern = nil +SWEP.ShotgunSpreadPatternOverrun = nil +-- {Angle(1, 1, 0), Angle(1, 0, 0) ..} +-- list of how far each pellet should veer +-- if only one pellet then it'll use the first index +-- if two then the first two +-- in case of overrun pellets will start looping, preferably with the second one, so use that for the loopables +-- precision will still be applied + +SWEP.RecoilDirection = Angle(1, 0, 0) +SWEP.RecoilDirectionSide = Angle(0, 1, 0) + +SWEP.Delay = 60 / 750 -- 60 / RPM. +SWEP.Num = 1 -- number of shots per trigger pull. +SWEP.Firemode = 1 -- 0: safe, 1: semi, 2: auto, negative: burst +SWEP.RunawayBurst = false +SWEP.Firemodes = { + -- { + -- Mode = 1, + -- CustomBars = "----_", -- custom bar setup + -- PrintName = "PUMP", + -- RunAwayBurst = false, + -- PostBurstDelay = 0, + -- } +} + +SWEP.NotForNPCS = false +SWEP.NPCWeaponType = nil -- string or table, the NPC weapons for this gun to replace +-- if nil, this will be based on holdtype +SWEP.NPCWeight = 100 -- relative likeliness for an NPC to have this weapon + +SWEP.AccuracyMOA = 15 -- accuracy in Minutes of Angle. There are 60 MOA in a degree. +SWEP.HipDispersion = 500 -- inaccuracy added by hip firing. +SWEP.MoveDispersion = 150 -- inaccuracy added by moving. Applies in sights as well! Walking speed is considered as "maximum". +SWEP.SightsDispersion = 0 -- dispersion that remains even in sights + +SWEP.ShootWhileSprint = false + +SWEP.Primary.Ammo = "pistol" -- what ammo type the gun uses +SWEP.MagID = "mpk1" -- the magazine pool this gun draws from + +SWEP.ShootVol = 125 -- volume of shoot sound +SWEP.ShootPitch = 100 -- pitch of shoot sound + +SWEP.FirstShootSound = nil +SWEP.ShootSound = "" +SWEP.FirstShootSoundSilenced = nil +SWEP.DistantShootSound = nil +SWEP.ShootSoundSilenced = "weapons/arccw/m4a1/m4a1-1.wav" +SWEP.FiremodeSound = "weapons/arccw/firemode.wav" +SWEP.MeleeSwingSound = "weapons/arccw/m249/m249_draw.wav" +SWEP.MeleeHitSound = "weapons/arccw/knife/knife_hitwall1.wav" +SWEP.MeleeHitNPCSound = "physics/body/body_medium_break2.wav" +SWEP.EnterBipodSound = "weapons/arccw/m249/m249_coverdown.wav" +SWEP.ExitBipodSound = "weapons/arccw/m249/m249_coverup.wav" +SWEP.SelectUBGLSound = "weapons/arccw/ubgl_select.wav" +SWEP.ExitUBGLSound = "weapons/arccw/ubgl_exit.wav" + +SWEP.MuzzleEffect = "arccw_muzzleeffect" + +SWEP.ShellModel = "models/shells/shell_556.mdl" +SWEP.ShellMaterial = nil +SWEP.ShellScale = 1 +SWEP.ShellPhysScale = 1 +SWEP.ShellPitch = 100 +SWEP.ShellSounds = ArcCW.ShellSoundsTable +SWEP.ShellRotate = 0 +SWEP.ShellTime = 1 -- add shell life time + +SWEP.MuzzleEffectAttachment = 1 -- which attachment to put the muzzle on +SWEP.CaseEffectAttachment = 2 -- which attachment to put the case effect on + +SWEP.SpeedMult = 0.9 +SWEP.SightedSpeedMult = 0.75 + +SWEP.BulletBones = { -- the bone that represents bullets in gun/mag + -- [0] = "bulletchamber", + -- [1] = "bullet1" +} + +SWEP.CaseBones = {} + +SWEP.KeepBaseIrons = false -- do not override iron sights when scope installed + +SWEP.IronSightStruct = { + Pos = Vector(-8.728, -13.702, 4.014), + Ang = Angle(-1.397, -0.341, -2.602), + Magnification = 1, + BlackBox = false, + ScopeTexture = nil, + ScopeFOV = nil, -- FOV of the scope texture + SwitchToSound = "", -- sound that plays when switching to this sight + SwitchFromSound = "", + ScrollFunc = ArcCW.SCROLL_NONE, + CrosshairInSights = false, +} + +SWEP.ProceduralRegularFire = false +SWEP.ProceduralIronFire = false +SWEP.SightTime = 0.33 + +SWEP.HoldtypeHolstered = "passive" +SWEP.HoldtypeActive = "shotgun" +SWEP.HoldtypeSights = "smg" +SWEP.HoldtypeCustomize = "slam" +SWEP.HoldtypeNPC = nil + +SWEP.AnimShoot = ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2 + +SWEP.CanBash = true +SWEP.PrimaryBash = false -- primary attack triggers melee attack + +SWEP.MeleeDamage = 25 +SWEP.MeleeRange = 16 +SWEP.MeleeDamageType = DMG_CLUB +SWEP.MeleeTime = 0.5 +SWEP.MeleeGesture = nil +SWEP.MeleeAttackTime = 0.2 + +SWEP.Melee2 = false +SWEP.Melee2Damage = 25 +SWEP.Melee2Range = 16 +SWEP.Melee2Time = 0.5 +SWEP.Melee2Gesture = nil +SWEP.Melee2AttackTime = 0.2 + +SWEP.BashPreparePos = Vector(2.187, -4.117, -7.14) +SWEP.BashPrepareAng = Angle(32.182, -3.652, -19.039) + +SWEP.BashPos = Vector(8.876, 0, 0) +SWEP.BashAng = Angle(-16.524, 70, -11.046) + +SWEP.ActivePos = Vector(0, 0, 0) +SWEP.ActiveAng = Angle(0, 0, 0) + +SWEP.CrouchPos = nil +SWEP.CrouchAng = nil + +SWEP.HolsterPos = Vector(0.532, -6, 0) +SWEP.HolsterAng = Angle(-4.633, 36.881, 0) + +SWEP.BarrelOffsetSighted = Vector(0, 0, 0) +SWEP.BarrelOffsetHip = Vector(3, 0, -3) + +SWEP.CustomizePos = Vector(9.824, 0, -4.897) +SWEP.CustomizeAng = Angle(12.149, 30.547, 0) + +SWEP.BarrelLength = 24 + +SWEP.Bipod_Integral = false + +SWEP.SightPlusOffset = nil + +SWEP.DefaultElements = {} -- {"ele1", "ele2"} + +SWEP.AttachmentElements = { + -- ["name"] = { + -- RequireFlags = {}, -- same as attachments + -- ExcludeFlags = {}, + -- NamePriority = 0, -- higher = more likely to be chosen + -- NameChange = "", + -- TrueNameChange = "", + -- AddPrefix = "", + -- AddSuffix = "", + -- VMColor = Color(), + -- VMMaterial = "", + -- VMBodygroups = {{ind = 1, bg = 1}}, + -- VMElements = { + -- { + -- Model = "", + -- Bone = "", + -- Offset = { + -- pos = Vector(), + -- ang = Angle(), + -- }, + -- ModelSkin = 0, + -- ModelBodygroups = "", + -- Scale = Vector(1, 1, 1), + -- IsMuzzleDevice = false -- this element is a muzzle device, and the muzzle flash should come from here. + -- } + -- }, + -- VMOverride = "", -- change the view model to something else. Please make sure it's compatible with the last one. + -- VMBoneMods = { + -- ["bone"] = Vector(0, 0, 0) + -- }, + -- WMColor = Color(), + -- WMMaterial = "", + -- WMBodygroups = {}, + -- WMElements = { + -- { + -- Model = "", + -- Offset = { + -- pos = Vector(), + -- ang = Angle(), + -- }, + -- IsMuzzleDevice = false -- this element is a muzzle device, and the muzzle flash should come from here. + -- } + -- }, + -- WMOverride = "", -- change the world model to something else. Please make sure it's compatible with the last one. + -- WMBoneMods = { + -- ["bone"] = Vector(0, 0, 0) + -- }, + -- AttPosMods = { + -- [1] = { + -- bone = "", -- optional + -- vpos = Vector(0, 0, 0), + -- vang = Angle(0, 0, 0), + -- wpos = Vector(0, 0, 0), + -- wang = Angle(0, 0, 0), + -- slide = { -- only if base att has slideable + -- vmin = Vector(0, 0, 0), + -- vmax = Vector(0, 0, 0), + -- wmin = Vector(0, 0, 0), + -- wmax = Vector(0, 0, 0) + -- } + -- } + -- } + -- } +} + +SWEP.RejectAttachments = { + -- ["optic_docter"] = true -- stop this attachment from being usable on this gun +} + +SWEP.AttachmentOverrides = { + -- ["optic_docter"] = {} -- allows you to overwrite atttbl values +} + +SWEP.Attachments = {} +-- [1] = { +-- PrintName = "Optic", -- print name +-- DefaultAttName = "Iron Sights", -- used to display the "no attachment" text +-- Slot = "pic_sight", -- what kind of attachments can fit here +-- MergeSlots = {}, -- these other slots will be merged into this one. +-- Bone = "sight", -- relevant bone any attachments will be mostly referring to +-- KeepBaseIrons = false, +-- ExtraSightDist = 0, +-- Offset = { +-- vpos = Vector(0, 0, 0), -- offset that the attachment will be relative to the bone +-- vang = Angle(0, 0, 0), +-- wpos = Vector(0, 0, 0), -- same, for the worldmodels +-- wang = Angle(0, 0, 0) +-- }, +-- RejectAttachments = {}, -- specific blacklist of attachments this slot cannot accept. Needs to be like {"optic_mrs" = true} +-- VScale = Vector(1, 1, 1), +-- WScale = Vector(1, 1, 1), +-- LHIKOutTime = 0.5, -- how much time we should blend out any left hand IK for +-- LHIKInTime = 0.5, -- ditto +-- SlideAmount = { -- how far this attachment can slide in both directions. +-- -- overrides Offset. +-- vmin = Vector(0, 0, 0), +-- vmax = Vector(0, 0, 0), +-- wmin = Vector(0, 0, 0), +-- wmax = Vector(0, 0, 0), +-- }, +-- CorrectiveAng = Vector(1, 1, 1), -- okay, I know I said sights were pain-free. +-- CorrectivePos = Vector(0, 0, 0), -- that won't always be the case. Use these to fix it. Issues mainly crop up in case of sights parented to bones that are not a root bone. +-- InstalledEles = {"toprail"}, -- activate these AttachmentElements if something is installed +-- Hidden = false, -- attachment cannot be seen in customize menu +-- Integral = false, -- attachment is assumed never to change +-- RandomChance = 1, -- multiplies chance this slot will get a random attachment +-- DoNotRandomize = false, +-- NoWM = false, -- do not make this show up on worldmodel +-- NoVM = false, -- what do *you* think this one does? +-- FreeSlot = false, -- slot does not count towards attachment capacity +-- -- ABOUT THE FLAG SYSTEM: +-- -- Attachments and slots can give flags +-- -- All attachments automatically give themselves as a flag, e.g. "optic_mrs" +-- -- If requirements are not satisfied, the slot or attachment will not be attachable +-- ExcludeFlags = {}, -- if the weapon has this flag, hide this slot +-- RequireFlags = {}, -- if the weapon does NOT have all these flags, hide this slot +-- GivesFlags = {} -- give these slots if something is installed here +-- } + +-- ready: deploy first time +-- draw +-- holster +-- reload +-- fire +-- fire_empty +-- cycle (for bolt actions) +-- bash +-- enter_bipod +-- exit_bipod +-- enter_sight +-- exit_sight +-- a_to_b: switch from firemode a to firemode b. e.g.: 1_to_2 +-- idle +-- idle_sights +-- idle_sprint +-- idle_bipod +-- enter_inspect +-- idle_inspect +-- exit_inspect +-- append _empty for empty variation +-- use SWEP.Hook_TranslateAnimation, same as in attachment, to do even more behaviours + +SWEP.Animations = { + -- ["idle"] = { + -- Source = "idle", + -- Time = 10 + -- }, + -- ["draw"] = { + -- RestoreAmmo = 1, -- only used by shotgun reload + -- Source = "deploy", + -- RareSource = "", -- 1/100 chance of playing this animation instead + -- Time = 0.5, + -- TPAnim = ACT_HL2MP_GESTURE_RELOAD_AR2, -- third person animation to play when this animation is played + -- TPAnimStartTime = 0, -- when to start it from + -- Checkpoints = {}, -- time checkpoints. If weapon is unequipped, the animation will continue to play from these checkpoints when reequipped. + -- ShellEjectAt = 0, -- animation includes a shell eject at these times + -- LHIKIn = 0.25, -- left hand inverse kinematics. In/Out controls how long it takes to switch to regular animation. + -- LHIKOut = 0.25, -- (not actually inverse kinematics) + -- LHIK = true, -- basically disable foregrips on this anim + -- SoundTable = { + -- { + -- s = "", -- sound; can be string or table + -- p = 100, -- pitch + -- v = 75, -- volume + -- t = 1, -- time at which to play relative to Animations.Time + -- c = CHAN_ITEM -- channel to play the sound + -- } + -- }, + -- ViewPunchTable = { + -- { + -- p = Vector(0, 0, 0), + -- t = 1 + -- } + -- }, + -- ProcDraw = false, -- for draw/deploy animations, always procedurally draw in addition to playing animation + -- ProcHolster = false -- procedural holster weapon, THEN play animation + -- LastClip1OutTime = 0 -- when should the belt visually replenish on a belt fed + -- } +} + +-- don't change any of this stuff + +SWEP.Primary.Automatic = true +SWEP.Primary.DefaultClip = 1 +SWEP.Secondary.ClipSize = -1 +SWEP.Secondary.DefaultClip = -1 +SWEP.Secondary.Automatic = false +SWEP.Secondary.Ammo = "none" +SWEP.DrawCrosshair = true + +SWEP.ArcCW = true +SWEP.BurstCount = 0 +SWEP.AnimQueue = {} +SWEP.FiremodeIndex = 1 +SWEP.UnReady = true + +SWEP.ProneMod_DisableTransitions = true + +SWEP.DrawWeaponInfoBox = false +SWEP.BounceWeaponIcon = false + +if CLIENT or game.SinglePlayer() then + +SWEP.RecoilAmount = 0 +SWEP.RecoilAmountSide = 0 +SWEP.RecoilPunchBack = 0 +SWEP.RecoilPunchUp = 0 +SWEP.RecoilPunchSide = 0 +SWEP.HammerDown = false + +SWEP.LHIKTimeline = nil +-- {number starttime, number intime, number outtime, number finishouttime} + +end + +if SERVER then + +include("sv_npc.lua") +include("sv_shield.lua") + +end + +include("sh_model.lua") +include("sh_timers.lua") +include("sh_think.lua") +include("sh_deploy.lua") +include("sh_anim.lua") +include("sh_firing.lua") +include("sh_reload.lua") +include("sh_attach.lua") +include("sh_sights.lua") +include("sh_firemodes.lua") +include("sh_customize.lua") +include("sh_ubgl.lua") +include("sh_rocket.lua") +include("sh_bash.lua") +include("sh_bipod.lua") +include("sh_grenade.lua") +AddCSLuaFile("sh_model.lua") +AddCSLuaFile("sh_timers.lua") +AddCSLuaFile("sh_think.lua") +AddCSLuaFile("sh_deploy.lua") +AddCSLuaFile("sh_anim.lua") +AddCSLuaFile("sh_firing.lua") +AddCSLuaFile("sh_reload.lua") +AddCSLuaFile("sh_attach.lua") +AddCSLuaFile("sh_sights.lua") +AddCSLuaFile("sh_firemodes.lua") +AddCSLuaFile("sh_customize.lua") +AddCSLuaFile("sh_ubgl.lua") +AddCSLuaFile("sh_rocket.lua") +AddCSLuaFile("sh_bash.lua") +AddCSLuaFile("sh_bipod.lua") +AddCSLuaFile("sh_grenade.lua") + +AddCSLuaFile("cl_viewmodel.lua") +AddCSLuaFile("cl_scope.lua") +AddCSLuaFile("cl_crosshair.lua") +AddCSLuaFile("cl_hud.lua") +AddCSLuaFile("cl_holosight.lua") +AddCSLuaFile("cl_lhik.lua") +AddCSLuaFile("cl_laser.lua") +AddCSLuaFile("cl_blur.lua") +AddCSLuaFile("cl_presets.lua") + +if CLIENT then + include("cl_viewmodel.lua") + include("cl_scope.lua") + include("cl_crosshair.lua") + include("cl_hud.lua") + include("cl_holosight.lua") + include("cl_lhik.lua") + include("cl_laser.lua") + include("cl_blur.lua") + include("cl_presets.lua") +end + +function SWEP:SetupDataTables() + self:NetworkVar("Int", 0, "State") +end + +function SWEP:IsProne() + if PRONE_INPRONE then + return self:GetOwner():IsProne() + else + return false + end +end + +function SWEP:BarrelHitWall() + local offset = self.BarrelOffsetHip + + if self:GetState() == ArcCW.STATE_SIGHTS then + offset = self.BarrelOffsetSighted + end + + local dir = self:GetOwner():EyeAngles() + local src = self:GetOwner():EyePos() + + src = src + dir:Right() * offset[1] + src = src + dir:Forward() * offset[2] + src = src + dir:Up() * offset[3] + + local mask = MASK_SOLID + + local tr = util.TraceLine({ + start = src, + endpos = src + (dir:Forward() * (self.BarrelLength + self:GetBuff_Add("Add_BarrelLength"))), + filter = {self:GetOwner()}, + mask = mask + }) + + if tr.Hit then + local l = (tr.HitPos - src):Length() + l = l + return 1 - math.Clamp(l / (self.BarrelLength + self:GetBuff_Add("Add_BarrelLength")), 0, 1) + else + return 0 + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sv_npc.lua b/lua/weapons/arccw_base/sv_npc.lua new file mode 100644 index 00000000..a4c1347b --- /dev/null +++ b/lua/weapons/arccw_base/sv_npc.lua @@ -0,0 +1,306 @@ +-- NPC integration + +function SWEP:NPC_Initialize() + if CLIENT then return end + + if !IsValid(self:GetOwner()) then return end + if !self:GetOwner():IsNPC() then return end + + self:NPC_SetupAttachments() + + self:SetHoldType(self.HoldtypeNPC or self:GetBuff_Override("Override_HoldtypeActive") or self.HoldtypeActive) + + self:SetNextPrimaryFire(CurTime()) + + self:SetClip1(self:GetCapacity() or self.Primary.ClipSize) + + local range = self.Range + + range = range / ArcCW.HUToM + + range = range * 2 + + if self.DamageMin > self.Damage then + range = 15000 + end + + range = math.Clamp(range, 2048, 36000) + + self:GetOwner():Input("SetMaxLookDistance", nil, nil, range) + + self:SetNextPrimaryFire(CurTime()) + self:GetOwner():NextThink(CurTime()) +end + +function SWEP:NPC_SetupAttachments() + if !GetConVar("arccw_npc_atts"):GetBool() then return end + + local pick = GetConVar("arccw_atts_pickx"):GetInt() + + local chance = 25 + + local chancestep = 0 + + if pick > 0 then + + chancestep = chance / pick + chance = chancestep + + else + + pick = 1000 + + end + + local n = 0 + + for _, slot in pairs(self.Attachments) do + if n >= pick then continue end + if !self:CheckFlags(slot.ExcludeFlags, slot.RequireFlags) then continue end + if math.Rand(0, 100) > (chance * (slot.RandomChance or 1)) then continue end + + if slot.DoNotRandomize then continue end + + if slot.Installed then continue end + + local atts = ArcCW:GetAttsForSlot(slot.Slot, self) + + if #atts <= 0 then continue end + + chance = chance + chancestep + + slot.Installed = table.Random(atts) + + local atttbl = ArcCW.AttachmentTable[slot.Installed] + + if atttbl.MountPositionOverride then + slot.SlidePos = atttbl.MountPositionOverride + end + + n = n + 1 + end +end + +function SWEP:NPC_Shoot() + -- if self:GetNextPrimaryFire() > CurTime() then return end + + if !IsValid(self:GetOwner()) then return end + if self:Clip1() <= 0 then self:GetOwner():SetSchedule(SCHED_HIDE_AND_RELOAD) return end + + + self.Primary.Automatic = self:ShouldBeAutomatic() + + + local delay = (self.Delay * (1 / self:GetBuff_Mult("Mult_RPM"))) + + delay = self:GetBuff_Hook("Hook_ModifyRPM", delay) or delay + + local num = self:GetBuff_Override("Override_Num") + + if !num then + num = self.Num + end + + num = num + self:GetBuff_Add("Add_Num") + + local spread = ArcCW.MOAToAcc * self.AccuracyMOA * self:GetBuff_Mult("Mult_AccuracyMOA") + + local btabl = { + Attacker = self:GetOwner(), + Damage = 0, + Force = 1, + Distance = 33000, + Num = num, + Tracer = self.TracerNum, + AmmoType = self.Primary.Ammo, + Dir = self:GetOwner():GetAimVector(), + Src = self:GetShootSrc(), + Spread = Vector(spread, spread, spread), + Callback = function(att, tr, dmg) + local dist = (tr.HitPos - tr.StartPos):Length() * ArcCW.HUToM + + local pen = self.Penetration * self:GetBuff_Mult("Mult_Penetration") + + -- local frags = math.random(1, self.Frangibility) + + -- for i = 1, frags do + -- self:DoPenetration(tr, (self.Penetration / frags) - 0.5, tr.Entity) + -- end + + if self.DamageMin > self.Damage then + dist = -dist + self.Range + self.Range + end + + local m = 1 * self:GetBuff_Mult("Mult_DamageNPC") + + local ret = self:GetBuff_Hook("Hook_BulletHit", { + range = dist, + damage = self:GetDamage(dist) * m, + dmgtype = self:GetBuff_Override("Override_DamageType") or self.DamageType, + penleft = pen, + att = att, + tr = tr, + dmg = dmg + }) + + if !ret then return end + + dmg:SetDamageType(ret.dmgtype) + dmg:SetDamage(ret.damage) + + if dmg:GetDamageType() == DMG_BURN and ret.range <= self.Range then + if num == 1 then + dmg:SetDamageType(DMG_BULLET) + else + dmg:SetDamageType(DMG_BUCKSHOT) + end + local fx = EffectData() + fx:SetOrigin(tr.HitPos) + util.Effect("arccw_incendiaryround", fx) + + util.Decal("FadingScorch", tr.StartPos, tr.HitPos - (tr.HitNormal * 16), self:GetOwner()) + + tr.Entity:Ignite(1, 32) + end + end + } + + local sp = self:GetBuff_Override("Override_ShotgunSpreadPattern") or self.ShotgunSpreadPattern + local spo = self:GetBuff_Override("Override_ShotgunSpreadPatternOverrun") or self.ShotgunSpreadPatternOverrun + + if sp or spo then + btabl = self:GetBuff_Hook("Hook_FireBullets", btabl) + + if !btabl then return end + if btabl.Num == 0 then return end + + for n = 1, btabl.Num do + btabl.Num = 1 + local ang = self:GetOwner():GetAimVector():Angle() + self:GetShotgunSpreadOffset(n) + + btabl.Dir = ang:Forward() + + self:GetOwner():FireBullets(btabl) + end + elseif se then + self:FireRocket(se, self.MuzzleVelocity * ArcCW.HUToM * self:GetBuff_Mult("Mult_MuzzleVelocity")) + else + self:GetBuff_Hook("Hook_FireBullets", btabl) + self:FireBullets(btabl) + end + + self:DoEffects() + + if !self.RevolverReload then + self:DoShellEject() + end + + local ss = self.ShootSound + + if self:GetBuff_Override("Silencer") then + ss = self.ShootSoundSilenced + end + + ss = self:GetBuff_Hook("Hook_GetShootSound", ss) + + local dss = self.DistantShootSound + + if self:GetBuff_Override("Silencer") then + dss = nil + end + + dss = self:GetBuff_Hook("Hook_GetDistantShootSound", dss) + + local svol = self.ShootVol * self:GetBuff_Mult("Mult_ShootVol") + local spitch = self.ShootPitch * math.Rand(0.95, 1.05) * self:GetBuff_Mult("Mult_ShootPitch") + + svol = svol * 0.75 + + svol = math.Clamp(svol, 51, 149) + spitch = math.Clamp(spitch, 51, 149) + + if dss then + -- sound.Play(self.DistantShootSound, self:GetPos(), 149, self.ShootPitch * math.Rand(0.95, 1.05), 1) + self:EmitSound(dss, 130, spitch, 0.5, CHAN_BODY) + end + + if ss then + self:EmitSound(ss, svol, spitch, 1, CHAN_WEAPON) + end + + self:SetClip1(self:Clip1() - 1) + + self:SetNextPrimaryFire(CurTime() + delay) + if delay < 0.1 then + self:GetOwner():NextThink(CurTime() + delay) + end +end + +function SWEP:GetNPCBulletSpread(prof) + local mode = self:GetCurrentFiremode() + mode = mode.Mode + + if mode < 0 then + return 15 + elseif mode == 0 then + return 20 + elseif mode == 1 then + if math.Rand(0, 100) < 25 then + return 5 + else + return 50 + end + elseif mode >= 2 then + return 20 + end + + return 15 +end + +function SWEP:GetNPCBurstSettings() + local mode = self:GetCurrentFiremode() + mode = mode.Mode + + local delay = (self.Delay * (1 / self:GetBuff_Mult("Mult_RPM"))) + + delay = self:GetBuff_Hook("Hook_ModifyRPM", delay) or delay + + self:SetNextPrimaryFire(CurTime() + delay) + + if !mode then return 1, 1, delay end + + if self.ManualAction or self:GetBuff_Override("Override_ManualAction") then + return 0, 1, delay + self:GetAnimTime("cycle") + end + + if mode < 0 then + return -mode, -mode, delay + elseif mode == 0 then + return 0, 0, delay + elseif mode == 1 then + return 0, 1, delay + math.Rand(0.3, 0.6) + elseif mode >= 2 then + if self:GetCurrentFiremode().RunawayBurst then + return self:Clip1(), self:Clip1(), delay + else + return 2, math.floor(2.5 / delay), delay + end + end +end + +function SWEP:GetNPCRestTimes() + local postburst = self:GetCurrentFiremode().PostBurstDelay or 0 + local m = 1 * self:GetBuff_Mult("Mult_Recoil") + local rs = 1 * self:GetBuff_Mult("Mult_RecoilSide") + + local o = 1 + + o = o + (m * rs * 0.5) + o = o + postburst + + return 0.2 * o, 0.6 * o +end + +function SWEP:CanBePickedUpByNPCs() + return !self.NotForNPCs +end \ No newline at end of file diff --git a/lua/weapons/arccw_base/sv_shield.lua b/lua/weapons/arccw_base/sv_shield.lua new file mode 100644 index 00000000..ece4c138 --- /dev/null +++ b/lua/weapons/arccw_base/sv_shield.lua @@ -0,0 +1,78 @@ +SWEP.Shields = {} + +function SWEP:SetupShields() + self:KillShields() + + bonename = "ValveBiped.Bip01_R_Hand" + + local boneindex = self:GetOwner():LookupBone(bonename) + + if !boneindex then return end + + local bpos, bang = self:GetOwner():GetBonePosition(boneindex) + + for i, k in pairs(self.Attachments) do + if !k then continue end + if !k.Installed then continue end + + local atttbl = ArcCW.AttachmentTable[k.Installed] + + if atttbl.ModelIsShield then + + for _, e in pairs(self:GetActiveElements()) do + local ele = self.AttachmentElements[e] + + if !ele then continue end + + if ((ele.AttPosMods or {})[i] or {}).wpos then + wmelemod = ele.AttPosMods[i].wpos + end + + if ((ele.AttPosMods or {})[i] or {}).slide then + slidemod = ele.AttPosMods[i].slide + end + end + + local delta = k.SlidePos or 0.5 + + local offset = wmelemod or k.Offset.wpos or Vector(0, 0, 0) + + if k.SlideAmount then + offset = LerpVector(delta, (slidemod or k.SlideAmount).wmin, (slidemod or k.SlideAmount).wmax) + end + + local pos = offset + (atttbl.ShieldCorrectPos or Vector(0, 0, 0)) + local ang = k.Offset.wang or Angle(0, 0, 0) + + local apos = LocalToWorld(pos, ang, bpos, bang) + + local shield = ents.Create("physics_prop") + if !shield then + print("!!! Unable to spawn shield!") + continue + end + + shield:SetModel( atttbl.Model ) + shield:FollowBone( self:GetOwner(), self:GetOwner():LookupBone("ValveBiped.Bip01_R_Hand") ) + shield:SetPos( apos ) + shield:SetAngles( self.Owner:GetAngles() + ang + (atttbl.ShieldCorrectAng or Angle(0, 0, 0)) ) + shield:SetCollisionGroup( COLLISION_GROUP_WORLD ) + shield:SetColor( Color(0, 0, 0, 0) ) + table.insert(self.Shields, shield) + shield:Spawn() + shield:Activate() + + local phys = shield:GetPhysicsObject() + + phys:SetMass(1000) + + shield:SetRenderMode(RENDERMODE_NONE) + end + end +end + +function SWEP:KillShields() + for i, k in pairs(self.Shields) do + SafeRemoveEntity(k) + end +end \ No newline at end of file diff --git a/lua/weapons/arccw_base_melee/shared.lua b/lua/weapons/arccw_base_melee/shared.lua new file mode 100644 index 00000000..46b6f543 --- /dev/null +++ b/lua/weapons/arccw_base_melee/shared.lua @@ -0,0 +1,62 @@ +SWEP.Base = "arccw_base" + +SWEP.MeleeDamage = 25 +SWEP.MeleeRange = 16 +SWEP.MeleeDamageType = DMG_CLUB +SWEP.MeleeTime = 0.5 +SWEP.MeleeGesture = nil +SWEP.MeleeAttackTime = 0.2 + +SWEP.Melee2 = false +SWEP.Melee2Damage = 25 +SWEP.Melee2Range = 16 +SWEP.Melee2Time = 0.5 +SWEP.Melee2Gesture = nil +SWEP.Melee2AttackTime = 0.2 + +SWEP.NotForNPCs = true + +SWEP.Firemodes = { + { + Mode = 1, + PrintName = "MELEE" + }, +} + +SWEP.HoldtypeHolstered = "normal" +SWEP.HoldtypeActive = "melee" + +SWEP.Primary.ClipSize = -1 + +SWEP.Animations = { + -- ["draw"] = { + -- Source = "draw", + -- Time = 0.5, + -- }, + -- ["ready"] = { + -- Source = "draw", + -- Time = 0.5, + -- }, + -- ["bash"] = { + -- Source = {"stab", "midslash1", "midslash2", "stab_miss"}, + -- Time = 0.5, + -- }, +} + +SWEP.IronSightStruct = false + +SWEP.BashPreparePos = Vector(0, 0, 0) +SWEP.BashPrepareAng = Angle(0, 0, 0) + +SWEP.BashPos = Vector(0, 0, 0) +SWEP.BashAng = Angle(0, 0, 0) + +SWEP.HolsterPos = Vector(0, -1, 0) +SWEP.HolsterAng = Angle(-10, 0, 0) + +SWEP.ShootWhileSprint = true + +SWEP.SpeedMult = 1 + +SWEP.Secondary.Automatic = true + diff --git a/lua/weapons/arccw_base_nade/shared.lua b/lua/weapons/arccw_base_nade/shared.lua new file mode 100644 index 00000000..b0cecc94 --- /dev/null +++ b/lua/weapons/arccw_base_nade/shared.lua @@ -0,0 +1,65 @@ +SWEP.Base = "arccw_base" + +SWEP.Throwing = true + +SWEP.NotForNPCs = true + +SWEP.Firemodes = { + { + Mode = 1, + PrintName = "NADE" + }, +} + +SWEP.PullPinTime = 0.25 +SWEP.FuseTime = 3.5 + +SWEP.HoldtypeHolstered = "normal" +SWEP.HoldtypeActive = "grenade" + +SWEP.Primary.ClipSize = 1 +SWEP.Primary.Ammo = "grenade" + +SWEP.Animations = { + -- ["draw"] = { + -- Source = "draw", + -- Time = 0.5, + -- }, + -- ["ready"] = { + -- Source = "draw", + -- Time = 0.5, + -- }, + -- ["pre_throw"] = { + -- Source = "pullpin", + -- Time = 0.5, + -- }, + -- ["throw"] = { + -- Source = "throw", + -- Time = 0.5 + -- } +} + +SWEP.BashPreparePos = Vector(2.187, -7.117, -1) +SWEP.BashPrepareAng = Angle(5, -3.652, -19.039) + +SWEP.BashPos = Vector(8.876, 0, 0) +SWEP.BashAng = Angle(-16.524, 70, -11.046) + +SWEP.HolsterPos = Vector(0.532, -1, 0) +SWEP.HolsterAng = Angle(-10, 0, 0) + +SWEP.IronSightStruct = false + +SWEP.MeleeSwingSound = "weapons/arccw/m249/m249_draw.wav" +SWEP.MeleeHitSound = "weapons/arccw/knife/knife_hitwall1.wav" +SWEP.MeleeHitNPCSound = "physics/body/body_medium_break2.wav" + +SWEP.ShootWhileSprint = true + +SWEP.SpeedMult = 1 + +SWEP.Secondary.Automatic = true + +function SWEP:SecondaryAttack() + self:PrimaryAttack() +end diff --git a/materials/arccw/laser.vmt b/materials/arccw/laser.vmt new file mode 100644 index 00000000..4b956fbb --- /dev/null +++ b/materials/arccw/laser.vmt @@ -0,0 +1,8 @@ +UnLitGeneric +{ + "$basetexture" "arccw\laser" + "$additive" "1" + "$translucent" "1" + "$vertexcolor" "1" + "$vertexalpha" "1" +} diff --git a/materials/arccw/laser.vtf b/materials/arccw/laser.vtf new file mode 100644 index 00000000..463b3b0f Binary files /dev/null and b/materials/arccw/laser.vtf differ diff --git a/materials/effects/fas_debris.vmt b/materials/effects/fas_debris.vmt new file mode 100644 index 00000000..110b8d49 --- /dev/null +++ b/materials/effects/fas_debris.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_debris" + "$vertexcolor" 1 + "$vertexalpha" 1 + "$translucent" 1 +} diff --git a/materials/effects/fas_debris.vtf b/materials/effects/fas_debris.vtf new file mode 100644 index 00000000..30185dac Binary files /dev/null and b/materials/effects/fas_debris.vtf differ diff --git a/materials/effects/fas_debris_add_b.vmt b/materials/effects/fas_debris_add_b.vmt new file mode 100644 index 00000000..e319e902 --- /dev/null +++ b/materials/effects/fas_debris_add_b.vmt @@ -0,0 +1,9 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_debris_add_b" + "$vertexcolor" 1 + "$vertexalpha" 1 + "$translucent" 1 + "$additive" 1 + "$overbrightfactor" 5 +} diff --git a/materials/effects/fas_debris_add_b.vtf b/materials/effects/fas_debris_add_b.vtf new file mode 100644 index 00000000..295646e4 Binary files /dev/null and b/materials/effects/fas_debris_add_b.vtf differ diff --git a/materials/effects/fas_dust_a.vmt b/materials/effects/fas_dust_a.vmt new file mode 100644 index 00000000..a2dcefcf --- /dev/null +++ b/materials/effects/fas_dust_a.vmt @@ -0,0 +1,12 @@ +"SpriteCard" +{ + $basetexture "effects/fas_dust_a" + $SEQUENCE_BLEND_MODE 1 //2 + $MAXLUMFRAMEBLEND1 0 + $MAXLUMFRAMEBLEND2 1 + $depthblend 1 + $STARTFADESIZE .45 + $ENDFADESIZE .575 + "$vertexcolor" 1 + "$vertexalpha" 1 +} \ No newline at end of file diff --git a/materials/effects/fas_dust_a.vtf b/materials/effects/fas_dust_a.vtf new file mode 100644 index 00000000..787048ea Binary files /dev/null and b/materials/effects/fas_dust_a.vtf differ diff --git a/materials/effects/fas_dust_a_near.vmt b/materials/effects/fas_dust_a_near.vmt new file mode 100644 index 00000000..90ccbb2f --- /dev/null +++ b/materials/effects/fas_dust_a_near.vmt @@ -0,0 +1,14 @@ +"SpriteCard" +{ + $basetexture "effects/fas_dust_a" + $SEQUENCE_BLEND_MODE 1 //2 + $MAXLUMFRAMEBLEND1 0 + $MAXLUMFRAMEBLEND2 1 + $depthblend 1 + $STARTFADESIZE 3 + $ENDFADESIZE 4.5 + $MAXDISTANCE 800 + $FARFADEINTERVAL 100 + "$vertexcolor" 1 + "$vertexalpha" 1 +} \ No newline at end of file diff --git a/materials/effects/fas_dust_b.vmt b/materials/effects/fas_dust_b.vmt new file mode 100644 index 00000000..e13a6c29 --- /dev/null +++ b/materials/effects/fas_dust_b.vmt @@ -0,0 +1,12 @@ +"SpriteCard" +{ + $basetexture "effects/fas_dust_b" + $SEQUENCE_BLEND_MODE 1 //2 + $MAXLUMFRAMEBLEND1 0 + $MAXLUMFRAMEBLEND2 1 + $depthblend 1 + $STARTFADESIZE .45 + $ENDFADESIZE .575 + "$vertexcolor" 1 + "$vertexalpha" 1 +} \ No newline at end of file diff --git a/materials/effects/fas_dust_b.vtf b/materials/effects/fas_dust_b.vtf new file mode 100644 index 00000000..d52809bb Binary files /dev/null and b/materials/effects/fas_dust_b.vtf differ diff --git a/materials/effects/fas_dust_b_near.vmt b/materials/effects/fas_dust_b_near.vmt new file mode 100644 index 00000000..65e7a343 --- /dev/null +++ b/materials/effects/fas_dust_b_near.vmt @@ -0,0 +1,14 @@ +"SpriteCard" +{ + $basetexture "effects/fas_dust_b" + $SEQUENCE_BLEND_MODE 1 //2 + $MAXLUMFRAMEBLEND1 0 + $MAXLUMFRAMEBLEND2 1 + $depthblend 1 + $STARTFADESIZE .45 + $ENDFADESIZE .575 + $MAXDISTANCE 800 + $FARFADEINTERVAL 100 + "$vertexcolor" 1 + "$vertexalpha" 1 +} \ No newline at end of file diff --git a/materials/effects/fas_dust_thick.vmt b/materials/effects/fas_dust_thick.vmt new file mode 100644 index 00000000..eb0571e4 --- /dev/null +++ b/materials/effects/fas_dust_thick.vmt @@ -0,0 +1,12 @@ +"SpriteCard" +{ + $basetexture "effects/fas_dust_thick" + $SEQUENCE_BLEND_MODE 1 //2 + $MAXLUMFRAMEBLEND1 0 + $MAXLUMFRAMEBLEND2 1 + $depthblend 1 + $STARTFADESIZE 3 + $ENDFADESIZE 4.5 + "$vertexcolor" 1 + "$vertexalpha" 1 +} \ No newline at end of file diff --git a/materials/effects/fas_dust_thick.vtf b/materials/effects/fas_dust_thick.vtf new file mode 100644 index 00000000..4e601eb0 Binary files /dev/null and b/materials/effects/fas_dust_thick.vtf differ diff --git a/materials/effects/fas_flamering.vmt b/materials/effects/fas_flamering.vmt new file mode 100644 index 00000000..a664d316 --- /dev/null +++ b/materials/effects/fas_flamering.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_flamering" + "$additive" "1" + "$vertexcolor" 1 + "$vertexalpha" "1" +} diff --git a/materials/effects/fas_flamering.vtf b/materials/effects/fas_flamering.vtf new file mode 100644 index 00000000..b0eb5674 Binary files /dev/null and b/materials/effects/fas_flamering.vtf differ diff --git a/materials/effects/fas_glow_debris.vmt b/materials/effects/fas_glow_debris.vmt new file mode 100644 index 00000000..aed5d45b --- /dev/null +++ b/materials/effects/fas_glow_debris.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_glow_debris" + "$additive" "1" + "$vertexcolor" 1 + "$vertexalpha" "1" +} diff --git a/materials/effects/fas_glow_debris.vtf b/materials/effects/fas_glow_debris.vtf new file mode 100644 index 00000000..e4a58368 Binary files /dev/null and b/materials/effects/fas_glow_debris.vtf differ diff --git a/materials/effects/fas_heavy_smoke_spike.vmt b/materials/effects/fas_heavy_smoke_spike.vmt new file mode 100644 index 00000000..5627b96d --- /dev/null +++ b/materials/effects/fas_heavy_smoke_spike.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_heavy_smoke_spike" + "$vertexcolor" 1 + "$vertexalpha" 1 + "$translucent" 1 +} diff --git a/materials/effects/fas_heavy_smoke_spike.vtf b/materials/effects/fas_heavy_smoke_spike.vtf new file mode 100644 index 00000000..9bb27ff5 Binary files /dev/null and b/materials/effects/fas_heavy_smoke_spike.vtf differ diff --git a/materials/effects/fas_light_glare.vtf b/materials/effects/fas_light_glare.vtf new file mode 100644 index 00000000..7a838e1b Binary files /dev/null and b/materials/effects/fas_light_glare.vtf differ diff --git a/materials/effects/fas_light_glare_noz.vmt b/materials/effects/fas_light_glare_noz.vmt new file mode 100644 index 00000000..62c339fe --- /dev/null +++ b/materials/effects/fas_light_glare_noz.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_light_glare" + "$additive" "1" + "$vertexcolor" 1 + "$vertexalpha" 1 + "$ignorez" "1" +} diff --git a/materials/effects/fas_muzzle_break_test.vmt b/materials/effects/fas_muzzle_break_test.vmt new file mode 100644 index 00000000..125f7f90 --- /dev/null +++ b/materials/effects/fas_muzzle_break_test.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_muzzle_break_test" + "$additive" "1" + "$vertexcolor" 1 + "$vertexalpha" "1" +} diff --git a/materials/effects/fas_muzzle_break_test.vtf b/materials/effects/fas_muzzle_break_test.vtf new file mode 100644 index 00000000..a221ad47 Binary files /dev/null and b/materials/effects/fas_muzzle_break_test.vtf differ diff --git a/materials/effects/fas_smoke_beam.vmt b/materials/effects/fas_smoke_beam.vmt new file mode 100644 index 00000000..51175487 --- /dev/null +++ b/materials/effects/fas_smoke_beam.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_smoke_beam" + "$vertexcolor" 1 + "$vertexalpha" 1 + "$translucent" 1 +} diff --git a/materials/effects/fas_smoke_beam.vtf b/materials/effects/fas_smoke_beam.vtf new file mode 100644 index 00000000..41401d5e Binary files /dev/null and b/materials/effects/fas_smoke_beam.vtf differ diff --git a/materials/effects/fas_smoke_trail.vmt b/materials/effects/fas_smoke_trail.vmt new file mode 100644 index 00000000..dd5c3cce --- /dev/null +++ b/materials/effects/fas_smoke_trail.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/fas_smoke_trail" + "$vertexcolor" 1 + "$vertexalpha" 1 + "$translucent" 1 +} diff --git a/materials/effects/fas_smoke_trail.vtf b/materials/effects/fas_smoke_trail.vtf new file mode 100644 index 00000000..4a8d1699 Binary files /dev/null and b/materials/effects/fas_smoke_trail.vtf differ diff --git a/materials/effects/happy_rainbows.vmt b/materials/effects/happy_rainbows.vmt new file mode 100644 index 00000000..c3b7d8d3 --- /dev/null +++ b/materials/effects/happy_rainbows.vmt @@ -0,0 +1,9 @@ +"UnlitGeneric" +{ + "$basetexture" "effects\happy_rainbows" + $vertexcolor 1 + $vertexalpha 1 + $translucent 1 + $additive 1 + $ignorez 1 +} \ No newline at end of file diff --git a/materials/effects/happy_rainbows.vtf b/materials/effects/happy_rainbows.vtf new file mode 100644 index 00000000..e91cba5c Binary files /dev/null and b/materials/effects/happy_rainbows.vtf differ diff --git a/materials/effects/hl2_muzzleflash.vtf b/materials/effects/hl2_muzzleflash.vtf new file mode 100644 index 00000000..df54781f Binary files /dev/null and b/materials/effects/hl2_muzzleflash.vtf differ diff --git a/materials/effects/hl2_muzzleflash_add.vmt b/materials/effects/hl2_muzzleflash_add.vmt new file mode 100644 index 00000000..4d6708bf --- /dev/null +++ b/materials/effects/hl2_muzzleflash_add.vmt @@ -0,0 +1,14 @@ +"SpriteCard" +{ + $basetexture "effects/hl2_muzzleflash" + $SEQUENCE_BLEND_MODE 1 //2 + $MAXLUMFRAMEBLEND1 0 + $MAXLUMFRAMEBLEND2 1 + $OVERBRIGHTFACTOR 5 + $additive 1 + $depthblend 1 + $STARTFADESIZE 5 + $ENDFADESIZE 7 + "$vertexcolor" 1 + "$vertexalpha" 1 +} \ No newline at end of file diff --git a/materials/effects/sparkwires.vmt b/materials/effects/sparkwires.vmt new file mode 100644 index 00000000..53f8dde9 --- /dev/null +++ b/materials/effects/sparkwires.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "effects/sparkwires_b" + "$additive" "1" + "$vertexcolor" 1 + "$vertexalpha" "1" +} diff --git a/materials/effects/sparkwires_b.vtf b/materials/effects/sparkwires_b.vtf new file mode 100644 index 00000000..86001b03 Binary files /dev/null and b/materials/effects/sparkwires_b.vtf differ diff --git a/materials/effects/whiteflare.vmt b/materials/effects/whiteflare.vmt new file mode 100644 index 00000000..1986fc82 --- /dev/null +++ b/materials/effects/whiteflare.vmt @@ -0,0 +1,8 @@ +"Sprite" +{ + "$basetexture" "effects/whiteflare" + + "$vertexalpha" 1 + "$vertexcolor" 1 + "$spriterendermode" 5 +} \ No newline at end of file diff --git a/materials/effects/whiteflare.vtf b/materials/effects/whiteflare.vtf new file mode 100644 index 00000000..00f899ee Binary files /dev/null and b/materials/effects/whiteflare.vtf differ diff --git a/materials/entities/arccw_ammo_357.png b/materials/entities/arccw_ammo_357.png new file mode 100644 index 00000000..31a0ba23 Binary files /dev/null and b/materials/entities/arccw_ammo_357.png differ diff --git a/materials/entities/arccw_ammo_357_large.png b/materials/entities/arccw_ammo_357_large.png new file mode 100644 index 00000000..c1764b19 Binary files /dev/null and b/materials/entities/arccw_ammo_357_large.png differ diff --git a/materials/entities/arccw_ammo_ar2.png b/materials/entities/arccw_ammo_ar2.png new file mode 100644 index 00000000..6ff580ce Binary files /dev/null and b/materials/entities/arccw_ammo_ar2.png differ diff --git a/materials/entities/arccw_ammo_ar2_large.png b/materials/entities/arccw_ammo_ar2_large.png new file mode 100644 index 00000000..7efea2d0 Binary files /dev/null and b/materials/entities/arccw_ammo_ar2_large.png differ diff --git a/materials/entities/arccw_ammo_buckshot.png b/materials/entities/arccw_ammo_buckshot.png new file mode 100644 index 00000000..1fa17fca Binary files /dev/null and b/materials/entities/arccw_ammo_buckshot.png differ diff --git a/materials/entities/arccw_ammo_buckshot_large.png b/materials/entities/arccw_ammo_buckshot_large.png new file mode 100644 index 00000000..22d323ae Binary files /dev/null and b/materials/entities/arccw_ammo_buckshot_large.png differ diff --git a/materials/entities/arccw_ammo_pistol.png b/materials/entities/arccw_ammo_pistol.png new file mode 100644 index 00000000..b522e535 Binary files /dev/null and b/materials/entities/arccw_ammo_pistol.png differ diff --git a/materials/entities/arccw_ammo_pistol_large.png b/materials/entities/arccw_ammo_pistol_large.png new file mode 100644 index 00000000..0905a292 Binary files /dev/null and b/materials/entities/arccw_ammo_pistol_large.png differ diff --git a/materials/entities/arccw_ammo_smg1.png b/materials/entities/arccw_ammo_smg1.png new file mode 100644 index 00000000..42b2831c Binary files /dev/null and b/materials/entities/arccw_ammo_smg1.png differ diff --git a/materials/entities/arccw_ammo_smg1_grenade.png b/materials/entities/arccw_ammo_smg1_grenade.png new file mode 100644 index 00000000..03a1f632 Binary files /dev/null and b/materials/entities/arccw_ammo_smg1_grenade.png differ diff --git a/materials/entities/arccw_ammo_smg1_grenade_large.png b/materials/entities/arccw_ammo_smg1_grenade_large.png new file mode 100644 index 00000000..332e0775 Binary files /dev/null and b/materials/entities/arccw_ammo_smg1_grenade_large.png differ diff --git a/materials/entities/arccw_ammo_smg1_large.png b/materials/entities/arccw_ammo_smg1_large.png new file mode 100644 index 00000000..90c5f1f8 Binary files /dev/null and b/materials/entities/arccw_ammo_smg1_large.png differ diff --git a/materials/entities/arccw_ammo_sniper.png b/materials/entities/arccw_ammo_sniper.png new file mode 100644 index 00000000..b4bd96d9 Binary files /dev/null and b/materials/entities/arccw_ammo_sniper.png differ diff --git a/materials/entities/arccw_ammo_sniper_large.png b/materials/entities/arccw_ammo_sniper_large.png new file mode 100644 index 00000000..c46d0ae3 Binary files /dev/null and b/materials/entities/arccw_ammo_sniper_large.png differ diff --git a/materials/hud/atts/default.png b/materials/hud/atts/default.png new file mode 100644 index 00000000..d87f967f Binary files /dev/null and b/materials/hud/atts/default.png differ diff --git a/materials/hud/black.png b/materials/hud/black.png new file mode 100644 index 00000000..3cf27f47 Binary files /dev/null and b/materials/hud/black.png differ diff --git a/materials/hud/scopes/duplex.png b/materials/hud/scopes/duplex.png new file mode 100644 index 00000000..73fdb850 Binary files /dev/null and b/materials/hud/scopes/duplex.png differ diff --git a/materials/hud/scopes/shadow.png b/materials/hud/scopes/shadow.png new file mode 100644 index 00000000..61dca31c Binary files /dev/null and b/materials/hud/scopes/shadow.png differ diff --git a/materials/models/items/arccw/magnum_ammo.vmt b/materials/models/items/arccw/magnum_ammo.vmt new file mode 100644 index 00000000..a91f8460 --- /dev/null +++ b/materials/models/items/arccw/magnum_ammo.vmt @@ -0,0 +1,7 @@ +"VertexLitGeneric" +{ + "$baseTexture" "models/items/arccw/magnum_ammo" + "$envmap" "env_cubemap" + "$basealphaenvmapmask" 1 + "$model" 1 +} diff --git a/materials/models/items/arccw/magnum_ammo.vtf b/materials/models/items/arccw/magnum_ammo.vtf new file mode 100644 index 00000000..f452a061 Binary files /dev/null and b/materials/models/items/arccw/magnum_ammo.vtf differ diff --git a/materials/models/items/arccw/magnum_ammo_misc.vmt b/materials/models/items/arccw/magnum_ammo_misc.vmt new file mode 100644 index 00000000..2342eb28 --- /dev/null +++ b/materials/models/items/arccw/magnum_ammo_misc.vmt @@ -0,0 +1,7 @@ +"VertexLitGeneric" +{ + "$baseTexture" "models/items/arccw/magnum_ammo_misc" + "$envmap" "env_cubemap" + "$basealphaenvmapmask" 1 + "$model" 1 +} diff --git a/materials/models/items/arccw/magnum_ammo_misc.vtf b/materials/models/items/arccw/magnum_ammo_misc.vtf new file mode 100644 index 00000000..c35da159 Binary files /dev/null and b/materials/models/items/arccw/magnum_ammo_misc.vtf differ diff --git a/materials/models/items/arccw/magnum_ammo_misc_nocss.vmt b/materials/models/items/arccw/magnum_ammo_misc_nocss.vmt new file mode 100644 index 00000000..839780c9 --- /dev/null +++ b/materials/models/items/arccw/magnum_ammo_misc_nocss.vmt @@ -0,0 +1,7 @@ +"VertexLitGeneric" +{ + "$baseTexture" "models/items/arccw/magnum_ammo_misc_nocss" + "$envmap" "env_cubemap" + "$basealphaenvmapmask" 1 + "$model" 1 +} diff --git a/materials/models/items/arccw/magnum_ammo_misc_nocss.vtf b/materials/models/items/arccw/magnum_ammo_misc_nocss.vtf new file mode 100644 index 00000000..d881628a Binary files /dev/null and b/materials/models/items/arccw/magnum_ammo_misc_nocss.vtf differ diff --git a/materials/models/items/arccw/magnum_ammo_nocss.vmt b/materials/models/items/arccw/magnum_ammo_nocss.vmt new file mode 100644 index 00000000..f5f9b672 --- /dev/null +++ b/materials/models/items/arccw/magnum_ammo_nocss.vmt @@ -0,0 +1,7 @@ +"VertexLitGeneric" +{ + "$baseTexture" "models/items/arccw/magnum_ammo_nocss" + "$envmap" "env_cubemap" + "$basealphaenvmapmask" 1 + "$model" 1 +} diff --git a/materials/models/items/arccw/magnum_ammo_nocss.vtf b/materials/models/items/arccw/magnum_ammo_nocss.vtf new file mode 100644 index 00000000..7ba7e4af Binary files /dev/null and b/materials/models/items/arccw/magnum_ammo_nocss.vtf differ diff --git a/materials/models/items/arccw/pistol_ammo.vmt b/materials/models/items/arccw/pistol_ammo.vmt new file mode 100644 index 00000000..0128195d --- /dev/null +++ b/materials/models/items/arccw/pistol_ammo.vmt @@ -0,0 +1,11 @@ + +VertexLitGeneric +{ + + $basetexture models/items/arccw/pistol_ammo + $bumpmap dev/bump_normal + + $halflambert 1 + $ambientocclusion 1 + +} diff --git a/materials/models/items/arccw/pistol_ammo.vtf b/materials/models/items/arccw/pistol_ammo.vtf new file mode 100644 index 00000000..70311262 Binary files /dev/null and b/materials/models/items/arccw/pistol_ammo.vtf differ diff --git a/materials/models/items/arccw/rifle_ammo.vmt b/materials/models/items/arccw/rifle_ammo.vmt new file mode 100644 index 00000000..143e26ba --- /dev/null +++ b/materials/models/items/arccw/rifle_ammo.vmt @@ -0,0 +1,11 @@ + +VertexLitGeneric +{ + + $basetexture models/items/arccw/rifle_ammo + $bumpmap dev/bump_normal + + $halflambert 1 + $ambientocclusion 1 + +} diff --git a/materials/models/items/arccw/rifle_ammo.vtf b/materials/models/items/arccw/rifle_ammo.vtf new file mode 100644 index 00000000..8dff4038 Binary files /dev/null and b/materials/models/items/arccw/rifle_ammo.vtf differ diff --git a/materials/models/items/arccw/rifle_ammo_hawaii1.vmt b/materials/models/items/arccw/rifle_ammo_hawaii1.vmt new file mode 100644 index 00000000..d2f17c7d --- /dev/null +++ b/materials/models/items/arccw/rifle_ammo_hawaii1.vmt @@ -0,0 +1,11 @@ + +VertexLitGeneric +{ + + $basetexture models/items/arccw/rifle_ammo_hawaii1 + $bumpmap dev/bump_normal + + $halflambert 1 + $ambientocclusion 1 + +} diff --git a/materials/models/items/arccw/rifle_ammo_hawaii1.vtf b/materials/models/items/arccw/rifle_ammo_hawaii1.vtf new file mode 100644 index 00000000..9b7fbce1 Binary files /dev/null and b/materials/models/items/arccw/rifle_ammo_hawaii1.vtf differ diff --git a/materials/models/items/arccw/rifle_ammo_hawaii2.vmt b/materials/models/items/arccw/rifle_ammo_hawaii2.vmt new file mode 100644 index 00000000..26ce2414 --- /dev/null +++ b/materials/models/items/arccw/rifle_ammo_hawaii2.vmt @@ -0,0 +1,11 @@ + +VertexLitGeneric +{ + + $basetexture models/items/arccw/rifle_ammo_hawaii2 + $bumpmap dev/bump_normal + + $halflambert 1 + $ambientocclusion 1 + +} diff --git a/materials/models/items/arccw/rifle_ammo_hawaii2.vtf b/materials/models/items/arccw/rifle_ammo_hawaii2.vtf new file mode 100644 index 00000000..da9d28d7 Binary files /dev/null and b/materials/models/items/arccw/rifle_ammo_hawaii2.vtf differ diff --git a/materials/models/items/arccw/rifle_ammo_nocss.vmt b/materials/models/items/arccw/rifle_ammo_nocss.vmt new file mode 100644 index 00000000..af3c5ea6 --- /dev/null +++ b/materials/models/items/arccw/rifle_ammo_nocss.vmt @@ -0,0 +1,11 @@ + +VertexLitGeneric +{ + + $basetexture models/items/arccw/rifle_ammo_nocss + $bumpmap dev/bump_normal + + $halflambert 1 + $ambientocclusion 1 + +} diff --git a/materials/models/items/arccw/rifle_ammo_nocss.vtf b/materials/models/items/arccw/rifle_ammo_nocss.vtf new file mode 100644 index 00000000..9bbdd9e2 Binary files /dev/null and b/materials/models/items/arccw/rifle_ammo_nocss.vtf differ diff --git a/materials/models/items/arccw/riflegrenade_ammo.vmt b/materials/models/items/arccw/riflegrenade_ammo.vmt new file mode 100644 index 00000000..e3ad2cd9 --- /dev/null +++ b/materials/models/items/arccw/riflegrenade_ammo.vmt @@ -0,0 +1,4 @@ +"VertexLitGeneric" +{ + "$basetexture" "models/items/arccw/riflegrenade_ammo" +} diff --git a/materials/models/items/arccw/riflegrenade_ammo.vtf b/materials/models/items/arccw/riflegrenade_ammo.vtf new file mode 100644 index 00000000..82e2aec0 Binary files /dev/null and b/materials/models/items/arccw/riflegrenade_ammo.vtf differ diff --git a/materials/models/items/arccw/shotgun_ammo.vmt b/materials/models/items/arccw/shotgun_ammo.vmt new file mode 100644 index 00000000..4299e955 --- /dev/null +++ b/materials/models/items/arccw/shotgun_ammo.vmt @@ -0,0 +1,4 @@ +"VertexLitGeneric" +{ + "$basetexture" "models/items/arccw/shotgun_ammo" +} diff --git a/materials/models/items/arccw/shotgun_ammo.vtf b/materials/models/items/arccw/shotgun_ammo.vtf new file mode 100644 index 00000000..4729db8c Binary files /dev/null and b/materials/models/items/arccw/shotgun_ammo.vtf differ diff --git a/materials/models/items/arccw/shotgun_ammo_nocss.vmt b/materials/models/items/arccw/shotgun_ammo_nocss.vmt new file mode 100644 index 00000000..34d89158 --- /dev/null +++ b/materials/models/items/arccw/shotgun_ammo_nocss.vmt @@ -0,0 +1,4 @@ +"VertexLitGeneric" +{ + "$basetexture" "models/items/arccw/shotgun_ammo_nocss" +} diff --git a/materials/models/items/arccw/shotgun_ammo_nocss.vtf b/materials/models/items/arccw/shotgun_ammo_nocss.vtf new file mode 100644 index 00000000..9375cb5e Binary files /dev/null and b/materials/models/items/arccw/shotgun_ammo_nocss.vtf differ diff --git a/materials/models/items/arccw/smg_ammo.vmt b/materials/models/items/arccw/smg_ammo.vmt new file mode 100644 index 00000000..b18af1c1 --- /dev/null +++ b/materials/models/items/arccw/smg_ammo.vmt @@ -0,0 +1,4 @@ +"VertexLitGeneric" +{ + "$basetexture" "models/items/arccw/smg_ammo" +} diff --git a/materials/models/items/arccw/smg_ammo.vtf b/materials/models/items/arccw/smg_ammo.vtf new file mode 100644 index 00000000..74b60658 Binary files /dev/null and b/materials/models/items/arccw/smg_ammo.vtf differ diff --git a/materials/models/items/arccw/sniper_ammo.vmt b/materials/models/items/arccw/sniper_ammo.vmt new file mode 100644 index 00000000..80eef4c1 --- /dev/null +++ b/materials/models/items/arccw/sniper_ammo.vmt @@ -0,0 +1,10 @@ +VertexLitGeneric +{ + + $basetexture models/items/arccw/sniper_ammo + $bumpmap dev/bump_normal + + $halflambert 1 + $ambientocclusion 1 + +} diff --git a/materials/models/items/arccw/sniper_ammo.vtf b/materials/models/items/arccw/sniper_ammo.vtf new file mode 100644 index 00000000..5d0f92d9 Binary files /dev/null and b/materials/models/items/arccw/sniper_ammo.vtf differ diff --git a/materials/models/items/arccw/sniper_ammo_camo.vmt b/materials/models/items/arccw/sniper_ammo_camo.vmt new file mode 100644 index 00000000..7f88e215 --- /dev/null +++ b/materials/models/items/arccw/sniper_ammo_camo.vmt @@ -0,0 +1,10 @@ +VertexLitGeneric +{ + + $basetexture models/items/arccw/sniper_ammo_camo + $bumpmap dev/bump_normal + + $halflambert 1 + $ambientocclusion 1 + +} diff --git a/materials/models/items/arccw/sniper_ammo_camo.vtf b/materials/models/items/arccw/sniper_ammo_camo.vtf new file mode 100644 index 00000000..86db49f5 Binary files /dev/null and b/materials/models/items/arccw/sniper_ammo_camo.vtf differ diff --git a/materials/models/items/newsniperbox.vtf b/materials/models/items/newsniperbox.vtf new file mode 100644 index 00000000..945b13f2 Binary files /dev/null and b/materials/models/items/newsniperbox.vtf differ diff --git a/materials/models/items/newsniperboxmaterial.vmt b/materials/models/items/newsniperboxmaterial.vmt new file mode 100644 index 00000000..ad87c4c6 --- /dev/null +++ b/materials/models/items/newsniperboxmaterial.vmt @@ -0,0 +1,4 @@ +"VertexLitGeneric" +{ + $baseTexture "models\items\newsniperbox.vtf" +} diff --git a/materials/models/items/round.vmt b/materials/models/items/round.vmt new file mode 100644 index 00000000..678aea94 --- /dev/null +++ b/materials/models/items/round.vmt @@ -0,0 +1,4 @@ +"VertexLitGeneric" +{ + "$basetexture" "Models/Items/round" +} diff --git a/materials/models/items/round.vtf b/materials/models/items/round.vtf new file mode 100644 index 00000000..0bcb61df Binary files /dev/null and b/materials/models/items/round.vtf differ diff --git a/materials/models/weapons/arcticcw/atts/fabstock.vmt b/materials/models/weapons/arcticcw/atts/fabstock.vmt new file mode 100644 index 00000000..fdaec57b --- /dev/null +++ b/materials/models/weapons/arcticcw/atts/fabstock.vmt @@ -0,0 +1,7 @@ +"VertexLitGeneric" +{ + "$basetexture" "models\weapons\arcticcw\atts\glockstock" + $envmapmask models\weapons\arcticcw\atts\glockstock_s + $envmap env_cubemap + $envmaptint .5 .5 .5 +} \ No newline at end of file diff --git a/materials/models/weapons/arcticcw/atts/glockstock.vtf b/materials/models/weapons/arcticcw/atts/glockstock.vtf new file mode 100644 index 00000000..fbc1edfe Binary files /dev/null and b/materials/models/weapons/arcticcw/atts/glockstock.vtf differ diff --git a/materials/models/weapons/arcticcw/atts/glockstock_s.vtf b/materials/models/weapons/arcticcw/atts/glockstock_s.vtf new file mode 100644 index 00000000..e7a2f6a4 Binary files /dev/null and b/materials/models/weapons/arcticcw/atts/glockstock_s.vtf differ diff --git a/models/items/arccw/magnum_ammo.dx80.vtx b/models/items/arccw/magnum_ammo.dx80.vtx new file mode 100644 index 00000000..538615b4 Binary files /dev/null and b/models/items/arccw/magnum_ammo.dx80.vtx differ diff --git a/models/items/arccw/magnum_ammo.dx90.vtx b/models/items/arccw/magnum_ammo.dx90.vtx new file mode 100644 index 00000000..e3f249f0 Binary files /dev/null and b/models/items/arccw/magnum_ammo.dx90.vtx differ diff --git a/models/items/arccw/magnum_ammo.mdl b/models/items/arccw/magnum_ammo.mdl new file mode 100644 index 00000000..09e57da3 Binary files /dev/null and b/models/items/arccw/magnum_ammo.mdl differ diff --git a/models/items/arccw/magnum_ammo.phy b/models/items/arccw/magnum_ammo.phy new file mode 100644 index 00000000..aee56e0a Binary files /dev/null and b/models/items/arccw/magnum_ammo.phy differ diff --git a/models/items/arccw/magnum_ammo.sw.vtx b/models/items/arccw/magnum_ammo.sw.vtx new file mode 100644 index 00000000..81d72a38 Binary files /dev/null and b/models/items/arccw/magnum_ammo.sw.vtx differ diff --git a/models/items/arccw/magnum_ammo.vvd b/models/items/arccw/magnum_ammo.vvd new file mode 100644 index 00000000..53e72e76 Binary files /dev/null and b/models/items/arccw/magnum_ammo.vvd differ diff --git a/models/items/arccw/magnum_ammo_closed.dx80.vtx b/models/items/arccw/magnum_ammo_closed.dx80.vtx new file mode 100644 index 00000000..e5a7cb50 Binary files /dev/null and b/models/items/arccw/magnum_ammo_closed.dx80.vtx differ diff --git a/models/items/arccw/magnum_ammo_closed.dx90.vtx b/models/items/arccw/magnum_ammo_closed.dx90.vtx new file mode 100644 index 00000000..7f010066 Binary files /dev/null and b/models/items/arccw/magnum_ammo_closed.dx90.vtx differ diff --git a/models/items/arccw/magnum_ammo_closed.mdl b/models/items/arccw/magnum_ammo_closed.mdl new file mode 100644 index 00000000..54bf8f34 Binary files /dev/null and b/models/items/arccw/magnum_ammo_closed.mdl differ diff --git a/models/items/arccw/magnum_ammo_closed.phy b/models/items/arccw/magnum_ammo_closed.phy new file mode 100644 index 00000000..9552786a Binary files /dev/null and b/models/items/arccw/magnum_ammo_closed.phy differ diff --git a/models/items/arccw/magnum_ammo_closed.sw.vtx b/models/items/arccw/magnum_ammo_closed.sw.vtx new file mode 100644 index 00000000..532589d9 Binary files /dev/null and b/models/items/arccw/magnum_ammo_closed.sw.vtx differ diff --git a/models/items/arccw/magnum_ammo_closed.vvd b/models/items/arccw/magnum_ammo_closed.vvd new file mode 100644 index 00000000..91cb43a0 Binary files /dev/null and b/models/items/arccw/magnum_ammo_closed.vvd differ diff --git a/models/items/arccw/pistol_ammo.dx80.vtx b/models/items/arccw/pistol_ammo.dx80.vtx new file mode 100644 index 00000000..5e044731 Binary files /dev/null and b/models/items/arccw/pistol_ammo.dx80.vtx differ diff --git a/models/items/arccw/pistol_ammo.dx90.vtx b/models/items/arccw/pistol_ammo.dx90.vtx new file mode 100644 index 00000000..a794df8b Binary files /dev/null and b/models/items/arccw/pistol_ammo.dx90.vtx differ diff --git a/models/items/arccw/pistol_ammo.mdl b/models/items/arccw/pistol_ammo.mdl new file mode 100644 index 00000000..ec441ea4 Binary files /dev/null and b/models/items/arccw/pistol_ammo.mdl differ diff --git a/models/items/arccw/pistol_ammo.phy b/models/items/arccw/pistol_ammo.phy new file mode 100644 index 00000000..8542065f Binary files /dev/null and b/models/items/arccw/pistol_ammo.phy differ diff --git a/models/items/arccw/pistol_ammo.sw.vtx b/models/items/arccw/pistol_ammo.sw.vtx new file mode 100644 index 00000000..db7ecf4a Binary files /dev/null and b/models/items/arccw/pistol_ammo.sw.vtx differ diff --git a/models/items/arccw/pistol_ammo.vvd b/models/items/arccw/pistol_ammo.vvd new file mode 100644 index 00000000..0fcc836d Binary files /dev/null and b/models/items/arccw/pistol_ammo.vvd differ diff --git a/models/items/arccw/rifle_ammo.dx80.vtx b/models/items/arccw/rifle_ammo.dx80.vtx new file mode 100644 index 00000000..2c620dc8 Binary files /dev/null and b/models/items/arccw/rifle_ammo.dx80.vtx differ diff --git a/models/items/arccw/rifle_ammo.dx90.vtx b/models/items/arccw/rifle_ammo.dx90.vtx new file mode 100644 index 00000000..4a851c22 Binary files /dev/null and b/models/items/arccw/rifle_ammo.dx90.vtx differ diff --git a/models/items/arccw/rifle_ammo.mdl b/models/items/arccw/rifle_ammo.mdl new file mode 100644 index 00000000..012d5a98 Binary files /dev/null and b/models/items/arccw/rifle_ammo.mdl differ diff --git a/models/items/arccw/rifle_ammo.phy b/models/items/arccw/rifle_ammo.phy new file mode 100644 index 00000000..ad4ef03b Binary files /dev/null and b/models/items/arccw/rifle_ammo.phy differ diff --git a/models/items/arccw/rifle_ammo.sw.vtx b/models/items/arccw/rifle_ammo.sw.vtx new file mode 100644 index 00000000..56760cfd Binary files /dev/null and b/models/items/arccw/rifle_ammo.sw.vtx differ diff --git a/models/items/arccw/rifle_ammo.vvd b/models/items/arccw/rifle_ammo.vvd new file mode 100644 index 00000000..fb2d2553 Binary files /dev/null and b/models/items/arccw/rifle_ammo.vvd differ diff --git a/models/items/arccw/riflegrenade_ammo.dx80.vtx b/models/items/arccw/riflegrenade_ammo.dx80.vtx new file mode 100644 index 00000000..53fc7c77 Binary files /dev/null and b/models/items/arccw/riflegrenade_ammo.dx80.vtx differ diff --git a/models/items/arccw/riflegrenade_ammo.dx90.vtx b/models/items/arccw/riflegrenade_ammo.dx90.vtx new file mode 100644 index 00000000..a9658a26 Binary files /dev/null and b/models/items/arccw/riflegrenade_ammo.dx90.vtx differ diff --git a/models/items/arccw/riflegrenade_ammo.mdl b/models/items/arccw/riflegrenade_ammo.mdl new file mode 100644 index 00000000..1b8eea59 Binary files /dev/null and b/models/items/arccw/riflegrenade_ammo.mdl differ diff --git a/models/items/arccw/riflegrenade_ammo.phy b/models/items/arccw/riflegrenade_ammo.phy new file mode 100644 index 00000000..46f8c65f Binary files /dev/null and b/models/items/arccw/riflegrenade_ammo.phy differ diff --git a/models/items/arccw/riflegrenade_ammo.sw.vtx b/models/items/arccw/riflegrenade_ammo.sw.vtx new file mode 100644 index 00000000..f9b5a35e Binary files /dev/null and b/models/items/arccw/riflegrenade_ammo.sw.vtx differ diff --git a/models/items/arccw/riflegrenade_ammo.vvd b/models/items/arccw/riflegrenade_ammo.vvd new file mode 100644 index 00000000..7d04e656 Binary files /dev/null and b/models/items/arccw/riflegrenade_ammo.vvd differ diff --git a/models/items/arccw/shotgun_ammo.dx80.vtx b/models/items/arccw/shotgun_ammo.dx80.vtx new file mode 100644 index 00000000..bbba993a Binary files /dev/null and b/models/items/arccw/shotgun_ammo.dx80.vtx differ diff --git a/models/items/arccw/shotgun_ammo.dx90.vtx b/models/items/arccw/shotgun_ammo.dx90.vtx new file mode 100644 index 00000000..db4561ea Binary files /dev/null and b/models/items/arccw/shotgun_ammo.dx90.vtx differ diff --git a/models/items/arccw/shotgun_ammo.mdl b/models/items/arccw/shotgun_ammo.mdl new file mode 100644 index 00000000..87a43691 Binary files /dev/null and b/models/items/arccw/shotgun_ammo.mdl differ diff --git a/models/items/arccw/shotgun_ammo.phy b/models/items/arccw/shotgun_ammo.phy new file mode 100644 index 00000000..7853f819 Binary files /dev/null and b/models/items/arccw/shotgun_ammo.phy differ diff --git a/models/items/arccw/shotgun_ammo.sw.vtx b/models/items/arccw/shotgun_ammo.sw.vtx new file mode 100644 index 00000000..6550dd75 Binary files /dev/null and b/models/items/arccw/shotgun_ammo.sw.vtx differ diff --git a/models/items/arccw/shotgun_ammo.vvd b/models/items/arccw/shotgun_ammo.vvd new file mode 100644 index 00000000..0f64aa90 Binary files /dev/null and b/models/items/arccw/shotgun_ammo.vvd differ diff --git a/models/items/arccw/shotgun_ammo_closed.dx80.vtx b/models/items/arccw/shotgun_ammo_closed.dx80.vtx new file mode 100644 index 00000000..17277a82 Binary files /dev/null and b/models/items/arccw/shotgun_ammo_closed.dx80.vtx differ diff --git a/models/items/arccw/shotgun_ammo_closed.dx90.vtx b/models/items/arccw/shotgun_ammo_closed.dx90.vtx new file mode 100644 index 00000000..5eaafd0d Binary files /dev/null and b/models/items/arccw/shotgun_ammo_closed.dx90.vtx differ diff --git a/models/items/arccw/shotgun_ammo_closed.mdl b/models/items/arccw/shotgun_ammo_closed.mdl new file mode 100644 index 00000000..745fb8fa Binary files /dev/null and b/models/items/arccw/shotgun_ammo_closed.mdl differ diff --git a/models/items/arccw/shotgun_ammo_closed.phy b/models/items/arccw/shotgun_ammo_closed.phy new file mode 100644 index 00000000..7d28f458 Binary files /dev/null and b/models/items/arccw/shotgun_ammo_closed.phy differ diff --git a/models/items/arccw/shotgun_ammo_closed.sw.vtx b/models/items/arccw/shotgun_ammo_closed.sw.vtx new file mode 100644 index 00000000..63032d6d Binary files /dev/null and b/models/items/arccw/shotgun_ammo_closed.sw.vtx differ diff --git a/models/items/arccw/shotgun_ammo_closed.vvd b/models/items/arccw/shotgun_ammo_closed.vvd new file mode 100644 index 00000000..0bbf51d5 Binary files /dev/null and b/models/items/arccw/shotgun_ammo_closed.vvd differ diff --git a/models/items/arccw/smg_ammo.dx80.vtx b/models/items/arccw/smg_ammo.dx80.vtx new file mode 100644 index 00000000..ed9b11cf Binary files /dev/null and b/models/items/arccw/smg_ammo.dx80.vtx differ diff --git a/models/items/arccw/smg_ammo.dx90.vtx b/models/items/arccw/smg_ammo.dx90.vtx new file mode 100644 index 00000000..2362a6bd Binary files /dev/null and b/models/items/arccw/smg_ammo.dx90.vtx differ diff --git a/models/items/arccw/smg_ammo.mdl b/models/items/arccw/smg_ammo.mdl new file mode 100644 index 00000000..ede8e732 Binary files /dev/null and b/models/items/arccw/smg_ammo.mdl differ diff --git a/models/items/arccw/smg_ammo.phy b/models/items/arccw/smg_ammo.phy new file mode 100644 index 00000000..2f4b8542 Binary files /dev/null and b/models/items/arccw/smg_ammo.phy differ diff --git a/models/items/arccw/smg_ammo.sw.vtx b/models/items/arccw/smg_ammo.sw.vtx new file mode 100644 index 00000000..2637321e Binary files /dev/null and b/models/items/arccw/smg_ammo.sw.vtx differ diff --git a/models/items/arccw/smg_ammo.vvd b/models/items/arccw/smg_ammo.vvd new file mode 100644 index 00000000..d450689c Binary files /dev/null and b/models/items/arccw/smg_ammo.vvd differ diff --git a/models/items/arccw/sniper_ammo.dx80.vtx b/models/items/arccw/sniper_ammo.dx80.vtx new file mode 100644 index 00000000..f69ec073 Binary files /dev/null and b/models/items/arccw/sniper_ammo.dx80.vtx differ diff --git a/models/items/arccw/sniper_ammo.dx90.vtx b/models/items/arccw/sniper_ammo.dx90.vtx new file mode 100644 index 00000000..0f8c9a71 Binary files /dev/null and b/models/items/arccw/sniper_ammo.dx90.vtx differ diff --git a/models/items/arccw/sniper_ammo.mdl b/models/items/arccw/sniper_ammo.mdl new file mode 100644 index 00000000..53c4ef28 Binary files /dev/null and b/models/items/arccw/sniper_ammo.mdl differ diff --git a/models/items/arccw/sniper_ammo.phy b/models/items/arccw/sniper_ammo.phy new file mode 100644 index 00000000..84625359 Binary files /dev/null and b/models/items/arccw/sniper_ammo.phy differ diff --git a/models/items/arccw/sniper_ammo.sw.vtx b/models/items/arccw/sniper_ammo.sw.vtx new file mode 100644 index 00000000..7e98eeca Binary files /dev/null and b/models/items/arccw/sniper_ammo.sw.vtx differ diff --git a/models/items/arccw/sniper_ammo.vvd b/models/items/arccw/sniper_ammo.vvd new file mode 100644 index 00000000..7a8a0e87 Binary files /dev/null and b/models/items/arccw/sniper_ammo.vvd differ diff --git a/models/items/sniper_round_box.dx80.vtx b/models/items/sniper_round_box.dx80.vtx new file mode 100644 index 00000000..1cdf3097 Binary files /dev/null and b/models/items/sniper_round_box.dx80.vtx differ diff --git a/models/items/sniper_round_box.dx90.vtx b/models/items/sniper_round_box.dx90.vtx new file mode 100644 index 00000000..772d2069 Binary files /dev/null and b/models/items/sniper_round_box.dx90.vtx differ diff --git a/models/items/sniper_round_box.mdl b/models/items/sniper_round_box.mdl new file mode 100644 index 00000000..ebe59c4e Binary files /dev/null and b/models/items/sniper_round_box.mdl differ diff --git a/models/items/sniper_round_box.phy b/models/items/sniper_round_box.phy new file mode 100644 index 00000000..a0bf5bbb Binary files /dev/null and b/models/items/sniper_round_box.phy differ diff --git a/models/items/sniper_round_box.vvd b/models/items/sniper_round_box.vvd new file mode 100644 index 00000000..b10fbc56 Binary files /dev/null and b/models/items/sniper_round_box.vvd differ diff --git a/models/weapons/arccw/atts/stock_fab.dx80.vtx b/models/weapons/arccw/atts/stock_fab.dx80.vtx new file mode 100644 index 00000000..2241c139 Binary files /dev/null and b/models/weapons/arccw/atts/stock_fab.dx80.vtx differ diff --git a/models/weapons/arccw/atts/stock_fab.dx90.vtx b/models/weapons/arccw/atts/stock_fab.dx90.vtx new file mode 100644 index 00000000..8daa6d3a Binary files /dev/null and b/models/weapons/arccw/atts/stock_fab.dx90.vtx differ diff --git a/models/weapons/arccw/atts/stock_fab.mdl b/models/weapons/arccw/atts/stock_fab.mdl new file mode 100644 index 00000000..49cdb6bc Binary files /dev/null and b/models/weapons/arccw/atts/stock_fab.mdl differ diff --git a/models/weapons/arccw/atts/stock_fab.phy b/models/weapons/arccw/atts/stock_fab.phy new file mode 100644 index 00000000..551ba1e7 Binary files /dev/null and b/models/weapons/arccw/atts/stock_fab.phy differ diff --git a/models/weapons/arccw/atts/stock_fab.sw.vtx b/models/weapons/arccw/atts/stock_fab.sw.vtx new file mode 100644 index 00000000..1f4beb41 Binary files /dev/null and b/models/weapons/arccw/atts/stock_fab.sw.vtx differ diff --git a/models/weapons/arccw/atts/stock_fab.vvd b/models/weapons/arccw/atts/stock_fab.vvd new file mode 100644 index 00000000..874b3e9a Binary files /dev/null and b/models/weapons/arccw/atts/stock_fab.vvd differ diff --git a/particles/muzzleflashes_test.pcf b/particles/muzzleflashes_test.pcf new file mode 100644 index 00000000..0e2a72d8 Binary files /dev/null and b/particles/muzzleflashes_test.pcf differ diff --git a/particles/muzzleflashes_test_b.pcf b/particles/muzzleflashes_test_b.pcf new file mode 100644 index 00000000..1ab4e17d Binary files /dev/null and b/particles/muzzleflashes_test_b.pcf differ diff --git a/resource/fonts/bahnschrift.ttf b/resource/fonts/bahnschrift.ttf new file mode 100644 index 00000000..bf6003e8 Binary files /dev/null and b/resource/fonts/bahnschrift.ttf differ diff --git a/sound/weapons/arccw/dragatt.wav b/sound/weapons/arccw/dragatt.wav new file mode 100644 index 00000000..f66a31af Binary files /dev/null and b/sound/weapons/arccw/dragatt.wav differ diff --git a/sound/weapons/arccw/dryfire.wav b/sound/weapons/arccw/dryfire.wav new file mode 100644 index 00000000..faa9c854 Binary files /dev/null and b/sound/weapons/arccw/dryfire.wav differ diff --git a/sound/weapons/arccw/firemode.wav b/sound/weapons/arccw/firemode.wav new file mode 100644 index 00000000..a9d71eb9 Binary files /dev/null and b/sound/weapons/arccw/firemode.wav differ diff --git a/sound/weapons/arccw/install.wav b/sound/weapons/arccw/install.wav new file mode 100644 index 00000000..803f2311 Binary files /dev/null and b/sound/weapons/arccw/install.wav differ diff --git a/sound/weapons/arccw/ubgl_exit.wav b/sound/weapons/arccw/ubgl_exit.wav new file mode 100644 index 00000000..5753946f Binary files /dev/null and b/sound/weapons/arccw/ubgl_exit.wav differ diff --git a/sound/weapons/arccw/ubgl_select.wav b/sound/weapons/arccw/ubgl_select.wav new file mode 100644 index 00000000..3f045e4d Binary files /dev/null and b/sound/weapons/arccw/ubgl_select.wav differ diff --git a/sound/weapons/arccw/uninstall.wav b/sound/weapons/arccw/uninstall.wav new file mode 100644 index 00000000..f3cf7629 Binary files /dev/null and b/sound/weapons/arccw/uninstall.wav differ diff --git a/sound/weapons/arccw/useatt.wav b/sound/weapons/arccw/useatt.wav new file mode 100644 index 00000000..92017e56 Binary files /dev/null and b/sound/weapons/arccw/useatt.wav differ