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,60 @@
function ENT:CalcViewOverride( ply, pos, angles, fov, pod )
return pos, angles, fov
end
function ENT:CalcViewDriver( ply, pos, angles, fov, pod )
local view = {}
view.origin = pos
view.fov = fov
view.drawviewer = true
view.angles = ply:EyeAngles()
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: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,25 @@
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 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 )
else
self:LVSDrawCircle( hX, hY, H * 0.35, self:GetThrottle() )
end
end

View File

@@ -0,0 +1,4 @@
include("shared.lua")
include("sh_camera_eyetrace.lua")
include("cl_camera.lua")
include("cl_hud.lua")

View File

@@ -0,0 +1,90 @@
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "cl_camera.lua" )
AddCSLuaFile( "cl_hud.lua" )
AddCSLuaFile( "sh_camera_eyetrace.lua" )
include("shared.lua")
include("sv_controls.lua")
include("sv_components.lua")
include("sv_vehiclespecific.lua")
include("sh_camera_eyetrace.lua")
include("sv_ai.lua")
DEFINE_BASECLASS( "lvs_base" )
function ENT:OnDriverChanged( Old, New, VehicleIsActive )
if VehicleIsActive then
if not self:GetEngineActive() and self:IsEngineStartAllowed() then
self:SetEngineActive( true )
end
return
end
self:SetEngineActive( false )
self:SetMove( 0, 0 )
end
function ENT:StartEngine()
for _, wheel in pairs( self:GetWheels() ) do
if not IsValid( wheel ) then continue end
wheel:PhysWake()
end
BaseClass.StartEngine( self )
end
function ENT:PhysicsSimulate( phys, deltatime )
if self:GetEngineActive() then phys:Wake() end
local OnGroundMul = self:HitGround() and 1 or 0
local VelL = phys:WorldToLocal( phys:GetPos() + phys:GetVelocity() )
local InputMove = self:GetMove()
self._smMove = self._smMove and (self._smMove + (Vector(InputMove.x,InputMove.y,0):GetNormalized() - self._smMove) * deltatime * self.ForceLinearRate * 10) or InputMove
local MoveX = (self.MaxVelocityX + self.BoostAddVelocityX * InputMove.z) * self._smMove.x
local MoveY = (self.MaxVelocityY + self.BoostAddVelocityY * InputMove.z) * self._smMove.y
local Ang = self:GetAngles()
if not self:GetEngineActive() then
self:SetSteerTo( Ang.y )
self.smY = Ang.y
end
self.smY = self.smY and math.ApproachAngle( self.smY, self:GetSteerTo(), self.MaxTurnRate * deltatime * 100 ) or Ang.y
local Steer = self:WorldToLocalAngles( Angle(Ang.p,self.smY,Ang.y) ).y
local ForceLinear = ((Vector( MoveX, MoveY, 0 ) - Vector(VelL.x,VelL.y,0)) * self.ForceLinearMultiplier) * OnGroundMul * deltatime * 500
local ForceAngle = (Vector(0,0,Steer) * self.ForceAngleMultiplier * 2 - phys:GetAngleVelocity() * self.ForceAngleDampingMultiplier) * OnGroundMul * deltatime * 600
return self:PhysicsSimulateOverride( ForceAngle, ForceLinear, phys, deltatime, self:GetDisabled() and SIM_NOTHING or SIM_LOCAL_ACCELERATION )
end
function ENT:PhysicsSimulateOverride( ForceAngle, ForceLinear, phys, deltatime, simulate )
return ForceAngle, ForceLinear, simulate
end
function ENT:IsEngineStartAllowed()
if hook.Run( "LVS.IsEngineStartAllowed", self ) == false then return false end
if self:GetDisabled() then return false end
if self:WaterLevel() > self.WaterLevelPreventStart then return false end
return true
end
function ENT:OnDisabled( name, old, new)
if new == old then return end
if new then
if not self:GetEngineActive() then return end
self:SetEngineActive( false )
end
end

View File

@@ -0,0 +1,42 @@
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 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,72 @@
ENT.Base = "lvs_base"
ENT.PrintName = "[LVS] Generic Fake Hover"
ENT.Author = "Luna"
ENT.Information = "Luna's Vehicle Script"
ENT.Category = "[LVS]"
ENT.ForceAngleMultiplier = 1
ENT.ForceAngleDampingMultiplier = 1
ENT.ForceLinearMultiplier = 1
ENT.ForceLinearRate = 1
ENT.MaxVelocityX = 300
ENT.MaxVelocityY = 300
ENT.MaxTurnRate = 1
ENT.BoostAddVelocityX = 200
ENT.BoostAddVelocityY = 200
ENT.GroundTraceHitWater = true
ENT.GroundTraceLength = 50
ENT.GroundTraceHull = 100
ENT.DisableBallistics = true
function ENT:SetupDataTables()
self:AddDT( "Vector", "AIAimVector" )
self:AddDT( "Bool", "Disabled" )
if SERVER then
self:NetworkVarNotify( "Disabled", self.OnDisabled )
end
self:CreateBaseDT()
end
function ENT:HitGround()
local data = {
start = self:LocalToWorld( self:OBBCenter() ),
endpos = self:LocalToWorld( Vector(0,0,self:OBBMins().z - self.GroundTraceLength) ),
mins = Vector( -self.GroundTraceHull, -self.GroundTraceHull, 0 ),
maxs = Vector( self.GroundTraceHull, self.GroundTraceHull, 0 ),
filter = self:GetCrosshairFilterEnts()
}
local trace = util.TraceHull( data )
data.mask = MASK_WATER
local traceWater = util.TraceHull( data )
return ((trace.Hit or (traceWater.Hit and self.GroundTraceHitWater)) and not trace.HitSky)
end
function ENT:GetThrottle()
return math.min( self:GetVelocity():Length() / math.abs( self.MaxVelocityX + self.BoostAddVelocityX, self.MaxVelocityY + self.BoostAddVelocityY ), 1 )
end
function ENT:GetMaxThrottle()
return 1
end
function ENT:GetThrustStrenght()
return 0
end
function ENT:GetVehicleType()
return "fakehover"
end

View File

@@ -0,0 +1,125 @@
function ENT:OnCreateAI()
self:StartEngine()
end
function ENT:OnRemoveAI()
self:StopEngine()
end
function ENT:RunAI()
local RangerLength = 25000
local Target = self:AIGetTarget( 180 )
local StartPos = self:LocalToWorld( self:OBBCenter() )
local TraceFilter = self:GetCrosshairFilterEnts()
local Front = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:GetForward() * RangerLength } )
local FrontLeft = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,15,0) ):Forward() * RangerLength } )
local FrontRight = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,-15,0) ):Forward() * RangerLength } )
local FrontLeft1 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,60,0) ):Forward() * RangerLength } )
local FrontRight1 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,-60,0) ):Forward() * RangerLength } )
local FrontLeft2 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,85,0) ):Forward() * RangerLength } )
local FrontRight2 = util.TraceLine( { start = StartPos, filter = TraceFilter, endpos = StartPos + self:LocalToWorldAngles( Angle(0,-85,0) ):Forward() * RangerLength } )
local TargetPos = (Front.HitPos + FrontLeft.HitPos + FrontRight.HitPos + FrontLeft1.HitPos + FrontRight1.HitPos + FrontLeft2.HitPos + FrontRight2.HitPos) / 7
self._AIFireInput = false
if IsValid( self:GetHardLockTarget() ) then
TargetPos = self:GetHardLockTarget():GetPos()
if self:AITargetInFront( self:GetHardLockTarget(), 65 ) then
self._AIFireInput = true
end
else
if IsValid( Target ) then
TargetPos = Target:LocalToWorld( Target:OBBCenter() )
if self:AITargetInFront( Target, 65 ) then
self._AIFireInput = true
end
end
end
if self._AIFireInput 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( CurTime() ) > 0 then
self:AISelectWeapon( 1 )
end
end
end
end
local DistToTarget = (TargetPos - self:GetPos()):Length()
local LocalMove = self:WorldToLocal( TargetPos )
if DistToTarget < 1000 then
LocalMove.x = -1
end
if DistToTarget > 800 and DistToTarget < 1200 then
LocalMove.y = math.sin( CurTime() * 1.5 + self:EntIndex() * 1337 ) * 10
end
self:SetMove( LocalMove.x, LocalMove.y )
local pod = self:GetDriverSeat()
if not IsValid( pod ) then return end
local AimVector = (TargetPos - pod:LocalToWorld( Vector(0,0,33) )):GetNormalized()
self:SetAIAimVector( AimVector )
self:SetSteerTo( AimVector:Angle().y )
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:AISelectWeapon( ID )
if ID == self:GetSelectedWeapon() then return end
local T = CurTime()
if (self._nextAISwitchWeapon or 0) > T then return end
self._nextAISwitchWeapon = T + 1
self:SelectWeapon( ID )
end
function ENT:SetHardLockTarget( target )
if not self:IsEnemy( target ) then return end
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,106 @@
ENT._WheelEnts = {}
function ENT:GetWheels()
for id, ent in pairs( self._WheelEnts ) do
if IsValid( ent ) then continue end
self._WheelEnts[ id ] = nil
end
return self._WheelEnts
end
function ENT:AddWheel( pos, radius, mass, buoyancyratio, brakeforce )
if not isvector( pos ) or not isnumber( radius ) or not isnumber( mass ) then return end
local wheel = ents.Create( "lvs_fakehover_wheel" )
if not IsValid( wheel ) then
self:Remove()
print("LVS: Failed to initialize wheel. Vehicle terminated.")
return
end
local WheelPos = self:LocalToWorld( pos )
local CenterPos = self:LocalToWorld( self:OBBCenter() )
debugoverlay.Sphere( WheelPos, radius, 5, Color(150,150,150), true )
debugoverlay.Line( CenterPos, WheelPos, 5, Color(150,150,150), true )
wheel:SetPos( WheelPos )
wheel:SetAngles( self:LocalToWorldAngles( Angle(0,90,0) ) )
wheel:Spawn()
wheel:Activate()
wheel:SetBase( self )
wheel:SetNoDraw( true )
wheel:DrawShadow( false )
wheel.DoNotDuplicate = true
wheel:Define(
{
radius = radius,
mass = mass,
buoyancyratio = buoyancyratio or 0,
}
)
table.insert( self._WheelEnts, wheel )
local PhysObj = wheel:GetPhysicsObject()
if not IsValid( PhysObj ) then
self:Remove()
print("LVS: Failed to initialize wheel phys model. Vehicle terminated.")
return
end
if PhysObj:GetMaterial() ~= "gmod_silent" then
self:Remove()
print("LVS: Failed to initialize physprop material on wheel. Vehicle terminated.")
return
end
self:DeleteOnRemove( wheel )
self:TransferCPPI( wheel )
local ballsocket = constraint.AdvBallsocket(wheel, self,0,0,Vector(0,0,0),Vector(0,0,0),0,0, -1, -1, -1, 1, 1, 1, 0, 0, 0, 0, 1)
ballsocket.DoNotDuplicate = true
self:TransferCPPI( ballsocket )
local nocollide = constraint.NoCollide( wheel, self, 0, 0 )
nocollide.DoNotDuplicate = true
self:TransferCPPI( nocollide )
PhysObj:EnableMotion( true )
return wheel
end
function ENT:AddEngineSound( pos )
local EngineSND = ents.Create( "lvs_fakehover_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,65 @@
function ENT:StartCommand( ply, cmd )
if self:GetDriver() ~= ply then return end
local KeyJump = ply:lvsKeyDown( "VSPEC" )
if self._lvsOldKeyJump ~= KeyJump then
self._lvsOldKeyJump = KeyJump
if KeyJump then
self:ToggleVehicleSpecific()
end
end
local Forward = cmd:KeyDown( IN_FORWARD )
local Back = cmd:KeyDown( IN_BACK )
local Left = cmd:KeyDown( IN_MOVELEFT )
local Right = cmd:KeyDown( IN_MOVERIGHT )
local Boost = cmd:KeyDown( IN_SPEED )
local X = (Forward and 1 or 0) - (Back and 1 or 0)
local Y = (Left and 1 or 0) - (Right and 1 or 0)
self:SetMove( X, Y, Boost )
local pod = self:GetDriverSeat()
if not IsValid( pod ) then return end
if ply:lvsKeyDown( "FREELOOK" ) then
self:SetSteerTo( self:GetAngles().y)
return
end
self:SetSteerTo( pod:WorldToLocalAngles( ply:EyeAngles() ).y )
end
function ENT:SetSteerTo( Steer )
if not isnumber( Steer ) then return end
self._steer = Steer
end
function ENT:GetSteerTo()
if not self:GetEngineActive() then return self:GetAngles().y end
return (self._steer or self:GetAngles().y)
end
function ENT:SetMove( X, Y, Boost )
if not isnumber( X ) or not isnumber( Y ) then return end
X = math.Clamp( X, -1, 1 )
Y = math.Clamp( Y, -1, 1 )
Z = Boost and 1 or 0
self._move = Vector( X, Y, Z )
end
function ENT:GetMove()
if not self:GetEngineActive() then return Vector(0,0,0) end
return (self._move or Vector(0,0,0))
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