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