· 7 years ago · Oct 10, 2018, 10:50 PM
1function SWEP:Melee()
2end
3
4function SWEP:Precache()
5 util.PrecacheSound( "weapons/slam/throw.wav" )
6 util.PrecacheSound( "weapons/drink/Open.wav" )
7 util.PrecacheSound( "weapons/drink/Drink.wav" )
8 util.PrecacheModel( "models/weapons/ErrolLiamP/c_drink_blue.mdl" )
9 util.PrecacheModel( "models/props_junk/PopCan01a.mdl" )
10 end
11
12if (SERVER) then
13 AddCSLuaFile("shared.lua")
14 SWEP.HoldType = "slam"
15end
16
17if (CLIENT) then
18 SWEP.Category = "Drinks"
19 SWEP.PrintName = "Blue Drink(+15 HP)"
20 SWEP.Author = "Airul"
21 SWEP.Slot = 1
22 SWEP.ViewModelFOV = 50
23 SWEP.DrawSecondaryAmmo = false
24 SWEP.DrawAmmo = false
25 SWEP.WepSelectIcon = surface.GetTextureID("vgui/hud/drink_blue")
26end
27
28SWEP.ViewModelFlip = false
29
30SWEP.Spawnable = true
31SWEP.AdminSpawnable = true
32
33SWEP.ViewModel = "models/weapons/ErrolLiamP/c_drink_blue.mdl"
34SWEP.WorldModel = "models/weapons/w_pistol.mdl"
35SWEP.WElements = {
36 ["world_can"] = { type = "Model", model = "models/props_junk/popcan01a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(3.861, 2.717, -0.897), angle = Angle(-17.878, -111.371, 171.75), size = Vector(0.801, 0.801, 0.801), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
37}
38
39SWEP.UseHands = true
40SWEP.ShowWorldModel = false
41SWEP.HoldType = "slam"
42
43SWEP.Primary.Delay = 3.5
44SWEP.Primary.Automatic = true
45SWEP.Primary.Ammo = "none"
46SWEP.Secondary.Ammo = "none"
47
48function SWEP:EjectBrass()
49end
50
51SWEP.data = {}
52SWEP.mode = "auto"
53
54SWEP.data.semi = {}
55
56SWEP.data.auto = {}
57
58
59/*---------------------------------------------------------
60SecondaryAttack
61---------------------------------------------------------*/
62function SWEP:SecondaryAttack()
63end
64
65function SWEP:ShouldDropOnDie()
66 return true
67end
68
69/*---------------------------------------------------------
70PrimaryAttack
71---------------------------------------------------------*/
72function SWEP:PrimaryAttack()
73self:SetWeaponHoldType("melee")
74timer.Create( "Drink", 0.7, 1, function()
75if !IsValid(self.Owner) then return end
76self.Owner:ViewPunch( Angle( -15, 0, 0 ) )
77end)
78timer.Create( "Throw", 1.8, 1, function()
79if !IsValid(self.Owner) then return end
80self.Owner:ViewPunch( Angle( 0, 50, 0 ) )
81end)
82timer.Create( "Throw2", 1.5, 1, function()
83self.Owner:ViewPunch( Angle( 0, -50, 0 ) )
84end)
85timer.Create( "Throw Can", 2, 1, function()
86self:ThrowCan( "models/props_junk/popcan01a.mdl" )
87self.Owner:EmitSound("weapons/slam/throw.wav", 500, 100)
88if SERVER then
89self.Owner:StripWeapon( "drink_blue" ) end
90end)
91local dmginfo = DamageInfo()
92self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK )
93self.Weapon:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
94self.Weapon:SetNWBool("Drinking",true)
95self.DoDrinkSound = CurTime() + 0.4
96self.Heal1 = CurTime() + 0.6
97self.Heal2 = CurTime() + 1.1
98self.Heal3 = CurTime() + 1.7
99self.StopDrinking = CurTime() + self.Primary.Delay
100end
101
102function SWEP:ThrowCan( model_file )
103
104 if ( CLIENT ) then return end
105
106 local ent = ents.Create( "prop_physics" )
107 if ( !IsValid( ent ) ) then return end
108 ent:SetModel( model_file )
109 ent:SetPos( self.Owner:EyePos() + ( self.Owner:GetAimVector() * 10 ) )
110 ent:SetAngles( self.Owner:EyeAngles() )
111 ent:SetCollisionGroup( COLLISION_GROUP_WEAPON )
112 ent:Spawn()
113
114 local phys = ent:GetPhysicsObject()
115 if ( !IsValid( phys ) ) then ent:Remove() return end
116
117 local velocity = self.Owner:GetAimVector()
118 velocity = velocity * 300
119 velocity = velocity + ( VectorRand() * 10 )
120 phys:ApplyForceCenter( velocity )
121
122 cleanup.Add( self.Owner, "props", ent )
123 SafeRemoveEntityDelayed( ent, 10 );
124
125 undo.Create( "Can" )
126 undo.AddEntity( ent )
127 undo.SetPlayer( self.Owner )
128 undo.Finish()
129
130end
131
132/*---------------------------------------------------------
133Deploy
134---------------------------------------------------------*/
135function SWEP:Deploy()
136timer.Create( "Open", 1.8, 1, function()
137if !IsValid(self.Owner) then return end
138self.Owner:EmitSound("weapons/drink/Open.wav", 500, 100)
139self.Owner:ViewPunch( Angle( -4, 0, 0 ) )
140end)
141 self.Weapon:SetNextPrimaryFire(CurTime() + 3.5)
142 self.Weapon:SendWeaponAnim( ACT_VM_DRAW )
143 self.Weapon:SetNWBool("Drinking",false)
144 self.DoDrinkSound = nil
145 self.Heal1 = nil
146 self.Heal2 = nil
147 self.Heal3 = nil
148 return true
149end
150
151function SWEP:Holster()
152timer.Destroy("Drink")
153timer.Destroy("Open")
154timer.Destroy("Throw")
155timer.Destroy("Throw2")
156timer.Destroy("Throw Can")
157if self.Weapon:GetNWBool("Drinking") then
158return false
159else
160return true
161end
162end
163
164/*---------------------------------------------------------
165Reload
166---------------------------------------------------------*/
167function SWEP:Reload()
168end
169
170/*---------------------------------------------------------
171Think
172---------------------------------------------------------*/
173function SWEP:Think()
174if self.Idle and CurTime()>=self.Idle then
175self.Idle = nil
176self.Weapon:SendWeaponAnim( ACT_VM_IDLE )
177end
178if self.DoDrinkSound and CurTime()>=self.DoDrinkSound then
179self.DoDrinkSound = nil
180self.Weapon:EmitSound("weapons/drink/Drink.wav")
181end
182if self.Heal1 and CurTime()>=self.Heal1 then
183self.Heal1 = nil
184self.Owner:SetHealth(self.Owner:Health() + 5)
185if self.Owner:Health() >= 250 then self.Owner:SetHealth(250) end
186end
187if self.Heal2 and CurTime()>=self.Heal2 then
188self.Heal2 = nil
189self.Owner:SetHealth(self.Owner:Health() + 5)
190if self.Owner:Health() >= 250 then self.Owner:SetHealth(250) end
191end
192if self.Heal3 and CurTime()>=self.Heal3 then
193self.Heal3 = nil
194self.Owner:SetHealth(self.Owner:Health() + 5)
195if self.Owner:Health() >= 250 then self.Owner:SetHealth(250) end
196end
197if self.StopDrinking and CurTime()>=self.StopDrinking then
198self.StopDrinking = nil
199self.Weapon:SetNWBool("Drinking",false)
200self.Owner:SetJumpPower(200)
201end
202end
203
204/*---------------------------------------------------------
205CanPrimaryAttack
206---------------------------------------------------------*/
207
208function SWEP:Initialize()
209
210
211 self:SetWeaponHoldType("slam")
212
213
214 if CLIENT then
215
216 // Create a new table for every weapon instance
217 self.VElements = table.FullCopy( self.VElements )
218 self.WElements = table.FullCopy( self.WElements )
219 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
220
221 self:CreateModels(self.VElements) // create viewmodels
222 self:CreateModels(self.WElements) // create worldmodels
223
224 // init view model bone build function
225 if IsValid(self.Owner) then
226 local vm = self.Owner:GetViewModel()
227 if IsValid(vm) then
228 self:ResetBonePositions(vm)
229
230 // Init viewmodel visibility
231 if (self.ShowViewModel == nil or self.ShowViewModel) then
232 vm:SetColor(Color(255,255,255,255))
233 else
234 // we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
235 vm:SetColor(Color(255,255,255,1))
236 // ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
237 // 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
238 vm:SetMaterial("Debug/hsv")
239 end
240 end
241 end
242
243 end
244
245end
246
247function SWEP:Holster()
248
249 if CLIENT and IsValid(self.Owner) then
250 local vm = self.Owner:GetViewModel()
251 if IsValid(vm) then
252 self:ResetBonePositions(vm)
253 end
254 end
255
256 return true
257end
258
259function SWEP:OnRemove()
260 self:Holster()
261end
262
263if CLIENT then
264
265 SWEP.vRenderOrder = nil
266 function SWEP:ViewModelDrawn()
267
268 local vm = self.Owner:GetViewModel()
269 if !IsValid(vm) then return end
270
271 if (!self.VElements) then return end
272
273 self:UpdateBonePositions(vm)
274
275 if (!self.vRenderOrder) then
276
277 // we build a render order because sprites need to be drawn after models
278 self.vRenderOrder = {}
279
280 for k, v in pairs( self.VElements ) do
281 if (v.type == "Model") then
282 table.insert(self.vRenderOrder, 1, k)
283 elseif (v.type == "Sprite" or v.type == "Quad") then
284 table.insert(self.vRenderOrder, k)
285 end
286 end
287
288 end
289
290 for k, name in ipairs( self.vRenderOrder ) do
291
292 local v = self.VElements[name]
293 if (!v) then self.vRenderOrder = nil break end
294 if (v.hide) then continue end
295
296 local model = v.modelEnt
297 local sprite = v.spriteMaterial
298
299 if (!v.bone) then continue end
300
301 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
302
303 if (!pos) then continue end
304
305 if (v.type == "Model" and IsValid(model)) then
306
307 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
308 ang:RotateAroundAxis(ang:Up(), v.angle.y)
309 ang:RotateAroundAxis(ang:Right(), v.angle.p)
310 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
311
312 model:SetAngles(ang)
313 //model:SetModelScale(v.size)
314 local matrix = Matrix()
315 matrix:Scale(v.size)
316 model:EnableMatrix( "RenderMultiply", matrix )
317
318 if (v.material == "") then
319 model:SetMaterial("")
320 elseif (model:GetMaterial() != v.material) then
321 model:SetMaterial( v.material )
322 end
323
324 if (v.skin and v.skin != model:GetSkin()) then
325 model:SetSkin(v.skin)
326 end
327
328 if (v.bodygroup) then
329 for k, v in pairs( v.bodygroup ) do
330 if (model:GetBodygroup(k) != v) then
331 model:SetBodygroup(k, v)
332 end
333 end
334 end
335
336 if (v.surpresslightning) then
337 render.SuppressEngineLighting(true)
338 end
339
340 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
341 render.SetBlend(v.color.a/255)
342 model:DrawModel()
343 render.SetBlend(1)
344 render.SetColorModulation(1, 1, 1)
345
346 if (v.surpresslightning) then
347 render.SuppressEngineLighting(false)
348 end
349
350 elseif (v.type == "Sprite" and sprite) then
351
352 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
353 render.SetMaterial(sprite)
354 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
355
356 elseif (v.type == "Quad" and v.draw_func) then
357
358 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
359 ang:RotateAroundAxis(ang:Up(), v.angle.y)
360 ang:RotateAroundAxis(ang:Right(), v.angle.p)
361 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
362
363 cam.Start3D2D(drawpos, ang, v.size)
364 v.draw_func( self )
365 cam.End3D2D()
366
367 end
368
369 end
370
371 end
372
373 SWEP.wRenderOrder = nil
374 function SWEP:DrawWorldModel()
375
376 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
377 self:DrawModel()
378 end
379
380 if (!self.WElements) then return end
381
382 if (!self.wRenderOrder) then
383
384 self.wRenderOrder = {}
385
386 for k, v in pairs( self.WElements ) do
387 if (v.type == "Model") then
388 table.insert(self.wRenderOrder, 1, k)
389 elseif (v.type == "Sprite" or v.type == "Quad") then
390 table.insert(self.wRenderOrder, k)
391 end
392 end
393
394 end
395
396 if (IsValid(self.Owner)) then
397 bone_ent = self.Owner
398 else
399 // when the weapon is dropped
400 bone_ent = self
401 end
402
403 for k, name in pairs( self.wRenderOrder ) do
404
405 local v = self.WElements[name]
406 if (!v) then self.wRenderOrder = nil break end
407 if (v.hide) then continue end
408
409 local pos, ang
410
411 if (v.bone) then
412 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
413 else
414 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
415 end
416
417 if (!pos) then continue end
418
419 local model = v.modelEnt
420 local sprite = v.spriteMaterial
421
422 if (v.type == "Model" and IsValid(model)) then
423
424 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
425 ang:RotateAroundAxis(ang:Up(), v.angle.y)
426 ang:RotateAroundAxis(ang:Right(), v.angle.p)
427 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
428
429 model:SetAngles(ang)
430 //model:SetModelScale(v.size)
431 local matrix = Matrix()
432 matrix:Scale(v.size)
433 model:EnableMatrix( "RenderMultiply", matrix )
434
435 if (v.material == "") then
436 model:SetMaterial("")
437 elseif (model:GetMaterial() != v.material) then
438 model:SetMaterial( v.material )
439 end
440
441 if (v.skin and v.skin != model:GetSkin()) then
442 model:SetSkin(v.skin)
443 end
444
445 if (v.bodygroup) then
446 for k, v in pairs( v.bodygroup ) do
447 if (model:GetBodygroup(k) != v) then
448 model:SetBodygroup(k, v)
449 end
450 end
451 end
452
453 if (v.surpresslightning) then
454 render.SuppressEngineLighting(true)
455 end
456
457 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
458 render.SetBlend(v.color.a/255)
459 model:DrawModel()
460 render.SetBlend(1)
461 render.SetColorModulation(1, 1, 1)
462
463 if (v.surpresslightning) then
464 render.SuppressEngineLighting(false)
465 end
466
467 elseif (v.type == "Sprite" and sprite) then
468
469 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
470 render.SetMaterial(sprite)
471 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
472
473 elseif (v.type == "Quad" and v.draw_func) then
474
475 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
476 ang:RotateAroundAxis(ang:Up(), v.angle.y)
477 ang:RotateAroundAxis(ang:Right(), v.angle.p)
478 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
479
480 cam.Start3D2D(drawpos, ang, v.size)
481 v.draw_func( self )
482 cam.End3D2D()
483
484 end
485
486 end
487
488 end
489
490 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
491
492 local bone, pos, ang
493 if (tab.rel and tab.rel != "") then
494
495 local v = basetab[tab.rel]
496
497 if (!v) then return end
498
499 // Technically, if there exists an element with the same name as a bone
500 // you can get in an infinite loop. Let's just hope nobody's that stupid.
501 pos, ang = self:GetBoneOrientation( basetab, v, ent )
502
503 if (!pos) then return end
504
505 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
506 ang:RotateAroundAxis(ang:Up(), v.angle.y)
507 ang:RotateAroundAxis(ang:Right(), v.angle.p)
508 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
509
510 else
511
512 bone = ent:LookupBone(bone_override or tab.bone)
513
514 if (!bone) then return end
515
516 pos, ang = Vector(0,0,0), Angle(0,0,0)
517 local m = ent:GetBoneMatrix(bone)
518 if (m) then
519 pos, ang = m:GetTranslation(), m:GetAngles()
520 end
521
522 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
523 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
524 ang.r = -ang.r // Fixes mirrored models
525 end
526
527 end
528
529 return pos, ang
530 end
531
532 function SWEP:CreateModels( tab )
533
534 if (!tab) then return end
535
536 // Create the clientside models here because Garry says we can't do it in the render hook
537 for k, v in pairs( tab ) do
538 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
539 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
540
541 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
542 if (IsValid(v.modelEnt)) then
543 v.modelEnt:SetPos(self:GetPos())
544 v.modelEnt:SetAngles(self:GetAngles())
545 v.modelEnt:SetParent(self)
546 v.modelEnt:SetNoDraw(true)
547 v.createdModel = v.model
548 else
549 v.modelEnt = nil
550 end
551
552 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
553 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
554
555 local name = v.sprite.."-"
556 local params = { ["$basetexture"] = v.sprite }
557 // make sure we create a unique name based on the selected options
558 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
559 for i, j in pairs( tocheck ) do
560 if (v[j]) then
561 params["$"..j] = 1
562 name = name.."1"
563 else
564 name = name.."0"
565 end
566 end
567
568 v.createdSprite = v.sprite
569 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
570
571 end
572 end
573
574 end
575
576 local allbones
577 local hasGarryFixedBoneScalingYet = false
578
579 function SWEP:UpdateBonePositions(vm)
580
581 if self.ViewModelBoneMods then
582
583 if (!vm:GetBoneCount()) then return end
584
585 // !! WORKAROUND !! //
586 // We need to check all model names :/
587 local loopthrough = self.ViewModelBoneMods
588 if (!hasGarryFixedBoneScalingYet) then
589 allbones = {}
590 for i=0, vm:GetBoneCount() do
591 local bonename = vm:GetBoneName(i)
592 if (self.ViewModelBoneMods[bonename]) then
593 allbones[bonename] = self.ViewModelBoneMods[bonename]
594 else
595 allbones[bonename] = {
596 scale = Vector(1,1,1),
597 pos = Vector(0,0,0),
598 angle = Angle(0,0,0)
599 }
600 end
601 end
602
603 loopthrough = allbones
604 end
605 // !! ----------- !! //
606
607 for k, v in pairs( loopthrough ) do
608 local bone = vm:LookupBone(k)
609 if (!bone) then continue end
610
611 // !! WORKAROUND !! //
612 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
613 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
614 local ms = Vector(1,1,1)
615 if (!hasGarryFixedBoneScalingYet) then
616 local cur = vm:GetBoneParent(bone)
617 while(cur >= 0) do
618 local pscale = loopthrough[vm:GetBoneName(cur)].scale
619 ms = ms * pscale
620 cur = vm:GetBoneParent(cur)
621 end
622 end
623
624 s = s * ms
625 // !! ----------- !! //
626
627 if vm:GetManipulateBoneScale(bone) != s then
628 vm:ManipulateBoneScale( bone, s )
629 end
630 if vm:GetManipulateBoneAngles(bone) != v.angle then
631 vm:ManipulateBoneAngles( bone, v.angle )
632 end
633 if vm:GetManipulateBonePosition(bone) != p then
634 vm:ManipulateBonePosition( bone, p )
635 end
636 end
637 else
638 self:ResetBonePositions(vm)
639 end
640
641 end
642
643 function SWEP:ResetBonePositions(vm)
644
645 if (!vm:GetBoneCount()) then return end
646 for i=0, vm:GetBoneCount() do
647 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
648 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
649 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
650 end
651
652 end
653
654 /**************************
655 Global utility code
656 **************************/
657
658 // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
659 // Does not copy entities of course, only copies their reference.
660 // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
661 function table.FullCopy( tab )
662
663 if (!tab) then return nil end
664
665 local res = {}
666 for k, v in pairs( tab ) do
667 if (type(v) == "table") then
668 res[k] = table.FullCopy(v) // recursion ho!
669 elseif (type(v) == "Vector") then
670 res[k] = Vector(v.x, v.y, v.z)
671 elseif (type(v) == "Angle") then
672 res[k] = Angle(v.p, v.y, v.r)
673 else
674 res[k] = v
675 end
676 end
677
678 return res
679
680 end
681
682end