· 10 years ago · Sep 25, 2016, 08:44 AM
1if SERVER then
2 AddCSLuaFile()
3end
4
5SWEP.HoldType = "melee"
6
7if CLIENT then
8
9 SWEP.PrintName = "Harpoon"
10 SWEP.Slot = 6
11
12 SWEP.ViewModelFlip = false
13 SWEP.ViewModelFOV = 70
14
15 SWEP.EquipMenuData = {
16 type = "item_weapon",
17 desc = [[
18 A deadly harpoon that is thrown for a
19 quick kill.]]
20 };
21
22 SWEP.Icon = "vgui/ttt/icon_sttts_harpoon"
23end
24
25SWEP.Base = "weapon_tttbase"
26
27SWEP.UseHands = true
28SWEP.ViewModel = "models/props_junk/harpoon002a.mdl"
29SWEP.WorldModel = "models/weapons/w_package.mdl"
30SWEP.ShowWorldModel = false
31
32SWEP.DrawCrosshair = false
33SWEP.Primary.Damage = 100
34SWEP.Primary.ClipSize = -1
35SWEP.Primary.DefaultClip = -1
36SWEP.Primary.Automatic = true
37SWEP.Primary.Delay = 0.6
38SWEP.Primary.Ammo = "none"
39SWEP.Secondary.ClipSize = -1
40SWEP.Secondary.DefaultClip = -1
41SWEP.Secondary.Automatic = true
42SWEP.Secondary.Ammo = "none"
43SWEP.Secondary.Delay = 1.4
44
45SWEP.Kind = WEAPON_EQUIP
46SWEP.CanBuy = {ROLE_TRAITOR} -- only traitors can buy
47SWEP.LimitedStock = true -- only buyable once
48SWEP.AllowDrop = false -- dropping wont reset bones for already equipped weapons, also shadow of a package
49
50SWEP.IsSilent = true
51
52-- Pull out faster than standard guns
53SWEP.DeploySpeed = 2
54
55SWEP.WElements = {
56 ["harpoon"] = { type = "Model", model = "models/props_junk/harpoon002a.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(4.413, 5.945, -0.894), angle = Angle(-5.52, -71.026, -122.169), size = Vector(0.578, 0.578, 0.578), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
57}
58
59if file.Exists( "models/weapons/v_knife_t.mdl", "GAME" ) then
60 SWEP.ViewModel = "models/weapons/v_knife_t.mdl" -- Weapon view model
61 SWEP.VElements = {
62 ["harpoon"] = { type = "Model", model = "models/props_junk/harpoon002a.mdl", bone = "v_weapon.knife_Parent", rel = "", pos = Vector(6.3, -6.481, -5.825), angle = Angle(128.731, -17.442, -142.782), size = Vector(0.5, 0.5, 0.5), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
63 }
64 SWEP.ViewModelBoneMods = {
65 ["v_weapon.Knife_Handle"] = { scale = Vector(1, 1, 1), pos = Vector(-30, 30, -30), angle = Angle(0, 0, 0) },
66 ["v_weapon.Right_Arm"] = { scale = Vector(1, 1, 1), pos = Vector(-30, 30, 30), angle = Angle(0, 0, 0) }
67 }
68end
69
70function SWEP:Initialize()
71 if CLIENT and self:Clip1() == -1 then
72 self:SetClip1(self.Primary.DefaultClip)
73 elseif SERVER then
74 self.fingerprints = {}
75
76 self:SetIronsights(false)
77 end
78
79 self:SetDeploySpeed(self.DeploySpeed)
80
81 -- compat for gmod update
82 if self.SetHoldType then
83 self:SetHoldType(self.HoldType or "pistol")
84 end
85
86 if CLIENT then
87 -- // Create a new table for every weapon instance
88 self.VElements = table.FullCopy( self.VElements )
89 self.WElements = table.FullCopy( self.WElements )
90 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
91
92 self:CreateModels(self.VElements) -- create viewmodels
93 self:CreateModels(self.WElements) -- create worldmodels
94
95 -- // init view model bone build function
96 if IsValid(self.Owner) and self.Owner:IsPlayer() then
97 if self.Owner:Alive() then
98 local vm = self.Owner:GetViewModel()
99 if IsValid(vm) then
100 self:ResetBonePositions(vm)
101 -- // Init viewmodel visibility
102 if (self.ShowViewModel == nil or self.ShowViewModel) then
103 vm:SetColor(Color(255,255,255,255))
104 else
105 -- // 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
106 vm:SetMaterial("Debug/hsv")
107 end
108 end
109
110 end
111 end
112 end
113end
114
115function SWEP:Holster()
116 if CLIENT and IsValid(self.Owner) and not self.Owner:IsNPC() then
117 local vm = self.Owner:GetViewModel()
118 if IsValid(vm) then
119 self:ResetBonePositions(vm)
120 end
121 end
122
123 return true
124end
125
126function SWEP:Equip()
127 self.Weapon:SetNextPrimaryFire( CurTime() + (self.Primary.Delay * 1.5) )
128end
129
130function SWEP:OnRemove()
131 if CLIENT and IsValid(self.Owner) and self.Owner == LocalPlayer() and self.Owner:Alive() then
132 RunConsoleCommand("lastinv")
133 end
134end
135
136function SWEP:PrimaryAttack()
137 self:FireRocket()
138 self.Owner:SetAnimation( PLAYER_ATTACK1 )
139 self.Weapon:SetNextPrimaryFire(CurTime()+1/(60/60))
140 self.Weapon:EmitSound(Sound("Weapon_Knife.Slash"))
141 self:CheckWeaponsAndAmmo()
142end
143
144local function launchRocket(ent, owner, angle)
145 if not IsValid(ent) then return false end
146
147 local pos = owner:GetShootPos()
148 local ourVector = owner:GetAimVector()
149 local aimAngle = ourVector:Angle()
150 ent:SetAngles(aimAngle)
151 ent:SetPos(pos)
152 ent:SetOwner(owner)
153 ent:SetPhysicsAttacker(owner)
154 ent:Spawn()
155 ent.Owner = owner
156 ent:Activate()
157 eyes = owner:EyeAngles()
158 local phys = ent:GetPhysicsObject()
159 ourVector:Rotate(angle)
160 local velocity = ourVector
161 phys:SetVelocity(velocity * 2000)
162end
163
164function SWEP:FireRocket()
165 if SERVER then
166 local rocket = ents.Create("ttt_harpoon")
167 launchRocket(rocket, self.Owner, Angle(0,0,0))
168 if self.Owner.TripleHarpoon then
169 local rocket2 = ents.Create("ttt_harpoon")
170 local rocket3 = ents.Create("ttt_harpoon")
171 rocket2.canPickup = false
172 rocket3.canPickup = false
173 launchRocket(rocket2, self.Owner, Angle(0,5,0))
174 launchRocket(rocket3, self.Owner, Angle(0,-5,0))
175 end
176 end
177 if SERVER and !self.Owner:IsNPC() then
178 local anglo = Angle(-10, -5, 0)
179 self.Owner:ViewPunch(anglo)
180 end
181end
182
183function SWEP:CheckWeaponsAndAmmo()
184 if self.Weapon ~= nil then
185 timer.Simple(.01, function()
186 if not IsValid(self) then return end
187 if not IsValid(self.Owner) then return end
188
189 local owner = self.Owner -- After we strip weapon, self.Owner is no longer valid
190 if SERVER then
191 self.Owner:StripWeapon("weapon_ttt_harpoon")
192 end
193
194 if CLIENT then
195 local vm = owner:GetViewModel()
196 if IsValid(vm) then
197 self:ResetBonePositions(vm)
198 end
199 end
200 end)
201 end
202end
203
204function SWEP:SecondaryAttack()
205return false
206end
207
208function SWEP:Think()
209end
210
211function SWEP:GetViewModelPosition( pos, ang )
212 if not self.IronSightsPos then return pos, ang end
213
214 local bIron = self:GetIronsights()
215
216 if bIron != self.bLastIron then
217 self.bLastIron = bIron
218 self.fIronTime = CurTime()
219
220 if bIron then
221 self.SwayScale = 0.3
222 self.BobScale = 0.1
223 else
224 self.SwayScale = 1.0
225 self.BobScale = 1.0
226 end
227
228 end
229
230 local fIronTime = self.fIronTime or 0
231 if (not bIron) and fIronTime < CurTime() - IRONSIGHT_TIME then
232 return pos, ang
233 end
234
235 local mul = 1.0
236
237 if fIronTime > CurTime() - IRONSIGHT_TIME then
238
239 mul = math.Clamp( (CurTime() - fIronTime) / IRONSIGHT_TIME, 0, 1 )
240
241 if not bIron then mul = 1 - mul end
242 end
243
244 local offset = self.IronSightsPos + (ttt_lowered:GetBool() and LOWER_POS or vector_origin)
245
246 if self.IronSightsAng then
247 ang = ang * 1
248 ang:RotateAroundAxis( ang:Right(), self.IronSightsAng.x * mul )
249 ang:RotateAroundAxis( ang:Up(), self.IronSightsAng.y * mul )
250 ang:RotateAroundAxis( ang:Forward(), self.IronSightsAng.z * mul )
251 end
252
253 pos = pos + offset.x * ang:Right() * mul
254 pos = pos + offset.y * ang:Forward() * mul
255 pos = pos + offset.z * ang:Up() * mul
256
257 return pos, ang
258end
259
260if CLIENT then
261 SWEP.vRenderOrder = nil
262 function SWEP:ViewModelDrawn()
263 if not IsValid(self.Owner) then return end
264
265 local vm = self.Owner:GetViewModel()
266 if !IsValid(vm) then return end
267
268 if (!self.VElements) then return end
269
270 self:UpdateBonePositions(vm)
271
272 if (!self.vRenderOrder) then
273
274 -- // we build a render order because sprites need to be drawn after models
275 self.vRenderOrder = {}
276
277 for k, v in pairs( self.VElements ) do
278 if (v.type == "Model") then
279 table.insert(self.vRenderOrder, 1, k)
280 elseif (v.type == "Sprite" or v.type == "Quad") then
281 table.insert(self.vRenderOrder, k)
282 end
283 end
284
285 end
286
287 for k, name in ipairs( self.vRenderOrder ) do
288
289 local v = self.VElements[name]
290 if (!v) then self.vRenderOrder = nil break end
291 if (v.hide) then continue end
292
293 local model = v.modelEnt
294 local sprite = v.spriteMaterial
295
296 if (!v.bone) then continue end
297
298 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
299
300 if (!pos) then continue end
301
302 if (v.type == "Model" and IsValid(model)) then
303
304 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
305 ang:RotateAroundAxis(ang:Up(), v.angle.y)
306 ang:RotateAroundAxis(ang:Right(), v.angle.p)
307 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
308
309 model:SetAngles(ang)
310 -- //model:SetModelScale(v.size)
311 local matrix = Matrix()
312 matrix:Scale(v.size)
313 model:EnableMatrix( "RenderMultiply", matrix )
314
315 if (v.material == "") then
316 model:SetMaterial("")
317 elseif (model:GetMaterial() != v.material) then
318 model:SetMaterial( v.material )
319 end
320
321 if (v.skin and v.skin != model:GetSkin()) then
322 model:SetSkin(v.skin)
323 end
324
325 if (v.bodygroup) then
326 for k, v in pairs( v.bodygroup ) do
327 if (model:GetBodygroup(k) != v) then
328 model:SetBodygroup(k, v)
329 end
330 end
331 end
332
333 if (v.surpresslightning) then
334 render.SuppressEngineLighting(true)
335 end
336
337 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
338 render.SetBlend(v.color.a/255)
339 model:DrawModel()
340 render.SetBlend(1)
341 render.SetColorModulation(1, 1, 1)
342
343 if (v.surpresslightning) then
344 render.SuppressEngineLighting(false)
345 end
346
347 elseif (v.type == "Sprite" and sprite) then
348
349 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
350 render.SetMaterial(sprite)
351 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
352
353 elseif (v.type == "Quad" and v.draw_func) then
354
355 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
356 ang:RotateAroundAxis(ang:Up(), v.angle.y)
357 ang:RotateAroundAxis(ang:Right(), v.angle.p)
358 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
359
360 cam.Start3D2D(drawpos, ang, v.size)
361 v.draw_func( self )
362 cam.End3D2D()
363
364 end
365
366 end
367
368 end
369
370 SWEP.wRenderOrder = nil
371 function SWEP:DrawWorldModel()
372
373 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
374 self:DrawModel()
375 end
376
377 if (!self.WElements) then return end
378
379 if (!self.wRenderOrder) then
380
381 self.wRenderOrder = {}
382
383 for k, v in pairs( self.WElements ) do
384 if (v.type == "Model") then
385 table.insert(self.wRenderOrder, 1, k)
386 elseif (v.type == "Sprite" or v.type == "Quad") then
387 table.insert(self.wRenderOrder, k)
388 end
389 end
390
391 end
392
393 if (IsValid(self.Owner)) then
394 bone_ent = self.Owner
395 else
396 -- // when the weapon is dropped
397 bone_ent = self
398 end
399
400 for k, name in pairs( self.wRenderOrder ) do
401
402 local v = self.WElements[name]
403 if (!v) then self.wRenderOrder = nil break end
404 if (v.hide) then continue end
405
406 local pos, ang
407
408 if (v.bone) then
409 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
410 else
411 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
412 end
413
414 if (!pos) then continue end
415
416 local model = v.modelEnt
417 local sprite = v.spriteMaterial
418
419 if (v.type == "Model" and IsValid(model)) then
420
421 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
422 ang:RotateAroundAxis(ang:Up(), v.angle.y)
423 ang:RotateAroundAxis(ang:Right(), v.angle.p)
424 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
425
426 model:SetAngles(ang)
427 -- //model:SetModelScale(v.size)
428 local matrix = Matrix()
429 matrix:Scale(v.size)
430 model:EnableMatrix( "RenderMultiply", matrix )
431
432 if (v.material == "") then
433 model:SetMaterial("")
434 elseif (model:GetMaterial() != v.material) then
435 model:SetMaterial( v.material )
436 end
437
438 if (v.skin and v.skin != model:GetSkin()) then
439 model:SetSkin(v.skin)
440 end
441
442 if (v.bodygroup) then
443 for k, v in pairs( v.bodygroup ) do
444 if (model:GetBodygroup(k) != v) then
445 model:SetBodygroup(k, v)
446 end
447 end
448 end
449
450 if (v.surpresslightning) then
451 render.SuppressEngineLighting(true)
452 end
453
454 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
455 render.SetBlend(v.color.a/255)
456 model:DrawModel()
457 render.SetBlend(1)
458 render.SetColorModulation(1, 1, 1)
459
460 if (v.surpresslightning) then
461 render.SuppressEngineLighting(false)
462 end
463
464 elseif (v.type == "Sprite" and sprite) then
465
466 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
467 render.SetMaterial(sprite)
468 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
469
470 elseif (v.type == "Quad" and v.draw_func) then
471
472 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
473 ang:RotateAroundAxis(ang:Up(), v.angle.y)
474 ang:RotateAroundAxis(ang:Right(), v.angle.p)
475 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
476
477 cam.Start3D2D(drawpos, ang, v.size)
478 v.draw_func( self )
479 cam.End3D2D()
480
481 end
482
483 end
484
485 end
486
487 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
488
489 local bone, pos, ang
490 if (tab.rel and tab.rel != "") then
491
492 local v = basetab[tab.rel]
493
494 if (!v) then return end
495
496 -- // Technically, if there exists an element with the same name as a bone
497 -- // you can get in an infinite loop. Let's just hope nobody's that stupid.
498 pos, ang = self:GetBoneOrientation( basetab, v, ent )
499
500 if (!pos) then return end
501
502 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
503 ang:RotateAroundAxis(ang:Up(), v.angle.y)
504 ang:RotateAroundAxis(ang:Right(), v.angle.p)
505 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
506
507 else
508
509 bone = ent:LookupBone(bone_override or tab.bone)
510
511 if (!bone) then return end
512
513 pos, ang = Vector(0,0,0), Angle(0,0,0)
514 local m = ent:GetBoneMatrix(bone)
515 if (m) then
516 pos, ang = m:GetTranslation(), m:GetAngles()
517 end
518
519 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
520 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
521 ang.r = -ang.r --// Fixes mirrored models
522 end
523
524 end
525
526 return pos, ang
527 end
528
529 function SWEP:CreateModels( tab )
530
531 if (!tab) then return end
532
533 -- // Create the clientside models here because Garry says we can't do it in the render hook
534 for k, v in pairs( tab ) do
535 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
536 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
537
538 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
539 if (IsValid(v.modelEnt)) then
540 v.modelEnt:SetPos(self:GetPos())
541 v.modelEnt:SetAngles(self:GetAngles())
542 v.modelEnt:SetParent(self)
543 v.modelEnt:SetNoDraw(true)
544 v.createdModel = v.model
545 else
546 v.modelEnt = nil
547 end
548
549 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
550 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
551
552 local name = v.sprite.."-"
553 local params = { ["$basetexture"] = v.sprite }
554 -- // make sure we create a unique name based on the selected options
555 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
556 for i, j in pairs( tocheck ) do
557 if (v[j]) then
558 params["$"..j] = 1
559 name = name.."1"
560 else
561 name = name.."0"
562 end
563 end
564
565 v.createdSprite = v.sprite
566 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
567
568 end
569 end
570
571 end
572
573 local allbones
574 local hasGarryFixedBoneScalingYet = false
575
576 function SWEP:UpdateBonePositions(vm)
577
578 if self.ViewModelBoneMods then
579
580 if (!vm:GetBoneCount()) then return end
581
582 -- // !! WORKAROUND !! --//
583 -- // We need to check all model names :/
584 local loopthrough = self.ViewModelBoneMods
585 if (!hasGarryFixedBoneScalingYet) then
586 allbones = {}
587 for i=0, vm:GetBoneCount() do
588 local bonename = vm:GetBoneName(i)
589 if (self.ViewModelBoneMods[bonename]) then
590 allbones[bonename] = self.ViewModelBoneMods[bonename]
591 else
592 allbones[bonename] = {
593 scale = Vector(1,1,1),
594 pos = Vector(0,0,0),
595 angle = Angle(0,0,0)
596 }
597 end
598 end
599
600 loopthrough = allbones
601 end
602 //!! ----------- !! --
603
604 for k, v in pairs( loopthrough ) do
605 local bone = vm:LookupBone(k)
606 if (!bone) then continue end
607
608 -- // !! WORKAROUND !! --//
609 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
610 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
611 local ms = Vector(1,1,1)
612 if (!hasGarryFixedBoneScalingYet) then
613 local cur = vm:GetBoneParent(bone)
614 while(cur >= 0) do
615 local pscale = loopthrough[vm:GetBoneName(cur)].scale
616 ms = ms * pscale
617 cur = vm:GetBoneParent(cur)
618 end
619 end
620
621 s = s * ms
622 //!! ----------- !! --
623
624 if vm:GetManipulateBoneScale(bone) != s then
625 vm:ManipulateBoneScale( bone, s )
626 end
627 if vm:GetManipulateBoneAngles(bone) != v.angle then
628 vm:ManipulateBoneAngles( bone, v.angle )
629 end
630 if vm:GetManipulateBonePosition(bone) != p then
631 vm:ManipulateBonePosition( bone, p )
632 end
633 end
634 else
635 self:ResetBonePositions(vm)
636 end
637
638 end
639
640 function SWEP:ResetBonePositions(vm)
641
642 if (!vm:GetBoneCount()) then return end
643 for i=0, vm:GetBoneCount() do
644 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
645 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
646 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
647 end
648
649 end
650
651 -- // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
652 -- // Does not copy entities of course, only copies their reference.
653 -- // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
654 function table.FullCopy( tab )
655
656 if (!tab) then return nil end
657
658 local res = {}
659 for k, v in pairs( tab ) do
660 if (type(v) == "table") then
661 res[k] = table.FullCopy(v) --// recursion ho!
662 elseif (type(v) == "Vector") then
663 res[k] = Vector(v.x, v.y, v.z)
664 elseif (type(v) == "Angle") then
665 res[k] = Angle(v.p, v.y, v.r)
666 else
667 res[k] = v
668 end
669 end
670
671 return res
672
673 end
674end