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