mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
45
lua/entities/lvs_base_gunner/cl_init.lua
Normal file
45
lua/entities/lvs_base_gunner/cl_init.lua
Normal file
@@ -0,0 +1,45 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
end
|
||||
|
||||
function ENT:GetAimVector()
|
||||
if self:GetAI() then
|
||||
return self:GetNWAimVector()
|
||||
end
|
||||
|
||||
local Driver = self:GetDriver()
|
||||
|
||||
if IsValid( Driver ) then
|
||||
if self._AimVectorUnlocked then
|
||||
local pod = self:GetDriverSeat()
|
||||
|
||||
if IsValid( pod ) then
|
||||
return pod:WorldToLocalAngles( Driver:EyeAngles() ):Forward()
|
||||
end
|
||||
end
|
||||
|
||||
return Driver:GetAimVector()
|
||||
else
|
||||
return self:GetForward()
|
||||
end
|
||||
end
|
||||
304
lua/entities/lvs_base_gunner/init.lua
Normal file
304
lua/entities/lvs_base_gunner/init.lua
Normal file
@@ -0,0 +1,304 @@
|
||||
--[[
|
||||
| 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( "shared.lua" )
|
||||
AddCSLuaFile( "cl_init.lua" )
|
||||
include("shared.lua")
|
||||
include("sv_ai.lua")
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
self:HandleActive()
|
||||
self:WeaponsThink()
|
||||
|
||||
if self:GetAI() then
|
||||
self:RunAI()
|
||||
end
|
||||
|
||||
self:NextThink( CurTime() )
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:HandleActive()
|
||||
local Pod = self:GetDriverSeat()
|
||||
|
||||
if not IsValid( Pod ) then
|
||||
return
|
||||
end
|
||||
|
||||
local Driver = Pod:GetDriver()
|
||||
|
||||
if Driver ~= self:GetDriver() then
|
||||
local NewDriver = Driver
|
||||
local OldDriver = self:GetDriver()
|
||||
|
||||
self:SetDriver( Driver )
|
||||
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if IsValid( Base ) then
|
||||
Base:OnPassengerChanged( OldDriver, NewDriver, Pod:GetNWInt( "pPodIndex", -1 ) )
|
||||
end
|
||||
|
||||
if IsValid( Driver ) then
|
||||
Driver:lvsBuildControls()
|
||||
else
|
||||
self:WeaponsFinish()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
|
||||
function ENT:WeaponsFinish()
|
||||
if not self._activeWeapon then return end
|
||||
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return end
|
||||
|
||||
local CurWeapon = Base.WEAPONS[ self:GetPodIndex() ][ self._activeWeapon ]
|
||||
|
||||
if not CurWeapon then return end
|
||||
|
||||
if CurWeapon.FinishAttack then
|
||||
CurWeapon.FinishAttack( self )
|
||||
end
|
||||
|
||||
self._activeWeapon = nil
|
||||
self.OldAttack = false
|
||||
end
|
||||
|
||||
function ENT:GetAmmo()
|
||||
if self:GetAI() then return self:GetMaxAmmo() end
|
||||
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
if not CurWeapon then return -1 end
|
||||
|
||||
return CurWeapon._CurAmmo or self:GetMaxAmmo()
|
||||
end
|
||||
|
||||
function ENT:TakeAmmo( num )
|
||||
if self:GetMaxAmmo() <= 0 then return end
|
||||
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
CurWeapon._CurAmmo = math.max( self:GetAmmo() - (num or 1), 0 )
|
||||
|
||||
self:SetNWAmmo( CurWeapon._CurAmmo )
|
||||
end
|
||||
|
||||
function ENT:GetHeat()
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
if not CurWeapon then return 0 end
|
||||
|
||||
return (CurWeapon._CurHeat or 0)
|
||||
end
|
||||
|
||||
function ENT:GetOverheated()
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
if not CurWeapon then return false end
|
||||
|
||||
return CurWeapon.Overheated == true
|
||||
end
|
||||
|
||||
function ENT:SetOverheated( overheat )
|
||||
if self:GetOverheated() == overheat then return end
|
||||
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
if not CurWeapon then return end
|
||||
|
||||
CurWeapon.Overheated = overheat
|
||||
|
||||
if self:GetHeat() == 0 then return end
|
||||
|
||||
if CurWeapon.OnOverheat then
|
||||
CurWeapon.OnOverheat( self )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:SetHeat( heat )
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
if not CurWeapon then return end
|
||||
|
||||
heat = math.Clamp( heat, 0, 1 )
|
||||
|
||||
CurWeapon._CurHeat = heat
|
||||
|
||||
if self:GetNWHeat() == heat then return end
|
||||
|
||||
self:SetNWHeat( heat )
|
||||
end
|
||||
|
||||
function ENT:CanAttack()
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
return (CurWeapon._NextFire or 0) < CurTime()
|
||||
end
|
||||
|
||||
function ENT:SetNextAttack( time )
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
CurWeapon._NextFire = time
|
||||
end
|
||||
|
||||
function ENT:WeaponsShouldFire()
|
||||
if self:GetAI() then return self._AIFireInput end
|
||||
|
||||
local ply = self:GetDriver()
|
||||
|
||||
if not IsValid( ply ) then return false end
|
||||
|
||||
return ply:lvsKeyDown( "ATTACK" )
|
||||
end
|
||||
|
||||
function ENT:WeaponsThink()
|
||||
local T = CurTime()
|
||||
local FT = FrameTime()
|
||||
local CurWeapon, SelectedID = self:GetActiveWeapon()
|
||||
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return end
|
||||
|
||||
for ID, Weapon in pairs( Base.WEAPONS[ self:GetPodIndex() ] ) do
|
||||
local IsActive = ID == SelectedID
|
||||
if Weapon.OnThink then Weapon.OnThink( self, IsActive ) end
|
||||
|
||||
if IsActive then continue end
|
||||
|
||||
-- cool all inactive weapons down
|
||||
Weapon._CurHeat = Weapon._CurHeat and Weapon._CurHeat - math.min( Weapon._CurHeat, (Weapon.HeatRateDown or 0.25) * FT ) or 0
|
||||
end
|
||||
|
||||
if not CurWeapon then return end
|
||||
|
||||
local ShouldFire = self:WeaponsShouldFire()
|
||||
local CurHeat = self:GetHeat()
|
||||
|
||||
if self:GetOverheated() then
|
||||
if CurHeat <= 0 then
|
||||
self:SetOverheated( false )
|
||||
else
|
||||
ShouldFire = false
|
||||
end
|
||||
else
|
||||
if CurHeat >= 1 then
|
||||
self:SetOverheated( true )
|
||||
ShouldFire = false
|
||||
end
|
||||
end
|
||||
|
||||
if self:GetMaxAmmo() > 0 then
|
||||
if self:GetAmmo() <= 0 then
|
||||
ShouldFire = false
|
||||
end
|
||||
end
|
||||
|
||||
if ShouldFire ~= self.OldAttack then
|
||||
self.OldAttack = ShouldFire
|
||||
|
||||
if ShouldFire then
|
||||
if CurWeapon.StartAttack then
|
||||
CurWeapon.StartAttack( self )
|
||||
end
|
||||
self._activeWeapon = SelectedID
|
||||
else
|
||||
self:WeaponsFinish()
|
||||
end
|
||||
end
|
||||
|
||||
if ShouldFire then
|
||||
if not self:CanAttack() then return end
|
||||
|
||||
local ShootDelay = (CurWeapon.Delay or 0)
|
||||
|
||||
self:SetNextAttack( T + ShootDelay )
|
||||
self:SetHeat( CurHeat + (CurWeapon.HeatRateUp or 0.2) * math.max(ShootDelay, FT) )
|
||||
|
||||
if not CurWeapon.Attack then return end
|
||||
|
||||
if CurWeapon.Attack( self ) then
|
||||
self:SetHeat( CurHeat - math.min( self:GetHeat(), (CurWeapon.HeatRateDown or 0.25) * FT ) )
|
||||
self:SetNextAttack( T )
|
||||
end
|
||||
else
|
||||
self:SetHeat( self:GetHeat() - math.min( self:GetHeat(), (CurWeapon.HeatRateDown or 0.25) * FT ) )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:SelectWeapon( ID )
|
||||
if not isnumber( ID ) then return end
|
||||
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return end
|
||||
|
||||
if Base.WEAPONS[ self:GetPodIndex() ][ ID ] then
|
||||
self:SetSelectedWeapon( ID )
|
||||
end
|
||||
|
||||
local ply = self:GetDriver()
|
||||
|
||||
if not IsValid( ply ) then return end
|
||||
|
||||
net.Start( "lvs_select_weapon" )
|
||||
net.Send( ply )
|
||||
end
|
||||
|
||||
function ENT:OnWeaponChanged( name, old, new)
|
||||
if new == old then return end
|
||||
|
||||
self:WeaponsFinish()
|
||||
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return end
|
||||
|
||||
local PrevWeapon = Base.WEAPONS[ self:GetPodIndex() ][ old ]
|
||||
if PrevWeapon and PrevWeapon.OnDeselect then
|
||||
PrevWeapon.OnDeselect( self )
|
||||
end
|
||||
|
||||
local NextWeapon = Base.WEAPONS[ self:GetPodIndex() ][ new ]
|
||||
if NextWeapon and NextWeapon.OnSelect then
|
||||
NextWeapon.OnSelect( self )
|
||||
self:SetNWAmmo( NextWeapon._CurAmmo or NextWeapon.Ammo or -1 )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:LVSFireBullet( data )
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return end
|
||||
|
||||
data.Entity = Base
|
||||
|
||||
data.Velocity = data.Velocity + self:GetVelocity():Length()
|
||||
data.SrcEntity = Base:WorldToLocal( data.Src )
|
||||
|
||||
LVS:FireBullet( data )
|
||||
end
|
||||
166
lua/entities/lvs_base_gunner/shared.lua
Normal file
166
lua/entities/lvs_base_gunner/shared.lua
Normal file
@@ -0,0 +1,166 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.PrintName = "LBaseGunner"
|
||||
ENT.Author = "Luna"
|
||||
ENT.Information = "Luna's Vehicle Script"
|
||||
ENT.Category = "[LVS]"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
ENT.DoNotDuplicate = true
|
||||
|
||||
ENT.LVS_GUNNER = true
|
||||
ENT.VectorNull = Vector(0,0,0)
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar( "Entity",0, "Driver" )
|
||||
self:NetworkVar( "Entity",1, "DriverSeat" )
|
||||
|
||||
self:NetworkVar( "Int", 0, "PodIndex")
|
||||
self:NetworkVar( "Int", 1, "NWAmmo")
|
||||
self:NetworkVar( "Int", 2, "SelectedWeapon" )
|
||||
|
||||
self:NetworkVar( "Float", 0, "NWHeat" )
|
||||
|
||||
self:NetworkVar( "Vector", 0, "NWAimVector" )
|
||||
|
||||
if SERVER then
|
||||
self:NetworkVarNotify( "SelectedWeapon", self.OnWeaponChanged )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:UnlockAimVector()
|
||||
self._AimVectorUnlocked = true
|
||||
end
|
||||
|
||||
function ENT:LockAimVector()
|
||||
self._AimVectorUnlocked = nil
|
||||
end
|
||||
|
||||
function ENT:GetEyeTrace()
|
||||
local startpos = self:GetPos()
|
||||
|
||||
local trace = util.TraceLine( {
|
||||
start = startpos,
|
||||
endpos = (startpos + self:GetAimVector() * 50000),
|
||||
filter = self:GetCrosshairFilterEnts()
|
||||
} )
|
||||
|
||||
return trace
|
||||
end
|
||||
|
||||
function ENT:GetAI()
|
||||
if IsValid( self:GetDriver() ) then return false end
|
||||
|
||||
local veh = self:GetVehicle()
|
||||
|
||||
if not IsValid( veh ) then return false end
|
||||
|
||||
return veh:GetAI()
|
||||
end
|
||||
|
||||
function ENT:GetAITEAM()
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return 0 end
|
||||
|
||||
return Base:GetAITEAM()
|
||||
end
|
||||
|
||||
function ENT:GetVehicle()
|
||||
local Pod = self:GetParent()
|
||||
|
||||
if not IsValid( Pod ) then return NULL end
|
||||
|
||||
return Pod:GetParent()
|
||||
end
|
||||
|
||||
function ENT:HasWeapon( ID )
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return false end
|
||||
|
||||
return istable( Base.WEAPONS[ self:GetPodIndex() ][ ID ] )
|
||||
end
|
||||
|
||||
function ENT:AIHasWeapon( ID )
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return false end
|
||||
|
||||
local weapon = Base.WEAPONS[ self:GetPodIndex() ][ ID ]
|
||||
|
||||
if not istable( weapon ) then return false end
|
||||
|
||||
return weapon.UseableByAI
|
||||
end
|
||||
|
||||
function ENT:GetActiveWeapon()
|
||||
local SelectedID = self:GetSelectedWeapon()
|
||||
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return {}, SelectedID end
|
||||
|
||||
local CurWeapon = Base.WEAPONS[ self:GetPodIndex() ][ SelectedID ]
|
||||
|
||||
return CurWeapon, SelectedID
|
||||
end
|
||||
|
||||
function ENT:GetMaxAmmo()
|
||||
local CurWeapon = self:GetActiveWeapon()
|
||||
|
||||
if not CurWeapon then return -1 end
|
||||
|
||||
return CurWeapon.Ammo or -1
|
||||
end
|
||||
|
||||
function ENT:GetCrosshairFilterEnts()
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return {} end
|
||||
|
||||
return Base:GetCrosshairFilterEnts()
|
||||
end
|
||||
|
||||
function ENT:Sign( n )
|
||||
if n > 0 then return 1 end
|
||||
|
||||
if n < 0 then return -1 end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
function ENT:VectorSubtractNormal( Normal, Velocity )
|
||||
local VelForward = Velocity:GetNormalized()
|
||||
|
||||
local Ax = math.acos( math.Clamp( Normal:Dot( VelForward ) ,-1,1) )
|
||||
|
||||
local Fx = math.cos( Ax ) * Velocity:Length()
|
||||
|
||||
local NewVelocity = Velocity - Normal * math.abs( Fx )
|
||||
|
||||
return NewVelocity
|
||||
end
|
||||
|
||||
function ENT:VectorSplitNormal( Normal, Velocity )
|
||||
return math.cos( math.acos( math.Clamp( Normal:Dot( Velocity:GetNormalized() ) ,-1,1) ) ) * Velocity:Length()
|
||||
end
|
||||
|
||||
function ENT:AngleBetweenNormal( Dir1, Dir2 )
|
||||
return math.deg( math.acos( math.Clamp( Dir1:Dot( Dir2 ) ,-1,1) ) )
|
||||
end
|
||||
|
||||
function ENT:GetVehicleType()
|
||||
return "LBaseGunner"
|
||||
end
|
||||
101
lua/entities/lvs_base_gunner/sv_ai.lua
Normal file
101
lua/entities/lvs_base_gunner/sv_ai.lua
Normal file
@@ -0,0 +1,101 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
function ENT:GetAimVector()
|
||||
if self:GetAI() then
|
||||
local Dir = self._ai_look_dir or self.VectorNull
|
||||
|
||||
self:SetNWAimVector( Dir )
|
||||
|
||||
return Dir
|
||||
end
|
||||
|
||||
local Driver = self:GetDriver()
|
||||
|
||||
if IsValid( Driver ) then
|
||||
if self._AimVectorUnlocked then
|
||||
local pod = self:GetDriverSeat()
|
||||
|
||||
if IsValid( pod ) then
|
||||
return pod:WorldToLocalAngles( Driver:EyeAngles() ):Forward()
|
||||
end
|
||||
end
|
||||
|
||||
return Driver:GetAimVector()
|
||||
else
|
||||
return self:GetForward()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:AITargetInFront( ent, range )
|
||||
if not IsValid( ent ) then return false end
|
||||
|
||||
if not range then range = 45 end
|
||||
|
||||
local DirToTarget = (ent:GetPos() - self:GetPos()):GetNormalized()
|
||||
|
||||
local InFront = math.deg( math.acos( math.Clamp( self:GetForward():Dot( DirToTarget ) ,-1,1) ) ) < range
|
||||
|
||||
return InFront
|
||||
end
|
||||
|
||||
function ENT:RunAI()
|
||||
local Target = self:AIGetTarget()
|
||||
|
||||
if not IsValid( Target ) then
|
||||
self._ai_look_dir = self:GetForward()
|
||||
self._AIFireInput = false
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local TargetPos = Target:GetPos()
|
||||
|
||||
if self._AIFireInput then
|
||||
local T = CurTime() * 0.5 + self:EntIndex()
|
||||
local X = math.cos( T ) * 32
|
||||
local Y = math.sin( T ) * 32
|
||||
local Z = math.sin( math.cos( T / 0.5 ) * math.pi ) * 32
|
||||
TargetPos = Target:LocalToWorld( Target:OBBCenter() + Vector(X,Y,Z) )
|
||||
end
|
||||
|
||||
self._ai_look_dir = (TargetPos - self:GetPos()):GetNormalized()
|
||||
|
||||
local StartPos = self:GetPos()
|
||||
|
||||
local trace = util.TraceHull( {
|
||||
start = StartPos,
|
||||
endpos = (StartPos + self._ai_look_dir * 50000),
|
||||
mins = Vector( -50, -50, -50 ),
|
||||
maxs = Vector( 50, 50, 50 ),
|
||||
filter = self:GetCrosshairFilterEnts()
|
||||
} )
|
||||
|
||||
if not self:AIHasWeapon( self:GetSelectedWeapon() ) then
|
||||
self._AIFireInput = false
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if IsValid( trace.Entity ) and trace.Entity.GetAITEAM then
|
||||
self._AIFireInput = (trace.Entity:GetAITEAM() ~= self:GetAITEAM() or trace.Entity:GetAITEAM() == 0)
|
||||
else
|
||||
self._AIFireInput = true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:AIGetTarget()
|
||||
local Base = self:GetVehicle()
|
||||
|
||||
if not IsValid( Base ) then return NULL end
|
||||
|
||||
return Base:AIGetTarget()
|
||||
end
|
||||
Reference in New Issue
Block a user