add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
ENT._lvsSmoothFreeLook = 0
function ENT:CalcViewDirectInput( ply, pos, angles, fov, pod )
local ViewPosL = pod:WorldToLocal( pos )
local view = {}
view.fov = fov
view.drawviewer = true
view.angles = self:GetAngles()
local FreeLook = ply:lvsKeyDown( "FREELOOK" )
local Zoom = ply:lvsKeyDown( "ZOOM" )
if not pod:GetThirdPersonMode() then
if FreeLook then
view.angles = pod:LocalToWorldAngles( ply:EyeAngles() )
end
local velL = self:WorldToLocal( self:GetPos() + self:GetVelocity() )
local Dividor = math.abs( velL.x )
local SideForce = math.Clamp( velL.y / Dividor, -1, 1)
local UpForce = math.Clamp( velL.z / Dividor, -1, 1)
local ViewPunch = Vector(0,math.Clamp(SideForce * 10,-1,1),math.Clamp(UpForce * 10,-1,1))
if Zoom then
ViewPunch = Vector(0,0,0)
end
pod._lerpPosOffset = pod._lerpPosOffset and pod._lerpPosOffset + (ViewPunch - pod._lerpPosOffset) * RealFrameTime() * 5 or Vector(0,0,0)
pod._lerpPos = pos
view.origin = pos + pod:GetForward() * -pod._lerpPosOffset.y * 0.5 + pod:GetUp() * pod._lerpPosOffset.z * 0.5
view.angles.p = view.angles.p - pod._lerpPosOffset.z * 0.1
view.angles.y = view.angles.y + pod._lerpPosOffset.y * 0.1
view.drawviewer = false
return view
end
pod._lerpPos = pod._lerpPos or self:GetPos()
local radius = 550
radius = radius + radius * pod:GetCameraDistance()
if FreeLook then
local velL = self:WorldToLocal( self:GetPos() + self:GetVelocity() )
local SideForce = math.Clamp(velL.y / 10,-250,250)
local UpForce = math.Clamp(velL.z / 10,-250,250)
pod._lerpPosL = pod._lerpPosL and (pod._lerpPosL + (Vector(radius, SideForce,150 + radius * 0.1 + radius * pod:GetCameraHeight() + UpForce) - pod._lerpPosL) * RealFrameTime() * 12) or Vector(0,0,0)
pod._lerpPos = self:LocalToWorld( pod._lerpPosL )
view.origin = pod._lerpPos
view.angles = self:LocalToWorldAngles( Angle(0,180,0) )
else
local TargetPos = self:LocalToWorld( Vector(500,0,150 + radius * 0.1 + radius * pod:GetCameraHeight()) )
local Sub = TargetPos - pod._lerpPos
local Dir = Sub:GetNormalized()
local Dist = Sub:Length()
local DesiredPos = TargetPos - self:GetForward() * (300 + radius) - Dir * 100
pod._lerpPos = pod._lerpPos + (DesiredPos - pod._lerpPos) * RealFrameTime() * (Zoom and 30 or 12)
pod._lerpPosL = self:WorldToLocal( pod._lerpPos )
local vel = self:GetVelocity()
view.origin = pod._lerpPos
view.angles = self:GetAngles()
end
view.origin = view.origin + ViewPosL
return view
end
function ENT:CalcViewMouseAim( ply, pos, angles, fov, pod )
local cvarFocus = math.Clamp( LVS.cvarCamFocus:GetFloat() , -1, 1 )
self._lvsSmoothFreeLook = self._lvsSmoothFreeLook + ((ply:lvsKeyDown( "FREELOOK" ) and 0 or 1) - self._lvsSmoothFreeLook) * RealFrameTime() * 10
local view = {}
view.origin = pos
view.fov = fov
view.drawviewer = true
view.angles = (self:GetForward() * (1 + cvarFocus) * self._lvsSmoothFreeLook * 0.8 + ply:EyeAngles():Forward() * math.max(1 - cvarFocus, 1 - self._lvsSmoothFreeLook)):Angle()
if cvarFocus >= 1 then
view.angles = LerpAngle( self._lvsSmoothFreeLook, ply:EyeAngles(), self:GetAngles() )
else
view.angles.r = 0
end
if not pod:GetThirdPersonMode() then
view.drawviewer = false
return view
end
local radius = 550
radius = radius + radius * pod:GetCameraDistance()
local TargetOrigin = view.origin - view.angles:Forward() * radius + view.angles:Up() * (radius * 0.2 + radius * pod:GetCameraHeight())
local WallOffset = 4
local tr = util.TraceHull( {
start = view.origin,
endpos = TargetOrigin,
filter = function( e )
local c = e:GetClass()
local collide = not c:StartWith( "prop_physics" ) and not c:StartWith( "prop_dynamic" ) and not c:StartWith( "prop_ragdoll" ) and not e:IsVehicle() and not c:StartWith( "gmod_" ) and not c:StartWith( "lvs_" ) and not c:StartWith( "player" ) and not e.LVS
return collide
end,
mins = Vector( -WallOffset, -WallOffset, -WallOffset ),
maxs = Vector( WallOffset, WallOffset, WallOffset ),
} )
view.origin = tr.HitPos
if tr.Hit and not tr.StartSolid then
view.origin = view.origin + tr.HitNormal * WallOffset
end
return view
end
function ENT:CalcViewOverride( ply, pos, angles, fov, pod )
return pos, angles, fov
end
function ENT:CalcViewDriver( ply, pos, angles, fov, pod )
if ply:lvsMouseAim() then
return self:CalcViewMouseAim( ply, pos, angles, fov, pod )
else
return self:CalcViewDirectInput( ply, pos, angles, fov, pod )
end
end
function ENT:CalcViewPassenger( ply, pos, angles, fov, pod )
return LVS:CalcView( self, ply, pos, angles, fov, pod )
end
function ENT:LVSCalcView( ply, original_pos, original_angles, original_fov, pod )
local pos, angles, fov = self:CalcViewOverride( ply, original_pos, original_angles, original_fov, pod )
if self:GetDriverSeat() == pod then
return self:CalcViewDriver( ply, pos, angles, fov, pod )
else
return self:CalcViewPassenger( ply, pos, angles, fov, pod )
end
end

View File

@@ -0,0 +1,17 @@
function ENT:OnDestroyed()
if not self.DeathSound then return end
if self:GetVelocity():Length() <= self.MaxVelocity * 0.5 then return end
self._sndDeath = CreateSound( self, self.DeathSound )
self._sndDeath:SetSoundLevel( 125 )
self._sndDeath:PlayEx( 1, 50 + 50 * self:CalcDoppler( LocalPlayer() ) )
end
function ENT:StopDeathSound()
if not self._sndDeath then return end
self._sndDeath:Stop()
end

View File

@@ -0,0 +1,63 @@
ENT.FlyByAdvance = 0
function ENT:FlyByThink()
local ply = LocalPlayer()
if not IsValid( ply ) then return end
local EntTable = self:GetTable()
if ply:lvsGetVehicle() == self then self.OldApproaching = false return end
local ViewEnt = ply:GetViewEntity()
if not IsValid( ViewEnt ) then return end
local Time = CurTime()
if (EntTable._nextflyby or 0) > Time then return end
EntTable._nextflyby = Time + 0.1
local Vel = self:GetVelocity()
if self:GetThrottle() <= 0.75 or Vel:Length() <= EntTable.MaxVelocity * 0.75 then return end
local Sub = ViewEnt:GetPos() - self:GetPos() - Vel * EntTable.FlyByAdvance
local ToPlayer = Sub:GetNormalized()
local VelDir = Vel:GetNormalized()
local ApproachAngle = math.deg( math.acos( math.Clamp( ToPlayer:Dot( VelDir ) ,-1,1) ) )
local Approaching = ApproachAngle < 80
if Approaching ~= EntTable.OldApproaching then
EntTable.OldApproaching = Approaching
if Approaching then
self:StopFlyBy()
else
self:OnFlyBy( 60 + 80 * math.min(ApproachAngle / 140,1) )
end
end
end
function ENT:OnFlyBy( Pitch )
if not self.FlyBySound then return end
local EntTable = self:GetTable()
EntTable.flybysnd = CreateSound( self, EntTable.FlyBySound )
EntTable.flybysnd:SetSoundLevel( 95 )
EntTable.flybysnd:PlayEx( 1, Pitch )
end
function ENT:StopFlyBy()
local EntTable = self:GetTable()
if not EntTable.flybysnd then return end
EntTable.flybysnd:Stop()
EntTable.flybysnd = nil
end

View File

@@ -0,0 +1,72 @@
ENT.IconEngine = Material( "lvs/engine.png" )
function ENT:LVSHudPaintInfoText( X, Y, W, H, ScrX, ScrY, ply )
local speed = math.Round( LVS:GetUnitValue( self:GetVelocity():Length() ) ,0)
draw.DrawText( LVS:GetUnitName().." ", "LVS_FONT", X + 72, Y + 35, color_white, TEXT_ALIGN_RIGHT )
draw.DrawText( speed, "LVS_FONT_HUD_LARGE", X + 72, Y + 20, color_white, TEXT_ALIGN_LEFT )
if ply ~= self:GetDriver() then return end
local Throttle = self:GetThrottle()
local Col = Throttle <= 1 and color_white or Color(0,0,0,255)
local hX = X + W - H * 0.5
local hY = Y + H * 0.25 + H * 0.25
surface.SetMaterial( self.IconEngine )
surface.SetDrawColor( 0, 0, 0, 200 )
surface.DrawTexturedRectRotated( hX + 4, hY + 1, H * 0.5, H * 0.5, 0 )
surface.SetDrawColor( color_white )
surface.DrawTexturedRectRotated( hX + 2, hY - 1, H * 0.5, H * 0.5, 0 )
if not self:GetEngineActive() then
draw.SimpleText( "X" , "LVS_FONT", hX, hY, Color(0,0,0,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
end
self:LVSDrawCircle( hX, hY, H * 0.35, math.min( Throttle, 1 ) )
if Throttle > 1 then
draw.SimpleText( "+"..math.Round((Throttle - 1) * 100,0).."%" , "LVS_FONT", hX, hY, Col, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
end
end
function ENT:LVSPreHudPaint( X, Y, ply )
return true
end
function ENT:LVSHudPaint( X, Y, ply )
if not self:LVSPreHudPaint( X, Y, ply ) then return end
if ply ~= self:GetDriver() then return end
local HitPlane = self:GetEyeTrace( true ).HitPos:ToScreen()
local HitPilot = self:GetEyeTrace().HitPos:ToScreen()
self:PaintCrosshairCenter( HitPlane )
self:PaintCrosshairOuter( HitPilot )
if ply:lvsMouseAim() and not ply:lvsKeyDown( "FREELOOK" ) then
self:LVSHudPaintMouseAim( HitPlane, HitPilot )
end
self:LVSPaintHitMarker( HitPilot )
end
function ENT:LVSHudPaintDirectInput( Pos2D )
self:PaintCrosshairCenter( Pos2D )
self:PaintCrosshairOuter( Pos2D )
end
function ENT:LVSHudPaintMouseAim( HitPlane, HitPilot )
local Sub = Vector(HitPilot.x,HitPilot.y,0) - Vector(HitPlane.x,HitPlane.y,0)
local Len = Sub:Length()
local Dir = Sub:GetNormalized()
surface.SetDrawColor( 255, 255, 255, 100 )
if Len > 20 then
surface.DrawLine( HitPlane.x + Dir.x * 5, HitPlane.y + Dir.y * 5, HitPilot.x - Dir.x * 20, HitPilot.y- Dir.y * 20 )
-- shadow
surface.SetDrawColor( 0, 0, 0, 50 )
surface.DrawLine( HitPlane.x + Dir.x * 5 + 1, HitPlane.y + Dir.y * 5 + 1, HitPilot.x - Dir.x * 20+ 1, HitPilot.y- Dir.y * 20 + 1 )
end
end

View File

@@ -0,0 +1,86 @@
include("shared.lua")
include("cl_camera.lua")
include("sh_camera_eyetrace.lua")
include("cl_hud.lua")
include("cl_flyby.lua")
include("cl_deathsound.lua")
ENT.TrailAlpha = 25
DEFINE_BASECLASS( "lvs_base" )
function ENT:Think()
BaseClass.Think( self )
self.EFxScale = self.EFxScale and (self.EFxScale - self.EFxScale * RealFrameTime()) or 0
self:CalcOnThrottle()
end
function ENT:CalcOnThrottle()
if not self:GetEngineActive() then
self._oldOnTHR = nil
return
end
local Throttle = self:GetThrottle()
if self._oldOnTHR ~= Throttle then
if self._oldOnTHR == 0 and Throttle > 0 then
self._IsAccelerating = true
end
if Throttle > (self._oldOnTHR or 0) then
self._IsAccelerating = true
else
self._IsAccelerating = false
end
if self._oldOnTHR == 1 then
self:StopBoost()
end
self._oldOnTHR = Throttle
end
if self._oldAccelerating ~= self._IsAccelerating then
self._oldAccelerating = self._IsAccelerating
if not self._IsAccelerating then return end
self:StartBoost()
end
end
function ENT:StartBoost()
local T = CurTime()
if (self._NextSND or 0) > T then return end
self._NextSND = T + 1
self.EFxScale = 100
self:OnStartBoost()
end
function ENT:StopBoost()
local T = CurTime()
if (self._NextSND or 0) > T then return end
self._NextSND = T + 1
self:OnStopBoost()
end
function ENT:GetBoost()
return (self.EFxScale or 0)
end
function ENT:OnStartBoost()
end
function ENT:OnStopBoost()
end

View File

@@ -0,0 +1,210 @@
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "cl_camera.lua" )
AddCSLuaFile( "sh_camera_eyetrace.lua" )
AddCSLuaFile( "cl_hud.lua" )
AddCSLuaFile( "cl_flyby.lua" )
AddCSLuaFile( "cl_deathsound.lua" )
include("shared.lua")
include("sv_ai.lua")
include("sv_mouseaim.lua")
include("sv_components.lua")
include("sv_vehiclespecific.lua")
include("sh_camera_eyetrace.lua")
DEFINE_BASECLASS( "lvs_base" )
function ENT:OnDriverChanged( Old, New, VehicleIsActive )
if not VehicleIsActive and self:GetThrottle() == 0 then
self:SetSteer( vector_origin )
self:SetVtolMove( vector_origin )
end
self:OnPassengerChanged( Old, New, 1 )
end
function ENT:StartEngine()
if self:GetEngineActive() or not self:IsEngineStartAllowed() then return end
self:GetPhysicsObject():EnableGravity( false )
BaseClass.StartEngine( self )
end
function ENT:StopEngine()
if not self:GetEngineActive() then return end
self:GetPhysicsObject():EnableGravity( true )
BaseClass.StopEngine( self )
end
function ENT:OnCreateAI()
self:StartEngine()
self.COL_GROUP_OLD = self:GetCollisionGroup()
self:SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS )
end
function ENT:OnRemoveAI()
self:StopEngine()
self:SetCollisionGroup( self.COL_GROUP_OLD or COLLISION_GROUP_NONE )
end
function ENT:ApproachTargetAngle( TargetAngle, OverridePitch, OverrideYaw, OverrideRoll, FreeMovement )
local LocalAngles = self:WorldToLocalAngles( TargetAngle )
if self:GetAI() then self:SetAIAimVector( LocalAngles:Forward() ) end
local LocalAngPitch = LocalAngles.p
local LocalAngYaw = LocalAngles.y
local LocalAngRoll = LocalAngles.r
local TargetForward = TargetAngle:Forward()
local Forward = self:GetForward()
local AngDiff = math.deg( math.acos( math.Clamp( Forward:Dot( TargetForward ) ,-1,1) ) )
local WingFinFadeOut = math.max( (90 - AngDiff ) / 90, 0 )
local RudderFadeOut = math.min( math.max( (120 - AngDiff ) / 120, 0 ) * 3, 1 )
local AngVel = self:GetPhysicsObject():GetAngleVelocity()
local SmoothPitch = math.Clamp( math.Clamp(AngVel.y / 100,-0.25,0.25) / math.abs( LocalAngPitch ), -1, 1 )
local SmoothYaw = math.Clamp( math.Clamp(AngVel.z / 100,-0.25,0.25) / math.abs( LocalAngYaw ), -1, 1 )
local Pitch = math.Clamp( -LocalAngPitch / 10 + SmoothPitch, -1, 1 )
local Yaw = math.Clamp( -LocalAngYaw / 2 + SmoothYaw,-1,1) * RudderFadeOut
local Roll = math.Clamp( (-math.Clamp(LocalAngYaw * 16 * self:GetThrottle(),-90,90) + LocalAngRoll * RudderFadeOut * 0.75) * WingFinFadeOut / 180 , -1 , 1 )
if FreeMovement then
Roll = math.Clamp( -LocalAngYaw * WingFinFadeOut / 180 , -1 , 1 )
end
if OverridePitch and OverridePitch ~= 0 then
Pitch = OverridePitch
end
if OverrideYaw and OverrideYaw ~= 0 then
Yaw = OverrideYaw
end
if OverrideRoll and OverrideRoll ~= 0 then
Roll = OverrideRoll
end
self:SetSteer( Vector( math.Clamp(Roll * 1.25,-1,1), math.Clamp(-Pitch * 1.25,-1,1), -Yaw) )
end
function ENT:CalcAero( phys, deltatime, EntTable )
if not EntTable then
EntTable = self:GetTable()
end
-- mouse aim needs to run at high speed.
if self:GetAI() then
if EntTable._lvsAITargetAng then
self:ApproachTargetAngle( EntTable._lvsAITargetAng )
end
else
local ply = self:GetDriver()
if IsValid( ply ) and ply:lvsMouseAim() then
self:PlayerMouseAim( ply )
end
end
local Steer = self:GetSteer()
local Forward = self:GetForward()
local Left = -self:GetRight()
local Vel = self:GetVelocity()
local VelForward = Vel:GetNormalized()
local GravityPitch = 0
local GravityYaw = 0
-- crash bebehavior
if self:IsDestroyed() then
local WorldGravity = self:GetWorldGravity()
local WorldUp = self:GetWorldUp()
local Up = self:GetUp()
Steer = phys:GetAngleVelocity() / 200
local PitchPull = (math.deg( math.acos( math.Clamp( WorldUp:Dot( Up ) ,-1,1) ) ) - 90) / 90
local YawPull = (math.deg( math.acos( math.Clamp( WorldUp:Dot( Left ) ,-1,1) ) ) - 90) / 90
local GravMul = WorldGravity / 600
GravityPitch = math.abs( PitchPull ) ^ 1.25 * self:Sign( PitchPull ) * GravMul
GravityYaw = math.abs( YawPull ) ^ 1.25 * self:Sign( YawPull ) * GravMul
if not phys:IsGravityEnabled() then
phys:EnableGravity( true )
end
end
local Pitch = math.Clamp(Steer.y - GravityPitch,-1,1) * EntTable.TurnRatePitch * 3
local Yaw = math.Clamp(Steer.z * 4 + GravityYaw,-1,1) * EntTable.TurnRateYaw
local Roll = math.Clamp(Steer.x * 1.5,-1,1) * EntTable.TurnRateRoll * 12
local VelL = self:WorldToLocal( self:GetPos() + Vel )
local MulZ = (math.max( math.deg( math.acos( math.Clamp( VelForward:Dot( Forward ) ,-1,1) ) ) - math.abs( Steer.y ), 0 ) / 90) * 0.3
local MulY = (math.max( math.abs( math.deg( math.acos( math.Clamp( VelForward:Dot( Left ) ,-1,1) ) ) - 90 ) - math.abs( Steer.z ), 0 ) / 90) * 0.15
local VtolMove = self:GetVtolMove()
local Move = Vector( (VtolMove.x < 0) and -math.min(VelL.x * 0.15,0) or 0, -VelL.y * MulY, -VelL.z * MulZ ) + VtolMove
return Move, Vector( Roll, Pitch, Yaw )
end
function ENT:OnSkyCollide( data, PhysObj )
local NewVelocity = self:VectorSubtractNormal( data.HitNormal, data.OurOldVelocity ) - data.HitNormal * math.Clamp(self:GetThrustStrenght() * self.MaxThrust,250,800)
PhysObj:SetVelocityInstantaneous( NewVelocity )
PhysObj:SetAngleVelocityInstantaneous( data.OurOldAngularVelocity )
return true
end
function ENT:PhysicsSimulate( phys, deltatime )
if self:GetEngineActive() then
phys:Wake()
else
return vector_origin, vector_origin, SIM_NOTHING
end
local EntTable = self:GetTable()
local Aero, Torque = self:CalcAero( phys, deltatime, EntTable )
local Thrust = self:GetThrustStrenght() * EntTable.MaxThrust * 100
if self:IsDestroyed() then
Thrust = math.max( Thrust, 0 ) -- dont allow braking, but allow accelerating while destroyed
end
local ForceLinear = (Aero * 10000 * EntTable.ForceLinearMultiplier + Vector(Thrust,0,0)) * deltatime
local ForceAngle = (Torque * 25 * EntTable.ForceAngleMultiplier - phys:GetAngleVelocity() * 1.5 * EntTable.ForceAngleDampingMultiplier) * deltatime * 250
return self:PhysicsSimulateOverride( ForceAngle, ForceLinear, phys, deltatime, SIM_LOCAL_ACCELERATION )
end
function ENT:PhysicsSimulateOverride( ForceAngle, ForceLinear, phys, deltatime, simulate )
return ForceAngle, ForceLinear, simulate
end
function ENT:OnMaintenance()
for _, Engine in pairs( self:GetEngines() ) do
if not IsValid( Engine ) then continue end
if not Engine.SetHP or not Engine.GetMaxHP or not Engine.SetDestroyed then continue end
Engine:SetHP( Engine:GetMaxHP() )
Engine:SetDestroyed( false )
end
end

View File

@@ -0,0 +1,58 @@
function ENT:GetEyeTrace( trace_forward )
local startpos = self:LocalToWorld( self:OBBCenter() )
local pod = self:GetDriverSeat()
if IsValid( pod ) then
startpos = pod:LocalToWorld( pod:OBBCenter() )
end
local AimVector = trace_forward and self:GetForward() or self:GetAimVector()
local data = {
start = startpos,
endpos = (startpos + AimVector * 50000),
filter = self:GetCrosshairFilterEnts(),
}
local trace = util.TraceLine( data )
return trace
end
function ENT:GetAimVector()
if self:GetAI() then
return self:GetAIAimVector()
end
local Driver = self:GetDriver()
if not IsValid( Driver ) then return self:GetForward() end
if not Driver:lvsMouseAim() then
if Driver:lvsKeyDown( "FREELOOK" ) then
local pod = self:GetDriverSeat()
if not IsValid( pod ) then return Driver:EyeAngles():Forward() end
if pod:GetThirdPersonMode() then
return -self:GetForward()
else
return Driver:GetAimVector()
end
else
return self:GetForward()
end
end
if SERVER then
local pod = self:GetDriverSeat()
if not IsValid( pod ) then return Driver:EyeAngles():Forward() end
return pod:WorldToLocalAngles( Driver:EyeAngles() ):Forward()
else
return Driver:EyeAngles():Forward()
end
end

View File

@@ -0,0 +1,194 @@
ENT.Base = "lvs_base"
ENT.PrintName = "[LVS] Base Starfighter"
ENT.Author = "Luna"
ENT.Information = "Luna's Vehicle Script"
ENT.Category = "[LVS]"
ENT.Spawnable = false
ENT.AdminSpawnable = false
ENT.MaxVelocity = 3000
ENT.MaxThrust = 3000
ENT.ThrustVtol = 55
ENT.ThrustRateVtol = 3
ENT.ThrottleRateUp = 0.6
ENT.ThrottleRateDown = 0.6
ENT.TurnRatePitch = 1
ENT.TurnRateYaw = 1
ENT.TurnRateRoll = 1
ENT.ForceLinearMultiplier = 1
ENT.ForceAngleMultiplier = 1
ENT.ForceAngleDampingMultiplier = 1
ENT.DisableBallistics = true
function ENT:SetupDataTables()
self:AddDT( "Vector", "Steer" )
self:AddDT( "Vector", "AIAimVector" )
self:AddDT( "Vector", "NWVtolMove" )
self:AddDT( "Float", "NWThrottle" )
self:AddDT( "Float", "MaxThrottle" )
if SERVER then
self:SetMaxThrottle( 1 )
end
self:CreateBaseDT()
end
function ENT:PlayerDirectInput( ply, cmd )
local Pod = self:GetDriverSeat()
local Delta = FrameTime()
local KeyLeft = ply:lvsKeyDown( "-ROLL_SF" )
local KeyRight = ply:lvsKeyDown( "+ROLL_SF" )
local KeyPitchUp = ply:lvsKeyDown( "+PITCH_SF" )
local KeyPitchDown = ply:lvsKeyDown( "-PITCH_SF" )
local KeyRollRight = ply:lvsKeyDown( "+YAW_SF" )
local KeyRollLeft = ply:lvsKeyDown( "-YAW_SF" )
local MouseX = cmd:GetMouseX()
local MouseY = cmd:GetMouseY()
if ply:lvsKeyDown( "FREELOOK" ) and not Pod:GetThirdPersonMode() then
MouseX = 0
MouseY = 0
else
ply:SetEyeAngles( Angle(0,90,0) )
end
local SensX, SensY, ReturnDelta = ply:lvsMouseSensitivity()
if KeyPitchDown then MouseY = (10 / SensY) * ReturnDelta end
if KeyPitchUp then MouseY = -(10 / SensY) * ReturnDelta end
if KeyRollRight or KeyRollLeft then
local NewX = (KeyRollRight and 10 or 0) - (KeyRollLeft and 10 or 0)
MouseX = (NewX / SensX) * ReturnDelta
end
local Input = Vector( MouseX * 0.4 * SensX, MouseY * SensY, 0 )
local Cur = self:GetSteer()
local Rate = Delta * 3 * ReturnDelta
local New = Vector(Cur.x, Cur.y, 0) - Vector( math.Clamp(Cur.x * Delta * 5 * ReturnDelta,-Rate,Rate), math.Clamp(Cur.y * Delta * 5 * ReturnDelta,-Rate,Rate), 0)
local Target = New + Input * Delta * 0.8
local Fx = math.Clamp( Target.x, -1, 1 )
local Fy = math.Clamp( Target.y, -1, 1 )
local TargetFz = (KeyLeft and 1 or 0) - (KeyRight and 1 or 0)
local Fz = Cur.z + math.Clamp(TargetFz - Cur.z,-Rate * 3,Rate * 3)
local F = Cur + (Vector( Fx, Fy, Fz ) - Cur) * math.min(Delta * 100,1)
self:SetSteer( F )
end
function ENT:CalcThrottle( ply, cmd )
if CLIENT then return end
local Delta = FrameTime()
local ThrottleUp = ply:lvsKeyDown( "+THRUST_SF" ) and self.ThrottleRateUp or 0
local ThrottleDown = ply:lvsKeyDown( "-THRUST_SF" ) and -self.ThrottleRateDown or 0
local Throttle = (ThrottleUp + ThrottleDown) * Delta
self:SetThrottle( self:GetThrottle() + Throttle )
end
function ENT:CalcVtolThrottle( ply, cmd )
local Delta = FrameTime()
local ThrottleZero = self:GetThrottle() <= 0
local VtolX = ThrottleZero and (ply:lvsKeyDown( "-VTOL_X_SF" ) and -1 or 0) or 0
local VtolY = ((ply:lvsKeyDown( "+VTOL_Y_SF" ) and 1 or 0) - (ply:lvsKeyDown( "-VTOL_Y_SF" ) and 1 or 0))
local VtolZ = ((ply:lvsKeyDown( "+VTOL_Z_SF" ) and 1 or 0) - (ply:lvsKeyDown( "-VTOL_Z_SF" ) and 1 or 0))
local DesiredVtol = Vector(VtolX,VtolY,VtolZ)
local NewVtolMove = self:GetNWVtolMove() + (DesiredVtol - self:GetNWVtolMove()) * self.ThrustRateVtol * Delta
if not ThrottleZero or self:WorldToLocal( self:GetPos() + self:GetVelocity() ).x > 100 then
NewVtolMove.x = 0
end
self:SetVtolMove( NewVtolMove )
end
function ENT:SetVtolMove( NewMove )
if self:GetEngineActive() then
self:SetNWVtolMove( NewMove )
else
self:SetNWVtolMove( Vector(0,0,0) )
end
end
function ENT:SetThrottle( NewThrottle )
if self:GetEngineActive() then
self:SetNWThrottle( math.Clamp(NewThrottle,0,self:GetMaxThrottle()) )
else
self:SetNWThrottle( 0 )
end
end
function ENT:GetThrottle()
if self:GetEngineActive() then
return self:GetNWThrottle()
else
return 0
end
end
function ENT:GetVtolMove()
if self:GetEngineActive() and not self:GetAI() then
return self:GetNWVtolMove() * self.ThrustVtol * (1 - math.min( self:GetThrottle(), 1 ))
else
return Vector(0,0,0)
end
end
function ENT:StartCommand( ply, cmd )
if self:GetDriver() ~= ply then return end
if SERVER then
local KeyJump = ply:lvsKeyDown( "VSPEC" )
if self._lvsOldKeyJump ~= KeyJump then
self._lvsOldKeyJump = KeyJump
if KeyJump then
self:ToggleVehicleSpecific()
end
end
end
if not ply:lvsMouseAim() then
self:PlayerDirectInput( ply, cmd )
end
self:CalcThrottle( ply, cmd )
self:CalcVtolThrottle( ply, cmd )
end
function ENT:GetThrustStrenght()
local ForwardVelocity = self:WorldToLocal( self:GetPos() + self:GetVelocity() ).x
return (self.MaxVelocity * self:GetThrottle() - ForwardVelocity) / self.MaxVelocity
end
function ENT:GetVehicleType()
return "starfighter"
end

View File

@@ -0,0 +1,192 @@
function ENT:OnCreateAI()
self:StartEngine()
end
function ENT:OnRemoveAI()
self:StopEngine()
end
function ENT:RunAI()
local RangerLength = 15000
local mySpeed = self:GetVelocity():Length()
local MinDist = 600 + mySpeed
local StartPos = self:LocalToWorld( self:OBBCenter() )
local TraceFilter = self:GetCrosshairFilterEnts()
local FrontLeft = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,20,0) ):Forward() * RangerLength } )
local FrontRight = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,-20,0) ):Forward() * RangerLength } )
local FrontLeft2 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(25,65,0) ):Forward() * RangerLength } )
local FrontRight2 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(25,-65,0) ):Forward() * RangerLength } )
local FrontLeft3 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(-25,65,0) ):Forward() * RangerLength } )
local FrontRight3 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(-25,-65,0) ):Forward() * RangerLength } )
local FrontUp = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(-20,0,0) ):Forward() * RangerLength } )
local FrontDown = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(20,0,0) ):Forward() * RangerLength } )
local TraceForward = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:GetForward() * RangerLength } )
local TraceDown = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + Vector(0,0,-RangerLength) } )
local TraceUp = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + Vector(0,0,RangerLength) } )
local cAvoid = Vector(0,0,0)
local myRadius = self:BoundingRadius()
local myPos = self:GetPos()
local myDir = self:GetForward()
for _, v in pairs( LVS:GetVehicles() ) do
if v == self then continue end
local theirRadius = v:BoundingRadius()
local Sub = (myPos - v:GetPos())
local Dir = Sub:GetNormalized()
local Dist = Sub:Length()
if Dist < (theirRadius + myRadius + 200) then
if math.deg( math.acos( math.Clamp( myDir:Dot( -Dir ) ,-1,1) ) ) < 90 then
cAvoid = cAvoid + Dir * (theirRadius + myRadius + 500)
end
end
end
local FLp = FrontLeft.HitPos + FrontLeft.HitNormal * MinDist + cAvoid * 8
local FRp = FrontRight.HitPos + FrontRight.HitNormal * MinDist + cAvoid * 8
local FL2p = FrontLeft2.HitPos + FrontLeft2.HitNormal * MinDist
local FR2p = FrontRight2.HitPos + FrontRight2.HitNormal * MinDist
local FL3p = FrontLeft3.HitPos + FrontLeft3.HitNormal * MinDist
local FR3p = FrontRight3.HitPos + FrontRight3.HitNormal * MinDist
local FUp = FrontUp.HitPos + FrontUp.HitNormal * MinDist
local FDp = FrontDown.HitPos + FrontDown.HitNormal * MinDist
local Up = TraceUp.HitPos + TraceUp.HitNormal * MinDist
local Dp = TraceDown.HitPos + TraceDown.HitNormal * MinDist
local TargetPos = (FLp+FRp+FL2p+FR2p+FL3p+FR3p+FUp+FDp+Up+Dp) / 10
local alt = (StartPos - TraceDown.HitPos):Length()
local ceiling = (StartPos - TraceUp.HitPos):Length()
local WallDist = (StartPos - TraceForward.HitPos):Length()
local Throttle = math.min( WallDist / mySpeed, 1 )
self._AIFireInput = false
if alt < 600 or ceiling < 600 or WallDist < (MinDist * 3 * (math.deg( math.acos( math.Clamp( Vector(0,0,1):Dot( myDir ) ,-1,1) ) ) / 180) ^ 2) then
Throttle = 1
if self:HitGround() then
TargetPos.z = StartPos.z + 750
end
else
if IsValid( self:GetHardLockTarget() ) then
TargetPos = self:GetHardLockTarget():GetPos() + cAvoid * 8
else
if alt > mySpeed then
local Target = self._LastAITarget
if not IsValid( self._LastAITarget ) or not self:AITargetInFront( self._LastAITarget, 135 ) or not self:AICanSee( self._LastAITarget ) then
Target = self:AIGetTarget()
end
if IsValid( Target ) then
if self:AITargetInFront( Target, 65 ) then
local T = CurTime() + self:EntIndex() * 1337
TargetPos = Target:GetPos() + cAvoid * 8 + Vector(0,0, math.sin( T * 5 ) * 500 ) + Target:GetVelocity() * math.abs( math.cos( T * 13.37 ) ) * 5
Throttle = math.min( (StartPos - TargetPos):Length() / mySpeed, 1 )
local tr = util.TraceHull( {
start = StartPos,
endpos = (StartPos + self:GetForward() * 50000),
mins = Vector( -50, -50, -50 ),
maxs = Vector( 50, 50, 50 ),
filter = TraceFilter
} )
local CanShoot = (IsValid( tr.Entity ) and tr.Entity.LVS and tr.Entity.GetAITEAM) and (tr.Entity:GetAITEAM() ~= self:GetAITEAM() or tr.Entity:GetAITEAM() == 0) or true
if CanShoot and self:AITargetInFront( Target, 22 ) then
local CurHeat = self:GetNWHeat()
local CurWeapon = self:GetSelectedWeapon()
if CurWeapon > 2 then
self:AISelectWeapon( 1 )
else
if CurHeat > 0.9 then
if CurWeapon == 1 and self:AIHasWeapon( 2 ) then
self:AISelectWeapon( 2 )
elseif CurWeapon == 2 then
self:AISelectWeapon( 1 )
end
else
if CurHeat == 0 and math.cos( T ) > 0 then
self:AISelectWeapon( 1 )
end
end
end
self._AIFireInput = true
end
else
self:AISelectWeapon( 1 )
if alt > 6000 and self:AITargetInFront( Target, 90 ) then
TargetPos = Target:GetPos()
end
end
end
else
TargetPos.z = StartPos.z + 2000
self:EnableVehicleSpecific()
end
end
end
self:SetThrottle( Throttle )
self.smTargetPos = self.smTargetPos and self.smTargetPos + (TargetPos - self.smTargetPos) * FrameTime() or self:GetPos()
self._lvsAITargetAng = (self.smTargetPos - self:GetPos()):GetNormalized():Angle()
end
function ENT:AISelectWeapon( ID )
if ID == self:GetSelectedWeapon() then return end
local T = CurTime()
if (self._nextAISwitchWeapon or 0) > T then return end
self._nextAISwitchWeapon = T + math.random(3,6)
self:SelectWeapon( ID )
end
function ENT:OnAITakeDamage( dmginfo )
local attacker = dmginfo:GetAttacker()
if not IsValid( attacker ) then return end
if not self:AITargetInFront( attacker, IsValid( self:AIGetTarget() ) and 120 or 45 ) then
self:SetHardLockTarget( attacker )
end
end
function ENT:SetHardLockTarget( target )
self._HardLockTarget = target
self._HardLockTime = CurTime() + 4
end
function ENT:GetHardLockTarget()
if (self._HardLockTime or 0) < CurTime() then return NULL end
return self._HardLockTarget
end

View File

@@ -0,0 +1,78 @@
function ENT:AddEngine( pos, ang, mins, maxs, health )
local Engine = ents.Create( "lvs_starfighter_engine" )
if not IsValid( Engine ) then
self:Remove()
print("LVS: Failed to create engine entity. Vehicle terminated.")
return
end
Engine:SetPos( self:LocalToWorld( pos ) )
Engine:SetAngles( self:GetAngles() )
Engine:Spawn()
Engine:Activate()
Engine:SetParent( self )
Engine:SetBase( self )
if not health then
health = self.MaxHealth / 8
end
Engine:SetMaxHP( health )
Engine:SetHP( health )
self:DeleteOnRemove( Engine )
self:TransferCPPI( Engine )
self:AddDS( {
pos = pos,
ang = (ang or Angle(0,0,0)),
mins = (mins or Vector(-40,-20,-30)),
maxs = (maxs or Vector(40,20,30)),
Callback = function( tbl, ent, dmginfo )
if dmginfo:GetDamage() <= 0 then return end
Engine:TakeDamageInfo( dmginfo )
end
} )
if not istable( self._lvsEngines ) then
self._lvsEngines = {}
end
table.insert( self._lvsEngines, Engine )
return Engine
end
function ENT:GetEngines()
return self._lvsEngines or {}
end
function ENT:AddEngineSound( pos )
local EngineSND = ents.Create( "lvs_starfighter_soundemitter" )
if not IsValid( EngineSND ) then
self:Remove()
print("LVS: Failed to create engine sound entity. Vehicle terminated.")
return
end
EngineSND:SetPos( self:LocalToWorld( pos ) )
EngineSND:SetAngles( self:GetAngles() )
EngineSND:Spawn()
EngineSND:Activate()
EngineSND:SetParent( self )
EngineSND:SetBase( self )
self:DeleteOnRemove( EngineSND )
self:TransferCPPI( EngineSND )
return EngineSND
end

View File

@@ -0,0 +1,45 @@
function ENT:PlayerMouseAim( ply )
local Pod = self:GetDriverSeat()
local PitchUp = ply:lvsKeyDown( "+PITCH_SF" )
local PitchDown = ply:lvsKeyDown( "-PITCH_SF" )
local YawRight = ply:lvsKeyDown( "+YAW_SF" )
local YawLeft = ply:lvsKeyDown( "-YAW_SF" )
local RollRight = ply:lvsKeyDown( "+ROLL_SF" )
local RollLeft = ply:lvsKeyDown( "-ROLL_SF" )
local FreeLook = ply:lvsKeyDown( "FREELOOK" )
local EyeAngles = Pod:WorldToLocalAngles( ply:EyeAngles() )
if FreeLook then
if isangle( self.StoredEyeAngles ) then
EyeAngles = self.StoredEyeAngles
end
else
self.StoredEyeAngles = EyeAngles
end
local OverridePitch = 0
local OverrideYaw = 0
local OverrideRoll = (RollRight and 1 or 0) - (RollLeft and 1 or 0)
if PitchUp or PitchDown then
EyeAngles = self:GetAngles()
self.StoredEyeAngles = Angle(EyeAngles.p,EyeAngles.y,0)
OverridePitch = (PitchUp and 1 or 0) - (PitchDown and 1 or 0)
end
if YawRight or YawLeft then
EyeAngles = self:GetAngles()
self.StoredEyeAngles = Angle(EyeAngles.p,EyeAngles.y,0)
OverrideYaw = (YawRight and 1 or 0) - (YawLeft and 1 or 0)
end
self:ApproachTargetAngle( EyeAngles, OverridePitch, OverrideYaw, OverrideRoll, FreeLook )
end

View File

@@ -0,0 +1,25 @@
function ENT:ToggleVehicleSpecific()
self._VSPEC = not self._VSPEC
self:OnVehicleSpecificToggled( self._VSPEC )
end
function ENT:EnableVehicleSpecific()
if self._VSPEC then return end
self._VSPEC = true
self:OnVehicleSpecificToggled( self._VSPEC )
end
function ENT:DisableVehicleSpecific()
if not self._VSPEC then return end
self._VSPEC = false
self:OnVehicleSpecificToggled( self._VSPEC )
end
function ENT:OnVehicleSpecificToggled( IsActive )
end