· 5 years ago · Apr 02, 2020, 11:28 AM
1AddCSLuaFile()
2AddCSLuaFile("shared.lua")
3
4-- resource.AddFile("materials/arleitiss/riotshield/shield_edges.vmt")
5-- resource.AddFile("materials/arleitiss/riotshield/shield_glass.vmt")
6-- resource.AddFile("materials/arleitiss/riotshield/shield_grip.vmt")
7-- resource.AddFile("materials/arleitiss/riotshield/shield_gripbump.vtf")
8-- resource.AddFile("models/arleitiss/riotshield/shield.mdl")
9-- resource.AddFile("materials/arleitiss/riotshield/riot_metal.vmt")
10-- resource.AddFile("materials/arleitiss/riotshield/riot_metal_bump.vtf")
11-- resource.AddFile("materials/arleitiss/riotshield/shield_cloth.vmt")
12-- resource.AddFile("materials/vgui/ttt/riotshield_icon_new.png")
13
14local TTT = false
15local sandbox = true
16
17local flags = {FCVAR_REPLICATED, FCVAR_ARCHIVE}
18CreateConVar("riotshield_chargeSpeedMultMax","4",flags)
19CreateConVar("riotshield_acceleration","0.05",flags)
20CreateConVar("riotshield_chargeDuration","1.25",flags)
21CreateConVar("riotshield_knockbackMagnitude","3.5",flags)
22CreateConVar("riotshield_blockrangeX","45",flags)
23CreateConVar("riotshield_blockrangeY","40",flags)
24CreateConVar("riotshield_DMGReductMult","1",flags)
25CreateConVar("riotshield_chargeCooldown","6",flags)
26CreateConVar("riotshield_speedThreshold","600",flags)
27CreateConVar("riotshield_damageMult","1.25",flags)
28CreateConVar("riotshield_stuntimeMult","1",flags)
29
30local chargeSpeedMultMax = GetConVarNumber("riotshield_chargeSpeedMultMax")
31local acceleration = GetConVarNumber("riotshield_acceleration")
32local chargeDuration = GetConVarNumber("riotshield_chargeDuration")
33local knockbackMagnitude = GetConVarNumber("riotshield_knockbackMagnitude")
34local blockrangeP = GetConVarNumber("riotshield_blockrangeY")
35local blockrangeY = GetConVarNumber("riotshield_blockrangeX")
36local DMGReductMult = GetConVarNumber("riotshield_DMGReductMult")
37local chargeDelay = GetConVarNumber("riotshield_chargeCooldown")
38local speedThreshold = GetConVarNumber("riotshield_speedThreshold")
39local damageMult = GetConVarNumber("riotshield_damageMult")
40local stuntimeMult = GetConVarNumber("riotshield_stuntimeMult")
41
42if CLIENT then
43 SWEP.PrintName = "Kalkan"
44 SWEP.Slot = 3
45 SWEP.SlotPos = 3
46 SWEP.DrawAmmo = false
47 SWEP.DrawCrosshair = false
48end
49
50SWEP.Spawnable = true
51SWEP.AdminSpawnable = true
52
53SWEP.ViewModelFOV = 60
54SWEP.ViewModelFlip = false
55SWEP.UseHands = false
56SWEP.DrawCrosshair = true
57SWEP.Weight = 30
58SWEP.ViewModel = "models/weapons/v_stunbaton.mdl"
59SWEP.WorldModel = "models/shield/shield.mdl"
60SWEP.ShowViewModel = true
61SWEP.ShowWorldModel = true
62SWEP.ViewModelBoneMods = {
63 ["Bip01 R UpperArm"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(-18.889, -18.889, 5.556) },
64 ["Dummy14"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) }
65}
66
67SWEP.VElements = {
68 ["shield"] = { type = "Model", model = "models/shield/shield.mdl", bone = "Bip01 R Hand", rel = "", pos = Vector(20.869, 10.753, -5.806), angle = Angle(0,90, 0), size = Vector(1.014, 1.014, 1.014), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
69}
70
71SWEP.WElements = {
72 ["w_shield"] = { type = "Model", model = "models/shield/shield.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(9.791, 3.753, 2.039), angle = Angle(15, -100.169, 190.13), size = Vector(0.7, 0.7, 0.7), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
73}
74
75SWEP.IronSightsPos = Vector(0, 0, 0)
76SWEP.IronSightsAng = Vector(0, 0, 0)
77
78SWEP.PrimaryAnim = ACT_VM_PRIMARYATTACK
79SWEP.Primary.Damage = 0
80SWEP.Primary.ClipSize = -1
81SWEP.Primary.DefaultClip = -1
82SWEP.Primary.Automatic = false
83SWEP.Primary.Delay = 1
84SWEP.Primary.Ammo = "none"
85
86SWEP.Secondary.ClipSize = -1
87SWEP.Secondary.Delay = GetConVarNumber("riotshield_chargeCooldown")
88SWEP.Secondary.Automatic = false
89SWEP.Secondary.Ammo = "none"
90
91if TTT == true then
92
93 SWEP.Base = "weapon_tttbase"
94 SWEP.Kind = WEAPON_EQUIP2
95
96 SWEP.EquipMenuData = {
97 name = "Riot Shield",
98 type = "item_weapon",
99 desc = "Protects you from bullets until it breaks."
100 };
101 SWEP.Icon = "materials/vgui/ttt/riotshield_icon_new.png"
102
103 --SWEP.InLoadoutFor = {ROLE_TRAITOR}
104 SWEP.CanBuy = {ROLE_DETECTIVE}
105 SWEP.LimitedStock = false
106
107 SWEP.AutoSpawnable = false
108 SWEP.AdminSpawnable = true
109 SWEP.AllowDrop = true
110 SWEP.IsSilent = false
111 SWEP.NoSights = true
112
113elseif sandbox == true then
114
115 SWEP.Base = "weapon_base"
116 SWEP.Category = "Warband Silahlar"
117 SWEP.Purpose = "Hold"
118 SWEP.Instructions = ""
119
120end
121
122 SWEP.HoldType = "melee2"
123
124 local speed
125 local ragdoll
126 local NPCState
127
128 local alreadyHit = {}
129
130 local impactsounds = {}
131
132 impactsounds[1] = "physics/glass/glass_impact_soft1.wav"
133 impactsounds[2] = "physics/glass/glass_impact_soft2.wav"
134 impactsounds[3] = "physics/glass/glass_impact_soft3.wav"
135 impactsounds[4] = "physics/glass/glass_impact_bullet1.wav"
136 impactsounds[5] = "physics/glass/glass_impact_bullet2.wav"
137 impactsounds[6] = "physics/glass/glass_impact_bullet3.wav"
138 impactsounds[7] = "physics/glass/glass_impact_bullet4.wav"
139 impactsounds[8] = "physics/glass/glass_impact_hard1.wav"
140 impactsounds[9] = "physics/glass/glass_impact_hard2.wav"
141 impactsounds[10] = "physics/glass/glass_impact_hard3.wav"
142
143 -- chargeHitSound = "physics/body/body_medium_impact_hard5.wav"
144
145-- function ragdollify(ent,ply)
146 -- if stuntimeMult != 0 and ent:IsValid() and ent:Health() >= 1 then
147
148 -- ent:SetModelScale(1,0)
149
150 -- local Data = duplicator.CopyEntTable( ent )
151 -- speed = ply:GetVelocity()
152 -- ragdoll = ents.Create( "prop_ragdoll" )
153 -- if not IsValid(ragdoll) then return end --failed to make a ragdoll
154 -- duplicator.DoGeneric( ragdoll, Data )
155 -- ragdoll:Spawn()
156 -- ragdoll:Activate()
157 -- if IsValid(ragdoll:GetPhysicsObject()) then
158 -- ragdoll:GetPhysicsObject():SetVelocity(Vector(speed.x*knockbackMagnitude,speed.y*knockbackMagnitude,speed.z*knockbackMagnitude/2))
159 -- end
160
161 -- ent:SetModelScale(0,0)
162 -- ent:SetParent(ragdoll)
163 -- if ent:IsPlayer() then
164 -- if TTT then
165 -- ent:SetActiveWeapon("holstered")
166 -- else
167 -- ent:SetActiveWeapon(nil)
168 -- ent:DrawViewModel(false)
169 -- end
170 -- ent:SpectateEntity(ragdoll)
171 -- elseif ent:IsNPC() then
172 -- NPCState = ent:GetNPCState()
173 -- ent:SetNPCState(NPC_STATE_IDLE )
174 -- end
175 -- end
176-- end
177
178-- function humanify(ent,ply)
179 -- if ent:IsNPC() and !IsValid(ent) then return end
180 -- ent:SetModelScale(1,0)
181 -- ent:SetParent()
182 -- ragdoll:Remove()
183 -- if ent:IsPlayer() then
184 -- ent:SetPos(ragdoll:GetPos()+Vector(0,0,1))
185 -- ent:UnSpectate()
186 -- if !TTT then
187 -- ent:DrawViewModel(true)
188 -- end
189 -- elseif ent:IsNPC() then
190 -- if IsValid(ent) then
191 -- ent:SetPos(ragdoll:GetPos()+Vector(0,0,1))
192 -- end
193 -- ent:SetNPCState(NPCState)
194 -- end
195-- end
196
197-- function tttChargeSpeed(ply)
198 -- if IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass() == "swat_shield" then
199 -- if ply:KeyDown(IN_ATTACK2) and ply:GetNWBool("isCharging") == true then
200 -- return ply:GetNWFloat("chargeSpeedMult")
201 -- end
202 -- end
203 -- return nil
204-- end
205
206-- function chargeCheckTick()
207 -- for k,ply in pairs(player.GetAll()) do
208 -- if IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass() == "swat_shield" then
209 -- if ply:GetNWBool("isCharging") == true then
210 -- if ply:GetNWFloat("chargeSpeedMult") < chargeSpeedMultMax then
211 -- if !TTT then
212 -- ply:SetWalkSpeed(ply:GetWalkSpeed()/ply:GetNWFloat("chargeSpeedMult"))
213 -- end
214 -- ply:SetNWFloat("chargeSpeedMult",ply:GetNWFloat("chargeSpeedMult")+acceleration)
215 -- if !TTT then
216 -- ply:SetWalkSpeed(ply:GetWalkSpeed()*ply:GetNWFloat("chargeSpeedMult"))
217 -- end
218 -- end
219 -- for i,j in pairs(ents.FindInCone(ply:GetPos(),ply:GetAimVector(),60,45)) do
220 -- if (j:IsPlayer() or j:IsNPC()) then
221 -- if !table.HasValue(alreadyHit,j) then
222 -- table.insert(alreadyHit,j)
223 -- endCharge(ply)
224 -- chargeHit(j,ply)
225 -- end
226 -- end
227 -- end
228 -- end
229 -- end
230 -- end
231-- end
232
233-- function chargeCheckRelease(ply,key)
234 -- if IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass() == "swat_shield" then
235 -- if ply:GetNWBool("isCharging") == true then
236 -- if key == IN_FORWARD or key == IN_ATTACK2 then
237 -- endCharge(ply)
238 -- end
239 -- end
240 -- end
241-- end
242
243-- function initiateCharge(ply)
244 -- ply:SetNWFloat("chargeSpeedMult",1)
245 -- ply:SetNWBool("isCharging",true)
246 -- timer.Simple(chargeDuration,function()
247 -- if IsValid(ply) and ply:GetNWBool("isCharging") then
248 -- endCharge(ply)
249 -- end
250 -- end)
251-- end
252
253-- function endCharge(ply)
254 -- if IsValid(ply) and ply:GetNWBool("isCharging") then
255 -- if !TTT then
256 -- ply:SetWalkSpeed(ply:GetWalkSpeed()/ply:GetNWFloat("chargeSpeedMult"))
257 -- end
258 -- ply:SetNWFloat("chargeSpeedMult",1)
259 -- ply:SetNWBool("isCharging",false)
260 -- alreadyHit = {}
261 -- end
262-- end
263
264-- function chargeHit(ent,ply)
265 -- if ent:IsPlayer() or ent:IsNPC() then
266 -- if SERVER and IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass() == "swat_shield" then
267 -- local dmginfo = DamageInfo()
268 -- dmginfo:SetDamage(Vector(ply:GetVelocity().x,ply:GetVelocity().y,0):Length()*damageMult/100)
269 -- dmginfo:SetAttacker(ply)
270 -- dmginfo:SetInflictor(ply:GetActiveWeapon())
271 -- dmginfo:SetDamageType(DMG_CLUB)
272 -- dmginfo:SetDamagePosition(ply:GetPos())
273 -- ent:TakeDamageInfo(dmginfo)
274 -- if (Vector(ply:GetVelocity().x,ply:GetVelocity().y,0):Length()) >= speedThreshold then
275 -- ragdollify(ent,ply)
276 -- timer.Simple((Vector(ply:GetVelocity().x,ply:GetVelocity().y,0):Length()/600)*stuntimeMult, function() humanify(ent,ply) end)
277 -- end
278 -- ply:GetActiveWeapon():SendWeaponAnim( ACT_VM_HITCENTER )
279 -- ply:EmitSound(chargeHitSound)
280 -- end
281 -- end
282-- end
283
284function shouldBeBlocked(target,dmginfo)
285 if target:IsValid() and target:IsPlayer() and IsValid(target:GetActiveWeapon()) and target:GetActiveWeapon():GetClass() == "swat_shield" then
286 local attackerangles = Angle(dmginfo:GetAttacker():GetAimVector():Angle().p,dmginfo:GetAttacker():GetAngles().y,0)
287 local ownerangles = Angle(target:GetAimVector():Angle().p,target:GetAngles().y,0)
288 local difangles = Angle(math.abs(math.AngleDifference(ownerangles.p,attackerangles.p)),math.abs(math.AngleDifference(ownerangles.y,attackerangles.y+180)),0)
289 if dmginfo:GetAttacker():IsValid() then
290 if difangles.p <= blockrangeP and difangles.y <= blockrangeY then
291 return true
292 end
293 end
294 end
295 return false
296end
297
298function shieldDMGReduct(target,dmginfo)
299 if dmginfo:IsDamageType(128) or dmginfo:IsBulletDamage() then
300 if shouldBeBlocked(target,dmginfo) then
301 target:SetBloodColor(-1)
302 if dmginfo:GetDamage() < 3 then
303 target:EmitSound(impactsounds[math.floor(math.Rand(1,3.99))])
304 elseif dmginfo:GetDamage() < 8 then
305 target:EmitSound(impactsounds[math.floor(math.Rand(4,7.99))])
306 else
307 target:EmitSound(impactsounds[math.floor(math.Rand(8,10.99))])
308 end
309 dmginfo:SetDamage(0)
310 dmginfo:ScaleDamage(0)
311 end
312 else
313 target:SetBloodColor(0)
314 end
315end
316
317function SWEP:Initialize()
318 -- self.Owner:SetNWFloat("chargeSpeedMult",chargeSpeedMult)
319
320 util.PrecacheSound(Sound("physics/glass/glass_impact_bullet1.wav"))
321 util.PrecacheSound(Sound("physics/glass/glass_impact_bullet2.wav"))
322 util.PrecacheSound(Sound("physics/glass/glass_impact_bullet3.wav"))
323 util.PrecacheSound(Sound("physics/glass/glass_impact_bullet4.wav"))
324 util.PrecacheSound(Sound("physics/glass/glass_impact_hard1.wav"))
325 util.PrecacheSound(Sound("physics/glass/glass_impact_hard2.wav"))
326 util.PrecacheSound(Sound("physics/glass/glass_impact_hard3.wav"))
327 util.PrecacheSound(Sound("physics/glass/glass_impact_hard4.wav"))
328 util.PrecacheSound(Sound("physics/glass/glass_impact_soft1.wav"))
329 util.PrecacheSound(Sound("physics/glass/glass_impact_soft2.wav"))
330 util.PrecacheSound(Sound("physics/glass/glass_impact_soft3.wav"))
331 -- util.PrecacheSound(chargeHitSound)
332
333 if table.Count(ents.FindByClass("swat_shield")) <= 1 then
334 hook.Add("EntityTakeDamage","ShieldDMGReduction",shieldDMGReduct)
335 -- hook.Add("Tick","chargeCheckTick",chargeCheckTick)
336 -- hook.Add("KeyRelease","chargeCheckRelease",chargeCheckRelease)
337 --hook.Add("CreateEntityRagdoll","chargeHitRagdoll",makeRagdoll)
338 -- if TTT then
339 -- hook.Add("TTTPlayerSpeed","tttChargeSpeed",tttChargeSpeed)
340 -- end
341 end
342
343 self:SetHoldType(self.HoldType)
344
345 // other initialize code goes here
346
347 if CLIENT then
348
349 // Create a new table for every weapon instance
350 self.VElements = table.FullCopy( self.VElements )
351 self.WElements = table.FullCopy( self.WElements )
352 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
353
354 self:CreateModels(self.VElements) // create viewmodels
355 self:CreateModels(self.WElements) // create worldmodels
356
357 // init view model bone build function
358 if IsValid(self.Owner) then
359 local vm = self.Owner:GetViewModel()
360 if IsValid(vm) then
361 self:ResetBonePositions(vm)
362
363 // Init viewmodel visibility
364 if (self.ShowViewModel == nil or self.ShowViewModel) then
365 vm:SetColor(Color(255,255,255,255))
366 else
367 // we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
368 vm:SetColor(Color(255,255,255,1))
369 // ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
370 // 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
371 vm:SetMaterial("Debug/hsv")
372 end
373 end
374 end
375
376 end
377end
378
379function SWEP:Holster()
380 self:SetModelScale(1,0)
381 if CLIENT and IsValid(self.Owner) then
382 local vm = self.Owner:GetViewModel()
383 if IsValid(vm) then
384 self:ResetBonePositions(vm)
385 end
386 end
387
388 return true
389end
390
391function SWEP:OnDrop()
392 self:SetModelScale(1,0)
393end
394
395function SWEP:Deploy()
396 self:SetModelScale(0,0)
397end
398
399function SWEP:OnRemove()
400 if table.Count(ents.FindByClass("swat_shield")) <= 0 then
401 hook.Remove("EntityTakeDamage","ShieldDMGReduction")
402 -- hook.Remove("Tick","chargeCheckTick")
403 -- hook.Remove("KeyRelease","chargeCheckRelease")
404 --hook.Remove("CreateEntityRagdoll","chargeHitRagdoll")
405 -- if TTT then
406 -- hook.Remove("TTTPlayerSpeed","tttChargeSpeed")
407 -- end
408 end
409 self:Holster()
410end
411
412if CLIENT then
413
414 SWEP.vRenderOrder = nil
415 function SWEP:ViewModelDrawn()
416
417 local vm = self.Owner:GetViewModel()
418 if !IsValid(vm) then return end
419
420 if (!self.VElements) then return end
421
422 self:UpdateBonePositions(vm)
423
424 if (!self.vRenderOrder) then
425
426 // we build a render order because sprites need to be drawn after models
427 self.vRenderOrder = {}
428
429 for k, v in pairs( self.VElements ) do
430 if (v.type == "Model") then
431 table.insert(self.vRenderOrder, 1, k)
432 elseif (v.type == "Sprite" or v.type == "Quad") then
433 table.insert(self.vRenderOrder, k)
434 end
435 end
436
437 end
438
439 for k, name in ipairs( self.vRenderOrder ) do
440
441 local v = self.VElements[name]
442 if (!v) then self.vRenderOrder = nil break end
443 if (v.hide) then continue end
444
445 local model = v.modelEnt
446 local sprite = v.spriteMaterial
447
448 if (!v.bone) then continue end
449
450 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
451
452 if (!pos) then continue end
453
454 if (v.type == "Model" and IsValid(model)) then
455
456 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
457 ang:RotateAroundAxis(ang:Up(), v.angle.y)
458 ang:RotateAroundAxis(ang:Right(), v.angle.p)
459 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
460
461 model:SetAngles(ang)
462 //model:SetModelScale(v.size)
463 local matrix = Matrix()
464 matrix:Scale(v.size)
465 model:EnableMatrix( "RenderMultiply", matrix )
466
467 if (v.material == "") then
468 model:SetMaterial("")
469 elseif (model:GetMaterial() != v.material) then
470 model:SetMaterial( v.material )
471 end
472
473 if (v.skin and v.skin != model:GetSkin()) then
474 model:SetSkin(v.skin)
475 end
476
477 if (v.bodygroup) then
478 for k, v in pairs( v.bodygroup ) do
479 if (model:GetBodygroup(k) != v) then
480 model:SetBodygroup(k, v)
481 end
482 end
483 end
484
485 if (v.surpresslightning) then
486 render.SuppressEngineLighting(true)
487 end
488
489 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
490 render.SetBlend(v.color.a/255)
491 model:DrawModel()
492 render.SetBlend(1)
493 render.SetColorModulation(1, 1, 1)
494
495 if (v.surpresslightning) then
496 render.SuppressEngineLighting(false)
497 end
498
499 elseif (v.type == "Sprite" and sprite) then
500
501 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
502 render.SetMaterial(sprite)
503 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
504
505 elseif (v.type == "Quad" and v.draw_func) then
506
507 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
508 ang:RotateAroundAxis(ang:Up(), v.angle.y)
509 ang:RotateAroundAxis(ang:Right(), v.angle.p)
510 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
511
512 cam.Start3D2D(drawpos, ang, v.size)
513 v.draw_func( self )
514 cam.End3D2D()
515
516 end
517
518 end
519
520 end
521
522 SWEP.wRenderOrder = nil
523 function SWEP:DrawWorldModel()
524
525 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
526 self:DrawModel()
527 end
528
529 if (!self.WElements) then return end
530
531 if (!self.wRenderOrder) then
532
533 self.wRenderOrder = {}
534
535 for k, v in pairs( self.WElements ) do
536 if (v.type == "Model") then
537 table.insert(self.wRenderOrder, 1, k)
538 elseif (v.type == "Sprite" or v.type == "Quad") then
539 table.insert(self.wRenderOrder, k)
540 end
541 end
542
543 end
544
545 if (IsValid(self.Owner)) then
546 bone_ent = self.Owner
547 else
548 // when the weapon is dropped
549 bone_ent = self
550 end
551
552 for k, name in pairs( self.wRenderOrder ) do
553
554 local v = self.WElements[name]
555 if (!v) then self.wRenderOrder = nil break end
556 if (v.hide) then continue end
557
558 local pos, ang
559
560 if (v.bone) then
561 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
562 else
563 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
564 end
565
566 if (!pos) then continue end
567
568 local model = v.modelEnt
569 local sprite = v.spriteMaterial
570
571 if (v.type == "Model" and IsValid(model)) then
572
573 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
574 ang:RotateAroundAxis(ang:Up(), v.angle.y)
575 ang:RotateAroundAxis(ang:Right(), v.angle.p)
576 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
577
578 model:SetAngles(ang)
579 //model:SetModelScale(v.size)
580 local matrix = Matrix()
581 matrix:Scale(v.size)
582 model:EnableMatrix( "RenderMultiply", matrix )
583
584 if (v.material == "") then
585 model:SetMaterial("")
586 elseif (model:GetMaterial() != v.material) then
587 model:SetMaterial( v.material )
588 end
589
590 if (v.skin and v.skin != model:GetSkin()) then
591 model:SetSkin(v.skin)
592 end
593
594 if (v.bodygroup) then
595 for k, v in pairs( v.bodygroup ) do
596 if (model:GetBodygroup(k) != v) then
597 model:SetBodygroup(k, v)
598 end
599 end
600 end
601
602 if (v.surpresslightning) then
603 render.SuppressEngineLighting(true)
604 end
605
606 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
607 render.SetBlend(v.color.a/255)
608 model:DrawModel()
609 render.SetBlend(1)
610 render.SetColorModulation(1, 1, 1)
611
612 if (v.surpresslightning) then
613 render.SuppressEngineLighting(false)
614 end
615
616 elseif (v.type == "Sprite" and sprite) then
617
618 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
619 render.SetMaterial(sprite)
620 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
621
622 elseif (v.type == "Quad" and v.draw_func) then
623
624 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
625 ang:RotateAroundAxis(ang:Up(), v.angle.y)
626 ang:RotateAroundAxis(ang:Right(), v.angle.p)
627 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
628
629 cam.Start3D2D(drawpos, ang, v.size)
630 v.draw_func( self )
631 cam.End3D2D()
632
633 end
634
635 end
636
637 end
638
639 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
640
641 local bone, pos, ang
642 if (tab.rel and tab.rel != "") then
643
644 local v = basetab[tab.rel]
645
646 if (!v) then return end
647
648 // Technically, if there exists an element with the same name as a bone
649 // you can get in an infinite loop. Let's just hope nobody's that stupid.
650 pos, ang = self:GetBoneOrientation( basetab, v, ent )
651
652 if (!pos) then return end
653
654 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
655 ang:RotateAroundAxis(ang:Up(), v.angle.y)
656 ang:RotateAroundAxis(ang:Right(), v.angle.p)
657 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
658
659 else
660
661 bone = ent:LookupBone(bone_override or tab.bone)
662
663 if (!bone) then return end
664
665 pos, ang = Vector(0,0,0), Angle(0,0,0)
666 local m = ent:GetBoneMatrix(bone)
667 if (m) then
668 pos, ang = m:GetTranslation(), m:GetAngles()
669 end
670
671 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
672 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
673 ang.r = -ang.r // Fixes mirrored models
674 end
675
676 end
677
678 return pos, ang
679 end
680
681 function SWEP:CreateModels( tab )
682
683 if (!tab) then return end
684
685 // Create the clientside models here because Garry says we can't do it in the render hook
686 for k, v in pairs( tab ) do
687 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
688 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
689
690 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
691 if (IsValid(v.modelEnt)) then
692 v.modelEnt:SetPos(self:GetPos())
693 v.modelEnt:SetAngles(self:GetAngles())
694 v.modelEnt:SetParent(self)
695 v.modelEnt:SetNoDraw(true)
696 v.createdModel = v.model
697 else
698 v.modelEnt = nil
699 end
700
701 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
702 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
703
704 local name = v.sprite.."-"
705 local params = { ["$basetexture"] = v.sprite }
706 // make sure we create a unique name based on the selected options
707 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
708 for i, j in pairs( tocheck ) do
709 if (v[j]) then
710 params["$"..j] = 1
711 name = name.."1"
712 else
713 name = name.."0"
714 end
715 end
716
717 v.createdSprite = v.sprite
718 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
719
720 end
721 end
722
723 end
724
725 local allbones
726 local hasGarryFixedBoneScalingYet = false
727
728 function SWEP:UpdateBonePositions(vm)
729
730 if self.ViewModelBoneMods then
731
732 if (!vm:GetBoneCount()) then return end
733
734 // !! WORKAROUND !! //
735 // We need to check all model names :/
736 local loopthrough = self.ViewModelBoneMods
737 if (!hasGarryFixedBoneScalingYet) then
738 allbones = {}
739 for i=0, vm:GetBoneCount() do
740 local bonename = vm:GetBoneName(i)
741 if (self.ViewModelBoneMods[bonename]) then
742 allbones[bonename] = self.ViewModelBoneMods[bonename]
743 else
744 allbones[bonename] = {
745 scale = Vector(1,1,1),
746 pos = Vector(0,0,0),
747 angle = Angle(0,0,0)
748 }
749 end
750 end
751
752 loopthrough = allbones
753 end
754 // !! ----------- !! //
755
756 for k, v in pairs( loopthrough ) do
757 local bone = vm:LookupBone(k)
758 if (!bone) then continue end
759
760 // !! WORKAROUND !! //
761 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
762 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
763 local ms = Vector(1,1,1)
764 if (!hasGarryFixedBoneScalingYet) then
765 local cur = vm:GetBoneParent(bone)
766 while(cur >= 0) do
767 local pscale = loopthrough[vm:GetBoneName(cur)].scale
768 ms = ms * pscale
769 cur = vm:GetBoneParent(cur)
770 end
771 end
772
773 s = s * ms
774 // !! ----------- !! //
775
776 if vm:GetManipulateBoneScale(bone) != s then
777 vm:ManipulateBoneScale( bone, s )
778 end
779 if vm:GetManipulateBoneAngles(bone) != v.angle then
780 vm:ManipulateBoneAngles( bone, v.angle )
781 end
782 if vm:GetManipulateBonePosition(bone) != p then
783 vm:ManipulateBonePosition( bone, p )
784 end
785 end
786 else
787 self:ResetBonePositions(vm)
788 end
789
790 end
791
792 function SWEP:ResetBonePositions(vm)
793
794 if (!vm:GetBoneCount()) then return end
795 for i=0, vm:GetBoneCount() do
796 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
797 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
798 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
799 end
800
801 end
802
803 /**************************
804 Global utility code
805 **************************/
806
807 // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
808 // Does not copy entities of course, only copies their reference.
809 // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
810 function table.FullCopy( tab )
811
812 if (!tab) then return nil end
813
814 local res = {}
815 for k, v in pairs( tab ) do
816 if (type(v) == "table") then
817 res[k] = table.FullCopy(v) // recursion ho!
818 elseif (type(v) == "Vector") then
819 res[k] = Vector(v.x, v.y, v.z)
820 elseif (type(v) == "Angle") then
821 res[k] = Angle(v.p, v.y, v.r)
822 else
823 res[k] = v
824 end
825 end
826
827 return res
828
829 end
830
831end