LVS = istable( LVS ) and LVS or {} LVS.VERSION = 348 LVS.VERSION_GITHUB = 0 LVS.VERSION_TYPE = ".WS" LVS.VERSION_ADDONS_OUTDATED = false LVS.KEYS_CATEGORIES = {} LVS.KEYS_REGISTERED = {} LVS.pSwitchKeys = {[KEY_1] = 1,[KEY_2] = 2,[KEY_3] = 3,[KEY_4] = 4,[KEY_5] = 5,[KEY_6] = 6,[KEY_7] = 7,[KEY_8] = 8,[KEY_9] = 9,[KEY_0] = 10} LVS.pSwitchKeysInv = {[1] = KEY_1,[2] = KEY_2,[3] = KEY_3,[4] = KEY_4,[5] = KEY_5,[6] = KEY_6,[7] = KEY_7,[8] = KEY_8,[9] = KEY_9,[10] = KEY_0} LVS.ThemeColor = Color(127,0,0,255) LVS.WHEEL_BRAKE = 1 LVS.WHEEL_STEER_NONE = 2 LVS.WHEEL_STEER_FRONT = 3 LVS.WHEEL_STEER_REAR = 4 LVS.WHEEL_STEER_ACKERMANN = 5 LVS.WHEELTYPE_NONE = 0 LVS.WHEELTYPE_LEFT = 1 LVS.WHEELTYPE_RIGHT = -1 LVS.HITCHTYPE_NONE = -1 LVS.HITCHTYPE_MALE = 0 LVS.HITCHTYPE_FEMALE = 1 LVS.SOUNDTYPE_NONE = 0 LVS.SOUNDTYPE_IDLE_ONLY = 1 LVS.SOUNDTYPE_REV_UP = 2 LVS.SOUNDTYPE_REV_DOWN = 3 LVS.SOUNDTYPE_REV_DN = 3 LVS.SOUNDTYPE_ALL = 4 LVS.FUELTYPE_PETROL = 0 LVS.FUELTYPE_DIESEL = 1 LVS.FUELTYPE_ELECTRIC = 2 LVS.FUELTYPES = { [LVS.FUELTYPE_PETROL] = { name = "Petrol", color = Vector(240,200,0), }, [LVS.FUELTYPE_DIESEL] = { name = "Diesel", color = Vector(255,60,0), }, [LVS.FUELTYPE_ELECTRIC] = { name = "Electric", color = Vector(0,127,255), }, } LVS.SPEEDUNITS = { ["u/s"] = { name = "u/s", value = 1, }, ["mph"] = { name = "mph", value = 0.0568182, }, ["km/h"] = { name = "km/h", value = 0.09144, }, } LVS.WEAPONS = { ["DEFAULT"] = { Icon = Material("lvs/weapons/bullet.png"), Ammo = 9999, Delay = 0, HeatRateUp = 0.2, HeatRateDown = 0.25, Attack = function( ent ) end, StartAttack = function( ent ) end, FinishAttack = function( ent ) end, OnSelect = function( ent, old ) end, OnDeselect = function( ent, new ) end, OnThink = function( ent, active ) end, OnOverheat = function( ent ) end, OnRemove = function( ent ) end, OnReload = function( ent ) end, }, ["LMG"] = { Icon = Material("lvs/weapons/mg.png"), Ammo = 1000, Delay = 0.1, Attack = function( ent ) ent.MirrorPrimary = not ent.MirrorPrimary local Mirror = ent.MirrorPrimary and -1 or 1 local Pos = ent:LocalToWorld( ent.PosLMG and Vector(ent.PosLMG.x,ent.PosLMG.y * Mirror,ent.PosLMG.z) or Vector(0,0,0) ) local Dir = ent.DirLMG or 0 local effectdata = EffectData() effectdata:SetOrigin( Pos ) effectdata:SetNormal( ent:GetForward() ) effectdata:SetEntity( ent ) util.Effect( "lvs_muzzle", effectdata ) local bullet = {} bullet.Src = Pos bullet.Dir = ent:LocalToWorldAngles( Angle(0,-Dir * Mirror,0) ):Forward() bullet.Spread = Vector( 0.015, 0.015, 0.015 ) bullet.TracerName = "lvs_tracer_white" bullet.Force = 1000 bullet.HullSize = 50 bullet.Damage = 35 bullet.Velocity = 30000 bullet.Attacker = ent:GetDriver() bullet.Callback = function(att, tr, dmginfo) end ent:LVSFireBullet( bullet ) ent:TakeAmmo() end, StartAttack = function( ent ) if not IsValid( ent.SoundEmitter1 ) then ent.SoundEmitter1 = ent:AddSoundEmitter( Vector(109.29,0,92.85), "lvs/weapons/mg_loop.wav", "lvs/weapons/mg_loop_interior.wav" ) ent.SoundEmitter1:SetSoundLevel( 95 ) end ent.SoundEmitter1:Play() end, FinishAttack = function( ent ) if IsValid( ent.SoundEmitter1 ) then ent.SoundEmitter1:Stop() ent.SoundEmitter1:EmitSound("lvs/weapons/mg_lastshot.wav") end end, OnSelect = function( ent ) ent:EmitSound("physics/metal/weapon_impact_soft3.wav") end, OnOverheat = function( ent ) ent:EmitSound("lvs/overheat.wav") end, }, ["TABLE_POINT_MG"] = { Icon = Material("lvs/weapons/mc.png"), Ammo = 2000, Delay = 0.1, Attack = function( ent ) if not ent.PosTPMG or not ent.DirTPMG then return end for i = 1, 2 do ent._NumTPMG = ent._NumTPMG and ent._NumTPMG + 1 or 1 if ent._NumTPMG > #ent.PosTPMG then ent._NumTPMG = 1 end local Pos = ent:LocalToWorld( ent.PosTPMG[ ent._NumTPMG ] ) local Dir = ent.DirTPMG[ ent._NumTPMG ] local effectdata = EffectData() effectdata:SetOrigin( Pos ) effectdata:SetNormal( ent:GetForward() ) effectdata:SetEntity( ent ) util.Effect( "lvs_muzzle", effectdata ) local bullet = {} bullet.Src = Pos bullet.Dir = ent:LocalToWorldAngles( Angle(0,-Dir,0) ):Forward() bullet.Spread = Vector( 0.035, 0.035, 0.035 ) bullet.TracerName = "lvs_tracer_yellow" bullet.Force = 1000 bullet.HullSize = 25 bullet.Damage = 35 bullet.Velocity = 40000 bullet.Attacker = ent:GetDriver() bullet.Callback = function(att, tr, dmginfo) end ent:LVSFireBullet( bullet ) end ent:TakeAmmo( 2 ) end, StartAttack = function( ent ) if not IsValid( ent.SoundEmitter1 ) then ent.SoundEmitter1 = ent:AddSoundEmitter( Vector(109.29,0,92.85), "lvs/weapons/mg_light_loop.wav", "lvs/weapons/mg_light_loop_interior.wav" ) ent.SoundEmitter1:SetSoundLevel( 95 ) end ent.SoundEmitter1:Play() end, FinishAttack = function( ent ) if IsValid( ent.SoundEmitter1 ) then ent.SoundEmitter1:Stop() ent.SoundEmitter1:EmitSound("lvs/weapons/mg_light_lastshot.wav") end end, OnSelect = function( ent ) ent:EmitSound("physics/metal/weapon_impact_soft3.wav") end, OnOverheat = function( ent ) ent:EmitSound("lvs/overheat.wav") end, }, ["HMG"] = { Icon = Material("lvs/weapons/hmg.png"), Ammo = 300, Delay = 0.14, Attack = function( ent ) ent.MirrorSecondary = not ent.MirrorSecondary local Mirror = ent.MirrorSecondary and -1 or 1 local Pos = ent:LocalToWorld( ent.PosHMG and Vector(ent.PosHMG.x,ent.PosHMG.y * Mirror,ent.PosHMG.z) or Vector(0,0,0) ) local Dir = ent.DirHMG or 0.5 local effectdata = EffectData() effectdata:SetOrigin( Pos ) effectdata:SetNormal( ent:GetForward() ) effectdata:SetEntity( ent ) util.Effect( "lvs_muzzle", effectdata ) local bullet = {} bullet.Src = Pos bullet.Dir = ent:LocalToWorldAngles( Angle(0,-Dir * Mirror,0) ):Forward() bullet.Spread = Vector( 0.02, 0.02, 0.02 ) bullet.TracerName = "lvs_tracer_orange" bullet.Force = 4000 bullet.HullSize = 15 bullet.Damage = 45 bullet.SplashDamage = 75 bullet.SplashDamageRadius = 200 bullet.Velocity = 15000 bullet.Attacker = ent:GetDriver() bullet.Callback = function(att, tr, dmginfo) end ent:LVSFireBullet( bullet ) ent:TakeAmmo() end, StartAttack = function( ent ) if not IsValid( ent.SoundEmitter2 ) then ent.SoundEmitter2 = ent:AddSoundEmitter( Vector(109.29,0,92.85), "lvs/weapons/mc_loop.wav", "lvs/weapons/mc_loop_interior.wav" ) ent.SoundEmitter2:SetSoundLevel( 95 ) end ent.SoundEmitter2:Play() end, FinishAttack = function( ent ) if IsValid( ent.SoundEmitter2 ) then ent.SoundEmitter2:Stop() ent.SoundEmitter2:EmitSound("lvs/weapons/mc_lastshot.wav") end end, OnSelect = function( ent ) ent:EmitSound("physics/metal/weapon_impact_soft2.wav") end, OnOverheat = function( ent ) ent:EmitSound("lvs/overheat.wav") end, }, ["TURBO"] = { Icon = Material("lvs/weapons/nos.png"), HeatRateUp = 0.1, HeatRateDown = 0.1, UseableByAI = false, Attack = function( ent ) local PhysObj = ent:GetPhysicsObject() if not IsValid( PhysObj ) then return end local THR = ent:GetThrottle() local FT = FrameTime() local Vel = ent:GetVelocity():Length() PhysObj:ApplyForceCenter( ent:GetForward() * math.Clamp(ent.MaxVelocity + 500 - Vel,0,1) * PhysObj:GetMass() * THR * FT * 150 ) -- increase speed PhysObj:AddAngleVelocity( PhysObj:GetAngleVelocity() * FT * 0.5 * THR ) -- increase turn rate end, StartAttack = function( ent ) ent.TargetThrottle = 1.3 ent:EmitSound("lvs/vehicles/generic/boost.wav") end, FinishAttack = function( ent ) ent.TargetThrottle = 1 end, OnSelect = function( ent ) ent:EmitSound("buttons/lever5.wav") end, OnThink = function( ent, active ) if not ent.TargetThrottle then return end local Rate = FrameTime() * 0.5 ent:SetMaxThrottle( ent:GetMaxThrottle() + math.Clamp(ent.TargetThrottle - ent:GetMaxThrottle(),-Rate,Rate) ) local MaxThrottle = ent:GetMaxThrottle() ent:SetThrottle( MaxThrottle ) if MaxThrottle == ent.TargetThrottle then ent.TargetThrottle = nil end end, OnOverheat = function( ent ) ent:EmitSound("lvs/overheat_boost.wav") end, }, } function LVS:GetVersion() return LVS.VERSION end function LVS:AddKey(name, category, printname, cmd, default) local data = { printname = printname, id = name, category = category, cmd = cmd, } if not LVS.KEYS_CATEGORIES[ category ] then LVS.KEYS_CATEGORIES[ category ] = {} end if SERVER then table.insert( LVS.KEYS_REGISTERED, data ) else if default then if isstring( default ) then local Key = input.LookupBinding( default ) if Key then default = input.GetKeyCode( Key ) else default = 0 end end else default = 0 end data.default = default table.insert( LVS.KEYS_REGISTERED, data ) CreateClientConVar( cmd, default, true, true ) end end function LVS:CheckUpdates() http.Fetch("https://raw.githubusercontent.com/SpaxscE/lvs_base/main/lua/autorun/lvs_init.lua", function(contents,size) local Entry = string.match( contents, "LVS.VERSION%s=%s%d+" ) if Entry then LVS.VERSION_GITHUB = tonumber( string.match( Entry , "%d+" ) ) or 0 else LVS.VERSION_GITHUB = 0 end if LVS.VERSION_GITHUB == 0 then print("[LVS] - Framework: latest version could not be detected, You have Version: "..LVS:GetVersion()) else if LVS:GetVersion() >= LVS.VERSION_GITHUB then print("[LVS] - Framework is up to date, Version: "..LVS:GetVersion()) else print("[LVS] - Framework: a newer version is available! Version: "..LVS.VERSION_GITHUB..", You have Version: "..LVS:GetVersion()) if LVS.VERSION_TYPE == ".GIT" then print("[LVS] - Framework: get the latest version at https://github.com/SpaxscE/lvs_base") else print("[LVS] - Framework: restart your game/server to get the latest version!") end if CLIENT then timer.Simple(18, function() chat.AddText( Color( 255, 0, 0 ), "[LVS] - Framework: a newer version is available!" ) end) end end end local Delay = 0 local addons = file.Find( "data_static/lvs/*", "GAME" ) for _, addonFile in pairs( addons ) do local addonInfo = file.Read( "data_static/lvs/"..addonFile, "GAME" ) if not addonInfo then continue end local data = string.Explode( "\n", addonInfo ) local wsid = string.Replace( addonFile, ".txt", "" ) local addon_name = wsid local addon_url local addon_version for _, entry in pairs( data ) do if string.StartsWith( entry, "url=" ) then addon_url = string.Replace( entry, "url=", "" ) end if string.StartsWith( entry, "version=" ) then addon_version = string.Replace( entry, "version=", "" ) end if string.StartsWith( entry, "name=" ) then addon_name = string.Replace( entry, "name=", "" ) end end if not addon_url or not addon_version then continue end addon_version = tonumber( addon_version ) Delay = Delay + 1.5 timer.Simple( Delay, function() http.Fetch(addon_url, function(con,_) local addon_entry = string.match( con, "version=%d+" ) local addon_version_git = 0 if addon_entry then addon_version_git = tonumber( string.match( addon_entry, "%d+" ) ) or 0 end local wsurl = "https://steamcommunity.com/sharedfiles/filedetails/?id="..wsid if addon_version_git == 0 then print("[LVS] latest version of "..addon_name.." ( "..wsurl.." ) could not be detected, You have Version: "..addon_version) else if addon_version_git > addon_version then print("[LVS] - "..addon_name.." ( "..wsurl.." ) is out of date!") if CLIENT then timer.Simple(18, function() chat.AddText( Color( 255, 0, 0 ),"[LVS] - "..addon_name.." is out of date!" ) end) end LVS.VERSION_ADDONS_OUTDATED = true else print("[LVS] - "..addon_name.." is up to date, Version: "..addon_version) end end end) end ) end end) end function LVS:GetWeaponPreset( name ) if not LVS.WEAPONS[ name ] then return table.Copy( LVS.WEAPONS["DEFAULT"] ) end return table.Copy( LVS.WEAPONS[ name ] ) end function LVS:AddWeaponPreset( name, data ) if not isstring( name ) or not istable( data ) then return end LVS.WEAPONS[ name ] = data end function LVS:GetVehicleTypes() local VehicleTypes = {} for s, v in pairs( scripted_ents.GetList() ) do if not v.t or not isfunction( v.t.GetVehicleType ) then continue end local vehicletype = v.t:GetVehicleType() if not isstring( vehicletype ) or string.StartsWith( vehicletype, "LBase" ) or table.HasValue( VehicleTypes, vehicletype ) then continue end table.insert( VehicleTypes, vehicletype ) end return VehicleTypes end if CLIENT then function LVS:GetUnitValue( number ) if not LVS.SPEEDUNITS[ LVS.SpeedUnit ] then return number end return (number * LVS.SPEEDUNITS[ LVS.SpeedUnit ].value) end function LVS:GetUnitName() if not LVS.SPEEDUNITS[ LVS.SpeedUnit ] then return "u/s" end return LVS.SPEEDUNITS[ LVS.SpeedUnit ].name end end AddCSLuaFile("lvs_framework/init.lua") include("lvs_framework/init.lua")