· 6 years ago · Aug 06, 2019, 10:24 AM
1function SWEP:Holster()
2
3 if CLIENT and IsValid(self.Owner) then
4 local vm = self.Owner:GetViewModel()
5 if IsValid(vm) then
6 self:ResetBonePositions(vm)
7 end
8 end
9 self:SetIsHealing(false)
10 return true
11end
12
13function SWEP:OnRemove()
14 self:Holster()
15end
16
17if CLIENT then
18
19 SWEP.vRenderOrder = nil
20 function SWEP:ViewModelDrawn()
21
22 local vm = self.Owner:GetViewModel()
23 if !IsValid(vm) then return end
24
25 if (!self.VElements) then return end
26
27 self:UpdateBonePositions(vm)
28
29 if (!self.vRenderOrder) then
30
31 // we build a render order because sprites need to be drawn after models
32 self.vRenderOrder = {}
33
34 for k, v in pairs( self.VElements ) do
35 if (v.type == "Model") then
36 table.insert(self.vRenderOrder, 1, k)
37 elseif (v.type == "Sprite" or v.type == "Quad") then
38 table.insert(self.vRenderOrder, k)
39 end
40 end
41
42 end
43
44 for k, name in ipairs( self.vRenderOrder ) do
45
46 local v = self.VElements[name]
47 if (!v) then self.vRenderOrder = nil break end
48 if (v.hide) then continue end
49
50 local model = v.modelEnt
51 local sprite = v.spriteMaterial
52
53 if (!v.bone) then continue end
54
55 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
56
57 if (!pos) then continue end
58
59 if (v.type == "Model" and IsValid(model)) then
60
61 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
62 ang:RotateAroundAxis(ang:Up(), v.angle.y)
63 ang:RotateAroundAxis(ang:Right(), v.angle.p)
64 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
65
66 model:SetAngles(ang)
67 //model:SetModelScale(v.size)
68 local matrix = Matrix()
69 matrix:Scale(v.size)
70 model:EnableMatrix( "RenderMultiply", matrix )
71
72 if (v.material == "") then
73 model:SetMaterial("")
74 elseif (model:GetMaterial() != v.material) then
75 model:SetMaterial( v.material )
76 end
77
78 if (v.skin and v.skin != model:GetSkin()) then
79 model:SetSkin(v.skin)
80 end
81
82 if (v.bodygroup) then
83 for k, v in pairs( v.bodygroup ) do
84 if (model:GetBodygroup(k) != v) then
85 model:SetBodygroup(k, v)
86 end
87 end
88 end
89
90 if (v.surpresslightning) then
91 render.SuppressEngineLighting(true)
92 end
93
94 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
95 render.SetBlend(v.color.a/255)
96 model:DrawModel()
97 render.SetBlend(1)
98 render.SetColorModulation(1, 1, 1)
99
100 if (v.surpresslightning) then
101 render.SuppressEngineLighting(false)
102 end
103
104 elseif (v.type == "Sprite" and sprite) then
105
106 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
107 render.SetMaterial(sprite)
108 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
109
110 elseif (v.type == "Quad" and v.draw_func) then
111
112 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
113 ang:RotateAroundAxis(ang:Up(), v.angle.y)
114 ang:RotateAroundAxis(ang:Right(), v.angle.p)
115 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
116
117 cam.Start3D2D(drawpos, ang, v.size)
118 v.draw_func( self )
119 cam.End3D2D()
120
121 end
122
123 end
124
125 end
126
127 SWEP.wRenderOrder = nil
128 function SWEP:DrawWorldModel()
129
130 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
131 self:DrawModel()
132 end
133
134 if (!self.WElements) then return end
135
136 if (!self.wRenderOrder) then
137
138 self.wRenderOrder = {}
139
140 for k, v in pairs( self.WElements ) do
141 if (v.type == "Model") then
142 table.insert(self.wRenderOrder, 1, k)
143 elseif (v.type == "Sprite" or v.type == "Quad") then
144 table.insert(self.wRenderOrder, k)
145 end
146 end
147
148 end
149
150 if (IsValid(self.Owner)) then
151 bone_ent = self.Owner
152 else
153 // when the weapon is dropped
154 bone_ent = self
155 end
156
157 for k, name in pairs( self.wRenderOrder ) do
158
159 local v = self.WElements[name]
160 if (!v) then self.wRenderOrder = nil break end
161 if (v.hide) then continue end
162
163 local pos, ang
164
165 if (v.bone) then
166 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
167 else
168 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
169 end
170
171 if (!pos) then continue end
172
173 local model = v.modelEnt
174 local sprite = v.spriteMaterial
175
176 if (v.type == "Model" and IsValid(model)) then
177
178 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
179 ang:RotateAroundAxis(ang:Up(), v.angle.y)
180 ang:RotateAroundAxis(ang:Right(), v.angle.p)
181 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
182
183 model:SetAngles(ang)
184 //model:SetModelScale(v.size)
185 local matrix = Matrix()
186 matrix:Scale(v.size)
187 model:EnableMatrix( "RenderMultiply", matrix )
188
189 if (v.material == "") then
190 model:SetMaterial("")
191 elseif (model:GetMaterial() != v.material) then
192 model:SetMaterial( v.material )
193 end
194
195 if (v.skin and v.skin != model:GetSkin()) then
196 model:SetSkin(v.skin)
197 end
198
199 if (v.bodygroup) then
200 for k, v in pairs( v.bodygroup ) do
201 if (model:GetBodygroup(k) != v) then
202 model:SetBodygroup(k, v)
203 end
204 end
205 end
206
207 if (v.surpresslightning) then
208 render.SuppressEngineLighting(true)
209 end
210
211 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
212 render.SetBlend(v.color.a/255)
213 model:DrawModel()
214 render.SetBlend(1)
215 render.SetColorModulation(1, 1, 1)
216
217 if (v.surpresslightning) then
218 render.SuppressEngineLighting(false)
219 end
220
221 elseif (v.type == "Sprite" and sprite) then
222
223 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
224 render.SetMaterial(sprite)
225 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
226
227 elseif (v.type == "Quad" and v.draw_func) then
228
229 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
230 ang:RotateAroundAxis(ang:Up(), v.angle.y)
231 ang:RotateAroundAxis(ang:Right(), v.angle.p)
232 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
233
234 cam.Start3D2D(drawpos, ang, v.size)
235 v.draw_func( self )
236 cam.End3D2D()
237
238 end
239
240 end
241
242 end
243
244 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
245
246 local bone, pos, ang
247 if (tab.rel and tab.rel != "") then
248
249 local v = basetab[tab.rel]
250
251 if (!v) then return end
252
253 // Technically, if there exists an element with the same name as a bone
254 // you can get in an infinite loop. Let's just hope nobody's that stupid.
255 pos, ang = self:GetBoneOrientation( basetab, v, ent )
256
257 if (!pos) then return end
258
259 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
260 ang:RotateAroundAxis(ang:Up(), v.angle.y)
261 ang:RotateAroundAxis(ang:Right(), v.angle.p)
262 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
263
264 else
265
266 bone = ent:LookupBone(bone_override or tab.bone)
267
268 if (!bone) then return end
269
270 pos, ang = Vector(0,0,0), Angle(0,0,0)
271 local m = ent:GetBoneMatrix(bone)
272 if (m) then
273 pos, ang = m:GetTranslation(), m:GetAngles()
274 end
275
276 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
277 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
278 ang.r = -ang.r // Fixes mirrored models
279 end
280
281 end
282
283 return pos, ang
284 end
285
286 function SWEP:CreateModels( tab )
287
288 if (!tab) then return end
289
290 // Create the clientside models here because Garry says we can't do it in the render hook
291 for k, v in pairs( tab ) do
292 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
293 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
294
295 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
296 if (IsValid(v.modelEnt)) then
297 v.modelEnt:SetPos(self:GetPos())
298 v.modelEnt:SetAngles(self:GetAngles())
299 v.modelEnt:SetParent(self)
300 v.modelEnt:SetNoDraw(true)
301 v.createdModel = v.model
302 else
303 v.modelEnt = nil
304 end
305
306 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
307 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
308
309 local name = v.sprite.."-"
310 local params = { ["$basetexture"] = v.sprite }
311 // make sure we create a unique name based on the selected options
312 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
313 for i, j in pairs( tocheck ) do
314 if (v[j]) then
315 params["$"..j] = 1
316 name = name.."1"
317 else
318 name = name.."0"
319 end
320 end
321
322 v.createdSprite = v.sprite
323 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
324
325 end
326 end
327
328 end
329
330 local allbones
331 local hasGarryFixedBoneScalingYet = false
332
333 function SWEP:UpdateBonePositions(vm)
334
335 if self.ViewModelBoneMods then
336
337 if (!vm:GetBoneCount()) then return end
338
339 // !! WORKAROUND !! //
340 // We need to check all model names :/
341 local loopthrough = self.ViewModelBoneMods
342 if (!hasGarryFixedBoneScalingYet) then
343 allbones = {}
344 for i=0, vm:GetBoneCount() do
345 local bonename = vm:GetBoneName(i)
346 if (self.ViewModelBoneMods[bonename]) then
347 allbones[bonename] = self.ViewModelBoneMods[bonename]
348 else
349 allbones[bonename] = {
350 scale = Vector(1,1,1),
351 pos = Vector(0,0,0),
352 angle = Angle(0,0,0)
353 }
354 end
355 end
356
357 loopthrough = allbones
358 end
359 // !! ----------- !! //
360
361 for k, v in pairs( loopthrough ) do
362 local bone = vm:LookupBone(k)
363 if (!bone) then continue end
364
365 // !! WORKAROUND !! //
366 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
367 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
368 local ms = Vector(1,1,1)
369 if (!hasGarryFixedBoneScalingYet) then
370 local cur = vm:GetBoneParent(bone)
371 while(cur >= 0) do
372 local pscale = loopthrough[vm:GetBoneName(cur)].scale
373 ms = ms * pscale
374 cur = vm:GetBoneParent(cur)
375 end
376 end
377
378 s = s * ms
379 // !! ----------- !! //
380
381 if vm:GetManipulateBoneScale(bone) != s then
382 vm:ManipulateBoneScale( bone, s )
383 end
384 if vm:GetManipulateBoneAngles(bone) != v.angle then
385 vm:ManipulateBoneAngles( bone, v.angle )
386 end
387 if vm:GetManipulateBonePosition(bone) != p then
388 vm:ManipulateBonePosition( bone, p )
389 end
390 end
391 else
392 self:ResetBonePositions(vm)
393 end
394
395 end
396
397 function SWEP:ResetBonePositions(vm)
398
399 if (!vm:GetBoneCount()) then return end
400 for i=0, vm:GetBoneCount() do
401 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
402 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
403 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
404 end
405
406 end
407
408 /**************************
409 Global utility code
410 **************************/
411
412 // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
413 // Does not copy entities of course, only copies their reference.
414 // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
415 function table.FullCopy( tab )
416
417 if (!tab) then return nil end
418
419 local res = {}
420 for k, v in pairs( tab ) do
421 if (type(v) == "table") then
422 res[k] = table.FullCopy(v) // recursion ho!
423 elseif (type(v) == "Vector") then
424 res[k] = Vector(v.x, v.y, v.z)
425 elseif (type(v) == "Angle") then
426 res[k] = Angle(v.p, v.y, v.r)
427 else
428 res[k] = v
429 end
430 end
431
432 return res
433
434 end
435
436end