SWEPS and what belongs CL, S, Sh - What is effective?

I’m pretty experienced in java, and have had a bit of a dabble in Lua. I’ve made a few sweps with it before, but one thing that’s really confusing me as a newbie is how things are communicated between client, server, and shared variables / hooks / functions.
Every “example” weapon I’ve seen so far has all data shoved into a single file, making it a complete clusterfuck of code, rather than the old cl_init, shared etc. files
If you’ve been in WAYWO you’ll have seen what i’ve been doing :

https://dl.dropboxusercontent.com/u/888382/squadcannon.webm

As a newbie though, what sort of things belong on the client, server, and shared areas?
I can understand that anything to do with rendering huds and sounds probably belong on the client, any mathwork on the server… but i’m clueless after that.

I’m asking this because some of my weapons work perfectly well in singleplayer, but if I test them on a multiplayer server many variables, functions, sounds etc. get duplicated and are played twice or more, including some of my entities completely shitting themselves and refusing to work.

I’ll admit that my current files are mishmashes of code from other people’s work just to see how they work and their methods of going about doing certain things so it may be that which is screwing up everything, but I digress.
I’m more than happy to put some of the code up here if it helps!

One thing is that weapons are predicted. I’m not an expert at SWEPs but in the shared realm should do the bullet stuff. You should also know about

Global.IsFirstTimePredicted

Post some of your code.

If you understand java/javascript, you should definitely be fine with syntax and whatnot. What is important, incredibly so is the wiki. (Most of the time) They explain everything and when certain functions are called, their arguments and so on.

I’m not one for keeping code secret, considering again this has been a mishmash of 4 different weapons, including two previous ones I’d attempted. It’s got some really nasty, nasty workarounds, but I’m not sure what is good practices or particularly bad ones.

This also has the SWEP Construction Kit base code in, which is most of the junk at the bottom of the file.



-- Variables that are used on both client and server

AddCSLuaFile()

SWEP.ViewModelBoneMods = {
	["Base"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) }
}

SWEP.IronSightsPos = Vector(-5.85, -12, 1.259)
SWEP.IronSightsAng = Vector(0, 0, 0)

SWEP.VElements = {
	["A11++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "Base", rel = "", pos = Vector(1.399, -1.5, 18), angle = Angle(180, 90, 90), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["Handle"] = { type = "Model", model = "models/props_c17/playground_teetertoter_stan.mdl", bone = "Base", rel = "", pos = Vector(0, -0.601, 2.596), angle = Angle(0, 0, -125.066), size = Vector(0.14, 0.2, 0.14), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["A11+++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "Base", rel = "", pos = Vector(-1.4, -1.5, 18), angle = Angle(180, 90, -90), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["X3+"] = { type = "Model", model = "models/props_c17/TrapPropeller_Lever.mdl", bone = "Base", rel = "", pos = Vector(1.25, -1.25, 10), angle = Angle(0, 0, -90), size = Vector(0.75, 0.75, 0.75), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["Grill"] = { type = "Model", model = "models/props_interiors/Radiator01a.mdl", bone = "Base", rel = "", pos = Vector(0, -1.351, 0.518), angle = Angle(0, 90, 90), size = Vector(0.1, 0.15, 0.05), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["A11+++++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "Base", rel = "", pos = Vector(-1.201, -1.3, -3.636), angle = Angle(180, 90, -90), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_crowbar/crowbar_cyl", skin = 0, bodygroup = {} },
	["Grill+"] = { type = "Model", model = "models/props_lab/eyescanner.mdl", bone = "Base", rel = "", pos = Vector(0, -2.201, 5.5), angle = Angle(-5, 90, 180), size = Vector(0.17, 0.17, 0.17), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["det11"] = { type = "Model", model = "models/props_lab/tpplugholder_single.mdl", bone = "Base", rel = "", pos = Vector(2.9, 1.799, 15), angle = Angle(-90, 90, 0), size = Vector(0.219, 0.219, 0.219), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["A11++++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "Base", rel = "", pos = Vector(1.2, -1.3, -3.636), angle = Angle(180, 90, 90), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_crowbar/crowbar_cyl", skin = 0, bodygroup = {} },
	["BAR1"] = { type = "Model", model = "models/props_wasteland/cargo_container01.mdl", bone = "Base", rel = "", pos = Vector(1.25, 1.25, 19), angle = Angle(0, 90, 90), size = Vector(0.018, 0.018, 0.018), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["det10"] = { type = "Model", model = "models/props_c17/playground_teetertoter_stan.mdl", bone = "Base", rel = "", pos = Vector(2, 0, 13.5), angle = Angle(180, -90, 10), size = Vector(0.1, 0.15, 0.1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["X3"] = { type = "Model", model = "models/props_c17/TrapPropeller_Lever.mdl", bone = "Base", rel = "", pos = Vector(-1.25, -1.25, 10), angle = Angle(0, 0, -90), size = Vector(0.75, 0.75, 0.75), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["BAR1+++"] = { type = "Model", model = "models/props_wasteland/cargo_container01.mdl", bone = "Base", rel = "", pos = Vector(-1.25, -1.25, 19), angle = Angle(0, 90, 90), size = Vector(0.018, 0.018, 0.018), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["DET"] = { type = "Model", model = "models/props_lab/tpplugholder.mdl", bone = "Base", rel = "", pos = Vector(1.5, -1.558, -1.558), angle = Angle(0, 0, 90), size = Vector(0.1, 0.1, 0.1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["A11+"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "Base", rel = "", pos = Vector(1.399, 1.2, 18), angle = Angle(0, 90, 90), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["D"] = { type = "Model", model = "models/props_vehicles/apc_tire001.mdl", bone = "Base", rel = "", pos = Vector(1.899, -0.519, 2), angle = Angle(0, 0, 0), size = Vector(0.05, 0.029, 0.029), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["BAR1++"] = { type = "Model", model = "models/props_wasteland/cargo_container01.mdl", bone = "Base", rel = "", pos = Vector(1.25, -1.25, 19), angle = Angle(0, 90, 90), size = Vector(0.018, 0.018, 0.018), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["HAN"] = { type = "Model", model = "models/props_junk/metalgascan.mdl", bone = "Base", rel = "", pos = Vector(0, 1, -7.792), angle = Angle(0, 180, 180), size = Vector(0.3, 0.3, 0.3), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["C"] = { type = "Model", model = "models/props_junk/TrashBin01a.mdl", bone = "Base", rel = "", pos = Vector(0, -0.101, 0), angle = Angle(0, 90, 0), size = Vector(0.159, 0.159, 0.3), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["X5"] = { type = "Model", model = "models/props_trainstation/mount_connection001a.mdl", bone = "Base", rel = "", pos = Vector(0, -0.5, 7.9), angle = Angle(-90, -90, 0), size = Vector(0.23, 0.15, 0.107), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["det9"] = { type = "Model", model = "models/props_wasteland/panel_leverHandle001a.mdl", bone = "Base", rel = "", pos = Vector(2, 0, 3.635), angle = Angle(0, 0, 0), size = Vector(0.3, 0.3, 0.3), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} }
}

SWEP.WElements = {
	["A11++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30, 0.5, -9.5), angle = Angle(90, -90, 0), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["Handle"] = { type = "Model", model = "models/props_c17/playground_teetertoter_stan.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(17.142, 2, -6), angle = Angle(180, 90, -50), size = Vector(0.15, 0.237, 0.237), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["WorldDet+++"] = { type = "Model", model = "models/props_lab/tpplug.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(1, 0, -3.636), angle = Angle(0, 176.494, -85), size = Vector(0.6, 0.4, 0.4), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["WorldDet+"] = { type = "Model", model = "models/props_junk/PushCart01a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(4.675, 1.557, 0.518), angle = Angle(0, 90, -104.027), size = Vector(0.07, 0.15, 0.1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["X3+"] = { type = "Model", model = "models/props_c17/TrapPropeller_Lever.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(24, 3.4, -8.5), angle = Angle(0, 90, 5), size = Vector(0.75, 0.75, 0.75), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["WorldDet"] = { type = "Model", model = "models/props_junk/garbage_coffeemug001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(-3, 0.5, -0.5), angle = Angle(45, -90, -100), size = Vector(1.299, 1.299, 1.299), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["A11+++++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(11, 3, -6.5), angle = Angle(90, 90, 0), size = Vector(0.2, 0.2, 0.2), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_crowbar/crowbar_cyl", skin = 0, bodygroup = {} },
	["Grill+"] = { type = "Model", model = "models/props_lab/eyescanner.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(19, 2, -8.4), angle = Angle(-85, -180, 0), size = Vector(0.17, 0.17, 0.17), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["det11"] = { type = "Model", model = "models/props_lab/tpplugholder_single.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(26.5, -0.7, -9), angle = Angle(5, 180, 0), size = Vector(0.15, 0.2, 0.2), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["A11++++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(11, 1, -6.5), angle = Angle(90, 90, 180), size = Vector(0.2, 0.2, 0.2), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_crowbar/crowbar_cyl", skin = 0, bodygroup = {} },
	["BAR1++++"] = { type = "Model", model = "models/props_wasteland/cargo_container01.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30.2, 0.6, -6.2), angle = Angle(0, 90, 5), size = Vector(0.018, 0.018, 0.018), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["BAR1"] = { type = "Model", model = "models/props_wasteland/cargo_container01.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30, 3.4, -9), angle = Angle(0, 90, 5), size = Vector(0.018, 0.018, 0.018), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["DET+"] = { type = "Model", model = "models/props_lab/tpplugholder.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(12, 0, -6.5), angle = Angle(0, 90, -5), size = Vector(0.15, 0.15, 0.15), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["det10"] = { type = "Model", model = "models/props_c17/playground_teetertoter_stan.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(26, -0.5, -7), angle = Angle(87.9, 10, 0), size = Vector(0.1, 0.172, 0.1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["det10+"] = { type = "Model", model = "models/props_c17/playground_teetertoter_stan.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(26, 4.5, -7), angle = Angle(87.9, -10, 0), size = Vector(0.1, 0.172, 0.1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["X3"] = { type = "Model", model = "models/props_c17/TrapPropeller_Lever.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(24, 0.6, -8.5), angle = Angle(0, 90, 5), size = Vector(0.75, 0.75, 0.75), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["det9+"] = { type = "Model", model = "models/props_wasteland/panel_leverHandle001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(15, -0.7, -5.5), angle = Angle(180, -90, -85), size = Vector(0.5, 0.5, 0.5), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["BAR1+++"] = { type = "Model", model = "models/props_wasteland/cargo_container01.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30.2, 3.4, -6.2), angle = Angle(0, 90, 5), size = Vector(0.018, 0.018, 0.018), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["DET"] = { type = "Model", model = "models/props_lab/tpplugholder.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(12, 4, -6.5), angle = Angle(0, -90, -5), size = Vector(0.15, 0.15, 0.15), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["A11++++++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30, 0.5, -5.401), angle = Angle(-90, 180, 90), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["WorldDet++"] = { type = "Model", model = "models/props_trainstation/trainstation_post001.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(4.675, 1.557, -3.636), angle = Angle(0, 90, -85), size = Vector(0.5, 0.5, 0.237), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["A11+"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30, 3.5, -9.5), angle = Angle(90, -90, 180), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["A11+++"] = { type = "Model", model = "models/props_c17/FurnitureShelf002a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30, 3.5, -5.401), angle = Angle(-90, -90, 0), size = Vector(0.172, 0.172, 0.172), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["BAR1++"] = { type = "Model", model = "models/props_wasteland/cargo_container01.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(30, 0.6, -9), angle = Angle(0, 90, 5), size = Vector(0.018, 0.018, 0.018), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["X5"] = { type = "Model", model = "models/props_trainstation/mount_connection001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(21, 2, -6.7), angle = Angle(175, 0, -180), size = Vector(0.2, 0.15, 0.129), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["HAN"] = { type = "Model", model = "models/props_junk/metalgascan.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(10, 2, -3.636), angle = Angle(0, 90, -85), size = Vector(0.349, 0.349, 0.349), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} },
	["C"] = { type = "Model", model = "models/props_junk/TrashBin01a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(14, 2, -5.5), angle = Angle(-95, 0, 0), size = Vector(0.2, 0.2, 0.3), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/items/boxsrounds", skin = 0, bodygroup = {} },
	["det9"] = { type = "Model", model = "models/props_wasteland/panel_leverHandle001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(15, 4.5, -5.5), angle = Angle(0, -90, -95), size = Vector(0.5, 0.5, 0.5), color = Color(255, 255, 255, 255), surpresslightning = false, material = "models/weapons/v_stunbaton/w_shaft01a", skin = 0, bodygroup = {} }
}

//General Variables\\
SWEP.base = "QUAD"

SWEP.AdminSpawnable = true

SWEP.AutoSwitchTo = false
SWEP.Slot = 2
SWEP.PrintName = "Q.U.A.D Launcher"
SWEP.Author = "BO"
SWEP.Spawnable = true
SWEP.AutoSwitchFrom = false
SWEP.FiresUnderwater = false
SWEP.Weight = 5
SWEP.DrawCrosshair = true
SWEP.Category = "Shite"
SWEP.SlotPos = 1
SWEP.DrawAmmo = true
SWEP.Instructions = "Use this to maul an area with a barrage of small but powerful rockets."
SWEP.Contact = ""
SWEP.Purpose = "Selective Quad Discharger"
SWEP.HoldType = "ar2"
SWEP.ViewModelFOV = 55
SWEP.ViewModelFlip = false
SWEP.ViewModel = "models/weapons/v_irifle.mdl"
SWEP.WorldModel = "models/weapons/w_pistol.mdl"
SWEP.UseHands = false
SWEP.ShowViewModel = true
SWEP.ShowWorldModel = true

SWEP.PrimarySound1 = Sound("weapons/squad_fire1.wav");
SWEP.PrimarySound2 = Sound("weapons/squad_fire2.wav");
SWEP.PrimarySound3 = Sound("weapons/squad_fire3.wav");
SWEP.SecondarySound1 = Sound("weapons/squad_altfire1.wav");
SWEP.SecondarySound2 = Sound("weapons/squad_altfire2.wav");
SWEP.SecondarySound3 = Sound("weapons/squad_altfire3.wav");
SWEP.ReloadSound = Sound("weapons/squad_reload.wav")


SWEP.Primary.TakeAmmo = 1
SWEP.Primary.ClipSize = 5
SWEP.Primary.Ammo = "SMG1_Grenade"
SWEP.Primary.DefaultClip = 10
SWEP.Primary.Spread = 1
SWEP.Primary.Cone = 0.3
SWEP.IronCone = 0.05
SWEP.DefaultCone = 0.3
SWEP.Primary.NumberofShots = 1
SWEP.Primary.Automatic = true
SWEP.Primary.Recoil = 1
SWEP.Primary.Delay = 0.5
SWEP.Primary.Force = 3

SWEP.Secondary.TakeAmmo = 1
SWEP.Secondary.NumberofShots = 1
SWEP.Secondary.Automatic = true
SWEP.Secondary.Recoil = 1
SWEP.Secondary.Delay = 0.8
SWEP.Secondary.Force = 3

resource.AddSingleFile("sound/weapons/squad_fire1.wav");
resource.AddSingleFile("sound/weapons/squad_fire2.wav");
resource.AddSingleFile("sound/weapons/squad_fire3.wav");
resource.AddSingleFile("sound/weapons/squad_altfire1.wav");
resource.AddSingleFile("sound/weapons/squad_altfire2.wav");
resource.AddSingleFile("sound/weapons/squad_altfire3.wav");
resource.AddSingleFile("sound/weapons/squad_reload.wav");

//1 - AR2, 2 - Air Boat Gun, 3 - Tool tracer, 4 - Gauss tracer, 5 - Gunship tracer, 6 - Default, 7 - Tool tracer 2.
SWEP.Tracer = 6

SWEP.IronFOV = 100;
SWEP.Sigma = 0.1
SWEP.Weight				= 12
SWEP.m_WeaponDeploySpeed = 1.1
SWEP.CurrRock = 1;
function SWEP:Deploy()
	self.Weapon:SetNWBool("Reloading", false)

	return true
	
end

function SWEP:Think()
	if (SERVER) then return end
end

function SWEP:ClientUpdateFireAnimVal()
end
function SWEP:Initialize()

	if ( SERVER ) then
		self:SetWeaponHoldType( self.HoldType )
		self.Owner:GetViewModel():SetPlaybackRate(0.1)
	end
end

function SWEP:FireAnimation()
	if (SERVER) then return end

end

function SWEP:FireRocket()
	local aim = self.Owner:GetAimVector()
	local aimang = aim:Angle();
	local side = aimanga
	local up = aimang:Up();
	local pos = self.Owner:GetShootPos()+ side * 3 + up * -5 +aim*16
	local spud = Vector(0,0,0);
	local playerspeed = self.Owner:GetVelocity()

	if SERVER then
	for i=1,4 do
		local rocket = ents.Create("proj_quad");

		if (i >2 ) then
			spud = side;
		end
		if !rocket:IsValid() then return false end
		rocket:SetAngles(aim:Angle()+Angle(0,0,0))
		rocket:SetPos(pos )--+ (i%2)*up*2 + spud*2);
		rocket.PurePos = pos;
		rocket.Angoffset = i*(math.pi/2)+(math.pi/4);
		rocket:SetOwner(self.Owner)
		rocket:Spawn()
		rocket.Spin = true;
		rocket:Activate()
		end
	end
end

function SWEP:FireAccuRocket()

	local rnda = self.Primary.Recoil * 1
	local rndb = self.Primary.Recoil * math.random(-1, 1)
	
	self:ShootEffects()
	local firesound = table.Random( {self.SecondarySound1,self.SecondarySound2,self.SecondarySound3});
	local sndScale = game.GetTimeScale();
	self.Owner:EmitSound(firesound, 75, 100*sndScale, 1, CHAN_WEAPON );
	self.Owner:ViewPunch( Angle( rnda,rndb,rnda ) )

	self:FireAnimation();

	local aim = self.Owner:GetAimVector()
	local aimang = aim:Angle();
	local side = aimang:Right()
	local up = aimang:Up();
	local pos = self.Owner:GetShootPos() + up * -5 +aim*16 + side * 3
	local spud = Vector(0,0,0);
	local playerspeed = self.Owner:GetVelocity()

	if SERVER then
		if (self.CurrRock > 4) then
			self.CurrRock = 1;
		end

		local rocket = ents.Create("proj_quad");

		if (self.CurrRock >2 ) then
			spud = side;
		end
		if !rocket:IsValid() then return false end
		rocket:SetAngles(aim:Angle()+Angle(math.random(-2,2),math.random(-2,2),0))
		rocket:SetPos(pos + (self.CurrRock%2)*up*4-up*3 + spud*4);
		rocket.PurePos = pos;
		rocket.Spin = false;
		rocket.Angoffset = self.CurrRock*(math.pi/2);
		rocket:SetOwner(self.Owner)
		rocket:Spawn()
		rocket:Activate()
		self.CurrRock = self.CurrRock + 1;

	end
end

function SWEP:PrimaryAttack()
	if ( !self:CanPrimaryAttack() ) then return end
	self:FireRocket();
	local rnda = self.Primary.Recoil * 1
	local rndb = self.Primary.Recoil * math.random(-1, 1)
	self:ShootEffects()
	//self.Owner:FireBullets( bullet )
		local fx 		= EffectData()
		fx:SetEntity(self.Weapon)
		fx:SetOrigin(self.Owner:GetShootPos())
		fx:SetNormal(self.Owner:GetAimVector())
		fx:SetAttachment("1")
		local firesound = table.Random( {self.PrimarySound1,self.PrimarySound2,self.PrimarySound3});
		local sndScale = game.GetTimeScale();
	self.Owner:EmitSound(firesound, 75, 100*sndScale, 1, CHAN_WEAPON );
	self.Owner:ViewPunch( Angle( rnda,rndb,rnda ) )

	self:FireAnimation();
		self:TakePrimaryAmmo(self.Primary.TakeAmmo)
		self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
			self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )
	self:CallOnClient("ClientUpdateFireAnimVal") 

end

function SWEP:SecondaryAttack()
	if ( !self:CanPrimaryAttack() ) then return end
	if ( !self:CanSecondaryAttack() ) then return end
	self:FireAccuRocket();
	timer.Simple(self.Secondary.Delay/7, function () self:FireAccuRocket() end )
	timer.Simple(self.Secondary.Delay/7*2,function () self:FireAccuRocket() end )
	timer.Simple(self.Secondary.Delay/7*3,function () self:FireAccuRocket() end )

	self:TakePrimaryAmmo(self.Secondary.TakeAmmo)
	self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )
	self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
	self:CallOnClient("ClientUpdateFireAnimVal") 
	self.NextSecondaryAttack = CurTime() + 0.2
end

SWEP.Secondary.Ammo = "none"

local IRONSIGHT_TIME = 0.4

/*---------------------------------------------------------
   Name: GetViewModelPosition
   Desc: Allows you to re-position the view model
---------------------------------------------------------*/
function SWEP:GetViewModelPosition( pos, ang )

	if ( !self.IronSightsPos ) then return pos, ang end

	local bIron = self.Weapon:GetNetworkedBool( "Ironsights" )
	
	if ( bIron != self.bLastIron ) then
	
		self.bLastIron = bIron 
		self.fIronTime = CurTime()
		
		if ( bIron ) then 
			self.SwayScale 	= 0.3
			self.BobScale 	= 0.1
		else 
			self.SwayScale 	= 1.0
			self.BobScale 	= 1.0
		end
	
	end
	
	local fIronTime = self.fIronTime or 0

	if ( !bIron && fIronTime < CurTime() - IRONSIGHT_TIME ) then 
		return pos, ang 
	end
	
	local Mul = 1.0
	
	if ( fIronTime > CurTime() - IRONSIGHT_TIME ) then
	
		Mul = math.Clamp( (CurTime() - fIronTime) / IRONSIGHT_TIME, 0, 1 )
		
		if (!bIron) then Mul = 1 - Mul end
	
	end

	local Offset	= self.IronSightsPos
	
	if ( self.IronSightsAng ) then
	
		ang = ang * 1
		ang:RotateAroundAxis( ang:Right(), 		self.IronSightsAng.x * Mul )
		ang:RotateAroundAxis( ang:Up(), 		self.IronSightsAng.y * Mul )
		ang:RotateAroundAxis( ang:Forward(), 	self.IronSightsAng.z * Mul )
	
	
	end
	
	local Right 	= ang:Right()
	local Up 		= ang:Up()
	local Forward 	= ang:Forward()
	
	

	pos = pos + Offset.x * Right * Mul
	pos = pos + Offset.y * Forward * Mul
	pos = pos + Offset.z * Up * Mul

	return pos, ang
	
end


/*---------------------------------------------------------
	SetIronsights
---------------------------------------------------------*/
function SWEP:SetIronsights( b )

	self.Weapon:SetNetworkedBool( "Ironsights", b )

end

function SWEP:Holster()
		self:SetIronsights( false )
		self.Zoomed = false
end

SWEP.NextSecondaryAttack = 0
/*---------------------------------------------------------
	SecondaryAttack
---------------------------------------------------------*/

	
/*---------------------------------------------------------
	onRestore
	Loaded a saved game (or changelevel)
---------------------------------------------------------*/
function SWEP:OnRestore()

	self.NextSecondaryAttack = 0
	self:SetIronsights( false )
	
end

function SWEP:SetIronsFunctional()
		self.IronSightsPos = Vector(-5.85, -12, 1.259)
		self.IronSightsAng = Vector(0, 0, 0)
end

function SWEP:SetIronsReload()
	self.IronSightsPos = Vector(0, -2.01, 6.23)
	self.IronSightsAng = Vector(-35.176, 15.477, 0)
end

function SWEP:Reload()
	if (self.Weapon:GetNWBool("Reloading") ) then return end;
	local reserveAmmo = self.Owner:GetAmmoCount(self.Primary.Ammo);
	local magSize = self.Primary.ClipSize;
	local currMag = self.Weapon:Clip1();
	if (reserveAmmo <= 0 ) then return end
	if (currMag == magSize) then return end

	self.Weapon:SetNWBool("Reloading", true);


	


	

	self:SetIronsReload();
	self:CallOnClient("SetIronsReload") 
	self:SetIronsights(true)

	self.Zoomed = false
	if SERVER then
		self.Owner:SetFOV( 0, 0.3 ) -- Setting to 0 resets the FOV
	end
	local sndScale = game.GetTimeScale();
	self:EmitSound( self.ReloadSound, 75, 100*sndScale, 1, CHAN_AUTO);
		
	if not (CLIENT) then
		self.Owner:DrawViewModel(true)
	end
	timer.Simple(1.9, 
	function() 
		if self.Weapon == nil then return end
		self.Weapon:SetNWBool("Reloading", false)
				self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
				self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
				self:SetIronsights(false)
				self.Weapon:SetClip1(math.Clamp(reserveAmmo,0,5));
				self.Owner:SetAmmo(math.Clamp(reserveAmmo-5,0,999999),"SMG1_Grenade");
	end)
	
end

function SWEP:CanPrimaryAttack()

	if ( self.Weapon:Clip1() <= 0 || self.Weapon:GetNWBool("Reloading") ) then
	
		self:EmitSound( "Weapon_Pistol.Empty" )
		self:SetNextPrimaryFire( CurTime() + 1 )
		self:Reload()
		return false
		
	end

	return true

end

function SWEP:HitCallback(attacker, tr, dmginfo)
	
	if not IsFirstTimePredicted() then
	return {damage = false, effects = false}
	end
		
	local DoDefaultEffect = true
	if (tr.HitSky) then return end
	
		if self.Tracer == 0 or self.Tracer == 1 or self.Tracer == 2 or self.Tracer == 3 or self.Tracer == 4 then
			local effectdata = EffectData()
				effectdata:SetOrigin(tr.HitPos)
				effectdata:SetNormal(tr.HitNormal)
				effectdata:SetScale(20)
			util.Effect("AR2Impact", effectdata)
		elseif self.Tracer == 5 or self.Tracer == 7 then
			local effectdata = EffectData()
				effectdata:SetOrigin(tr.HitPos)
				effectdata:SetNormal(tr.HitNormal)
				effectdata:SetScale(20)
			util.Effect("StunstickImpact", effectdata)
		elseif self.Tracer == 6 then

		return 
	end
	
	return {damage = true, effects = DoDefaultEffect}
end

/********************************************************
	SWEP Construction Kit base code
		Created by Clavus
	Available for public use, thread at:
	   facepunch.com/threads/1032378
	   
	   
	DESCRIPTION:
		This script is meant for experienced scripters 
		that KNOW WHAT THEY ARE DOING. Don't come to me 
		with basic Lua questions.
		
		Just copy into your SWEP or SWEP base of choice
		and merge with your own code.
		
		The SWEP.VElements, SWEP.WElements and
		SWEP.ViewModelBoneMods tables are all optional
		and only have to be visible to the client.
********************************************************/

function SWEP:Initialize()

	// other initialize code goes here

	if CLIENT then

		self:SetWeaponHoldType( self.HoldType )	
		// Create a new table for every weapon instance
		self.VElements = table.FullCopy( self.VElements )
		self.WElements = table.FullCopy( self.WElements )
		self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )

		self:CreateModels(self.VElements) // create viewmodels
		self:CreateModels(self.WElements) // create worldmodels
		
		// init view model bone build function
		if IsValid(self.Owner) then
			local vm = self.Owner:GetViewModel()
			if IsValid(vm) then
				self:ResetBonePositions(vm)
				
				--[[// Init viewmodel visibility
				if (self.ShowViewModel == nil or self.ShowViewModel) then
					vm:SetColor(Color(255,255,255,255))
				else
					// we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
					vm:SetColor(Color(255,255,255,1))
					// ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
					// however for some reason the view model resets to render mode 0 every frame so we just apply a debug material to prevent it from drawing
					vm:SetMaterial("Debug/hsv")			
				end]]--
			end
		end
	end
end
function SWEP:Holster()
	
	if CLIENT and IsValid(self.Owner) then
		local vm = self.Owner:GetViewModel()
		if IsValid(vm) then
			self:ResetBonePositions(vm)
		end
	end
	
	return true
end

function SWEP:OnRemove()
	self:Holster()
end

if CLIENT then

	SWEP.vRenderOrder = nil
	function SWEP:ViewModelDrawn()
		
		local vm = self.Owner:GetViewModel()
		
		if ( IsValid( vm ) ) and self.Laser == 1 then
	local tr = self.Owner:GetEyeTrace()
		          render.SetMaterial( Material( "effects/redflare" ) )
                  render.DrawSprite( tr.HitPos,15,15,Color( 255,255,255 ) )
		end
		
		if !IsValid(vm) then return end
		
		if (!self.VElements) then return end
		
		self:UpdateBonePositions(vm)

		if (!self.vRenderOrder) then
			
			// we build a render order because sprites need to be drawn after models
			self.vRenderOrder = {}

			for k, v in pairs( self.VElements ) do
				if (v.type == "Model") then
					table.insert(self.vRenderOrder, 1, k)
				elseif (v.type == "Sprite" or v.type == "Quad") then
					table.insert(self.vRenderOrder, k)
				end
			end
			
		end

		for k, name in ipairs( self.vRenderOrder ) do
		
			local v = self.VElements[name]
			if (!v) then self.vRenderOrder = nil break end
			if (v.hide) then continue end
			
			local model = v.modelEnt
			local sprite = v.spriteMaterial
			
			if (!v.bone) then continue end
			
			local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
			
			if (!pos) then continue end
			
			if (v.type == "Model" and IsValid(model)) then

				model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
				ang:RotateAroundAxis(ang:Up(), v.angle.y)
				ang:RotateAroundAxis(ang:Right(), v.angle.p)
				ang:RotateAroundAxis(ang:Forward(), v.angle.r)

				model:SetAngles(ang)
				//model:SetModelScale(v.size)
				local matrix = Matrix()
				matrix:Scale(v.size)
				model:EnableMatrix( "RenderMultiply", matrix )
				
				if (v.material == "") then
					model:SetMaterial("")
				elseif (model:GetMaterial() != v.material) then
					model:SetMaterial( v.material )
				end
				
				if (v.skin and v.skin != model:GetSkin()) then
					model:SetSkin(v.skin)
				end
				
				if (v.bodygroup) then
					for k, v in pairs( v.bodygroup ) do
						if (model:GetBodygroup(k) != v) then
							model:SetBodygroup(k, v)
						end
					end
				end
				
				if (v.surpresslightning) then
					render.SuppressEngineLighting(true)
				end
				
				render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
				render.SetBlend(v.color.a/255)
				model:DrawModel()
				render.SetBlend(1)
				render.SetColorModulation(1, 1, 1)
				
				if (v.surpresslightning) then
					render.SuppressEngineLighting(false)
				end
				
			elseif (v.type == "Sprite" and sprite) then
				
				local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
				render.SetMaterial(sprite)
				render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
				
			elseif (v.type == "Quad" and v.draw_func) then
				
				local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
				ang:RotateAroundAxis(ang:Up(), v.angle.y)
				ang:RotateAroundAxis(ang:Right(), v.angle.p)
				ang:RotateAroundAxis(ang:Forward(), v.angle.r)
				
				cam.Start3D2D(drawpos, ang, v.size)
					v.draw_func( self )
				cam.End3D2D()

			end
			
		end
		
	end

	SWEP.wRenderOrder = nil
	function SWEP:DrawWorldModel()
		
		if (self.ShowWorldModel == nil or self.ShowWorldModel) then
			self:DrawModel()
		end
		
		if (!self.WElements) then return end
		
		if (!self.wRenderOrder) then

			self.wRenderOrder = {}

			for k, v in pairs( self.WElements ) do
				if (v.type == "Model") then
					table.insert(self.wRenderOrder, 1, k)
				elseif (v.type == "Sprite" or v.type == "Quad") then
					table.insert(self.wRenderOrder, k)
				end
			end

		end
		
		if (IsValid(self.Owner)) then
			bone_ent = self.Owner
		else
			// when the weapon is dropped
			bone_ent = self
		end
		
		for k, name in pairs( self.wRenderOrder ) do
		
			local v = self.WElements[name]
			if (!v) then self.wRenderOrder = nil break end
			if (v.hide) then continue end
			
			local pos, ang
			
			if (v.bone) then
				pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
			else
				pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
			end
			
			if (!pos) then continue end
			
			local model = v.modelEnt
			local sprite = v.spriteMaterial
			
			if (v.type == "Model" and IsValid(model)) then

				model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
				ang:RotateAroundAxis(ang:Up(), v.angle.y)
				ang:RotateAroundAxis(ang:Right(), v.angle.p)
				ang:RotateAroundAxis(ang:Forward(), v.angle.r)

				model:SetAngles(ang)
				//model:SetModelScale(v.size)
				local matrix = Matrix()
				matrix:Scale(v.size)
				model:EnableMatrix( "RenderMultiply", matrix )
				
				if (v.material == "") then
					model:SetMaterial("")
				elseif (model:GetMaterial() != v.material) then
					model:SetMaterial( v.material )
				end
				
				if (v.skin and v.skin != model:GetSkin()) then
					model:SetSkin(v.skin)
				end
				
				if (v.bodygroup) then
					for k, v in pairs( v.bodygroup ) do
						if (model:GetBodygroup(k) != v) then
							model:SetBodygroup(k, v)
						end
					end
				end
				
				if (v.surpresslightning) then
					render.SuppressEngineLighting(true)
				end
				
				render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
				render.SetBlend(v.color.a/255)
				model:DrawModel()
				render.SetBlend(1)
				render.SetColorModulation(1, 1, 1)
				
				if (v.surpresslightning) then
					render.SuppressEngineLighting(false)
				end
				
			elseif (v.type == "Sprite" and sprite) then
				
				local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
				render.SetMaterial(sprite)
				render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
				
			elseif (v.type == "Quad" and v.draw_func) then
				
				local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
				ang:RotateAroundAxis(ang:Up(), v.angle.y)
				ang:RotateAroundAxis(ang:Right(), v.angle.p)
				ang:RotateAroundAxis(ang:Forward(), v.angle.r)
				
				cam.Start3D2D(drawpos, ang, v.size)
					v.draw_func( self )
				cam.End3D2D()

			end
			
		end
		
	end

	function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
		
		local bone, pos, ang
		if (tab.rel and tab.rel != "") then
			
			local v = basetab[tab.rel]
			
			if (!v) then return end
			
			// Technically, if there exists an element with the same name as a bone
			// you can get in an infinite loop. Let's just hope nobody's that stupid.
			pos, ang = self:GetBoneOrientation( basetab, v, ent )
			
			if (!pos) then return end
			
			pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
			ang:RotateAroundAxis(ang:Up(), v.angle.y)
			ang:RotateAroundAxis(ang:Right(), v.angle.p)
			ang:RotateAroundAxis(ang:Forward(), v.angle.r)
				
		else
		
			bone = ent:LookupBone(bone_override or tab.bone)

			if (!bone) then return end
			
			pos, ang = Vector(0,0,0), Angle(0,0,0)
			local m = ent:GetBoneMatrix(bone)
			if (m) then
				pos, ang = m:GetTranslation(), m:GetAngles()
			end
			
			if (IsValid(self.Owner) and self.Owner:IsPlayer() and 
				ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
				ang.r = -ang.r // Fixes mirrored models
			end
		
		end
		
		return pos, ang
	end

	function SWEP:CreateModels( tab )

		if (!tab) then return end

		// Create the clientside models here because Garry says we can't do it in the render hook
		for k, v in pairs( tab ) do
			if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and 
					string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
				
				v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
				if (IsValid(v.modelEnt)) then
					v.modelEnt:SetPos(self:GetPos())
					v.modelEnt:SetAngles(self:GetAngles())
					v.modelEnt:SetParent(self)
					v.modelEnt:SetNoDraw(true)
					v.createdModel = v.model
				else
					v.modelEnt = nil
				end
				
			elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite) 
				and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
				
				local name = v.sprite.."-"
				local params = { ["$basetexture"] = v.sprite }
				// make sure we create a unique name based on the selected options
				local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
				for i, j in pairs( tocheck ) do
					if (v[j]) then
						params["$"..j] = 1
						name = name.."1"
					else
						name = name.."0"
					end
				end

				v.createdSprite = v.sprite
				v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
				
			end
		end
		
	end
	
	local allbones
	local hasGarryFixedBoneScalingYet = false

	function SWEP:UpdateBonePositions(vm)
		
		if self.ViewModelBoneMods then
			
			if (!vm:GetBoneCount()) then return end
			
			// !! WORKAROUND !! //
			// We need to check all model names :/
			local loopthrough = self.ViewModelBoneMods
			if (!hasGarryFixedBoneScalingYet) then
				allbones = {}
				for i=0, vm:GetBoneCount() do
					local bonename = vm:GetBoneName(i)
					if (self.ViewModelBoneMods[bonename]) then 
						allbones[bonename] = self.ViewModelBoneMods[bonename]
					else
						allbones[bonename] = { 
							scale = Vector(1,1,1),
							pos = Vector(0,0,0),
							angle = Angle(0,0,0)
						}
					end
				end
				
				loopthrough = allbones
			end
			// !! ----------- !! //
			
			for k, v in pairs( loopthrough ) do
				local bone = vm:LookupBone(k)
				if (!bone) then continue end
				
				// !! WORKAROUND !! //
				local s = Vector(v.scale.x,v.scale.y,v.scale.z)
				local p = Vector(v.pos.x,v.pos.y,v.pos.z)
				local ms = Vector(1,1,1)
				if (!hasGarryFixedBoneScalingYet) then
					local cur = vm:GetBoneParent(bone)
					while(cur >= 0) do
						local pscale = loopthrough[vm:GetBoneName(cur)].scale
						ms = ms * pscale
						cur = vm:GetBoneParent(cur)
					end
				end
				
				s = s * ms
				// !! ----------- !! //
				
				if vm:GetManipulateBoneScale(bone) != s then
					vm:ManipulateBoneScale( bone, s )
				end
				if vm:GetManipulateBoneAngles(bone) != v.angle then
					vm:ManipulateBoneAngles( bone, v.angle )
				end
				if vm:GetManipulateBonePosition(bone) != p then
					vm:ManipulateBonePosition( bone, p )
				end
			end
		else
			self:ResetBonePositions(vm)
		end
		   
	end
	 
	function SWEP:ResetBonePositions(vm)
		
		if (!vm:GetBoneCount()) then return end
		for i=0, vm:GetBoneCount() do
			vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
			vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
			vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
		end
		
	end

	/**************************
		Global utility code
	**************************/

	// Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
	// Does not copy entities of course, only copies their reference.
	// WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
	function table.FullCopy( tab )

		if (!tab) then return nil end
		
		local res = {}
		for k, v in pairs( tab ) do
			if (type(v) == "table") then
				res[k] = table.FullCopy(v) // recursion ho!
			elseif (type(v) == "Vector") then
				res[k] = Vector(v.x, v.y, v.z)
			elseif (type(v) == "Angle") then
				res[k] = Angle(v.p, v.y, v.r)
			else
				res[k] = v
			end
		end
		
		return res
		
	end
	
end


you’re using timers inside your SecondaryAttack function. this isn’t necessarily bad for single player, however in terms of prediction it’s terrible. i’d suggest to moving to a CurTime-based check inside of a Think hook.