· 7 years ago · Dec 29, 2018, 06:18 PM
1SWEP.PrintName = "Bullet Storm"
2
3SWEP.Author = "SpottheJellyfish34"
4SWEP.Contact = "steam account"
5SWEP.Purpose = "shoot a lot"
6SWEP.Instructions = "LMB to fire"
7
8SWEP.Category = "other"
9
10SWEP.Spawnable= true
11SWEP.AdminSpawnable= true
12SWEP.AdminOnly = false
13
14SWEP.ViewModelFOV = 55
15SWEP.ViewModel = "ar2"
16SWEP.WorldModel = "ar2"
17SWEP.ViewModelFlip = false
18
19SWEP.AutoSwitchTo = true
20SWEP.AutoSwitchFrom = false
21
22SWEP.Slot = 3
23SWEP.SlotPos = 3
24
25SWEP.UseHands = true
26
27SWEP.HoldType = "ar2"
28
29SWEP.FiresUnderwater = true
30
31SWEP.DrawCrosshair = true
32
33SWEP.DrawAmmo = true
34
35SWEP.ReloadSound = "sound/epicreload.wav"
36
37SWEP.Base = "weapon_base"
38
39SWEP.Primary.Sound = Sound("SMG1")
40SWEP.Primary.Damage = 2
41SWEP.Primary.TakeAmmo = 144
42SWEP.Primary.ClipSize = 720
43SWEP.Primary.Ammo = "SMG1"
44SWEP.Primary.DefaultClip = 2160
45SWEP.Primary.Spread = 0.1
46SWEP.Primary.NumberofShots = 144
47SWEP.Primary.Automatic = true
48SWEP.Primary.Recoil = 0.001
49SWEP.Primary.Delay = 0.01
50SWEP.Primary.Force = 120
51SWEP.Primary.Cone = 0.01
52
53SWEP.Secondary.ClipSize = 0
54SWEP.Secondary.DefaultClip = 0
55SWEP.Secondary.Automatic = false
56SWEP.Secondary.Ammo = "none"
57
58SWEP.CSMuzzleFlashes = true
59
60/********************************************************
61 SWEP Construction Kit base code
62 Created by Clavus
63 Available for public use, thread at:
64 facepunch.com/threads/1032378
65
66
67 DESCRIPTION:
68 This script is meant for experienced scripters
69 that KNOW WHAT THEY ARE DOING. Don't come to me
70 with basic Lua questions.
71
72 Just copy into your SWEP or SWEP base of choice
73 and merge with your own code.
74
75 The SWEP.VElements, SWEP.WElements and
76 SWEP.ViewModelBoneMods tables are all optional
77 and only have to be visible to the client.
78********************************************************/
79
80function SWEP:Initialize()
81
82 // other initialize code goes here
83
84 if CLIENT then
85
86 // Create a new table for every weapon instance
87 self.VElements = table.FullCopy( self.VElements )
88 self.WElements = table.FullCopy( self.WElements )
89 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
90
91 self:CreateModels(self.VElements) // create viewmodels
92 self:CreateModels(self.WElements) // create worldmodels
93
94 // init view model bone build function
95 if IsValid(self.Owner) then
96 local vm = self.Owner:GetViewModel()
97 if IsValid(vm) then
98 self:ResetBonePositions(vm)
99
100 // Init viewmodel visibility
101 if (self.ShowViewModel == nil or self.ShowViewModel) then
102 vm:SetColor(Color(255,255,255,255))
103 else
104 // we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
105 vm:SetColor(Color(255,255,255,1))
106 // ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
107 // 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
108 vm:SetMaterial("Debug/hsv")
109 end
110 end
111 end
112
113 end
114
115end
116
117function SWEP:Holster()
118
119 if CLIENT and IsValid(self.Owner) then
120 local vm = self.Owner:GetViewModel()
121 if IsValid(vm) then
122 self:ResetBonePositions(vm)
123 end
124 end
125
126 return true
127end
128
129function SWEP:OnRemove()
130 self:Holster()
131end
132
133if CLIENT then
134
135 SWEP.vRenderOrder = nil
136 function SWEP:ViewModelDrawn()
137
138 local vm = self.Owner:GetViewModel()
139 if !IsValid(vm) then return end
140
141 if (!self.VElements) then return end
142
143 self:UpdateBonePositions(vm)
144
145 if (!self.vRenderOrder) then
146
147 // we build a render order because sprites need to be drawn after models
148 self.vRenderOrder = {}
149
150 for k, v in pairs( self.VElements ) do
151 if (v.type == "Model") then
152 table.insert(self.vRenderOrder, 1, k)
153 elseif (v.type == "Sprite" or v.type == "Quad") then
154 table.insert(self.vRenderOrder, k)
155 end
156 end
157
158 end
159
160 for k, name in ipairs( self.vRenderOrder ) do
161
162 local v = self.VElements[name]
163 if (!v) then self.vRenderOrder = nil break end
164 if (v.hide) then continue end
165
166 local model = v.modelEnt
167 local sprite = v.spriteMaterial
168
169 if (!v.bone) then continue end
170
171 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
172
173 if (!pos) then continue end
174
175 if (v.type == "Model" and IsValid(model)) then
176
177 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
178 ang:RotateAroundAxis(ang:Up(), v.angle.y)
179 ang:RotateAroundAxis(ang:Right(), v.angle.p)
180 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
181
182 model:SetAngles(ang)
183 //model:SetModelScale(v.size)
184 local matrix = Matrix()
185 matrix:Scale(v.size)
186 model:EnableMatrix( "RenderMultiply", matrix )
187
188 if (v.material == "") then
189 model:SetMaterial("")
190 elseif (model:GetMaterial() != v.material) then
191 model:SetMaterial( v.material )
192 end
193
194 if (v.skin and v.skin != model:GetSkin()) then
195 model:SetSkin(v.skin)
196 end
197
198 if (v.bodygroup) then
199 for k, v in pairs( v.bodygroup ) do
200 if (model:GetBodygroup(k) != v) then
201 model:SetBodygroup(k, v)
202 end
203 end
204 end
205
206 if (v.surpresslightning) then
207 render.SuppressEngineLighting(true)
208 end
209
210 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
211 render.SetBlend(v.color.a/255)
212 model:DrawModel()
213 render.SetBlend(1)
214 render.SetColorModulation(1, 1, 1)
215
216 if (v.surpresslightning) then
217 render.SuppressEngineLighting(false)
218 end
219
220 elseif (v.type == "Sprite" and sprite) then
221
222 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
223 render.SetMaterial(sprite)
224 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
225
226 elseif (v.type == "Quad" and v.draw_func) then
227
228 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
229 ang:RotateAroundAxis(ang:Up(), v.angle.y)
230 ang:RotateAroundAxis(ang:Right(), v.angle.p)
231 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
232
233 cam.Start3D2D(drawpos, ang, v.size)
234 v.draw_func( self )
235 cam.End3D2D()
236
237 end
238
239 end
240
241 end
242
243 SWEP.wRenderOrder = nil
244 function SWEP:DrawWorldModel()
245
246 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
247 self:DrawModel()
248 end
249
250 if (!self.WElements) then return end
251
252 if (!self.wRenderOrder) then
253
254 self.wRenderOrder = {}
255
256 for k, v in pairs( self.WElements ) do
257 if (v.type == "Model") then
258 table.insert(self.wRenderOrder, 1, k)
259 elseif (v.type == "Sprite" or v.type == "Quad") then
260 table.insert(self.wRenderOrder, k)
261 end
262 end
263
264 end
265
266 if (IsValid(self.Owner)) then
267 bone_ent = self.Owner
268 else
269 // when the weapon is dropped
270 bone_ent = self
271 end
272
273 for k, name in pairs( self.wRenderOrder ) do
274
275 local v = self.WElements[name]
276 if (!v) then self.wRenderOrder = nil break end
277 if (v.hide) then continue end
278
279 local pos, ang
280
281 if (v.bone) then
282 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
283 else
284 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
285 end
286
287 if (!pos) then continue end
288
289 local model = v.modelEnt
290 local sprite = v.spriteMaterial
291
292 if (v.type == "Model" and IsValid(model)) then
293
294 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
295 ang:RotateAroundAxis(ang:Up(), v.angle.y)
296 ang:RotateAroundAxis(ang:Right(), v.angle.p)
297 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
298
299 model:SetAngles(ang)
300 //model:SetModelScale(v.size)
301 local matrix = Matrix()
302 matrix:Scale(v.size)
303 model:EnableMatrix( "RenderMultiply", matrix )
304
305 if (v.material == "") then
306 model:SetMaterial("")
307 elseif (model:GetMaterial() != v.material) then
308 model:SetMaterial( v.material )
309 end
310
311 if (v.skin and v.skin != model:GetSkin()) then
312 model:SetSkin(v.skin)
313 end
314
315 if (v.bodygroup) then
316 for k, v in pairs( v.bodygroup ) do
317 if (model:GetBodygroup(k) != v) then
318 model:SetBodygroup(k, v)
319 end
320 end
321 end
322
323 if (v.surpresslightning) then
324 render.SuppressEngineLighting(true)
325 end
326
327 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
328 render.SetBlend(v.color.a/255)
329 model:DrawModel()
330 render.SetBlend(1)
331 render.SetColorModulation(1, 1, 1)
332
333 if (v.surpresslightning) then
334 render.SuppressEngineLighting(false)
335 end
336
337 elseif (v.type == "Sprite" and sprite) then
338
339 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
340 render.SetMaterial(sprite)
341 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
342
343 elseif (v.type == "Quad" and v.draw_func) then
344
345 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
346 ang:RotateAroundAxis(ang:Up(), v.angle.y)
347 ang:RotateAroundAxis(ang:Right(), v.angle.p)
348 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
349
350 cam.Start3D2D(drawpos, ang, v.size)
351 v.draw_func( self )
352 cam.End3D2D()
353
354 end
355
356 end
357
358 end
359
360 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
361
362 local bone, pos, ang
363 if (tab.rel and tab.rel != "") then
364
365 local v = basetab[tab.rel]
366
367 if (!v) then return end
368
369 // Technically, if there exists an element with the same name as a bone
370 // you can get in an infinite loop. Let's just hope nobody's that stupid.
371 pos, ang = self:GetBoneOrientation( basetab, v, ent )
372
373 if (!pos) then return end
374
375 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
376 ang:RotateAroundAxis(ang:Up(), v.angle.y)
377 ang:RotateAroundAxis(ang:Right(), v.angle.p)
378 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
379
380 else
381
382 bone = ent:LookupBone(bone_override or tab.bone)
383
384 if (!bone) then return end
385
386 pos, ang = Vector(0,0,0), Angle(0,0,0)
387 local m = ent:GetBoneMatrix(bone)
388 if (m) then
389 pos, ang = m:GetTranslation(), m:GetAngles()
390 end
391
392 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
393 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
394 ang.r = -ang.r // Fixes mirrored models
395 end
396
397 end
398
399 return pos, ang
400 end
401
402 function SWEP:CreateModels( tab )
403
404 if (!tab) then return end
405
406 // Create the clientside models here because Garry says we can't do it in the render hook
407 for k, v in pairs( tab ) do
408 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
409 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
410
411 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
412 if (IsValid(v.modelEnt)) then
413 v.modelEnt:SetPos(self:GetPos())
414 v.modelEnt:SetAngles(self:GetAngles())
415 v.modelEnt:SetParent(self)
416 v.modelEnt:SetNoDraw(true)
417 v.createdModel = v.model
418 else
419 v.modelEnt = nil
420 end
421
422 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
423 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
424
425 local name = v.sprite.."-"
426 local params = { ["$basetexture"] = v.sprite }
427 // make sure we create a unique name based on the selected options
428 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
429 for i, j in pairs( tocheck ) do
430 if (v[j]) then
431 params["$"..j] = 1
432 name = name.."1"
433 else
434 name = name.."0"
435 end
436 end
437
438 v.createdSprite = v.sprite
439 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
440
441 end
442 end
443
444 end
445
446 local allbones
447 local hasGarryFixedBoneScalingYet = false
448
449 function SWEP:UpdateBonePositions(vm)
450
451 if self.ViewModelBoneMods then
452
453 if (!vm:GetBoneCount()) then return end
454
455 // !! WORKAROUND !! //
456 // We need to check all model names :/
457 local loopthrough = self.ViewModelBoneMods
458 if (!hasGarryFixedBoneScalingYet) then
459 allbones = {}
460 for i=0, vm:GetBoneCount() do
461 local bonename = vm:GetBoneName(i)
462 if (self.ViewModelBoneMods[bonename]) then
463 allbones[bonename] = self.ViewModelBoneMods[bonename]
464 else
465 allbones[bonename] = {
466 scale = Vector(1,1,1),
467 pos = Vector(0,0,0),
468 angle = Angle(0,0,0)
469 }
470 end
471 end
472
473 loopthrough = allbones
474 end
475 // !! ----------- !! //
476
477 for k, v in pairs( loopthrough ) do
478 local bone = vm:LookupBone(k)
479 if (!bone) then continue end
480
481 // !! WORKAROUND !! //
482 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
483 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
484 local ms = Vector(1,1,1)
485 if (!hasGarryFixedBoneScalingYet) then
486 local cur = vm:GetBoneParent(bone)
487 while(cur >= 0) do
488 local pscale = loopthrough[vm:GetBoneName(cur)].scale
489 ms = ms * pscale
490 cur = vm:GetBoneParent(cur)
491 end
492 end
493
494 s = s * ms
495 // !! ----------- !! //
496
497 if vm:GetManipulateBoneScale(bone) != s then
498 vm:ManipulateBoneScale( bone, s )
499 end
500 if vm:GetManipulateBoneAngles(bone) != v.angle then
501 vm:ManipulateBoneAngles( bone, v.angle )
502 end
503 if vm:GetManipulateBonePosition(bone) != p then
504 vm:ManipulateBonePosition( bone, p )
505 end
506 end
507 else
508 self:ResetBonePositions(vm)
509 end
510
511 end
512
513 function SWEP:ResetBonePositions(vm)
514
515 if (!vm:GetBoneCount()) then return end
516 for i=0, vm:GetBoneCount() do
517 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
518 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
519 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
520 end
521
522 end
523
524 /**************************
525 Global utility code
526 **************************/
527
528 // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
529 // Does not copy entities of course, only copies their reference.
530 // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
531 function table.FullCopy( tab )
532
533 if (!tab) then return nil end
534
535 local res = {}
536 for k, v in pairs( tab ) do
537 if (type(v) == "table") then
538 res[k] = table.FullCopy(v) // recursion ho!
539 elseif (type(v) == "Vector") then
540 res[k] = Vector(v.x, v.y, v.z)
541 elseif (type(v) == "Angle") then
542 res[k] = Angle(v.p, v.y, v.r)
543 else
544 res[k] = v
545 end
546 end
547
548 return res
549
550 end
551
552end
553
554function SWEP:Initialize()
555util.PrecacheSound(self.Primary.Sound)
556util.PrecacheSound(self.ReloadSound)
557 self:SetWeaponHoldType( self.HoldType )
558end
559
560function SWEP:PrimaryAttack()
561
562if ( !self:CanPrimaryAttack() ) then return end
563
564local bullet = {}
565bullet.Num = self.Primary.NumberofShots
566bullet.Src = self.Owner:GetShootPos()
567bullet.Dir = self.Owner:GetAimVector()
568bullet.Spread = Vector( self.Primary.Spread * 0.1 , self.Primary.Spread * 0.1, 0)
569bullet.Tracer = 1
570bullet.Force = self.Primary.Force
571bullet.Damage = self.Primary.Damage
572bullet.AmmoType = self.Primary.Ammo
573
574local rnda = self.Primary.Recoil * -1
575local rndb = self.Primary.Recoil * math.random(-1, 1)
576
577self:ShootEffects()
578
579self.Owner:FireBullets( bullet )
580self:EmitSound(Sound(self.Primary.Sound))
581self.Owner:ViewPunch( Angle( rnda,rndb,rnda ) )
582self:TakePrimaryAmmo(self.Primary.TakeAmmo)
583
584self:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
585self:SetNextSecondaryFire( CurTime() + self.Primary.Delay )
586end
587
588
589local IRONSIGHT_TIME = 0.25
590
591function SWEP:GetViewModelPosition( pos, ang )
592
593 if ( !self.IronSightsPos ) then return pos, ang end
594
595 local bIron = self.Weapon:GetNetworkedBool( "Ironsights" )
596
597 if ( bIron != self.bLastIron ) then
598
599 self.bLastIron = bIron
600 self.fIronTime = CurTime()
601
602 if ( bIron ) then
603 self.SwayScale = 0.3
604 self.BobScale = 0.1
605 else
606 self.SwayScale = 1.0
607 self.BobScale = 1.0
608 end
609
610 end
611
612 local fIronTime = self.fIronTime or 0
613
614 if ( !bIron && fIronTime < CurTime() - IRONSIGHT_TIME ) then
615 return pos, ang
616 end
617
618 local Mul = 1.0
619
620 if ( fIronTime > CurTime() - IRONSIGHT_TIME ) then
621
622 Mul = math.Clamp( (CurTime() - fIronTime) / IRONSIGHT_TIME, 0, 1 )
623
624 if (!bIron) then Mul = 1 - Mul end
625
626 end
627
628 local Offset = self.IronSightsPos
629
630 if ( self.IronSightsAng ) then
631
632 ang = ang * 1
633 ang:RotateAroundAxis( ang:Right(), self.IronSightsAng.x * Mul )
634 ang:RotateAroundAxis( ang:Up(), self.IronSightsAng.y * Mul )
635 ang:RotateAroundAxis( ang:Forward(), self.IronSightsAng.z * Mul )
636
637
638 end
639
640 local Right = ang:Right()
641 local Up = ang:Up()
642 local Forward = ang:Forward()
643
644
645
646 pos = pos + Offset.x * Right * Mul
647 pos = pos + Offset.y * Forward * Mul
648 pos = pos + Offset.z * Up * Mul
649
650 return pos, ang
651
652end
653
654function SWEP:SecondaryAttack()
655
656
657 if ( !self.IronSightsPos ) then return end
658 if ( self.NextSecondaryAttack > CurTime() ) then return end
659
660 bIronsights = !self.Weapon:GetNetworkedBool( "Ironsights", false )
661
662 self:SetIronsights( bIronsights )
663
664 self.NextSecondaryAttack = CurTime() + 0.3
665
666
667end
668
669function SWEP:SetIronsights( b )
670
671 self.Weapon:SetNetworkedBool( "Ironsights", b )
672
673end
674
675SWEP.NextSecondaryAttack = 0
676
677function SWEP:Reload()
678self:EmitSound(Sound(self.ReloadSound))
679 self.Weapon:DefaultReload( ACT_VM_RELOAD );
680
681end
682
683function SWEP:DrawHUD()
684
685 // No crosshair when ironsights is on
686 if ( self.Weapon:GetNetworkedBool( "Ironsights" ) ) then return end
687
688 local x = ScrW() / 2.0
689 local y = ScrH() / 2.0
690 local scale = 20 * self.Primary.Cone
691
692 // Scale the size of the crosshair according to how long ago we fired our weapon
693 local LastShootTime = self.Weapon:GetNetworkedFloat( "LastShootTime", 0 )
694 scale = scale * (2 - math.Clamp( (CurTime() - LastShootTime) * 5, 0.0, 1.0 ))
695
696 surface.SetDrawColor( 255, 191, 0, 255 )
697
698 // Draw an awesome crosshair
699 local gap = 20 * scale
700 local length = gap + 50 * scale
701 surface.DrawLine( x - length, y, x - gap, y )
702 surface.DrawLine( x + length, y, x + gap, y )
703 surface.DrawLine( x, y - length, x, y - gap )
704 surface.DrawLine( x, y + length, x, y + gap )
705
706end
707
708function SWEP:OnRestore()
709
710 self.NextSecondaryAttack = 0
711 self:SetIronsights( false )
712
713end
714
715function SWEP:Reload()
716self:EmitSound(Sound(self.ReloadSound))
717 self.Weapon:DefaultReload( ACT_VM_RELOAD );
718end