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