· 7 years ago · Nov 19, 2018, 11:58 PM
1/*
2 ©2018 Walrusking
3 This was created by Walrusking[
4 SteamID: STEAM_0:0:103519394
5 Link to profile: http://steamcommunity.com/id/Walrusking_1/
6 ]
7 Covered by Attribution-NonCommercial-NoDerivatives 4.0 International
8 http://creativecommons.org/licenses/by-nc-nd/4.0/
9 http://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
10*/
11AddCSLuaFile()
12
13SWEP.PrintName = "[PLACEHOLDER]"
14SWEP.Author = "Walrusking"
15SWEP.Instructions = "[PLACEHOLDER]"
16SWEP.Category = "DC SWEPS - Walrusking"
17SWEP.Spawnable = true
18SWEP.AdminOnly = false
19SWEP.ViewModel = "models/weapons/v_smg1.mdl"
20SWEP.WorldModel = "models/weapons/w_smg1.mdl"
21SWEP.Base = "weapon_base"
22SWEP.Slot = 1
23SWEP.SlotPos = 3
24SWEP.Primary.Ammo = "none"
25SWEP.Secondary.Ammo = "none"
26SWEP.Primary.ClipSize = 0
27SWEP.Primary.Automatic = false
28
29/********************************************************
30 SWEP Construction Kit base code
31 Created by Clavus
32 Available for public use, thread at:
33 facepunch.com/threads/1032378
34
35
36 DESCRIPTION:
37 This script is meant for experienced scripters
38 that KNOW WHAT THEY ARE DOING. Don't come to me
39 with basic Lua questions.
40
41 Just copy into your SWEP or SWEP base of choice
42 and merge with your own code.
43
44 The SWEP.VElements, SWEP.WElements and
45 SWEP.ViewModelBoneMods tables are all optional
46 and only have to be visible to the client.
47********************************************************/
48
49function SWEP:Initialize()
50
51 // other initialize code goes here
52
53 if CLIENT then
54
55 // Create a new table for every weapon instance
56 self.VElements = table.FullCopy( self.VElements )
57 self.WElements = table.FullCopy( self.WElements )
58 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
59
60 self:CreateModels(self.VElements) // create viewmodels
61 self:CreateModels(self.WElements) // create worldmodels
62
63 // init view model bone build function
64 if IsValid(self.Owner) then
65 local vm = self.Owner:GetViewModel()
66 if IsValid(vm) then
67 self:ResetBonePositions(vm)
68
69 // Init viewmodel visibility
70 if (self.ShowViewModel == nil or self.ShowViewModel) then
71 vm:SetColor(Color(255,255,255,255))
72 else
73 // we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
74 vm:SetColor(Color(255,255,255,1))
75 // ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
76 // 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
77 vm:SetMaterial("Debug/hsv")
78 end
79 end
80 end
81
82 end
83
84end
85
86function SWEP:Holster()
87
88 if CLIENT and IsValid(self.Owner) then
89 local vm = self.Owner:GetViewModel()
90 if IsValid(vm) then
91 self:ResetBonePositions(vm)
92 end
93 end
94
95 return true
96end
97
98function SWEP:OnRemove()
99 self:Holster()
100end
101
102if CLIENT then
103
104 SWEP.vRenderOrder = nil
105 function SWEP:ViewModelDrawn()
106
107 local vm = self.Owner:GetViewModel()
108 if !IsValid(vm) then return end
109
110 if (!self.VElements) then return end
111
112 self:UpdateBonePositions(vm)
113
114 if (!self.vRenderOrder) then
115
116 // we build a render order because sprites need to be drawn after models
117 self.vRenderOrder = {}
118
119 for k, v in pairs( self.VElements ) do
120 if (v.type == "Model") then
121 table.insert(self.vRenderOrder, 1, k)
122 elseif (v.type == "Sprite" or v.type == "Quad") then
123 table.insert(self.vRenderOrder, k)
124 end
125 end
126
127 end
128
129 for k, name in ipairs( self.vRenderOrder ) do
130
131 local v = self.VElements[name]
132 if (!v) then self.vRenderOrder = nil break end
133 if (v.hide) then continue end
134
135 local model = v.modelEnt
136 local sprite = v.spriteMaterial
137
138 if (!v.bone) then continue end
139
140 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
141
142 if (!pos) then continue end
143
144 if (v.type == "Model" and IsValid(model)) then
145
146 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
147 ang:RotateAroundAxis(ang:Up(), v.angle.y)
148 ang:RotateAroundAxis(ang:Right(), v.angle.p)
149 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
150
151 model:SetAngles(ang)
152 //model:SetModelScale(v.size)
153 local matrix = Matrix()
154 matrix:Scale(v.size)
155 model:EnableMatrix( "RenderMultiply", matrix )
156
157 if (v.material == "") then
158 model:SetMaterial("")
159 elseif (model:GetMaterial() != v.material) then
160 model:SetMaterial( v.material )
161 end
162
163 if (v.skin and v.skin != model:GetSkin()) then
164 model:SetSkin(v.skin)
165 end
166
167 if (v.bodygroup) then
168 for k, v in pairs( v.bodygroup ) do
169 if (model:GetBodygroup(k) != v) then
170 model:SetBodygroup(k, v)
171 end
172 end
173 end
174
175 if (v.surpresslightning) then
176 render.SuppressEngineLighting(true)
177 end
178
179 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
180 render.SetBlend(v.color.a/255)
181 model:DrawModel()
182 render.SetBlend(1)
183 render.SetColorModulation(1, 1, 1)
184
185 if (v.surpresslightning) then
186 render.SuppressEngineLighting(false)
187 end
188
189 elseif (v.type == "Sprite" and sprite) then
190
191 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
192 render.SetMaterial(sprite)
193 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
194
195 elseif (v.type == "Quad" and v.draw_func) then
196
197 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
198 ang:RotateAroundAxis(ang:Up(), v.angle.y)
199 ang:RotateAroundAxis(ang:Right(), v.angle.p)
200 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
201
202 cam.Start3D2D(drawpos, ang, v.size)
203 v.draw_func( self )
204 cam.End3D2D()
205
206 end
207
208 end
209
210 end
211
212 SWEP.wRenderOrder = nil
213 function SWEP:DrawWorldModel()
214
215 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
216 self:DrawModel()
217 end
218
219 if (!self.WElements) then return end
220
221 if (!self.wRenderOrder) then
222
223 self.wRenderOrder = {}
224
225 for k, v in pairs( self.WElements ) do
226 if (v.type == "Model") then
227 table.insert(self.wRenderOrder, 1, k)
228 elseif (v.type == "Sprite" or v.type == "Quad") then
229 table.insert(self.wRenderOrder, k)
230 end
231 end
232
233 end
234
235 if (IsValid(self.Owner)) then
236 bone_ent = self.Owner
237 else
238 // when the weapon is dropped
239 bone_ent = self
240 end
241
242 for k, name in pairs( self.wRenderOrder ) do
243
244 local v = self.WElements[name]
245 if (!v) then self.wRenderOrder = nil break end
246 if (v.hide) then continue end
247
248 local pos, ang
249
250 if (v.bone) then
251 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
252 else
253 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
254 end
255
256 if (!pos) then continue end
257
258 local model = v.modelEnt
259 local sprite = v.spriteMaterial
260
261 if (v.type == "Model" and IsValid(model)) then
262
263 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
264 ang:RotateAroundAxis(ang:Up(), v.angle.y)
265 ang:RotateAroundAxis(ang:Right(), v.angle.p)
266 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
267
268 model:SetAngles(ang)
269 //model:SetModelScale(v.size)
270 local matrix = Matrix()
271 matrix:Scale(v.size)
272 model:EnableMatrix( "RenderMultiply", matrix )
273
274 if (v.material == "") then
275 model:SetMaterial("")
276 elseif (model:GetMaterial() != v.material) then
277 model:SetMaterial( v.material )
278 end
279
280 if (v.skin and v.skin != model:GetSkin()) then
281 model:SetSkin(v.skin)
282 end
283
284 if (v.bodygroup) then
285 for k, v in pairs( v.bodygroup ) do
286 if (model:GetBodygroup(k) != v) then
287 model:SetBodygroup(k, v)
288 end
289 end
290 end
291
292 if (v.surpresslightning) then
293 render.SuppressEngineLighting(true)
294 end
295
296 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
297 render.SetBlend(v.color.a/255)
298 model:DrawModel()
299 render.SetBlend(1)
300 render.SetColorModulation(1, 1, 1)
301
302 if (v.surpresslightning) then
303 render.SuppressEngineLighting(false)
304 end
305
306 elseif (v.type == "Sprite" and sprite) then
307
308 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
309 render.SetMaterial(sprite)
310 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
311
312 elseif (v.type == "Quad" and v.draw_func) then
313
314 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
315 ang:RotateAroundAxis(ang:Up(), v.angle.y)
316 ang:RotateAroundAxis(ang:Right(), v.angle.p)
317 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
318
319 cam.Start3D2D(drawpos, ang, v.size)
320 v.draw_func( self )
321 cam.End3D2D()
322
323 end
324
325 end
326
327 end
328
329 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
330
331 local bone, pos, ang
332 if (tab.rel and tab.rel != "") then
333
334 local v = basetab[tab.rel]
335
336 if (!v) then return end
337
338 // Technically, if there exists an element with the same name as a bone
339 // you can get in an infinite loop. Let's just hope nobody's that stupid.
340 pos, ang = self:GetBoneOrientation( basetab, v, ent )
341
342 if (!pos) then return end
343
344 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
345 ang:RotateAroundAxis(ang:Up(), v.angle.y)
346 ang:RotateAroundAxis(ang:Right(), v.angle.p)
347 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
348
349 else
350
351 bone = ent:LookupBone(bone_override or tab.bone)
352
353 if (!bone) then return end
354
355 pos, ang = Vector(0,0,0), Angle(0,0,0)
356 local m = ent:GetBoneMatrix(bone)
357 if (m) then
358 pos, ang = m:GetTranslation(), m:GetAngles()
359 end
360
361 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
362 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
363 ang.r = -ang.r // Fixes mirrored models
364 end
365
366 end
367
368 return pos, ang
369 end
370
371 function SWEP:CreateModels( tab )
372
373 if (!tab) then return end
374
375 // Create the clientside models here because Garry says we can't do it in the render hook
376 for k, v in pairs( tab ) do
377 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
378 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
379
380 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
381 if (IsValid(v.modelEnt)) then
382 v.modelEnt:SetPos(self:GetPos())
383 v.modelEnt:SetAngles(self:GetAngles())
384 v.modelEnt:SetParent(self)
385 v.modelEnt:SetNoDraw(true)
386 v.createdModel = v.model
387 else
388 v.modelEnt = nil
389 end
390
391 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
392 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
393
394 local name = v.sprite.."-"
395 local params = { ["$basetexture"] = v.sprite }
396 // make sure we create a unique name based on the selected options
397 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
398 for i, j in pairs( tocheck ) do
399 if (v[j]) then
400 params["$"..j] = 1
401 name = name.."1"
402 else
403 name = name.."0"
404 end
405 end
406
407 v.createdSprite = v.sprite
408 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
409
410 end
411 end
412
413 end
414
415 local allbones
416 local hasGarryFixedBoneScalingYet = false
417
418 function SWEP:UpdateBonePositions(vm)
419
420 if self.ViewModelBoneMods then
421
422 if (!vm:GetBoneCount()) then return end
423
424 // !! WORKAROUND !! //
425 // We need to check all model names :/
426 local loopthrough = self.ViewModelBoneMods
427 if (!hasGarryFixedBoneScalingYet) then
428 allbones = {}
429 for i=0, vm:GetBoneCount() do
430 local bonename = vm:GetBoneName(i)
431 if (self.ViewModelBoneMods[bonename]) then
432 allbones[bonename] = self.ViewModelBoneMods[bonename]
433 else
434 allbones[bonename] = {
435 scale = Vector(1,1,1),
436 pos = Vector(0,0,0),
437 angle = Angle(0,0,0)
438 }
439 end
440 end
441
442 loopthrough = allbones
443 end
444 // !! ----------- !! //
445
446 for k, v in pairs( loopthrough ) do
447 local bone = vm:LookupBone(k)
448 if (!bone) then continue end
449
450 // !! WORKAROUND !! //
451 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
452 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
453 local ms = Vector(1,1,1)
454 if (!hasGarryFixedBoneScalingYet) then
455 local cur = vm:GetBoneParent(bone)
456 while(cur >= 0) do
457 local pscale = loopthrough[vm:GetBoneName(cur)].scale
458 ms = ms * pscale
459 cur = vm:GetBoneParent(cur)
460 end
461 end
462
463 s = s * ms
464 // !! ----------- !! //
465
466 if vm:GetManipulateBoneScale(bone) != s then
467 vm:ManipulateBoneScale( bone, s )
468 end
469 if vm:GetManipulateBoneAngles(bone) != v.angle then
470 vm:ManipulateBoneAngles( bone, v.angle )
471 end
472 if vm:GetManipulateBonePosition(bone) != p then
473 vm:ManipulateBonePosition( bone, p )
474 end
475 end
476 else
477 self:ResetBonePositions(vm)
478 end
479
480 end
481
482 function SWEP:ResetBonePositions(vm)
483
484 if (!vm:GetBoneCount()) then return end
485 for i=0, vm:GetBoneCount() do
486 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
487 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
488 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
489 end
490
491 end
492
493 /**************************
494 Global utility code
495 **************************/
496
497 // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
498 // Does not copy entities of course, only copies their reference.
499 // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
500 function table.FullCopy( tab )
501
502 if (!tab) then return nil end
503
504 local res = {}
505 for k, v in pairs( tab ) do
506 if (type(v) == "table") then
507 res[k] = table.FullCopy(v) // recursion ho!
508 elseif (type(v) == "Vector") then
509 res[k] = Vector(v.x, v.y, v.z)
510 elseif (type(v) == "Angle") then
511 res[k] = Angle(v.p, v.y, v.r)
512 else
513 res[k] = v
514 end
515 end
516
517 return res
518
519 end
520
521end