--[[ | 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( "sh_weapons.lua" ) AddCSLuaFile( "cl_init.lua" ) AddCSLuaFile( "cl_effects.lua" ) AddCSLuaFile( "cl_hud.lua" ) AddCSLuaFile( "cl_trailsystem.lua" ) AddCSLuaFile( "cl_seatswitcher.lua" ) AddCSLuaFile( "cl_boneposeparemeter.lua" ) include("shared.lua") include( "sh_weapons.lua" ) include("sv_ai.lua") include("sv_cppi.lua") include("sv_duping.lua") include("sv_pod.lua") include("sv_engine.lua") include("sv_physics.lua") include("sv_physics_damagesystem.lua") include("sv_damagesystem.lua") include("sv_shieldsystem.lua") include("sv_doorsystem.lua") ENT.WaterLevelPreventStart = 1 ENT.WaterLevelAutoStop = 2 ENT.WaterLevelDestroyAI = 2 function ENT:SpawnFunction( ply, tr, ClassName ) if ply:InVehicle() then local ent = ents.Create( ClassName ) ent:StoreCPPI( ply ) ent:SetPos( ply:GetPos() + Vector(0,0,100 + ent.SpawnNormalOffset) ) ent:SetAngles( Angle(0, ply:EyeAngles().y, 0 ) ) ent:Spawn() ent:Activate() return ent else if not tr.Hit then return end local ent = ents.Create( ClassName ) ent:StoreCPPI( ply ) ent:SetPos( tr.HitPos + tr.HitNormal * ent.SpawnNormalOffset ) ent:SetAngles( Angle(0, ply:EyeAngles().y, 0 ) ) ent:Spawn() ent:Activate() return ent end end function ENT:Initialize() self:SetModel( self.MDL ) self:PhysicsInit( SOLID_VPHYSICS ) self:SetMoveType( MOVETYPE_VPHYSICS ) self:SetSolid( SOLID_VPHYSICS ) self:SetUseType( SIMPLE_USE ) self:SetRenderMode( RENDERMODE_NORMAL ) self:AddFlags( FL_OBJECT ) local PObj = self:GetPhysicsObject() if not IsValid( PObj ) then self:Remove() print("LVS: missing model. Vehicle terminated.") return end PObj:SetMaterial( "default_silent" ) PObj:EnableMotion( false ) PObj:EnableDrag( false ) timer.Simple(0, function() if not IsValid( self ) or not IsValid( PObj ) then print("LVS: ERROR couldn't initialize vehicle.") return end self:PostInitialize( PObj ) end) if not istable( self.GibModels ) then return end for _, modelName in ipairs( self.GibModels ) do util.PrecacheModel( modelName ) end end function ENT:PostInitialize( PObj ) local SpawnSuccess, ErrorMsg = pcall( function() self:OnSpawn( PObj ) end ) if not SpawnSuccess then ErrorNoHalt( "\n[ERROR] "..ErrorMsg.."\n\n" ) end self:StartMotionController() self:AutoAI() self:CallOnRemove( "finish_weapons_on_delete", function( ent ) ent:WeaponsFinish() for _, pod in pairs( ent:GetPassengerSeats() ) do local weapon = pod:lvsGetWeapon() if not IsValid( weapon ) or not weapon._activeWeapon then continue end local CurWeapon = self.WEAPONS[ weapon:GetPodIndex() ][ weapon._activeWeapon ] if not CurWeapon then continue end if CurWeapon.FinishAttack then CurWeapon.FinishAttack( weapon ) end end ent:WeaponsOnRemove() end) self:SetlvsReady( true ) self:OnSpawnFinish( PObj ) end function ENT:OnSpawnFinish( PObj ) if GetConVar( "developer" ):GetInt() ~= 1 then PObj:EnableMotion( true ) end self:PhysWake() end function ENT:OnSpawn( PObj ) end function ENT:Think() self:NextThink( CurTime() ) if not self:IsInitialized() then return true end self:HandleActive() self:HandleStart() self:PhysicsThink() self:DamageThink() self:WeaponsThink() self:ShieldThink() if self:GetAI() then self:RunAI() end self:OnTick() return true end function ENT:OnDriverChanged( Old, New, VehicleIsActive ) self:OnPassengerChanged( Old, New, 1 ) end function ENT:OnPassengerChanged( Old, New, PodIndex ) end function ENT:OnSwitchSeat( ply, oldpod, newpod ) end function ENT:OnTick() end function ENT:OnRemoved() end function ENT:OnRemove() self:OnRemoved() end function ENT:Lock() for _, Handler in pairs( self:GetDoorHandlers() ) do if not IsValid( Handler ) then continue end Handler:Close( ply ) end if self:GetlvsLockedStatus() then return end self:SetlvsLockedStatus( true ) self:EmitSound( "doors/latchlocked2.wav" ) end function ENT:UnLock() if not self:GetlvsLockedStatus() then return end self:SetlvsLockedStatus( false ) self:EmitSound( "doors/latchunlocked1.wav" ) end function ENT:IsUseAllowed( ply ) if not IsValid( ply ) then return false end if (ply._lvsNextUse or 0) > CurTime() then return false end if self:GetlvsLockedStatus() or (LVS.TeamPassenger and ((self:GetAITEAM() ~= ply:lvsGetAITeam()) and ply:lvsGetAITeam() ~= 0 and self:GetAITEAM() ~= 0)) then self:EmitSound( "doors/default_locked.wav" ) return false end return true end function ENT:Use( ply ) if not self:IsUseAllowed( ply ) then return end if not istable( self._DoorHandlers ) then self:SetPassenger( ply ) return end if ply:KeyDown( IN_SPEED ) then return end local Handler = self:GetDoorHandler( ply ) if not IsValid( Handler ) then if self:HasDoorSystem() and ply:GetMoveType() == MOVETYPE_WALK then return end self:SetPassenger( ply ) return end local Pod = Handler:GetLinkedSeat() if not IsValid( Pod ) then Handler:Use( ply ) return end if not Handler:IsOpen() then Handler:Open( ply ) return end if Handler:IsOpen() then Handler:Close( ply ) else Handler:OpenAndClose( ply ) end if ply:KeyDown( IN_WALK ) then self:SetPassenger( ply ) return end local DriverSeat = self:GetDriverSeat() if Pod ~= self:GetDriverSeat() then if IsValid( Pod:GetDriver() ) then self:SetPassenger( ply ) else ply:EnterVehicle( Pod ) self:AlignView( ply ) hook.Run( "LVS.UpdateRelationship", self ) end return end if self:GetAI() then self:SetPassenger( ply ) return end if IsValid( Pod:GetDriver() ) then self:SetPassenger( ply ) return end if hook.Run( "LVS.CanPlayerDrive", ply, self ) ~= false then ply:EnterVehicle( Pod ) self:AlignView( ply ) hook.Run( "LVS.UpdateRelationship", self ) else hook.Run( "LVS.OnPlayerCannotDrive", ply, self ) end end function ENT:OnTakeDamage( dmginfo ) self:CalcShieldDamage( dmginfo ) self:CalcDamage( dmginfo ) self:TakePhysicsDamage( dmginfo ) self:OnAITakeDamage( dmginfo ) end function ENT:OnMaintenance() end function ENT:UpdateTransmitState() return TRANSMIT_ALWAYS end function ENT:GetMissileOffset() return self:OBBCenter() end function ENT:RebuildCrosshairFilterEnts() self.CrosshairFilterEnts = nil local CrosshairFilterEnts = table.Copy( self:GetCrosshairFilterEnts() ) for id, entity in pairs( CrosshairFilterEnts ) do if not IsValid( entity ) or entity:GetNoDraw() then CrosshairFilterEnts[ id ] = nil end end net.Start( "lvs_player_request_filter" ) net.WriteEntity( self ) net.WriteTable( CrosshairFilterEnts ) net.Broadcast() end function ENT:GetCrosshairFilterEnts() if not istable( self.CrosshairFilterEnts ) or not self:IsInitialized() then self.CrosshairFilterEnts = {} for _, Entity in pairs( constraint.GetAllConstrainedEntities( self ) ) do if not IsValid( Entity ) then continue end table.insert( self.CrosshairFilterEnts , Entity ) end for _, Parent in pairs( self.CrosshairFilterEnts ) do for _, Child in pairs( Parent:GetChildren() ) do if not IsValid( Child ) then continue end table.insert( self.CrosshairFilterEnts , Child ) end end end return self.CrosshairFilterEnts end function ENT:LVSFireBullet( data ) data.Entity = self data.Velocity = data.Velocity + self:GetVelocity():Length() data.SrcEntity = self:WorldToLocal( data.Src ) LVS:FireBullet( data ) end function ENT:AddSoundEmitter( pos, snd, snd_interior ) local Emitter = ents.Create( "lvs_soundemitter" ) if not IsValid( Emitter ) then self:Remove() print("LVS: Failed to create sound emitter entity. Vehicle terminated.") return end Emitter:SetPos( self:LocalToWorld( pos ) ) Emitter:SetAngles( self:GetAngles() ) Emitter:Spawn() Emitter:Activate() Emitter:SetParent( self ) Emitter:SetBase( self ) if snd and not snd_interior then Emitter:SetSound( snd ) Emitter:SetSoundInterior( snd ) else Emitter:SetSound( snd or "" ) Emitter:SetSoundInterior( snd_interior ) end self:DeleteOnRemove( Emitter ) self:TransferCPPI( Emitter ) return Emitter end