mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
381 lines
8.8 KiB
Lua
381 lines
8.8 KiB
Lua
|
|
--[[
|
||
|
|
| This file was obtained through the combined efforts
|
||
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
||
|
|
|
|
||
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
||
|
|
|
|
||
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||
|
|
--]]
|
||
|
|
|
||
|
|
AddCSLuaFile()
|
||
|
|
|
||
|
|
SWEP.Category = "[LVS]"
|
||
|
|
SWEP.Spawnable = true
|
||
|
|
SWEP.AdminSpawnable = false
|
||
|
|
SWEP.ViewModel = "models/weapons/c_repairlvs.mdl"
|
||
|
|
SWEP.WorldModel = "models/weapons/w_repairlvs.mdl"
|
||
|
|
SWEP.UseHands = true
|
||
|
|
|
||
|
|
SWEP.HoldType = "slam"
|
||
|
|
|
||
|
|
SWEP.Primary.ClipSize = -1
|
||
|
|
SWEP.Primary.DefaultClip = -1
|
||
|
|
SWEP.Primary.Automatic = true
|
||
|
|
SWEP.Primary.Ammo = "none"
|
||
|
|
|
||
|
|
SWEP.Secondary.ClipSize = -1
|
||
|
|
SWEP.Secondary.DefaultClip = -1
|
||
|
|
SWEP.Secondary.Automatic = false
|
||
|
|
SWEP.Secondary.Ammo = "none"
|
||
|
|
|
||
|
|
SWEP.MaxRange = 250
|
||
|
|
|
||
|
|
function SWEP:SetupDataTables()
|
||
|
|
self:NetworkVar( "Float",0, "FlameTime" )
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetLVS()
|
||
|
|
local ply = self:GetOwner()
|
||
|
|
|
||
|
|
if not IsValid( ply ) then return NULL end
|
||
|
|
|
||
|
|
local ent = ply:GetEyeTrace().Entity
|
||
|
|
|
||
|
|
if not IsValid( ent ) then return NULL end
|
||
|
|
|
||
|
|
if ent.LVS then return ent end
|
||
|
|
|
||
|
|
if not ent.GetBase then return NULL end
|
||
|
|
|
||
|
|
ent = ent:GetBase()
|
||
|
|
|
||
|
|
if IsValid( ent ) and ent.LVS then return ent end
|
||
|
|
|
||
|
|
return NULL
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:FindClosest()
|
||
|
|
local lvsEnt = self:GetLVS()
|
||
|
|
|
||
|
|
if not IsValid( lvsEnt ) then return NULL end
|
||
|
|
|
||
|
|
local ply = self:GetOwner()
|
||
|
|
|
||
|
|
if ply:InVehicle() then return end
|
||
|
|
|
||
|
|
local ShootPos = ply:GetShootPos()
|
||
|
|
local AimVector = ply:GetAimVector()
|
||
|
|
|
||
|
|
local ClosestDist = self.MaxRange
|
||
|
|
local ClosestPiece = NULL
|
||
|
|
|
||
|
|
for _, entity in pairs( lvsEnt:GetChildren() ) do
|
||
|
|
if entity:GetClass() ~= "lvs_armor" then continue end
|
||
|
|
|
||
|
|
local boxOrigin = entity:GetPos()
|
||
|
|
local boxAngles = entity:GetAngles()
|
||
|
|
local boxMins = entity:GetMins()
|
||
|
|
local boxMaxs = entity:GetMaxs()
|
||
|
|
|
||
|
|
local HitPos, _, _ = util.IntersectRayWithOBB( ShootPos, AimVector * 1000, boxOrigin, boxAngles, boxMins, boxMaxs )
|
||
|
|
|
||
|
|
if isvector( HitPos ) then
|
||
|
|
local Dist = (ShootPos - HitPos):Length()
|
||
|
|
|
||
|
|
if Dist < ClosestDist then
|
||
|
|
ClosestDist = Dist
|
||
|
|
ClosestPiece = entity
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return ClosestPiece
|
||
|
|
end
|
||
|
|
|
||
|
|
local function IsEngineMode( AimPos, Engine )
|
||
|
|
if not IsValid( Engine ) then return false end
|
||
|
|
|
||
|
|
if not isfunction( Engine.GetDoorHandler ) then return (AimPos - Engine:GetPos()):Length() < 25 end
|
||
|
|
|
||
|
|
local DoorHandler = Engine:GetDoorHandler()
|
||
|
|
|
||
|
|
if IsValid( DoorHandler ) then
|
||
|
|
if DoorHandler:IsOpen() then
|
||
|
|
return (AimPos - Engine:GetPos()):Length() < 50
|
||
|
|
end
|
||
|
|
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
return (AimPos - Engine:GetPos()):Length() < 25
|
||
|
|
end
|
||
|
|
|
||
|
|
if CLIENT then
|
||
|
|
SWEP.PrintName = "Repair Torch"
|
||
|
|
SWEP.Author = "Blu-x92"
|
||
|
|
|
||
|
|
SWEP.Slot = 5
|
||
|
|
SWEP.SlotPos = 1
|
||
|
|
|
||
|
|
SWEP.Purpose = "Repair Broken Armor"
|
||
|
|
SWEP.Instructions = "Primary to Repair\nHold Secondary to switch to Armor Repair Mode"
|
||
|
|
SWEP.DrawWeaponInfoBox = true
|
||
|
|
|
||
|
|
SWEP.WepSelectIcon = surface.GetTextureID( "weapons/lvsrepair" )
|
||
|
|
|
||
|
|
local ColorSelect = Color(0,255,255,50)
|
||
|
|
local ColorText = Color(255,255,255,255)
|
||
|
|
|
||
|
|
local function DrawText( pos, text, col )
|
||
|
|
cam.Start2D()
|
||
|
|
local data2D = pos:ToScreen()
|
||
|
|
|
||
|
|
if not data2D.visible then return end
|
||
|
|
|
||
|
|
local font = "TargetIDSmall"
|
||
|
|
|
||
|
|
local x = data2D.x
|
||
|
|
local y = data2D.y
|
||
|
|
|
||
|
|
draw.DrawText( text, font, x + 1, y + 1, Color( 0, 0, 0, 120 ), TEXT_ALIGN_CENTER )
|
||
|
|
draw.DrawText( text, font, x + 2, y + 2, Color( 0, 0, 0, 50 ), TEXT_ALIGN_CENTER )
|
||
|
|
draw.DrawText( text, font, x, y, col or color_white, TEXT_ALIGN_CENTER )
|
||
|
|
cam.End2D()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:DrawEffects( weapon, ply )
|
||
|
|
local ID = weapon:LookupAttachment( "muzzle" )
|
||
|
|
|
||
|
|
local Muzzle = weapon:GetAttachment( ID )
|
||
|
|
|
||
|
|
if not Muzzle then return end
|
||
|
|
|
||
|
|
local T = CurTime()
|
||
|
|
|
||
|
|
if self:GetFlameTime() < T or (self._NextFX1 or 0) > T then return end
|
||
|
|
|
||
|
|
self._NextFX1 = T + 0.02
|
||
|
|
|
||
|
|
local effectdata = EffectData()
|
||
|
|
effectdata:SetOrigin( Muzzle.Pos )
|
||
|
|
effectdata:SetAngles( Muzzle.Ang )
|
||
|
|
effectdata:SetScale( 0.5 )
|
||
|
|
util.Effect( "MuzzleEffect", effectdata, true, true )
|
||
|
|
|
||
|
|
if (self._NextFX2 or 0) > T then return end
|
||
|
|
|
||
|
|
self._NextFX2 = T + 0.06
|
||
|
|
|
||
|
|
local trace = ply:GetEyeTrace()
|
||
|
|
local ShootPos = ply:GetShootPos()
|
||
|
|
|
||
|
|
if (ShootPos - trace.HitPos):Length() > self.MaxRange then return end
|
||
|
|
|
||
|
|
local effectdata = EffectData()
|
||
|
|
effectdata:SetOrigin( trace.HitPos )
|
||
|
|
effectdata:SetNormal( trace.HitNormal * 0.15 )
|
||
|
|
util.Effect( "manhacksparks", effectdata, true, true )
|
||
|
|
|
||
|
|
local dlight = DynamicLight( self:EntIndex() )
|
||
|
|
|
||
|
|
if not dlight then return end
|
||
|
|
|
||
|
|
dlight.pos = (trace.HitPos + ShootPos) * 0.5
|
||
|
|
dlight.r = 206
|
||
|
|
dlight.g = 253
|
||
|
|
dlight.b = 255
|
||
|
|
dlight.brightness = 3
|
||
|
|
dlight.decay = 1000
|
||
|
|
dlight.size = 256
|
||
|
|
dlight.dietime = CurTime() + 0.1
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:PostDrawViewModel( vm, weapon, ply )
|
||
|
|
self:DrawEffects( vm, ply )
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:DrawWorldModel( flags )
|
||
|
|
self:DrawModel( flags )
|
||
|
|
self:DrawEffects( self, self:GetOwner() )
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:DrawHUD()
|
||
|
|
local ply = self:GetOwner()
|
||
|
|
|
||
|
|
if not IsValid( ply ) or not ply:KeyDown( IN_ATTACK2 ) then
|
||
|
|
local lvsEnt = self:GetLVS()
|
||
|
|
local Pos = ply:GetEyeTrace().HitPos
|
||
|
|
|
||
|
|
if IsValid( lvsEnt ) and (Pos - ply:GetShootPos()):Length() < self.MaxRange and not ply:InVehicle() then
|
||
|
|
if isfunction( lvsEnt.GetEngine ) then
|
||
|
|
local Engine = lvsEnt:GetEngine()
|
||
|
|
|
||
|
|
local AimPos = ply:GetEyeTrace().HitPos
|
||
|
|
|
||
|
|
local EngineMode = IsEngineMode( AimPos, Engine )
|
||
|
|
|
||
|
|
if IsValid( Engine ) and EngineMode then
|
||
|
|
DrawText( AimPos, "Engine\nHealth: "..math.Round(Engine:GetHP()).."/"..Engine:GetMaxHP(), ColorText )
|
||
|
|
else
|
||
|
|
DrawText( AimPos, "Frame\nHealth: "..math.Round(lvsEnt:GetHP()).."/"..lvsEnt:GetMaxHP(), ColorText )
|
||
|
|
end
|
||
|
|
else
|
||
|
|
DrawText( ply:GetEyeTrace().HitPos, "Frame\nHealth: "..math.Round(lvsEnt:GetHP()).."/"..lvsEnt:GetMaxHP(), ColorText )
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local Target = self:FindClosest()
|
||
|
|
|
||
|
|
if IsValid( Target ) then
|
||
|
|
local boxOrigin = Target:GetPos()
|
||
|
|
local boxAngles = Target:GetAngles()
|
||
|
|
local boxMins = Target:GetMins()
|
||
|
|
local boxMaxs = Target:GetMaxs()
|
||
|
|
|
||
|
|
cam.Start3D()
|
||
|
|
render.SetColorMaterial()
|
||
|
|
render.DrawBox( boxOrigin, boxAngles, boxMins, boxMaxs, ColorSelect )
|
||
|
|
cam.End3D()
|
||
|
|
|
||
|
|
DrawText( Target:LocalToWorld( (boxMins + boxMaxs) * 0.5 ), (Target:GetIgnoreForce() / 100).."mm "..Target:GetLabel().."\nHealth: "..math.Round(Target:GetHP()).."/"..Target:GetMaxHP(), ColorText )
|
||
|
|
else
|
||
|
|
local Pos = ply:GetEyeTrace().HitPos
|
||
|
|
|
||
|
|
if IsValid( self:GetLVS() ) and (Pos - ply:GetShootPos()):Length() < self.MaxRange and not ply:InVehicle() then
|
||
|
|
DrawText( Pos, "No Armor", ColorText )
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:Initialize()
|
||
|
|
self:SetHoldType( self.HoldType )
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:PrimaryAttack()
|
||
|
|
local T = CurTime()
|
||
|
|
|
||
|
|
self:SetNextPrimaryFire( T + 0.15 )
|
||
|
|
|
||
|
|
self:SetFlameTime( T + 0.3 )
|
||
|
|
|
||
|
|
local EngineMode = false
|
||
|
|
local ArmorMode = true
|
||
|
|
local Target = self:FindClosest()
|
||
|
|
|
||
|
|
local ply = self:GetOwner()
|
||
|
|
|
||
|
|
if IsValid( ply ) and not ply:KeyDown( IN_ATTACK2 ) then
|
||
|
|
Target = self:GetLVS()
|
||
|
|
|
||
|
|
if isfunction( Target.GetEngine ) then
|
||
|
|
local Engine = Target:GetEngine()
|
||
|
|
|
||
|
|
local AimPos = ply:GetEyeTrace().HitPos
|
||
|
|
|
||
|
|
EngineMode = IsEngineMode( AimPos, Engine )
|
||
|
|
|
||
|
|
if IsValid( Engine ) and EngineMode then
|
||
|
|
Target = Engine
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
ArmorMode = false
|
||
|
|
end
|
||
|
|
|
||
|
|
if not IsValid( Target ) then
|
||
|
|
local ent = ply:GetEyeTrace().Entity
|
||
|
|
|
||
|
|
if IsValid( ent ) and (ent:GetPos() - ply:GetShootPos()):Length() < self.MaxRange and ent:GetClass() == "lvs_item_mine" then
|
||
|
|
if SERVER then timer.Simple(0, function() if not IsValid( ent ) then return end ent:Detonate() end ) end
|
||
|
|
end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local HP = Target:GetHP()
|
||
|
|
local MaxHP = Target:GetMaxHP()
|
||
|
|
|
||
|
|
if IsFirstTimePredicted() then
|
||
|
|
local trace = ply:GetEyeTrace()
|
||
|
|
|
||
|
|
if HP ~= MaxHP then
|
||
|
|
local effectdata = EffectData()
|
||
|
|
effectdata:SetOrigin( trace.HitPos )
|
||
|
|
effectdata:SetNormal( trace.HitNormal )
|
||
|
|
util.Effect( "stunstickimpact", effectdata, true, true )
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if CLIENT then return end
|
||
|
|
|
||
|
|
Target:SetHP( math.min( HP + 7, MaxHP ) )
|
||
|
|
|
||
|
|
if EngineMode and Target:GetDestroyed() then
|
||
|
|
Target:SetDestroyed( false )
|
||
|
|
end
|
||
|
|
|
||
|
|
if not ArmorMode then return end
|
||
|
|
|
||
|
|
if Target:GetDestroyed() then Target:SetDestroyed( false ) end
|
||
|
|
|
||
|
|
if HP < MaxHP then return end
|
||
|
|
|
||
|
|
Target:OnRepaired()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:SecondaryAttack()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:Think()
|
||
|
|
local ply = self:GetOwner()
|
||
|
|
|
||
|
|
if not IsValid( ply ) then self:StopSND() return end
|
||
|
|
|
||
|
|
local PlaySound = self:GetFlameTime() >= CurTime() and (ply:GetShootPos() - ply:GetEyeTrace().HitPos):Length() < self.MaxRange
|
||
|
|
|
||
|
|
if PlaySound then
|
||
|
|
self:PlaySND()
|
||
|
|
else
|
||
|
|
self:StopSND()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:StopSND()
|
||
|
|
if CLIENT then return end
|
||
|
|
|
||
|
|
if not self._snd then return end
|
||
|
|
|
||
|
|
self._snd:Stop()
|
||
|
|
self._snd = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:PlaySND()
|
||
|
|
if CLIENT then return end
|
||
|
|
|
||
|
|
if self._snd then return end
|
||
|
|
|
||
|
|
local ply = self:GetOwner()
|
||
|
|
|
||
|
|
if not IsValid( ply ) then return end
|
||
|
|
|
||
|
|
self._snd = CreateSound( ply, "lvs/weldingtorch_loop.wav" )
|
||
|
|
self._snd:PlayEx(1, 70 )
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:OnRemove()
|
||
|
|
self:StopSND()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:OnDrop()
|
||
|
|
self:StopSND()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:Holster( wep )
|
||
|
|
self:StopSND()
|
||
|
|
return true
|
||
|
|
end
|