· 6 years ago · Apr 24, 2019, 10:24 PM
1if ( SERVER ) then
2 AddCSLuaFile( "shared.lua" )
3else
4 SWEP.PrintName = "Force Lightning"
5 SWEP.Author = "SweptThrone"
6 SWEP.Slot = 2
7 SWEP.SlotPos = 3
8end
9
10SWEP.Base = "weapon_swsft_base"
11SWEP.Category = "Throneco StarWars"
12SWEP.Spawnable = true
13SWEP.AdminSpawnable = true
14SWEP.FireSound = "weapons/starwars/force_lightning1.wav"
15SWEP.Weight = 5
16SWEP.AutoSwitchTo = false
17SWEP.AutoSwitchFrom = false
18SWEP.Primary.Recoil = 2.5
19SWEP.Primary.Damage = 200
20SWEP.Primary.NumShots = 1
21SWEP.Primary.Cone = 0.010
22SWEP.Primary.ClipSize = -1
23SWEP.Primary.Delay = 0.25
24SWEP.Primary.DefaultClip = -1
25SWEP.Primary.Automatic = false
26SWEP.Primary.Ammo = "none"
27SWEP.Primary.Tracer = "effect_sw_laser_blue"
28SWEP.Secondary.Automatic = true
29SWEP.Secondary.Ammo = "none"
30SWEP.Secondary.Delay = .1
31
32SWEP.HoldType = "duel"
33SWEP.ViewModelFOV = 90
34SWEP.ViewModelFlip = false
35SWEP.UseHands = true
36SWEP.ViewModel = "models/weapons/c_357.mdl"
37SWEP.WorldModel = "models/weapons/w_pistol.mdl"
38SWEP.ShowViewModel = true
39SWEP.ShowWorldModel = false
40SWEP.ViewModelBoneMods = {
41 ["ValveBiped.Bip01_R_Finger31"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 18.75, 0) },
42 ["Bullet3"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
43 ["ValveBiped.Bip01_R_Finger11"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0.03, 0.09), angle = Angle(-1.208, -21.73, 12.937) },
44 ["Bullet6"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
45 ["ValveBiped.Bip01_L_UpperArm"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(-25, 20, 0) },
46 ["ValveBiped.Bip01_R_UpperArm"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 5, 0) },
47 ["ValveBiped.Bip01_L_Hand"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(-50, -95, 150) },
48 ["ValveBiped.Bip01_R_Finger32"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 20.068, 0) },
49 ["ValveBiped.Bip01_R_Finger42"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 51.05, 0) },
50 ["Python"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
51 ["ValveBiped.Bip01_R_Finger01"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, -25, 0) },
52 ["ValveBiped.Bip01_R_Finger41"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 9.807, 0) },
53 ["Bullet1"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
54 ["ValveBiped.Bip01_R_Hand"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(41.911, 44.84, 23.868) },
55 ["Bullet4"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
56 ["ValveBiped.Bip01_R_Finger1"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(12.008, 16.745, 0) },
57 ["ValveBiped.Bip01_R_Finger21"] = { scale = Vector(0.933, 0.933, 0.933), pos = Vector(0, 0, 0), angle = Angle(-5.646, 21.253, 0) },
58 ["ValveBiped.Bip01_R_Finger4"] = { scale = Vector(1, 1, 1), pos = Vector(-0.21, 0, 0), angle = Angle(-30, 38.041, 0) },
59 ["ValveBiped.Bip01_R_Finger02"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, -20, 0) },
60 ["Cylinder"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
61 ["Bullet5"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
62 ["ValveBiped.Bip01_R_Finger22"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 27.802, 0) },
63 ["ValveBiped.Bip01_R_Finger2"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0.505, 58.675, 0) },
64 ["Cylinder_release"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
65 ["Bullet2"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
66 ["ValveBiped.Bip01_R_Finger3"] = { scale = Vector(1, 1, 1), pos = Vector(-0.26, -0.152, 0), angle = Angle(-18.764, 51.015, -14.695) },
67 ["ValveBiped.Bip01_R_Forearm"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 0, -70) }
68}
69
70SWEP.VElements = {
71 ["muzzleflare2"] = { type = "Sprite", sprite = "effects/electric1", bone = "ValveBiped.Bip01_L_Clavicle", rel = "muzzleflare", pos = Vector(0, 0, 10.923), angle = Angle(0,0,0), size = { x = 16, y = 16 }, color = Color(0, 85, 255, 255), nocull = true, additive = true, vertexalpha = true, vertexcolor = true, ignorez = false},
72 ["muzzleflare3"] = { type = "Sprite", sprite = "effects/electric1", bone = "ValveBiped.Bip01_L_Clavicle", rel = "muzzleflare", pos = Vector(0, 0, 10.923), angle = Angle(0,0,0), size = { x = 15, y = 15 }, color = Color(0, 0, 255, 255), nocull = true, additive = true, vertexalpha = true, vertexcolor = true, ignorez = false},
73 ["muzzleflare"] = { type = "Sprite", sprite = "effects/rollerglow", bone = "ValveBiped.Bip01_L_Clavicle", rel = "body", pos = Vector(0, 0, 20.319), angle = Angle(0,0,0), size = { x = 14, y = 14 }, color = Color(84, 94, 255, 255), nocull = true, additive = true, vertexalpha = true, vertexcolor = true, ignorez = false},
74}
75
76SWEP.WElements = {
77 ["muzzleflare"] = { type = "Sprite", sprite = "effects/rollerglow", bone = "ValveBiped.Bip01_R_Hand", rel = "body", pos = Vector(0, 0, 20.319), angle = Angle(0,0,0), size = { x = 14, y = 14 }, color = Color(0, 0, 255, 255), nocull = true, additive = true, vertexalpha = true, vertexcolor = true, ignorez = false},
78 ["muzzleflare2"] = { type = "Sprite", sprite = "effects/electric1", bone = "ValveBiped.Bip01_R_Hand", rel = "muzzleflare", pos = Vector(0, 0, -0.245), angle = Angle(0,0,0), size = { x = 16, y = 16 }, color = Color(0, 0, 255, 255), nocull = true, additive = true, vertexalpha = true, vertexcolor = true, ignorez = false},
79 ["muzzleflare3"] = { type = "Sprite", sprite = "effects/electric1", bone = "ValveBiped.Bip01_R_Hand", rel = "muzzleflare", pos = Vector(0, 0, -0.245), angle = Angle(0,0,0), size = { x = 15, y = 15 }, color = Color(0, 0, 255, 255), nocull = true, additive = true, vertexalpha = true, vertexcolor = true, ignorez = false}
80}
81
82
83function OverTheShoulder( ply, pos, angles, fov )
84 if !ply:IsValid() then return end
85 if !ply:GetActiveWeapon():IsValid() then return end
86 if ply:GetActiveWeapon():GetClass() == "st_forcelightning" then
87 local view = {}
88
89 view.origin = pos-( angles:Forward()*35 + angles:Right()*-20 )
90 view.angles = angles
91 view.fov = fov
92 view.drawviewer = true
93
94 return view
95 end
96end
97
98
99function ReturnToNormal( ply, pos, angles, fov )
100 local view = {}
101
102 view.origin = angles:Zero()
103 view.angles = angles
104 view.fov = fov
105 view.drawviewer = true
106
107 return view
108end
109
110hook.Add( "CalcView", "FLThirdPerson", OverTheShoulder )
111
112function SWEP:Reload()
113end
114
115function SWEP:SelectTargets( num, dist )
116
117 local t = {}
118 dist = dist or 512
119 local p = {}
120
121 for id, ply in pairs( ents.GetAll() ) do
122 if ( !ply:GetModel() || ply:GetModel() == "" || ply == self.Owner || ply:Health() < 1 ) then continue end
123 if ply.PlayerTeam then
124 if players_only then continue end
125 if not friends and ply.PlayerTeam == self.Owner:Team() then
126 continue
127 elseif friends and ply.PlayerTeam != self.Owner:Team() then
128 continue
129 end
130 end
131
132 if ply.Team then
133 if not friends and ply:Team() == self.Owner:Team() then
134 continue
135 elseif friends and ply:Team() != self.Owner:Team() then
136 continue
137 end
138 end
139
140 if ( string.StartWith( ply:GetModel() || "", "models/gibs/" ) ) then continue end
141 if ( string.find( ply:GetModel() || "", "chunk" ) ) then continue end
142 if ( string.find( ply:GetModel() || "", "_shard" ) ) then continue end
143 if ( string.find( ply:GetModel() || "", "_splinters" ) ) then continue end
144
145 local tr = util.TraceLine( {
146 start = self.Owner:GetShootPos(),
147 endpos = (ply.GetShootPos && ply:GetShootPos() || ply:GetPos()),
148 filter = function(ent) return ent == ply or not ent.Nick end
149 } )
150 if not IsValid( tr.Entity ) or tr.Entity != ply or tr.Entity == game.GetWorld() then continue end
151 local spos = self.Owner:GetShootPos()
152 local pos1 = self.Owner:GetPos() + self.Owner:GetAimVector() * dist
153 local pos2 = tr.HitPos
154 local dot = self.Owner:GetAimVector():Dot( ( pos2 - self.Owner:GetShootPos() ):GetNormalized() )
155 local dist2 = spos:Distance( pos2 )
156 if ( dist2 <= dist && ply:EntIndex() > 0 && ply:GetModel() && ply:GetModel() != "" ) then
157 table.insert( p, { ply = ply, dist = dist2, dot = dot, score = dot + ( ( dist - dist2 ) / dist ) * 50 } )
158 end
159 end
160
161 local d = {}
162
163 for id, ply in SortedPairsByMemberValue( p, "dist" ) do
164 table.insert( t, ply.ply )
165 d[ply.ply] = ply
166 if ( #t >= num ) then break end
167 end
168 local f = {}
169 for i = 1,num do
170 f[i] = t[i]
171 end
172 return f,d
173end
174
175
176sound.Add( {
177 name = "lighting_hands",
178 channel = CHAN_WEAPON,
179 volume = 0.05,
180 level = 100,
181 pitch = 100,
182 sound = "weapons/starwars/force_lightning1.wav"
183} )
184
185
186sound.Add( {
187 name = "hand_zap",
188 channel = CHAN_WEAPON,
189 volume = 0.05,
190 level = 100,
191 pitch = 100,
192 sound = "weapons/starwars/force_lightning2.wav"
193} )
194
195local dist = 800
196
197function SWEP:Think()
198
199
200 self.BaseClass.Think(self)
201 self.VElements["muzzleflare"].color.a = math.max(0,self.VElements["muzzleflare"].color.a - 10 * FrameTime() * 60)
202 self.VElements["muzzleflare"].size.x = math.max(0,self.VElements["muzzleflare"].size.x - 0.5 * FrameTime() * 60)
203 self.VElements["muzzleflare"].size.y = math.max(0,self.VElements["muzzleflare"].size.y - 0.5 * FrameTime() * 60)
204 self.VElements["muzzleflare2"].color.a = math.max(0,self.VElements["muzzleflare2"].color.a - 10 * FrameTime() * 60)
205 self.VElements["muzzleflare3"].color.a = math.max(0,self.VElements["muzzleflare3"].color.a - 10 * FrameTime() * 60)
206 self.WElements["muzzleflare"].color.a = math.max(0,self.WElements["muzzleflare"].color.a - 10 * FrameTime() * 60)
207 self.WElements["muzzleflare"].color.a = math.max(0,self.WElements["muzzleflare"].color.b - 10 * FrameTime() * 60)
208 self.WElements["muzzleflare"].size.x = math.max(0,self.WElements["muzzleflare"].size.x - 0.5 * FrameTime() * 60)
209 self.WElements["muzzleflare"].size.y = math.max(0,self.WElements["muzzleflare"].size.y - 0.5 * FrameTime() * 60)
210 self.WElements["muzzleflare2"].color.a = math.max(0,self.WElements["muzzleflare2"].color.a - 10 * FrameTime() * 60)
211 self.WElements["muzzleflare3"].color.a = math.max(0,self.WElements["muzzleflare3"].color.a - 10 * FrameTime() * 60)
212end
213
214function SWEP:PrimaryAttack()
215 if self.Owner:HasGodMode() == true then return end
216
217
218 if IsFirstTimePredicted() then
219
220 self.VElements["muzzleflare"].size.x = 20
221 self.VElements["muzzleflare"].size.y = 20
222 self.VElements["muzzleflare"].color.a = 255
223 self.VElements["muzzleflare2"].color.a = 255
224 self.VElements["muzzleflare3"].color.a = 255
225 self.WElements["muzzleflare"].size.x = 20
226 self.WElements["muzzleflare"].size.y = 20
227 self.WElements["muzzleflare"].color.a = 255
228 self.WElements["muzzleflare2"].color.a = 255
229 self.WElements["muzzleflare3"].color.a = 255
230 end
231
232 if SERVER then
233 local firedtime = 0
234 local targ,tab = self:SelectTargets(5,dist)
235 for k,v in pairs(targ) do
236 if tab[v].dot < 0.8 then continue end
237 local dmg = DamageInfo()
238 dmg:SetAttacker( self.Owner || self )
239 dmg:SetInflictor( self or self.Owner )
240 dmg:SetDamage( FrameTime() * 1333 )
241 v:TakeDamageInfo( dmg )
242 end
243 local ed = EffectData()
244 ed:SetEntity(self)
245 ed:SetAttachment(1)
246 ed:SetStart( self.Owner:GetPos() + Vector(0,0,30) )
247 ed:SetOrigin( self.Owner:GetPos() + Vector(0,0,30) + self.Owner:GetForward() * math.random(dist - 50,dist + 50) + self.Owner:GetRight() * math.random(-80,80) + self.Owner:GetUp() * math.random(-20,20))
248 ed:SetFlags(0x0002)
249 util.Effect( "effect_arc_tracer", ed, true, true )
250 end
251
252 if ( self.Owner:IsNPC() ) then return end
253 self.Owner:ViewPunch( Angle( math.Rand(-0.2,-0.1) * self.Primary.Recoil, math.Rand(-0.1,0.1) * self.Primary.Recoil, 0 ) )
254 self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
255end
256
257
258function SWEP:SecondaryAttack()
259 if self.Owner:HasGodMode() == true then return end
260
261 if IsFirstTimePredicted() then
262
263 self.VElements["muzzleflare"].size.x = 20
264 self.VElements["muzzleflare"].size.y = 20
265 self.VElements["muzzleflare"].color.a = 255
266 self.VElements["muzzleflare2"].color.a = 255
267 self.VElements["muzzleflare3"].color.a = 255
268 self.WElements["muzzleflare"].size.x = 20
269 self.WElements["muzzleflare"].size.y = 20
270 self.WElements["muzzleflare"].color.a = 255
271 self.WElements["muzzleflare2"].color.a = 255
272 self.WElements["muzzleflare3"].color.a = 255
273 end
274
275 if SERVER then
276 local firedtime = 0
277 local targ,tab = self:SelectTargets(5,dist)
278 for k,v in pairs(targ) do
279 if tab[v].dot < 0.8 then continue end
280 local dmg = DamageInfo()
281 dmg:SetAttacker( self.Owner || self )
282 dmg:SetInflictor( self or self.Owner )
283 dmg:SetDamage( FrameTime() * 220 )
284 v:TakeDamageInfo( dmg )
285 end
286 local ed = EffectData()
287 ed:SetEntity(self)
288 ed:SetAttachment(1)
289 ed:SetStart( self.Owner:GetPos() + Vector(0,0,30) )
290 ed:SetOrigin( self.Owner:GetPos() + Vector(0,0,30) + self.Owner:GetForward() * math.random(dist - 50,dist + 50) + self.Owner:GetRight() * math.random(-80,80) + self.Owner:GetUp() * math.random(-20,20))
291 ed:SetFlags(0x0002)
292 util.Effect( "effect_arc_tracer", ed, true, true )
293 end
294 if ( self.Owner:IsNPC() ) then return end
295 self.Owner:ViewPunch( Angle( math.Rand(-0.2,-0.1) * self.Primary.Recoil, math.Rand(-0.1,0.1) * self.Primary.Recoil, 0 ) )
296 self:SetNextSecondaryFire(CurTime() + self.Secondary.Delay)
297end
298
299function SWEP:Initialize()
300 self.BaseClass.Initialize(self)
301
302 if CLIENT then
303
304 self:SendWeaponAnim(ACT_DO_NOT_DISTURB)
305 self.VElements = table.FullCopy( self.VElements )
306 self.WElements = table.FullCopy( self.WElements )
307 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
308 self:CreateModels(self.VElements)
309 self:CreateModels(self.WElements)
310
311 if IsValid(self.Owner) then
312 local vm = self.Owner:GetViewModel()
313 if IsValid(vm) then
314 self:ResetBonePositions(vm)
315 if (self.ShowViewModel == nil or self.ShowViewModel) then
316 vm:SetColor(Color(255,255,255,255))
317 else
318 vm:SetColor(Color(255,255,255,1))
319 vm:SetMaterial("Debug/hsv")
320 end
321 end
322 end
323 end
324end
325
326
327
328function SWEP:Holster()
329 self.BaseClass.Holster(self)
330 if CLIENT and IsValid(self.Owner) then
331 local vm = self.Owner:GetViewModel()
332 if IsValid(vm) then
333 self:ResetBonePositions(vm)
334 end
335 end
336 if CLIENT then return end
337 self.Owner:GodDisable()
338 print("[FL] God disabled because the weapon was switched...")
339 return true
340end
341
342
343
344function SWEP:OnRemove()
345 self.BaseClass.OnRemove(self)
346 if CLIENT and IsValid(self.Owner) then
347 local vm = self.Owner:GetViewModel()
348 if IsValid(vm) then
349 self:ResetBonePositions(vm)
350 end
351 end
352end
353
354
355
356if CLIENT then
357 SWEP.vRenderOrder = nil
358 function SWEP:ViewModelDrawn()
359 local vm = self.Owner:GetViewModel()
360 if !IsValid(vm) then return end
361 vm:GetAttachment(1)
362 if (!self.VElements) then return end
363 self:UpdateBonePositions(vm)
364 if (!self.vRenderOrder) then
365 self.vRenderOrder = {}
366 for k, v in pairs( self.VElements ) do
367
368 if (v.type == "Model") then
369
370 table.insert(self.vRenderOrder, 1, k)
371
372 elseif (v.type == "Sprite" or v.type == "Quad") then
373
374 table.insert(self.vRenderOrder, k)
375
376 end
377
378 end
379
380
381
382 end
383
384
385
386 for k, name in ipairs( self.vRenderOrder ) do
387
388
389
390 local v = self.VElements[name]
391
392 if (!v) then self.vRenderOrder = nil break end
393
394 if (v.hide) then continue end
395
396
397
398 local model = v.modelEnt
399
400 local sprite = v.spriteMaterial
401
402
403
404 if (!v.bone) then continue end
405
406
407
408 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
409
410
411
412 if (!pos) then continue end
413
414
415
416 if (v.type == "Model" and IsValid(model)) then
417
418
419
420 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
421
422 ang:RotateAroundAxis(ang:Up(), v.angle.y)
423
424 ang:RotateAroundAxis(ang:Right(), v.angle.p)
425
426 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
427
428
429
430 model:SetAngles(ang)
431
432 //model:SetModelScale(v.size)
433
434 local matrix = Matrix()
435
436 matrix:Scale(v.size)
437
438 model:EnableMatrix( "RenderMultiply", matrix )
439
440
441
442 if (v.material == "") then
443
444 model:SetMaterial("")
445
446 elseif (model:GetMaterial() != v.material) then
447
448 model:SetMaterial( v.material )
449
450 end
451
452
453
454 if (v.skin and v.skin != model:GetSkin()) then
455
456 model:SetSkin(v.skin)
457
458 end
459
460
461
462 if (v.bodygroup) then
463
464 for k, v in pairs( v.bodygroup ) do
465
466 if (model:GetBodygroup(k) != v) then
467
468 model:SetBodygroup(k, v)
469
470 end
471
472 end
473
474 end
475
476
477
478 if (v.surpresslightning) then
479
480 render.SuppressEngineLighting(true)
481
482 end
483
484
485
486 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
487
488 render.SetBlend(v.color.a/255)
489
490 model:DrawModel()
491
492 render.SetBlend(1)
493
494 render.SetColorModulation(1, 1, 1)
495
496
497
498 if (v.surpresslightning) then
499
500 render.SuppressEngineLighting(false)
501
502 end
503
504
505
506 elseif (v.type == "Sprite" and sprite) then
507
508 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
509
510 render.SetMaterial(sprite)
511
512 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
513
514 elseif (v.type == "Quad" and v.draw_func) then
515
516
517
518 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
519
520 ang:RotateAroundAxis(ang:Up(), v.angle.y)
521
522 ang:RotateAroundAxis(ang:Right(), v.angle.p)
523
524 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
525
526
527
528 cam.Start3D2D(drawpos, ang, v.size)
529
530 v.draw_func( self )
531
532 cam.End3D2D()
533
534
535
536 end
537
538
539
540 end
541
542
543
544 end
545
546
547
548 SWEP.wRenderOrder = nil
549
550 function SWEP:DrawWorldModel()
551
552 if self.ShowWorldModel == nil or self.ShowWorldModel == true then
553
554 self:DrawModel()
555
556 end
557
558
559
560 if (!self.WElements) then return end
561
562
563
564 if (!self.wRenderOrder) then
565
566
567
568 self.wRenderOrder = {}
569
570
571
572 for k, v in pairs( self.WElements ) do
573
574 if (v.type == "Model") then
575
576 table.insert(self.wRenderOrder, 1, k)
577
578 elseif (v.type == "Sprite" or v.type == "Quad") then
579
580 table.insert(self.wRenderOrder, k)
581
582 end
583
584 end
585
586
587
588 end
589
590
591
592 if (IsValid(self.Owner)) then
593
594 bone_ent = self.Owner
595
596 else
597
598 // when the weapon is dropped
599
600 bone_ent = self
601
602 end
603
604
605
606 for k, name in pairs( self.wRenderOrder ) do
607
608
609
610 local v = self.WElements[name]
611
612 if (!v) then self.wRenderOrder = nil break end
613
614 if (v.hide) then continue end
615
616
617
618 local pos, ang
619
620
621
622 if (v.bone) then
623
624 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
625
626 else
627
628 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
629
630 end
631
632
633
634 if (!pos) then continue end
635
636
637
638 local model = v.modelEnt
639
640 local sprite = v.spriteMaterial
641
642
643
644 if (v.type == "Model" and IsValid(model)) then
645
646
647
648 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
649
650 ang:RotateAroundAxis(ang:Up(), v.angle.y)
651
652 ang:RotateAroundAxis(ang:Right(), v.angle.p)
653
654 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
655
656
657
658 model:SetAngles(ang)
659
660 //model:SetModelScale(v.size)
661
662 local matrix = Matrix()
663
664 matrix:Scale(v.size)
665
666 model:EnableMatrix( "RenderMultiply", matrix )
667
668
669
670 if (v.material == "") then
671
672 model:SetMaterial("")
673
674 elseif (model:GetMaterial() != v.material) then
675
676 model:SetMaterial( v.material )
677
678 end
679
680
681
682 if (v.skin and v.skin != model:GetSkin()) then
683
684 model:SetSkin(v.skin)
685
686 end
687
688
689
690 if (v.bodygroup) then
691
692 for k, v in pairs( v.bodygroup ) do
693
694 if (model:GetBodygroup(k) != v) then
695
696 model:SetBodygroup(k, v)
697
698 end
699
700 end
701
702 end
703
704
705
706 if (v.surpresslightning) then
707
708 render.SuppressEngineLighting(true)
709
710 end
711
712
713
714 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
715
716 render.SetBlend(v.color.a/255)
717
718 model:DrawModel()
719
720 render.SetBlend(1)
721
722 render.SetColorModulation(1, 1, 1)
723
724
725
726 if (v.surpresslightning) then
727
728 render.SuppressEngineLighting(false)
729
730 end
731
732
733
734 elseif (v.type == "Sprite" and sprite) then
735
736
737
738 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
739
740 render.SetMaterial(sprite)
741
742 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
743
744
745
746 elseif (v.type == "Quad" and v.draw_func) then
747
748
749
750 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
751
752 ang:RotateAroundAxis(ang:Up(), v.angle.y)
753
754 ang:RotateAroundAxis(ang:Right(), v.angle.p)
755
756 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
757
758
759
760 cam.Start3D2D(drawpos, ang, v.size)
761
762 v.draw_func( self )
763
764 cam.End3D2D()
765
766
767
768 end
769
770
771
772 end
773
774
775
776 end
777
778
779
780 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
781
782
783
784 local bone, pos, ang
785
786 if (tab.rel and tab.rel != "") then
787
788
789
790 local v = basetab[tab.rel]
791
792
793
794 if (!v) then return end
795
796
797
798 // Technically, if there exists an element with the same name as a bone
799
800 // you can get in an infinite loop. Let's just hope nobody's that stupid.
801
802 pos, ang = self:GetBoneOrientation( basetab, v, ent )
803
804
805
806 if (!pos) then return end
807
808
809
810 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
811
812 v.angle = v.angle or Angle(0,0,0)
813
814 ang:RotateAroundAxis(ang:Up(), v.angle.y)
815
816 ang:RotateAroundAxis(ang:Right(), v.angle.p)
817
818 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
819
820
821
822 else
823
824
825
826 bone = ent:LookupBone(bone_override or tab.bone)
827
828
829
830 if (!bone) then return end
831
832
833
834 pos, ang = Vector(0,0,0), Angle(0,0,0)
835
836 local m = ent:GetBoneMatrix(bone)
837
838 if (m) then
839
840 pos, ang = m:GetTranslation(), m:GetAngles()
841
842 end
843
844
845
846 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
847
848 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
849
850 ang.r = -ang.r // Fixes mirrored models
851
852 end
853
854
855
856 end
857
858
859
860 return pos, ang
861
862 end
863
864
865
866 function SWEP:CreateModels( tab )
867
868
869
870 if (!tab) then return end
871
872
873
874 // Create the clientside models here because Garry says we can't do it in the render hook
875
876 for k, v in pairs( tab ) do
877
878 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
879
880 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
881
882
883
884 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
885
886 if (IsValid(v.modelEnt)) then
887
888 v.modelEnt:SetPos(self:GetPos())
889
890 v.modelEnt:SetAngles(self:GetAngles())
891
892 v.modelEnt:SetParent(self)
893
894 v.modelEnt:SetNoDraw(true)
895
896 v.createdModel = v.model
897
898 else
899
900 v.modelEnt = nil
901
902 end
903
904
905
906 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
907
908 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
909
910
911
912 local name = v.sprite.."-"
913
914 local params = { ["$basetexture"] = v.sprite }
915
916 // make sure we create a unique name based on the selected options
917
918 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
919
920 for i, j in pairs( tocheck ) do
921
922 if (v[j]) then
923
924 params["$"..j] = 1
925
926 name = name.."1"
927
928 else
929
930 name = name.."0"
931
932 end
933
934 end
935
936
937
938 v.createdSprite = v.sprite
939
940 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
941
942
943
944 end
945
946 end
947
948
949
950 end
951
952
953
954 local allbones
955
956 local hasGarryFixedBoneScalingYet = false
957
958
959
960 function SWEP:UpdateBonePositions(vm)
961
962
963
964 if self.ViewModelBoneMods then
965
966
967
968 if (!vm:GetBoneCount()) then return end
969
970
971
972 // !! WORKAROUND !! //
973
974 // We need to check all model names :/
975
976 local loopthrough = self.ViewModelBoneMods
977
978 if (!hasGarryFixedBoneScalingYet) then
979
980 allbones = {}
981
982 for i=0, vm:GetBoneCount() do
983
984 local bonename = vm:GetBoneName(i)
985
986 if (self.ViewModelBoneMods[bonename]) then
987
988 allbones[bonename] = self.ViewModelBoneMods[bonename]
989
990 else
991
992 allbones[bonename] = {
993
994 scale = Vector(1,1,1),
995
996 pos = Vector(0,0,0),
997
998 angle = Angle(0,0,0)
999
1000 }
1001
1002 end
1003
1004 end
1005
1006
1007
1008 loopthrough = allbones
1009
1010 end
1011
1012 // !! ----------- !! //
1013
1014
1015
1016 for k, v in pairs( loopthrough ) do
1017
1018 local bone = vm:LookupBone(k)
1019
1020 if (!bone) then continue end
1021
1022
1023
1024 // !! WORKAROUND !! //
1025
1026 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
1027
1028 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
1029
1030 local ms = Vector(1,1,1)
1031
1032 if (!hasGarryFixedBoneScalingYet) then
1033
1034 local cur = vm:GetBoneParent(bone)
1035
1036 while(cur >= 0) do
1037
1038 local pscale = loopthrough[vm:GetBoneName(cur)].scale
1039
1040 ms = ms * pscale
1041
1042 cur = vm:GetBoneParent(cur)
1043
1044 end
1045
1046 end
1047
1048
1049
1050 s = s * ms
1051
1052 // !! ----------- !! //
1053
1054
1055
1056 if vm:GetManipulateBoneScale(bone) != s then
1057
1058 vm:ManipulateBoneScale( bone, s )
1059
1060 end
1061
1062 if vm:GetManipulateBoneAngles(bone) != v.angle then
1063
1064 vm:ManipulateBoneAngles( bone, v.angle )
1065
1066 end
1067
1068 if vm:GetManipulateBonePosition(bone) != p then
1069
1070 vm:ManipulateBonePosition( bone, p )
1071
1072 end
1073
1074 end
1075
1076 else
1077
1078 self:ResetBonePositions(vm)
1079
1080 end
1081
1082
1083
1084 end
1085
1086
1087
1088 function SWEP:ResetBonePositions(vm)
1089
1090
1091
1092 if (!vm:GetBoneCount()) then return end
1093
1094 for i=0, vm:GetBoneCount() do
1095
1096 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
1097
1098 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
1099
1100 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
1101
1102 end
1103
1104
1105
1106 end
1107
1108
1109
1110 /**************************
1111
1112 Global utility code
1113
1114 **************************/
1115
1116
1117
1118 // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
1119
1120 // Does not copy entities of course, only copies their reference.
1121
1122 // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
1123
1124 function table.FullCopy( tab )
1125
1126
1127
1128 if (!tab) then return nil end
1129
1130
1131
1132 local res = {}
1133
1134 for k, v in pairs( tab ) do
1135
1136 if (type(v) == "table") then
1137
1138 res[k] = table.FullCopy(v) // recursion ho!
1139
1140 elseif (type(v) == "Vector") then
1141
1142 res[k] = Vector(v.x, v.y, v.z)
1143
1144 elseif (type(v) == "Angle") then
1145
1146 res[k] = Angle(v.p, v.y, v.r)
1147
1148 else
1149
1150 res[k] = v
1151
1152 end
1153
1154 end
1155
1156
1157
1158 return res
1159
1160
1161
1162 end
1163
1164
1165
1166end