· 6 years ago · Aug 10, 2019, 12:20 PM
1SWEP.PrintName = "Hook"
2SWEP.Slot = 3
3SWEP.SlotPos = 1
4SWEP.DrawAmmo = true
5SWEP.DrawCrosshair = true
6
7SWEP.Weight = 5
8SWEP.AutoSwitchTo = true
9SWEP.AutoSwitchFrom = true
10
11SWEP.Author = "Seris"
12
13SWEP.Spawnable = true
14SWEP.AdminSpawnable = true
15
16SWEP.HoldType = "normal"
17
18SWEP.ViewModelFOV = 75
19SWEP.UseHands = true
20
21SWEP.ViewModel = "models/weapons/v_grenade.mdl"
22SWEP.WorldModel = "models/weapons/w_grenade.mdl"
23
24SWEP.ShowViewModel = true
25SWEP.ShowWorldModel = false
26
27SWEP.Primary.ClipSize = -1
28SWEP.Primary.DefaultClip = -1
29SWEP.Primary.Automatic = true
30SWEP.Primary.Ammo = "none"
31
32SWEP.Secondary.ClipSize = 1
33SWEP.Secondary.DefaultClip = 1
34SWEP.Secondary.Automatic = true
35SWEP.Secondary.Ammo = "hook"
36
37SWEP.RopeLength = 300
38SWEP.MaxDistance = 100
39
40SWEP.Hooks = {}
41
42local swingSound = Sound("WeaponFrag.Throw")
43local hitSound = Sound("Weapon_Crowbar.Melee_Hit")
44
45SWEP.ViewModelBoneMods = {
46 ["ValveBiped.Grenade_body"] = { scale = Vector(0.01, 0.01, 0.01), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
47 ["ValveBiped.Bip01"] = { scale = Vector(1, 1, 1), pos = Vector(0.555, 0.185, -0.925), angle = Angle(0, 27.777, -7.778) }
48}
49
50SWEP.VElements = {
51 ["Hook"] = { type = "Model", model = "models/props_junk/meathook001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(3.635, 0.518, -8.832), angle = Angle(5.843, 45.583, 19.87), size = Vector(0.5, 0.5, 0.5), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} },
52 ["Rope"] = { type = "Beam", bone = "ValveBiped.Grenade_body", pos = Vector(-0.5, 0, 0), endpos = Vector(-0.5, -8, 25), size = Vector(0.5, 0.5, 0.5), color = Color(255, 255, 255, 255), material = Material("cable/rope"), width = 2, hide = false }
53}
54
55SWEP.WElements = {
56 ["Hook"] = { type = "Model", model = "models/props_junk/meathook001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(5, 1.5, -9), angle = Angle(10, 45, 0), size = Vector(0.5, 0.5, 0.5), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
57}
58
59function SWEP:SetupDataTables()
60 self:NetworkVar("Entity", 0, "Rope")
61
62 self:SetRope(NULL)
63end
64
65function SWEP:Initialize()
66
67 self:SetHoldType("melee")
68
69 self.VElements = table.FullCopy( self.VElements )
70 self.WElements = table.FullCopy( self.WElements )
71 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
72
73 if CLIENT then
74
75 self:CreateModels(self.VElements) // create viewmodels
76 self:CreateModels(self.WElements) // create worldmodels
77
78 // init view model bone build function
79 if IsValid(self.Owner) then
80 local vm = self.Owner:GetViewModel()
81 if IsValid(vm) then
82 self:ResetBonePositions(vm)
83
84 // Init viewmodel visibility
85 if (self.ShowViewModel == nil or self.ShowViewModel) then
86 vm:SetColor(Color(255,255,255,255))
87 else
88 // we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
89 vm:SetColor(Color(255,255,255,1))
90 // ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
91 // 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
92 vm:SetMaterial("Debug/hsv")
93 end
94 end
95 end
96
97 end
98
99end
100
101function SWEP:Deploy()
102 if !self:CanThrowHook() then
103 local vm = self.Owner:GetViewModel()
104 vm:SendViewModelMatchingSequence(vm:LookupSequence("drawbackhigh"))
105 end
106end
107
108function SWEP:CanThrowHook()
109 return self.Owner:GetAmmoCount("hook") > 0 and !IsValid(self:GetRope())
110end
111
112function SWEP:UpdateRope(ent)
113 if CLIENT then return end
114 if IsValid(ent) then
115 ent:PlayerHold(self.Owner)
116 self:SetRope(ent)
117 elseif IsValid(self:GetRope()) then
118 self:GetRope():SetAttachmentPos(nil)
119 self:SetRope(NULL)
120 end
121end
122
123function SWEP:Think()
124
125 local use = false
126 if self.Owner:KeyPressed(IN_USE) then
127 use = true
128 end
129
130 if self:CanThrowHook() then
131 self.VElements["Hook"].size = Vector(0.5, 0.5, 0.5)
132 self.WElements["Hook"].size = Vector(0.5, 0.5, 0.5)
133 self.VElements["Rope"].hide = false
134 else
135 self.VElements["Hook"].size = Vector(0.001, 0.001, 0.001)
136 self.WElements["Hook"].size = Vector(0.001, 0.001, 0.001)
137 self.VElements["Rope"].hide = true
138 end
139
140 if self.Owner:KeyPressed(IN_RELOAD) or use then
141
142 if IsValid(self:GetRope()) then
143 if use then
144 self:UpdateRope(NULL)
145 else
146 self:Retrieve(self:GetRope())
147 end
148 return
149 end
150
151 local trace = util.TraceLine({
152 start = self.Owner:GetShootPos(),
153 endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * 75,
154 filter = function(ent) return ent:GetClass() == "prop_physics" or ent:GetClass():StartWith("boat") end
155 })
156
157 local e = ents.FindInSphere(trace.HitPos, 25)
158 for k, v in pairs(e) do
159 if v:GetClass():StartWith("boat_ropeend") then
160 if use then self:UpdateRope(v) else self:Retrieve(v) end
161 return
162 elseif v:GetModel() == "models/props_junk/meathook001a.mdl" then
163 self:Retrieve(v)
164 end
165 end
166 end
167
168 if IsValid(self:GetRope()) then
169 self:UpdateRope(self:GetRope())
170 end
171end
172
173function SWEP:ShouldAttach(ent)
174 return IsValid(ent) and ent:GetClass() == "prop_physics"
175end
176
177function SWEP:ThrowHook()
178 self:TakeSecondaryAmmo(1)
179
180 self.Owner:SetAnimation(PLAYER_ATTACK1)
181
182 local vm = self.Owner:GetViewModel()
183 vm:SendViewModelMatchingSequence(vm:LookupSequence("drawbackhigh"))
184
185 timer.Simple(0.4, function()
186 if IsValid(self) then
187 if self:CanThrowHook() then
188 local vm = self.Owner:GetViewModel()
189 vm:SendViewModelMatchingSequence(vm:LookupSequence("draw"))
190 else
191 self:SetHoldType(self.HoldType)
192 end
193 end
194 end)
195
196 if SERVER then
197 local pos, ang
198
199 local trace = self.Owner:GetEyeTrace()
200 local target = trace.Entity
201 local normal = trace.HitNormal
202 local isInRange = (target and target:GetPos():Distance(self.Owner:GetPos()) <= 80) or false
203 if self:ShouldAttach(target) and isInRange then
204 pos = trace.HitPos + normal * 5
205
206 normal = normal:Angle()
207 ang = normal
208 ang:RotateAroundAxis(normal:Up(), -90)
209 ang:RotateAroundAxis(normal:Forward(), 45)
210 ang:RotateAroundAxis(normal:Right(), 180)
211 else
212 pos, ang = self:GetBoneOrientation(self.WElements, self.WElements["Hook"], self.Owner)
213
214 local a = ang
215 ang:RotateAroundAxis(a:Right(), 45)
216 end
217
218 local hook = ents.Create("prop_physics")
219 hook:SetModel("models/props_junk/meathook001a.mdl")
220 hook:SetModelScale(0.5)
221 hook:SetSolid(SOLID_OBB)
222 hook:SetPos(pos)
223 hook:SetAngles(ang)
224 hook:SetCollisionGroup(COLLISION_GROUP_WEAPON)
225 hook:Spawn()
226 hook:Activate()
227 hook:SetOwner(self.Owner)
228
229 if self:ShouldAttach(target) and isInRange then
230 constraint.Weld(hook, target, 0, 0, 0, true, false)
231
232 local phys = target:GetPhysicsObject()
233 if IsValid(phys) then
234 phys:ApplyForceOffset(-trace.HitNormal * 800, pos)
235 end
236 else
237
238 hook.callback = hook:AddCallback("PhysicsCollide", function(ent, data)
239 timer.Simple(0, function()
240 if self:ShouldAttach(data.HitEntity) then
241 constraint.Weld(ent, data.HitEntity, 0, 0, 1000, true, false)
242 ent.RopeEnd:SetLength(ent:GetPos():Distance(ent.RopeEnd:GetPos()))
243 ent:RemoveCallback("PhysicsCollide", ent.callback)
244 end
245 end)
246 end)
247
248 local aim = self.Owner:GetEyeTrace().HitPos
249 local dir = (aim - pos):GetNormalized()
250 local forceMul = 10^2
251
252 local phys = hook:GetPhysicsObject()
253 if IsValid(phys) then
254 phys:SetMass(15)
255 phys:SetVelocityInstantaneous(dir * 3 * forceMul + dir:Cross(vector_up):Cross(dir) * 1.6 * forceMul)
256 //hook:SetLocalAngularVelocity(Angle(0, 0, 0))
257 //phys:AddAngleVelocity(Vector(0, 0, -10))
258 end
259 end
260
261 local ropeEnd = ents.Create("boat_ropeend")
262 ropeEnd:SetPos(self.Owner:GetPos())
263 ropeEnd:SetCollisionGroup(COLLISION_GROUP_WEAPON)
264 ropeEnd:Spawn()
265 ropeEnd:Activate()
266 ropeEnd:SetOwner(self.Owner)
267
268 constraint.NoCollide(hook, ropeEnd, 0, 0)
269
270 ropeEnd:DeleteOnRemove(hook)
271 hook:DeleteOnRemove(ropeEnd)
272
273 hook.RopeEnd = ropeEnd
274
275 if self.Owner:GetNW2Var("InShip") then
276 local ship = self.Owner:GetVehicle():GetParent()
277
278 if IsValid(ship) and ship.AllowAttachment then
279 ropeEnd:SetPos(ship:LocalToWorld(ship:GetAttachmentPos()))
280 constraint.Weld(ship, ropeEnd, 0, 0, 1000, true, false)
281 end
282 end
283
284 ropeEnd:Attach(hook, Vector(0, 1.5, 10), self.RopeLength)
285
286 table.insert(self.Hooks, hook)
287
288 timer.Simple(0, function()
289 self:UpdateRope(ropeEnd)
290 end)
291 end
292end
293
294function SWEP:Retrieve(v)
295
296 self:SetHoldType("melee")
297
298 local vm = self.Owner:GetViewModel()
299 vm:SendViewModelMatchingSequence(vm:LookupSequence("idle01"))
300
301 if SERVER then
302 self.Owner:GiveAmmo(1, "hook", true)
303 v:Remove()
304 end
305end
306
307function SWEP:Reload()
308
309end
310
311function SWEP:PrimaryAttack()
312 if !IsFirstTimePredicted() then return end
313
314 if self:CanThrowHook() then
315 self:Attack()
316 self:SetNextPrimaryFire(CurTime() + 0.6)
317 else
318 self:UseRope(true)
319 end
320end
321
322function SWEP:SecondaryAttack()
323 if !IsFirstTimePredicted() then return end
324
325 if self:CanThrowHook() then
326 self:ThrowHook()
327 self:SetNextSecondaryFire(CurTime() + 1.6)
328 else
329 self:UseRope(false)
330 end
331end
332
333function SWEP:UseRope(extend)
334 if !IsValid(self:GetRope()) then return end
335
336 local rope = self:GetRope()
337 rope.controller:SetDirection(extend and 1 or -1)
338 timer.Simple(0, function()
339 if IsValid(rope.controller) then rope.controller:SetDirection(0) end
340 end)
341end
342
343function SWEP:Attack()
344 local vm = self.Owner:GetViewModel()
345 vm:SendViewModelMatchingSequence(vm:LookupSequence("drawbackhigh"))
346
347 timer.Simple(0.35, function()
348 vm:SendViewModelMatchingSequence(vm:LookupSequence("throw"))
349 end)
350
351 timer.Simple(0.5, function()
352 vm:SendViewModelMatchingSequence(vm:LookupSequence("idle01"))
353 end)
354
355 self.Owner:SetAnimation(PLAYER_ATTACK1)
356
357 self:EmitSound(swingSound)
358
359 timer.Simple(0.35, function()
360
361 self.Owner:LagCompensation(true)
362
363 local tr = util.TraceLine( {
364 start = self.Owner:GetShootPos(),
365 endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * 48,
366 filter = self.Owner,
367 mask = MASK_SHOT_HULL
368 } )
369
370 util.Decal("Impact.Wood", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal)
371
372 if !IsValid(tr.Entity) then
373 tr = util.TraceHull( {
374 start = self.Owner:GetShootPos(),
375 endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * 48,
376 filter = self.Owner,
377 mins = Vector(-10, -10, -8),
378 maxs = Vector(10, 10, 8),
379 mask = MASK_SHOT_HULL
380 } )
381 end
382
383 if tr.Hit then
384 self:EmitSound(hitSound)
385 end
386
387 if SERVER and IsValid(tr.Entity) and (tr.Entity:IsNPC() or tr.Entity:IsPlayer() or tr.Entity:Health() > 0) then
388 local dmginfo = DamageInfo()
389
390 local attacker = self.Owner
391 if !IsValid(attacker) then attacker = self end
392 dmginfo:SetAttacker(attacker)
393
394 dmginfo:SetInflictor(self)
395 dmginfo:SetDamage(math.random(12, 17))
396 dmginfo:SetDamageForce(self.Owner:GetRight() * 4912 + self.Owner:GetForward() * 9998)
397
398 tr.Entity:TakeDamageInfo(dmginfo)
399 end
400
401 if SERVER and IsValid(tr.Entity) then
402 local phys = tr.Entity:GetPhysicsObject()
403 if IsValid(phys) then
404 phys:ApplyForceOffset(self.Owner:GetAimVector() * 80 * phys:GetMass(), tr.HitPos)
405 end
406 end
407
408 self.Owner:LagCompensation(false)
409 end)
410end
411
412function SWEP:Holster()
413
414 self:UpdateRope(NULL)
415
416 if CLIENT and IsValid(self.Owner) then
417 local vm = self.Owner:GetViewModel()
418 if IsValid(vm) then
419 self:ResetBonePositions(vm)
420 end
421 end
422
423 return true
424end
425
426function SWEP:OnRemove()
427
428 if SERVER then
429 self:RemoveHooks()
430 end
431
432 self:Holster()
433end
434
435function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
436
437 local bone, pos, ang
438 if (tab.rel and tab.rel != "") then
439
440 local v = basetab[tab.rel]
441
442 if (!v) then return end
443
444 // Technically, if there exists an element with the same name as a bone
445 // you can get in an infinite loop. Let's just hope nobody's that stupid.
446 pos, ang = self:GetBoneOrientation( basetab, v, ent )
447
448 if (!pos) then return end
449
450 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
451 ang:RotateAroundAxis(ang:Up(), v.angle.y)
452 ang:RotateAroundAxis(ang:Right(), v.angle.p)
453 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
454
455 else
456
457 bone = ent:LookupBone(bone_override or tab.bone)
458
459 if (!bone) then return end
460
461 pos, ang = Vector(0,0,0), Angle(0,0,0)
462 local m = ent:GetBoneMatrix(bone)
463 if (m) then
464 pos, ang = m:GetTranslation(), m:GetAngles()
465 end
466
467 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
468 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
469 ang.r = -ang.r // Fixes mirrored models
470 end
471
472 end
473
474 return pos, ang
475end
476
477/**************************
478 Global utility code
479**************************/
480
481// Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
482// Does not copy entities of course, only copies their reference.
483// WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
484function table.FullCopy( tab )
485
486 if (!tab) then return nil end
487
488 local res = {}
489 for k, v in pairs( tab ) do
490 if (type(v) == "table") then
491 res[k] = table.FullCopy(v) // recursion ho!
492 elseif (type(v) == "Vector") then
493 res[k] = Vector(v.x, v.y, v.z)
494 elseif (type(v) == "Angle") then
495 res[k] = Angle(v.p, v.y, v.r)
496 else
497 res[k] = v
498 end
499 end
500
501 return res
502
503end
504
505if SERVER then
506 function SWEP:RemoveHooks()
507 for k, v in pairs(self.Hooks) do
508 if IsValid(v) then
509 v:Remove()
510 end
511 end
512 end
513end
514
515if CLIENT then
516
517 SWEP.vRenderOrder = nil
518 function SWEP:ViewModelDrawn()
519
520 local vm = self.Owner:GetViewModel()
521 if !IsValid(vm) then return end
522
523 if (!self.VElements) then return end
524
525 self:UpdateBonePositions(vm)
526
527 if (!self.vRenderOrder) then
528
529 // we build a render order because sprites need to be drawn after models
530 self.vRenderOrder = {}
531
532 for k, v in pairs( self.VElements ) do
533 if (v.type == "Model") then
534 table.insert(self.vRenderOrder, 1, k)
535 elseif (v.type == "Sprite" or v.type == "Quad" or v.type == "Beam") then
536 table.insert(self.vRenderOrder, k)
537 end
538 end
539
540 end
541
542 for k, name in ipairs( self.vRenderOrder ) do
543
544 local v = self.VElements[name]
545 if (!v) then self.vRenderOrder = nil break end
546 if (v.hide) then continue end
547
548 local model = v.modelEnt
549 local sprite = v.spriteMaterial
550
551 if (!v.bone) then continue end
552
553 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
554
555 if (!pos) then continue end
556
557 if (v.type == "Model" and IsValid(model)) then
558
559 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
560 ang:RotateAroundAxis(ang:Up(), v.angle.y)
561 ang:RotateAroundAxis(ang:Right(), v.angle.p)
562 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
563
564 model:SetAngles(ang)
565 //model:SetModelScale(v.size)
566 local matrix = Matrix()
567 matrix:Scale(v.size)
568 model:EnableMatrix( "RenderMultiply", matrix )
569
570 if (v.material == "") then
571 model:SetMaterial("")
572 elseif (model:GetMaterial() != v.material) then
573 model:SetMaterial( v.material )
574 end
575
576 if (v.skin and v.skin != model:GetSkin()) then
577 model:SetSkin(v.skin)
578 end
579
580 if (v.bodygroup) then
581 for k, v in pairs( v.bodygroup ) do
582 if (model:GetBodygroup(k) != v) then
583 model:SetBodygroup(k, v)
584 end
585 end
586 end
587
588 if (v.surpresslightning) then
589 render.SuppressEngineLighting(true)
590 end
591
592 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
593 render.SetBlend(v.color.a/255)
594 model:DrawModel()
595 render.SetBlend(1)
596 render.SetColorModulation(1, 1, 1)
597
598 if (v.surpresslightning) then
599 render.SuppressEngineLighting(false)
600 end
601
602 elseif (v.type == "Sprite" and sprite) then
603
604 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
605 render.SetMaterial(sprite)
606 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
607
608 elseif (v.type == "Quad" and v.draw_func) then
609
610 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
611 ang:RotateAroundAxis(ang:Up(), v.angle.y)
612 ang:RotateAroundAxis(ang:Right(), v.angle.p)
613 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
614
615 cam.Start3D2D(drawpos, ang, v.size)
616 v.draw_func( self )
617 cam.End3D2D()
618
619 elseif v.type == "Beam" and !v.hide then
620
621 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
622 local endpos = pos + ang:Forward() * v.endpos.x + ang:Right() * v.endpos.y + ang:Up() * v.endpos.z
623 local length = endpos:Distance(pos)
624
625 render.SetMaterial(v.material)
626 render.DrawBeam(drawpos, endpos, v.width, 0, length/10, v.color)
627
628 end
629
630 end
631
632 end
633
634 SWEP.wRenderOrder = nil
635 function SWEP:DrawWorldModel()
636
637 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
638 self:DrawModel()
639 end
640
641 if (!self.WElements) then return end
642
643 if (!self.wRenderOrder) then
644
645 self.wRenderOrder = {}
646
647 for k, v in pairs( self.WElements ) do
648 if (v.type == "Model") then
649 table.insert(self.wRenderOrder, 1, k)
650 elseif (v.type == "Sprite" or v.type == "Quad") then
651 table.insert(self.wRenderOrder, k)
652 end
653 end
654
655 end
656
657 if (IsValid(self.Owner)) then
658 bone_ent = self.Owner
659 else
660 // when the weapon is dropped
661 bone_ent = self
662 end
663
664 for k, name in pairs( self.wRenderOrder ) do
665
666 local v = self.WElements[name]
667 if (!v) then self.wRenderOrder = nil break end
668 if (v.hide) then continue end
669
670 local pos, ang
671
672 if (v.bone) then
673 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
674 else
675 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
676 end
677
678 if (!pos) then continue end
679
680 local model = v.modelEnt
681 local sprite = v.spriteMaterial
682
683 if (v.type == "Model" and IsValid(model)) then
684
685 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
686 ang:RotateAroundAxis(ang:Up(), v.angle.y)
687 ang:RotateAroundAxis(ang:Right(), v.angle.p)
688 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
689
690 model:SetAngles(ang)
691 //model:SetModelScale(v.size)
692 local matrix = Matrix()
693 matrix:Scale(v.size)
694 model:EnableMatrix( "RenderMultiply", matrix )
695
696 if (v.material == "") then
697 model:SetMaterial("")
698 elseif (model:GetMaterial() != v.material) then
699 model:SetMaterial( v.material )
700 end
701
702 if (v.skin and v.skin != model:GetSkin()) then
703 model:SetSkin(v.skin)
704 end
705
706 if (v.bodygroup) then
707 for k, v in pairs( v.bodygroup ) do
708 if (model:GetBodygroup(k) != v) then
709 model:SetBodygroup(k, v)
710 end
711 end
712 end
713
714 if (v.surpresslightning) then
715 render.SuppressEngineLighting(true)
716 end
717
718 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
719 render.SetBlend(v.color.a/255)
720 model:DrawModel()
721 render.SetBlend(1)
722 render.SetColorModulation(1, 1, 1)
723
724 if (v.surpresslightning) then
725 render.SuppressEngineLighting(false)
726 end
727
728 elseif (v.type == "Sprite" and sprite) then
729
730 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
731 render.SetMaterial(sprite)
732 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
733
734 elseif (v.type == "Quad" and v.draw_func) then
735
736 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
737 ang:RotateAroundAxis(ang:Up(), v.angle.y)
738 ang:RotateAroundAxis(ang:Right(), v.angle.p)
739 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
740
741 cam.Start3D2D(drawpos, ang, v.size)
742 v.draw_func( self )
743 cam.End3D2D()
744
745 end
746
747 end
748
749 end
750
751 function SWEP:CreateModels( tab )
752
753 if (!tab) then return end
754
755 // Create the clientside models here because Garry says we can't do it in the render hook
756 for k, v in pairs( tab ) do
757 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
758 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
759
760 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
761 if (IsValid(v.modelEnt)) then
762 v.modelEnt:SetPos(self:GetPos())
763 v.modelEnt:SetAngles(self:GetAngles())
764 v.modelEnt:SetParent(self)
765 v.modelEnt:SetNoDraw(true)
766 v.createdModel = v.model
767 else
768 v.modelEnt = nil
769 end
770
771 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
772 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
773
774 local name = v.sprite.."-"
775 local params = { ["$basetexture"] = v.sprite }
776 // make sure we create a unique name based on the selected options
777 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
778 for i, j in pairs( tocheck ) do
779 if (v[j]) then
780 params["$"..j] = 1
781 name = name.."1"
782 else
783 name = name.."0"
784 end
785 end
786
787 v.createdSprite = v.sprite
788 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
789
790 end
791 end
792
793 end
794
795 local allbones
796 local hasGarryFixedBoneScalingYet = false
797
798 function SWEP:UpdateBonePositions(vm)
799
800 if self.ViewModelBoneMods then
801
802 if (!vm:GetBoneCount()) then return end
803
804 // !! WORKAROUND !! //
805 // We need to check all model names :/
806 local loopthrough = self.ViewModelBoneMods
807 if (!hasGarryFixedBoneScalingYet) then
808 allbones = {}
809 for i=0, vm:GetBoneCount() do
810 local bonename = vm:GetBoneName(i)
811 if (self.ViewModelBoneMods[bonename]) then
812 allbones[bonename] = self.ViewModelBoneMods[bonename]
813 else
814 allbones[bonename] = {
815 scale = Vector(1,1,1),
816 pos = Vector(0,0,0),
817 angle = Angle(0,0,0)
818 }
819 end
820 end
821
822 loopthrough = allbones
823 end
824 // !! ----------- !! //
825
826 for k, v in pairs( loopthrough ) do
827 local bone = vm:LookupBone(k)
828 if (!bone) then continue end
829
830 // !! WORKAROUND !! //
831 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
832 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
833 local ms = Vector(1,1,1)
834 if (!hasGarryFixedBoneScalingYet) then
835 local cur = vm:GetBoneParent(bone)
836 while(cur >= 0) do
837 local pscale = loopthrough[vm:GetBoneName(cur)].scale
838 ms = ms * pscale
839 cur = vm:GetBoneParent(cur)
840 end
841 end
842
843 s = s * ms
844 // !! ----------- !! //
845
846 if vm:GetManipulateBoneScale(bone) != s then
847 vm:ManipulateBoneScale( bone, s )
848 end
849 if vm:GetManipulateBoneAngles(bone) != v.angle then
850 vm:ManipulateBoneAngles( bone, v.angle )
851 end
852 if vm:GetManipulateBonePosition(bone) != p then
853 vm:ManipulateBonePosition( bone, p )
854 end
855 end
856 else
857 self:ResetBonePositions(vm)
858 end
859
860 end
861
862 function SWEP:ResetBonePositions(vm)
863
864 if (!vm:GetBoneCount()) then return end
865 for i=0, vm:GetBoneCount() do
866 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
867 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
868 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
869 end
870
871 end
872
873end