· 9 years ago · Jan 08, 2017, 06:46 PM
1
2/*
3Stungun SWEP Created by Donkie (http://steamcommunity.com/id/Donkie/)
4For personal/server usage only, do not resell or distribute!
5*/
6
7include("shared.lua")
8
9SWEP.PrintName = "Tazer"
10SWEP.Slot = 1
11SWEP.SlotPos = 1
12SWEP.DrawAmmo = (not SWEP.InfiniteAmmo)
13SWEP.DrawCrosshair = false
14
15language.Add("ammo_stungun_ammo", "Stungun Ammo")
16
17if STUNGUN.IsTTT then
18 //TTT stuff
19 -- Path to the icon material
20 SWEP.Icon = "stungun/icon_stungun"
21
22 local ammotext = ""
23 if SWEP.Ammo > 0 then
24 ammotext = "\nIt has "..SWEP.Ammo.." charges."
25 end
26
27 -- Text shown in the equip menu
28 SWEP.EquipMenuData = {
29 type = "Weapon",
30 desc = string.format("Stungun used to paralyze enemies making them\nunable to speak and move for a few seconds.%s\n\nCreated by: Donkie",ammotext)
31 }
32end
33
34
35SWEP.VElements = {
36 ["Yellowbox+"] = { type = "Model", model = "models/props_c17/FurnitureFridge001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "Yellowbox", pos = Vector(-3.182, 0, 0), angle = Angle(0, 0, 0), size = Vector(0.05, 0.1, 0.029), color = Color(255, 255, 0, 255), surpresslightning = false, material = "models/debug/debugwhite", skin = 0, bodygroup = {} },
37 ["Yellowbox"] = { type = "Model", model = "models/props_c17/FurnitureFridge001a.mdl", bone = "ValveBiped.square", rel = "", pos = Vector(0.259, 0.455, 2.273), angle = Angle(90, 0, 180), size = Vector(0.05, 0.1, 0.029), color = Color(255, 255, 0, 255), surpresslightning = false, material = "models/debug/debugwhite", skin = 0, bodygroup = {} },
38 ["Yellowbox+++"] = { type = "Model", model = "models/props_c17/FurnitureFridge001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(3.171, 1.784, -0.456), angle = Angle(0, 90, -101.25), size = Vector(0.054, 0.293, 0.05), color = Color(0, 0, 24, 255), surpresslightning = false, material = "models/debug/debugwhite", skin = 0, bodygroup = {} },
39 ["Yellowbox++"] = { type = "Model", model = "models/props_c17/FurnitureFridge001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "Yellowbox", pos = Vector(-1.8, -0.201, -0.75), angle = Angle(90, -90, 0), size = Vector(0.054, 0.4, 0.05), color = Color(0, 0, 0, 255), surpresslightning = false, material = "phoenix_storms/stripes", skin = 0, bodygroup = {} },
40 ["Blackreceiver"] = { type = "Model", model = "models/props_c17/FurnitureWashingmachine001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "Yellowbox", pos = Vector(-3.5, 0, -0.201), angle = Angle(0, -90, 90), size = Vector(0.119, 0.054, 0.3), color = Color(0, 0, 0, 0), surpresslightning = false, material = "phoenix_storms/stripes", skin = 0, bodygroup = {} },
41 ["counter"] = { type = "Quad", bone = "ValveBiped.Bip01_R_Hand", rel = "Blackreceiver", pos = Vector(0, 0, 4.099), angle = Angle(0, -90, 0), size = 0.02, draw_func = nil}
42}
43SWEP.WElements = {
44 ["Yellowbox"] = { type = "Model", model = "models/props_c17/FurnitureFridge001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(8.635, 2.273, -3.5), angle = Angle(-5, -2, 90), size = Vector(0.05, 0.1, 0.029), color = Color(255, 255, 0, 255), surpresslightning = false, material = "models/debug/debugwhite", skin = 0, bodygroup = {} },
45 ["Yellowbox+"] = { type = "Model", model = "models/props_c17/FurnitureFridge001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "Yellowbox", pos = Vector(-3.182, 0, 0), angle = Angle(0, 0, 0), size = Vector(0.05, 0.1, 0.029), color = Color(255, 255, 0, 255), surpresslightning = false, material = "models/debug/debugwhite", skin = 0, bodygroup = {} },
46 ["Blackreceiver"] = { type = "Model", model = "models/props_c17/FurnitureWashingmachine001a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "Yellowbox", pos = Vector(-3, 0, -0.201), angle = Angle(0, -90, 90), size = Vector(0.119, 0.057, 0.3), color = Color(0, 0, 0, 255), surpresslightning = false, material = "phoenix_storms/stripes", skin = 0, bodygroup = {} }
47}
48
49/*
50IN-HEAD VIEW
51*/
52net.Receive("tazestartview", function()
53 local rag = net.ReadEntity()
54 LocalPlayer().viewrag = rag
55end)
56net.Receive("tazeendview", function()
57 LocalPlayer().viewrag = nil
58end)
59
60hook.Add("PlayerBindPress", "Tazer", function(ply,bind,pressed)
61 if IsValid(ply:GetNWEntity("tazerviewrag")) and STUNGUN.Thirdperson and STUNGUN.AllowSwitchFromToThirdperson then
62 if bind == "+duck" then
63 if ply.thirdpersonview == nil then
64 ply.thirdpersonview = false
65 end
66
67 ply.thirdpersonview = not ply.thirdpersonview
68 print(ply.thirdpersonview)
69 end
70 end
71end)
72
73local dist = 200
74local view = {}
75hook.Add("CalcView", "Tazer", function(ply, origin, angles, fov)
76 local rag = ply:GetNWEntity("tazerviewrag")
77 if IsValid(rag) then
78 local bid = rag:LookupBone("ValveBiped.Bip01_Head1")
79 if bid then
80 local dothirdperson = false
81 if STUNGUN.Thirdperson then
82 if STUNGUN.AllowSwitchFromToThirdperson then
83 dothirdperson = ply.thirdpersonview
84 else
85 dothirdperson = true
86 end
87 end
88
89 if dothirdperson then
90 local ragpos = rag:GetBonePosition(bid)
91
92 local pos = ragpos - (ply:GetAimVector()*dist)
93 local ang = (ragpos - pos):Angle()
94
95 //Do a traceline so he can't see through walls
96 local trdata = {}
97 trdata.start = ragpos
98 trdata.endpos = pos
99 trdata.filter = rag
100 local trres = util.TraceLine(trdata)
101 if trres.Hit then
102 pos = trres.HitPos + (trres.HitWorld and trres.HitNormal * 3 or vector_origin)
103 end
104
105 view.origin = pos
106 view.angles = ang
107 else
108 local pos,ang = rag:GetBonePosition(bid)
109 pos = pos + ang:Forward() * 7
110 ang:RotateAroundAxis(ang:Up(), -90)
111 ang:RotateAroundAxis(ang:Forward(), -90)
112 pos = pos + ang:Forward() * 1
113
114 view.origin = pos
115 view.angles = ang
116 end
117
118 return view
119 end
120 end
121end)
122
123/*
124CROSSHAIR
125*/
126
127local col1 = Color(0,150,0,255)
128local col2 = Color(150,0,0,255)
129local w,h = ScrW(), ScrH()
130local w2,h2 = w/2,h/2
131function SWEP:DrawHUD()
132 if LocalPlayer() != self.Owner then return end // Not sure why this would happen but you never know.
133 if STUNGUN.IsTTT and GetConVar("ttt_disable_crosshair"):GetBool() then return end // If a TTT player wants it disabled, so be it.
134
135 //Small delay so we don't spam the shit out of the player.
136 if not self.trres or self.nexttr < CurTime() then
137 self.trres = util.TraceLine(util.GetPlayerTrace(LocalPlayer()))
138 self.nexttr = CurTime() + .05
139 end
140
141 local hit = self.trres.HitPos:Distance(LocalPlayer():GetShootPos()) <= self.Range and (IsValid(self.trres.Entity) and self.trres.Entity:IsPlayer())
142
143 surface.SetDrawColor(hit and col1 or col2)
144
145 local gap = (hit and 0 or 10) + 5
146 local length = 10
147
148 surface.DrawLine( w2 - length, h2, w2 - gap, h2 )
149 surface.DrawLine( w2 + length, h2, w2 + gap, h2 )
150 surface.DrawLine( w2, h2 - length, w2, h2 - gap )
151 surface.DrawLine( w2, h2 + length, w2, h2 + gap )
152end
153
154/*
155TARGET ID
156*/
157//Stops targetids from drawing in darkrp. TTT sadly has no hook like this.
158hook.Add("HUDShouldDraw", "Tazer", function(hud)
159 if hud == "DarkRP_EntityDisplay" then
160 local p = {}
161 local edited = false
162 for k,v in pairs(player.GetAll()) do
163 if not IsValid(v:GetNWEntity("tazerviewrag")) then
164 table.insert(p, v)
165 else
166 edited = true
167 end
168 end
169
170 if edited then // Only override if we actually done something. So others have a chance.
171 return true, p
172 end
173 end
174end)
175
176local function IsOnScreen(pos)
177 return pos.x > 0 and pos.x < w and pos.y > 0 and pos.y < h
178end
179
180local function GrabPlyInfo(ply)
181 if STUNGUN.IsTTT then
182 local text, color
183 if ply:GetNWBool("disguised", false) then
184 if LocalPlayer():IsTraitor() or LocalPlayer():IsSpec() then
185 text = ply:Nick() .. LANG.GetUnsafeLanguageTable().target_disg
186 else
187 -- Do not show anything
188 return
189 end
190
191 color = COLOR_RED
192 else
193 text = ply:Nick()
194 end
195
196 return text, (color or COLOR_WHITE), "TargetID"
197 elseif STUNGUN.IsDarkRP then
198 return ply:Nick(), (team.GetColor(ply:Team()) or Color(255,255,255)), "DarkRPHUD2"
199 else
200 return ply:Nick(), (team.GetColor(ply:Team()) or Color(255,255,255)), "TargetID"
201 end
202end
203
204hook.Add("HUDPaint", "Tazer", function()
205 //Draws info about crouch able to switch between third and firstperson
206 if STUNGUN.Thirdperson and STUNGUN.AllowSwitchFromToThirdperson and IsValid(LocalPlayer():GetNWEntity("tazerviewrag")) then
207 local txt = string.format("Press %s to switch between third and firstperson view.", input.LookupBinding("+duck"))
208 draw.SimpleText(txt, "TargetID", ScrW()/2 + 1, 10 + 1, Color(0,0,0,255), 1)
209 draw.SimpleText(txt, "TargetID", ScrW()/2, 10, Color(200,200,200,255), 1)
210 end
211
212 //Draws custom targetids on rags
213 if not STUNGUN.ShowPlayerInfo then return end
214
215 local targ = LocalPlayer():GetEyeTrace().Entity
216 if IsValid(targ) and IsValid(targ:GetNWEntity("plyowner")) and LocalPlayer():GetPos():Distance(targ:GetPos()) < 400 then
217 local pos = targ:GetPos():ToScreen()
218 if IsOnScreen(pos) then
219 local ply = targ:GetNWEntity("plyowner")
220 local nick,nickclr,font = GrabPlyInfo(ply)
221 if not nick then return end // Someone doesn't want us to draw his info.
222
223 draw.DrawText(nick, font, pos.x-1, pos.y - 51, Color(0,0,0), 1)
224 draw.DrawText(nick, font, pos.x, pos.y - 50, nickclr, 1)
225
226 local hp = (ply.newhp and ply.newhp or ply:Health())
227 if STUNGUN.IsTTT then
228 local txt,clr = util.HealthToString(hp) // Grab TTT Data
229 txt = LANG.GetUnsafeLanguageTable()[txt] // Convert to whatever language
230 draw.DrawText(txt, "TargetIDSmall2", pos.x-1, pos.y - 31, Color(0,0,0), 1)
231 draw.DrawText(txt, "TargetIDSmall2", pos.x, pos.y - 30, clr, 1)
232 elseif STUNGUN.IsDarkRP then
233 local txt
234 if STUNGUN.IsDarkRP25 then
235 txt = DarkRP.getPhrase("health", hp)
236 else
237 txt = LANGUAGE.health..hp
238 end
239
240 draw.DrawText(txt, "DarkRPHUD2", pos.x-1, pos.y - 31, Color(0,0,0), 1)
241 draw.DrawText(txt, "DarkRPHUD2", pos.x, pos.y - 30, Color(255,255,255,200), 1)
242 else
243 local txt = hp.."%"
244
245 draw.DrawText(txt, "TargetID", pos.x-1, pos.y - 31, Color(0,0,0), 1)
246 draw.DrawText(txt, "TargetID", pos.x, pos.y - 30, Color(255,255,255,200), 1)
247 end
248 end
249 end
250end)
251
252//For some reason, when they're ragdolled their hp isn't sent properly to the clients.
253net.Receive("tazersendhealth", function()
254 local ent = net.ReadEntity()
255 local newhp = net.ReadInt(32)
256 ent.newhp = newhp
257end)
258
259/********************************************************
260 SWEP Construction Kit base code
261 Created by Clavus
262 Available for public use, thread at:
263 facepunch.com/threads/1032378
264********************************************************/
265
266local boltpositions
267local boltcount
268local poly
269local glowtimer = 0
270
271local bolt1 = Material("stungun/lightningbolt.png")
272local bolt1_o = Material("stungun/lightningbolt_outline.png")
273local bolt1_g = Material("stungun/lightningbolt_glow.png")
274local bolt2 = Material("stungun/lightningbolt2.png")
275function SWEP:DrawScreen(x, y, w, h)
276 local frac = (self.Charge or 0) / 100
277 local fracinv = 1 - frac
278
279 if frac >= 1 then glowtimer = glowtimer + 1 else glowtimer = 0 end
280
281 local bx, by = x + w/2 - 16, y + h/2 - 32 + 10
282 if not poly then
283 /*
284 Setup boltpositions
285 */
286 boltpositions = {}
287 local v
288 local a
289 for i=-30,30,14 do
290 v = Vector(0,by - 25,0)
291 a = Angle(0,i,0)
292 v:Rotate(a)
293
294 table.insert(boltpositions, {pos = v, ang = a})
295 end
296 boltcount = #boltpositions
297
298 /*
299 Setup polygon
300 */
301 poly = {{
302 x = bx,
303 y = by + (fracinv * 64),
304 u = 0,
305 v = fracinv
306 },{
307 x = bx + 32,
308 y = by + (fracinv * 64),
309 u = 1,
310 v = fracinv
311 },{
312 x = bx + 32,
313 y = by + 64,
314 u = 1,
315 v = 1
316 },{
317 x = bx,
318 y = by + 64,
319 u = 0,
320 v = 1
321 }}
322 end
323
324
325 /*
326 Bolt fill
327 */
328 surface.SetDrawColor(Color(255,255,255,255))
329 surface.SetMaterial(bolt1)
330
331 poly[1].y = by + (fracinv * 64)
332 poly[1].v = fracinv
333 poly[2].y = poly[1].y
334 poly[2].v = poly[1].v
335
336 surface.DrawPoly(poly)
337
338 /*
339 Bolt outline
340 */
341 surface.SetMaterial(bolt1_o)
342 surface.DrawTexturedRect(bx, by, 32, 64)
343
344 /*
345 Small bolts
346 */
347 surface.SetMaterial(bolt2)
348
349 local a
350 for k,v in pairs(boltpositions) do
351 a = math.Clamp((frac * (254 * boltcount)) - (254*(k-1)), 0, 254)
352
353 surface.SetDrawColor(Color(0,0,255,a + 1))
354 surface.DrawTexturedRectRotated(v.pos.x + (x + w/2), v.pos.y, 16, 32, -(v.ang.y))
355 end
356
357 /*
358 Bolt glow
359 */
360 surface.SetDrawColor(Color(255,255,255,math.cos(glowtimer/40 + math.pi) * 50 + 50))
361 surface.SetMaterial(bolt1_g)
362 surface.DrawTexturedRect(bx-16, by-32, 64, 128)
363end
364
365function SWEP:Initialize()
366 // Create a new table for every weapon instance
367 self.VElements = table.FullCopy( self.VElements )
368 self.WElements = table.FullCopy( self.WElements )
369 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
370
371 self:CreateModels(self.VElements) // create viewmodels
372 self:CreateModels(self.WElements) // create worldmodels
373
374 // init view model bone build function
375 /*if IsValid(self.Owner) then
376 local vm = self.Owner:GetViewModel()
377 if IsValid(vm) then
378 self:ResetBonePositions(vm)
379 vm:DrawShadow( false )
380 vm:SetMaterial( "models/effects/vol_light001" )
381 vm:SetRenderMode( RENDERMODE_TRANSALPHA )
382 end
383 end*/
384
385 self.VElements["counter"].draw_func = function()
386 self:DrawScreen(-27,-65,65,123)
387 end
388end
389
390function SWEP:Holster()
391 /*if IsValid(self.Owner) then
392 local vm = self.Owner:GetViewModel()
393 if IsValid(vm) then
394 vm:DrawShadow( true )
395 vm:SetMaterial( "" )
396 vm:SetRenderMode( RENDERMODE_NORMAL )
397 self:ResetBonePositions(vm)
398 end
399 end
400 */
401 return true
402end
403
404function SWEP:Deploy()
405 self:SendWeaponAnim(ACT_VM_DRAW)
406/*
407 if IsValid(self.Owner) then
408 local vm = self.Owner:GetViewModel()
409 if IsValid(vm) then
410 //Ass code, but transparency is weird as fuck so I do this to really make sure it stays transparent.
411 vm:SetColor(Color(255,255,255,1))
412 vm:DrawShadow( false )
413 vm:SetMaterial( "models/effects/vol_light001" )
414 vm:SetRenderMode( RENDERMODE_TRANSALPHA )
415 timer.Simple(0.1,function()
416 vm:SetColor(Color(255,255,255,1))
417 vm:DrawShadow( false )
418 vm:SetMaterial( "models/effects/vol_light001" )
419 vm:SetRenderMode( RENDERMODE_TRANSALPHA )
420 end)
421 end
422 end
423*/
424 return true
425end
426
427function SWEP:OnRemove()
428 self:Holster()
429end
430
431function SWEP:OnDrop()
432 self:Holster()
433end
434
435net.Receive("tazerondrop",function()
436 local swep = net.ReadEntity()
437 swep:OnDrop()
438end)
439
440SWEP.vRenderOrder = nil
441function SWEP:ViewModelDrawn()
442
443 local vm = self.Owner:GetViewModel()
444 if !IsValid(vm) then return end
445
446 if (!self.VElements) then return end
447
448 self:UpdateBonePositions(vm)
449
450 if (!self.vRenderOrder) then
451
452 // we build a render order because sprites need to be drawn after models
453 self.vRenderOrder = {}
454
455 for k, v in pairs( self.VElements ) do
456 if (v.type == "Model") then
457 table.insert(self.vRenderOrder, 1, k)
458 elseif (v.type == "Sprite" or v.type == "Quad") then
459 table.insert(self.vRenderOrder, k)
460 end
461 end
462
463 end
464
465 for k, name in ipairs( self.vRenderOrder ) do
466
467 local v = self.VElements[name]
468 if (!v) then self.vRenderOrder = nil break end
469 if (v.hide) then continue end
470
471 local model = v.modelEnt
472 local sprite = v.spriteMaterial
473
474 if (!v.bone) then continue end
475
476 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
477
478 if (!pos) then continue end
479
480 if (v.type == "Model" and IsValid(model)) then
481
482 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
483 ang:RotateAroundAxis(ang:Up(), v.angle.y)
484 ang:RotateAroundAxis(ang:Right(), v.angle.p)
485 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
486
487 model:SetAngles(ang)
488 //model:SetModelScale(v.size)
489 local matrix = Matrix()
490 matrix:Scale(v.size)
491 model:EnableMatrix( "RenderMultiply", matrix )
492
493 if (v.material == "") then
494 model:SetMaterial("")
495 elseif (model:GetMaterial() != v.material) then
496 model:SetMaterial( v.material )
497 end
498
499 if (v.skin and v.skin != model:GetSkin()) then
500 model:SetSkin(v.skin)
501 end
502
503 if (v.bodygroup) then
504 for k, v in pairs( v.bodygroup ) do
505 if (model:GetBodygroup(k) != v) then
506 model:SetBodygroup(k, v)
507 end
508 end
509 end
510
511 if (v.surpresslightning) then
512 render.SuppressEngineLighting(true)
513 end
514
515 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
516 render.SetBlend(v.color.a/255)
517 model:DrawModel()
518 render.SetBlend(1)
519 render.SetColorModulation(1, 1, 1)
520
521 if (v.surpresslightning) then
522 render.SuppressEngineLighting(false)
523 end
524
525 elseif (v.type == "Sprite" and sprite) then
526
527 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
528 render.SetMaterial(sprite)
529 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
530
531 elseif (v.type == "Quad" and v.draw_func) then
532
533 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
534 ang:RotateAroundAxis(ang:Up(), v.angle.y)
535 ang:RotateAroundAxis(ang:Right(), v.angle.p)
536 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
537
538 cam.Start3D2D(drawpos, ang, v.size)
539 v.draw_func( self )
540 cam.End3D2D()
541
542 end
543
544 end
545
546end
547
548SWEP.wRenderOrder = nil
549function SWEP:DrawWorldModel()
550 //Fixes worldmodel being seen in firstperson spectating
551 local viewent = LocalPlayer():GetObserverTarget()
552 if IsValid(viewent) and viewent != LocalPlayer() and viewent == self.Owner then
553 return
554 end
555
556 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
557 self:DrawModel()
558 end
559
560 if (!self.WElements) then return end
561
562 if (!self.wRenderOrder) then
563
564 self.wRenderOrder = {}
565
566 for k, v in pairs( self.WElements ) do
567 if (v.type == "Model") then
568 table.insert(self.wRenderOrder, 1, k)
569 elseif (v.type == "Sprite" or v.type == "Quad") then
570 table.insert(self.wRenderOrder, k)
571 end
572 end
573
574 end
575
576 if (IsValid(self.Owner)) then
577 bone_ent = self.Owner
578 else
579 // when the weapon is dropped
580 bone_ent = self
581 end
582
583 for k, name in pairs( self.wRenderOrder ) do
584
585 local v = self.WElements[name]
586 if (!v) then self.wRenderOrder = nil break end
587 if (v.hide) then continue end
588
589 local pos, ang
590
591 if (v.bone) then
592 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
593 else
594 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
595 end
596
597 if (!pos) then continue end
598
599 local model = v.modelEnt
600 local sprite = v.spriteMaterial
601
602 if (v.type == "Model" and IsValid(model)) then
603
604 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
605 ang:RotateAroundAxis(ang:Up(), v.angle.y)
606 ang:RotateAroundAxis(ang:Right(), v.angle.p)
607 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
608
609 model:SetAngles(ang)
610 //model:SetModelScale(v.size)
611 local matrix = Matrix()
612 matrix:Scale(v.size)
613 model:EnableMatrix( "RenderMultiply", matrix )
614
615 if (v.material == "") then
616 model:SetMaterial("")
617 elseif (model:GetMaterial() != v.material) then
618 model:SetMaterial( v.material )
619 end
620
621 if (v.skin and v.skin != model:GetSkin()) then
622 model:SetSkin(v.skin)
623 end
624
625 if (v.bodygroup) then
626 for k, v in pairs( v.bodygroup ) do
627 if (model:GetBodygroup(k) != v) then
628 model:SetBodygroup(k, v)
629 end
630 end
631 end
632
633 if (v.surpresslightning) then
634 render.SuppressEngineLighting(true)
635 end
636
637 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
638 render.SetBlend(v.color.a/255)
639 model:DrawModel()
640 render.SetBlend(1)
641 render.SetColorModulation(1, 1, 1)
642
643 if (v.surpresslightning) then
644 render.SuppressEngineLighting(false)
645 end
646
647 elseif (v.type == "Sprite" and sprite) then
648
649 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
650 render.SetMaterial(sprite)
651 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
652
653 elseif (v.type == "Quad" and v.draw_func) then
654
655 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
656 ang:RotateAroundAxis(ang:Up(), v.angle.y)
657 ang:RotateAroundAxis(ang:Right(), v.angle.p)
658 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
659
660 cam.Start3D2D(drawpos, ang, v.size)
661 v.draw_func( self )
662 cam.End3D2D()
663
664 end
665
666 end
667
668end
669
670function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
671
672 local bone, pos, ang
673 if (tab.rel and tab.rel != "") then
674
675 local v = basetab[tab.rel]
676
677 if (!v) then return end
678
679 // Technically, if there exists an element with the same name as a bone
680 // you can get in an infinite loop. Let's just hope nobody's that stupid.
681 pos, ang = self:GetBoneOrientation( basetab, v, ent )
682
683 if (!pos) then return end
684
685 pos = 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 else
691
692 bone = ent:LookupBone(bone_override or tab.bone)
693
694 if (!bone) then return end
695
696 pos, ang = Vector(0,0,0), Angle(0,0,0)
697 local m = ent:GetBoneMatrix(bone)
698 if (m) then
699 pos, ang = m:GetTranslation(), m:GetAngles()
700 end
701
702 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
703 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
704 ang.r = -ang.r // Fixes mirrored models
705 end
706
707 end
708
709 return pos, ang
710end
711
712function SWEP:CreateModels( tab )
713
714 if (!tab) then return end
715
716 // Create the clientside models here because Garry says we can't do it in the render hook
717 for k, v in pairs( tab ) do
718 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
719 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
720
721 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
722 if (IsValid(v.modelEnt)) then
723 v.modelEnt:SetPos(self:GetPos())
724 v.modelEnt:SetAngles(self:GetAngles())
725 v.modelEnt:SetParent(self)
726 v.modelEnt:SetNoDraw(true)
727 v.createdModel = v.model
728 else
729 v.modelEnt = nil
730 end
731
732 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
733 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
734
735 local name = v.sprite.."-"
736 local params = { ["$basetexture"] = v.sprite }
737 // make sure we create a unique name based on the selected options
738 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
739 for i, j in pairs( tocheck ) do
740 if (v[j]) then
741 params["$"..j] = 1
742 name = name.."1"
743 else
744 name = name.."0"
745 end
746 end
747
748 v.createdSprite = v.sprite
749 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
750
751 end
752 end
753
754end
755
756local allbones
757local hasGarryFixedBoneScalingYet = false
758
759function SWEP:UpdateBonePositions(vm)
760
761 if self.ViewModelBoneMods then
762
763 if (!vm:GetBoneCount()) then return end
764
765 // !! WORKAROUND !! //
766 // We need to check all model names :/
767 local loopthrough = self.ViewModelBoneMods
768 if (!hasGarryFixedBoneScalingYet) then
769 allbones = {}
770 for i=0, vm:GetBoneCount() do
771 local bonename = vm:GetBoneName(i)
772 if (self.ViewModelBoneMods[bonename]) then
773 allbones[bonename] = self.ViewModelBoneMods[bonename]
774 else
775 allbones[bonename] = {
776 scale = Vector(1,1,1),
777 pos = Vector(0,0,0),
778 angle = Angle(0,0,0)
779 }
780 end
781 end
782
783 loopthrough = allbones
784 end
785 // !! ----------- !! //
786
787 for k, v in pairs( loopthrough ) do
788 local bone = vm:LookupBone(k)
789 if (!bone) then continue end
790
791 // !! WORKAROUND !! //
792 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
793 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
794 local ms = Vector(1,1,1)
795 if (!hasGarryFixedBoneScalingYet) then
796 local cur = vm:GetBoneParent(bone)
797 while(cur >= 0) do
798 local pscale = loopthrough[vm:GetBoneName(cur)].scale
799 ms = ms * pscale
800 cur = vm:GetBoneParent(cur)
801 end
802 end
803
804 s = s * ms
805 // !! ----------- !! //
806
807 if vm:GetManipulateBoneScale(bone) != s then
808 vm:ManipulateBoneScale( bone, s )
809 end
810 if vm:GetManipulateBoneAngles(bone) != v.angle then
811 vm:ManipulateBoneAngles( bone, v.angle )
812 end
813 if vm:GetManipulateBonePosition(bone) != p then
814 vm:ManipulateBonePosition( bone, p )
815 end
816 end
817 else
818 self:ResetBonePositions(vm)
819 end
820
821end
822
823function SWEP:ResetBonePositions(vm)
824
825 if (!vm:GetBoneCount()) then return end
826 for i=0, vm:GetBoneCount() do
827 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
828 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
829 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
830 end
831
832end
833
834/**************************
835 Global utility code
836**************************/
837
838// Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
839// Does not copy entities of course, only copies their reference.
840// WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
841function table.FullCopy( tab )
842
843 if (!tab) then return nil end
844
845 local res = {}
846 for k, v in pairs( tab ) do
847 if (type(v) == "table") then
848 res[k] = table.FullCopy(v) // recursion ho!
849 elseif (type(v) == "Vector") then
850 res[k] = Vector(v.x, v.y, v.z)
851 elseif (type(v) == "Angle") then
852 res[k] = Angle(v.p, v.y, v.r)
853 else
854 res[k] = v
855 end
856 end
857
858 return res
859
860end