606 lines
17 KiB
Lua
606 lines
17 KiB
Lua
local TAG = "SitAny_"
|
||
local PLUGIN = PLUGIN
|
||
SitAnywhere = SitAnywhere or {}
|
||
|
||
local NextUse = setmetatable({}, {__mode = 'k', __index = function() return 0 end})
|
||
|
||
-- Конфигурация через ix.config
|
||
ix.config.Add("sitOnPlayers", true, "Разрешить сидеть на игроках в SitAnywhere", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitOnPlayerEntities", true, "Разрешить сидеть на сущностях игроков", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitPlayerDamage", false, "Разрешить урон сидящим игрокам", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitAllowWeapons", false, "Разрешить использование оружия при сидении", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitAdminOnly", false, "Только админы могут сидеть", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitAntiPropSurf", true, "Запретить физган на объектах с сидящими игроками", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitAntiToolAbuse", true, "Запретить тулган на объектах с сидящими игроками", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitAllowTightPlaces", false, "Разрешить сидеть в тесных местах", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
ix.config.Add("sitForceNoWalk", false, "Отключить необходимость шага для сидения", nil, {
|
||
category = "Sit Anywhere"
|
||
})
|
||
|
||
local META = FindMetaTable("Player")
|
||
|
||
util.AddNetworkString("SitAnywhere")
|
||
|
||
net.Receive("SitAnywhere", function(len, ply)
|
||
local netID = net.ReadInt(4)
|
||
if netID == SitAnywhere.NET.SitWantedAng then
|
||
local wantedAng, traceStart, traceNormal = net.ReadFloat(), net.ReadVector(), net.ReadVector()
|
||
|
||
if traceStart:Distance(ply:EyePos()) > 10 then return end
|
||
local trace = util.TraceLine({
|
||
start = traceStart,
|
||
endpos = traceStart + traceNormal * 12000,
|
||
filter = player.GetAll()
|
||
})
|
||
|
||
ply:Sit(trace, nil, nil, nil, nil, nil, wantedAng)
|
||
elseif netID == SitAnywhere.NET.SitRequestExit then
|
||
ply:ExitSit()
|
||
end
|
||
end)
|
||
|
||
local function Sit(ply, pos, ang, parent, parentbone, func, exit)
|
||
if IsValid(ply:GetVehicle()) then
|
||
local veh = ply:GetVehicle()
|
||
if veh:GetClass() == "prop_vehicle_prisoner_pod" and IsValid(veh.holder) then
|
||
SafeRemoveEntity(veh.holder)
|
||
end
|
||
ply:ExitVehicle()
|
||
end
|
||
|
||
local vehicle = ents.Create("prop_vehicle_prisoner_pod")
|
||
local t = hook.Run("OnPlayerSit", ply, pos, ang, parent or NULL, parentbone, vehicle)
|
||
|
||
if t == false then
|
||
SafeRemoveEntity(vehicle)
|
||
return false
|
||
end
|
||
|
||
vehicle:SetAngles(ang)
|
||
pos = pos + vehicle:GetUp() * 18
|
||
vehicle:SetPos(pos)
|
||
|
||
vehicle.playerdynseat = true
|
||
vehicle:SetNWBool("playerdynseat", true)
|
||
vehicle.sittingPly = ply
|
||
vehicle.oldpos = vehicle:WorldToLocal(ply:GetPos())
|
||
vehicle.wasCrouching = ply:Crouching()
|
||
|
||
vehicle:SetModel("models/nova/airboat_seat.mdl")
|
||
vehicle:SetKeyValue("vehiclescript", "scripts/vehicles/prisoner_pod.txt")
|
||
vehicle:SetKeyValue("limitview", "0")
|
||
vehicle:Spawn()
|
||
vehicle:Activate()
|
||
|
||
if not IsValid(vehicle) or not IsValid(vehicle:GetPhysicsObject()) then
|
||
SafeRemoveEntity(vehicle)
|
||
return false
|
||
end
|
||
|
||
local phys = vehicle:GetPhysicsObject()
|
||
vehicle:SetMoveType(MOVETYPE_PUSH)
|
||
phys:Sleep()
|
||
vehicle:SetCollisionGroup(COLLISION_GROUP_WORLD)
|
||
vehicle:SetNotSolid(true)
|
||
phys:Sleep()
|
||
phys:EnableGravity(false)
|
||
phys:EnableMotion(false)
|
||
phys:EnableCollisions(false)
|
||
phys:SetMass(1)
|
||
vehicle:CollisionRulesChanged()
|
||
|
||
vehicle:DrawShadow(false)
|
||
vehicle:SetColor(Color(0,0,0,0))
|
||
vehicle:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||
vehicle:SetNoDraw(true)
|
||
|
||
vehicle.VehicleName = "Airboat Seat"
|
||
vehicle.ClassOverride = "prop_vehicle_prisoner_pod"
|
||
vehicle.PhysgunDisabled = true
|
||
vehicle.m_tblToolsAllowed = {}
|
||
vehicle.customCheck = function() return false end
|
||
|
||
if IsValid(parent) then
|
||
local r = math.rad(ang.yaw + 90)
|
||
vehicle.plyposhack = vehicle:WorldToLocal(pos + Vector(math.cos(r) * 2, math.sin(r) * 2, 2))
|
||
vehicle:SetParent(parent)
|
||
vehicle.parent = parent
|
||
else
|
||
vehicle.OnWorld = true
|
||
end
|
||
|
||
local prev = ply:GetAllowWeaponsInVehicle()
|
||
if prev then
|
||
ply.sitting_allowswep = nil
|
||
elseif ix.config.Get("sitAllowWeapons", false) then
|
||
ply.sitting_allowswep = prev
|
||
ply:SetAllowWeaponsInVehicle(true)
|
||
end
|
||
|
||
ply:EnterVehicle(vehicle)
|
||
|
||
if ix.config.Get("sitPlayerDamage", false) then
|
||
ply:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||
ply:CollisionRulesChanged()
|
||
end
|
||
|
||
if func then
|
||
func(ply)
|
||
end
|
||
|
||
ply.seatExit = exit
|
||
ply:SetEyeAngles(Angle(0,90,0))
|
||
|
||
return vehicle
|
||
end
|
||
|
||
local d = function(a,b) return math.abs(a-b) end
|
||
|
||
local SittingOnPlayerPoses = {
|
||
{
|
||
Pos = Vector(-33, 13, 7),
|
||
Ang = Angle(0, 90, 90),
|
||
FindAng = 90,
|
||
},
|
||
{
|
||
Pos = Vector(33, 13, 7),
|
||
Ang = Angle(0, 270, 90),
|
||
Func = function(ply)
|
||
if not ply:LookupBone("ValveBiped.Bip01_R_Thigh") then return end
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_R_Thigh"), Angle(0,90,0))
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_L_Thigh"), Angle(0,90,0))
|
||
end,
|
||
OnExitFunc = function(ply)
|
||
if not ply:LookupBone("ValveBiped.Bip01_R_Thigh") then return end
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_R_Thigh"), Angle(0,0,0))
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_L_Thigh"), Angle(0,0,0))
|
||
end,
|
||
FindAng = 270,
|
||
},
|
||
{
|
||
Pos = Vector(0, 16, -15),
|
||
Ang = Angle(0, 180, 0),
|
||
Func = function(ply)
|
||
if not ply:LookupBone("ValveBiped.Bip01_R_Thigh") then return end
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_R_Thigh"), Angle(45,0,0))
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_L_Thigh"), Angle(-45,0,0))
|
||
end,
|
||
OnExitFunc = function(ply)
|
||
if not ply:LookupBone("ValveBiped.Bip01_R_Thigh") then return end
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_R_Thigh"), Angle(0,0,0))
|
||
ply:ManipulateBoneAngles(ply:LookupBone("ValveBiped.Bip01_L_Thigh"), Angle(0,0,0))
|
||
end,
|
||
FindAng = 0,
|
||
},
|
||
{
|
||
Pos = Vector(0, 8, -18),
|
||
Ang = Angle(0, 0, 0),
|
||
FindAng = 180,
|
||
},
|
||
}
|
||
|
||
local lookup = {}
|
||
for k,v in pairs(SittingOnPlayerPoses) do
|
||
table.insert(lookup, {v.FindAng, v})
|
||
table.insert(lookup, {v.FindAng + 360, v})
|
||
table.insert(lookup, {v.FindAng - 360, v})
|
||
end
|
||
|
||
local function FindPose(this,me)
|
||
local avec = me:GetAimVector()
|
||
avec.z = 0
|
||
avec:Normalize()
|
||
local evec = this:GetRight()
|
||
evec.z = 0
|
||
evec:Normalize()
|
||
local derp = avec:Dot(evec)
|
||
|
||
local avec2 = me:GetAimVector()
|
||
avec2.z = 0
|
||
avec2:Normalize()
|
||
local evec2 = this:GetForward()
|
||
evec2.z = 0
|
||
evec2:Normalize()
|
||
local herp = avec2:Dot(evec2)
|
||
local v = Vector(derp,herp,0)
|
||
local a = v:Angle()
|
||
|
||
local ang = a.y
|
||
ang = ang + 90 + 180
|
||
ang = ang % 360
|
||
|
||
table.sort(lookup,function(aa,bb)
|
||
return d(ang,aa[1]) < d(ang,bb[1])
|
||
end)
|
||
return lookup[1][2]
|
||
end
|
||
|
||
function META.Sit(ply, EyeTrace, ang, parent, parentbone, func, exit, wantedAng)
|
||
if EyeTrace == nil then
|
||
EyeTrace = ply:GetEyeTrace()
|
||
elseif type(EyeTrace) == "Vector" then
|
||
return Sit(ply, EyeTrace, ang or Angle(0,0,0), parent, parentbone or 0, func, exit)
|
||
end
|
||
|
||
local valid, ent = SitAnywhere.ValidSitTrace(ply, EyeTrace)
|
||
if not valid then return end
|
||
local surfaceAng = EyeTrace.HitNormal:Angle() + Angle(-270, 0, 0)
|
||
ang = surfaceAng
|
||
|
||
if wantedAng and math.abs(surfaceAng.pitch) <= 15 then
|
||
ent = EyeTrace.Entity
|
||
if EyeTrace.HitWorld or not ent:IsPlayer() then
|
||
if SitAnywhere.CheckValidAngForSit(EyeTrace.HitPos, EyeTrace.HitNormal:Angle(), wantedAng) then
|
||
ang.yaw = wantedAng + 90
|
||
else
|
||
return
|
||
end
|
||
end
|
||
return Sit(ply, EyeTrace.HitPos - Vector(0, 0, 23), ang, ent, EyeTrace.PhysicsBone or 0)
|
||
end
|
||
|
||
if ix.config.Get("sitOnPlayers", true) then
|
||
local veh
|
||
if not EyeTrace.HitWorld and IsValid(EyeTrace.Entity) and EyeTrace.Entity:IsPlayer() and IsValid(EyeTrace.Entity:GetVehicle()) and EyeTrace.Entity:GetVehicle().playerdynseat then
|
||
local safe = 256
|
||
veh = EyeTrace.Entity:GetVehicle()
|
||
while IsValid(veh.SittingOnMe) and IsValid(veh.SittingOnMe:GetDriver()) and safe > 0 do
|
||
safe = safe - 1
|
||
veh = veh.SittingOnMe
|
||
end
|
||
else
|
||
for k, v in pairs(ents.FindInSphere(EyeTrace.HitPos, 12)) do
|
||
local safe = 256
|
||
veh = v
|
||
while IsValid(veh.SittingOnMe) and IsValid(veh.SittingOnMe:GetDriver()) and safe > 0 do
|
||
safe = safe - 1
|
||
veh = veh.SittingOnMe
|
||
end
|
||
end
|
||
end
|
||
|
||
if IsValid(veh) and veh:GetClass() == "prop_vehicle_prisoner_pod" and veh:GetModel() ~= "models/vehicles/prisoner_pod_inner.mdl" and veh:GetDriver() and veh:GetDriver():IsValid() and not veh.PlayerSitOnPlayer then
|
||
if IsValid(veh.holder) and veh.holder.GetTargetPlayer and veh.holder:GetTargetPlayer() == ply then return end
|
||
|
||
if veh:GetDriver():GetInfoNum("sitting_allow_on_me", 1) == 0 then
|
||
ply:ChatPrint(("%s отключил возможность сидеть на нём!"):format(veh:GetDriver():Name()))
|
||
return false
|
||
end
|
||
|
||
local pose = FindPose(veh, ply)
|
||
local pos = veh:GetDriver():GetPos()
|
||
|
||
if veh.plyposhack then
|
||
pos = veh:LocalToWorld(veh.plyposhack)
|
||
end
|
||
|
||
local vec, ang2 = LocalToWorld(pose.Pos, pose.Ang, pos, veh:GetAngles())
|
||
|
||
if veh:GetParent() == ply then return false end
|
||
|
||
ent = Sit(ply, vec, ang2, veh, 0, pose.Func, pose.OnExitFunc)
|
||
|
||
if ent and IsValid(ent) then
|
||
ent.PlayerOnPlayer = true
|
||
veh.SittingOnMe = ent
|
||
end
|
||
|
||
return true, ent
|
||
end
|
||
else
|
||
for k, v in pairs(ents.FindInSphere(EyeTrace.HitPos, 5)) do
|
||
if v.playerdynseat then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
|
||
local shouldSitOnPlayer = (ply.IsFlying and ply:IsFlying()) or EyeTrace.Entity == ply:GetGroundEntity() or ply:GetMoveType() == MOVETYPE_NOCLIP
|
||
if IsValid(EyeTrace.Entity) and EyeTrace.Entity:IsPlayer() and ix.config.Get("sitOnPlayerEntities", true) and shouldSitOnPlayer then
|
||
ent = EyeTrace.Entity
|
||
if IsValid(ent:GetVehicle()) then return end
|
||
|
||
local min, max = ent:GetCollisionBounds()
|
||
local zadjust = math.abs(min.z) + math.abs(max.z)
|
||
local seatPos = ent:GetPos() + Vector(0, 0, 10 + zadjust / 2)
|
||
|
||
local vehicle = Sit(ply, seatPos, ply:GetAngles(), ent, EyeTrace.PhysicsBone or 0)
|
||
return vehicle
|
||
end
|
||
|
||
if math.abs(surfaceAng.pitch) <= 15 then
|
||
ang = Angle()
|
||
local sampleResolution = 24
|
||
local dists, distsang, ang_smallest_hori, smallest_hori = SitAnywhere.GetAreaProfile(EyeTrace.HitPos, sampleResolution, false)
|
||
local infront = ((ang_smallest_hori or 0) + 180) % 360
|
||
|
||
local cancelSit, seat = hook.Run("HandleSit", ply, dists, EyeTrace)
|
||
if cancelSit then
|
||
return seat
|
||
end
|
||
|
||
if ang_smallest_hori and distsang[infront].Hit and distsang[infront].Distance > 14 and smallest_hori <= 16 then
|
||
local hori = distsang[ang_smallest_hori].HorizontalTrace
|
||
ang.yaw = (hori.HitNormal:Angle().yaw - 90)
|
||
return Sit(ply, EyeTrace.HitPos - Vector(0, 0, 23), ang, (not EyeTrace.HitWorld) and EyeTrace.Entity, EyeTrace.PhysicsBone or 0)
|
||
else
|
||
table.sort(dists, function(a,b) return b.Distance < a.Distance end)
|
||
local wants = {}
|
||
local eyeang = ply:EyeAngles() + Angle(0, 180, 0)
|
||
for I = 1, #dists do
|
||
local trace = dists[I]
|
||
local behind = distsang[(trace.ang + 180) % 360]
|
||
if behind.Distance2 > 3 then
|
||
table.insert(wants, {
|
||
cost = math.abs(eyeang.yaw - trace.ang),
|
||
ang = trace.ang,
|
||
})
|
||
end
|
||
end
|
||
|
||
table.sort(wants,function(a,b) return b.cost > a.cost end)
|
||
if #wants == 0 then return end
|
||
ang.yaw = (wants[1].ang - 90)
|
||
return Sit(ply, EyeTrace.HitPos - Vector(0, 0, 23), ang, (not EyeTrace.HitWorld) and EyeTrace.Entity, EyeTrace.PhysicsBone or 0)
|
||
end
|
||
end
|
||
end
|
||
|
||
local function checkAllowSit(ply)
|
||
local allowSit = hook.Run("ShouldAllowSit", ply)
|
||
|
||
local bottom, top = ply:GetHull()
|
||
local diff = top.Z - bottom.Z
|
||
local trace = util.QuickTrace(ply:GetPos(), Vector(0, 0, diff), player.GetAll())
|
||
|
||
if not ix.config.Get("sitAllowTightPlaces", false) and trace.HitWorld then return false end
|
||
if allowSit == false or allowSit == true then
|
||
return allowSit
|
||
end
|
||
|
||
if ix.config.Get("sitAdminOnly", false) and not ply:IsAdmin() then
|
||
return false
|
||
end
|
||
|
||
return true
|
||
end
|
||
|
||
local function sitcmd(ply)
|
||
if not IsValid(ply) then return end
|
||
if ply:InVehicle() then return end
|
||
if not checkAllowSit(ply) then return end
|
||
|
||
local now = CurTime()
|
||
if NextUse[ply] > now then return end
|
||
|
||
if ply:Sit() then
|
||
NextUse[ply] = now + 1
|
||
else
|
||
NextUse[ply] = now + 0.1
|
||
end
|
||
end
|
||
|
||
concommand.Add("sit", function(ply, cmd, args)
|
||
sitcmd(ply)
|
||
end)
|
||
|
||
local function UndoSitting(ply)
|
||
if not IsValid(ply) then return end
|
||
|
||
local prev = ply.sitting_allowswep
|
||
if prev ~= nil then
|
||
ply.sitting_allowswep = nil
|
||
ply:SetAllowWeaponsInVehicle(prev)
|
||
end
|
||
|
||
if ix.config.Get("sitPlayerDamage", false) then
|
||
ply:SetCollisionGroup(COLLISION_GROUP_PLAYER)
|
||
ply:CollisionRulesChanged()
|
||
end
|
||
|
||
if ply.seatExit then
|
||
ply.seatExit(ply)
|
||
ply.seatExit = nil
|
||
end
|
||
end
|
||
|
||
-- Хуки
|
||
function PLUGIN:CanExitVehicle(seat, ply)
|
||
if not IsValid(seat) or not IsValid(ply) then return end
|
||
if not seat.playerdynseat then return end
|
||
if CurTime() < NextUse[ply] then return false end
|
||
end
|
||
|
||
function PLUGIN:PlayerLeaveVehicle(ply, seat)
|
||
if not IsValid(seat) or not IsValid(ply) then return end
|
||
if not seat.playerdynseat then return end
|
||
|
||
local oldpos = seat:LocalToWorld(seat.oldpos)
|
||
ply:SetPos(oldpos)
|
||
if ply.UnStuck then
|
||
ply:UnStuck()
|
||
end
|
||
|
||
for _, v in next, seat:GetChildren() do
|
||
if IsValid(v) and v.playerdynseat and IsValid(v.sittingPly) then
|
||
v.sittingPly:ExitVehicle()
|
||
end
|
||
end
|
||
|
||
SafeRemoveEntityDelayed(seat, 1)
|
||
UndoSitting(ply)
|
||
end
|
||
|
||
function PLUGIN:AllowPlayerPickup(ply)
|
||
if ply:KeyDown(IN_WALK) then
|
||
return false
|
||
end
|
||
end
|
||
|
||
function PLUGIN:PlayerDeath(pl)
|
||
local veh = pl:GetVehicle()
|
||
if IsValid(veh) and veh.playerdynseat then
|
||
SafeRemoveEntity(veh)
|
||
end
|
||
|
||
for k, v in next, pl:GetChildren() do
|
||
if IsValid(v) and v.playerdynseat and IsValid(v.sittingPly) then
|
||
v.sittingPly:ExitVehicle()
|
||
end
|
||
end
|
||
end
|
||
|
||
function PLUGIN:PlayerEnteredVehicle(pl, veh)
|
||
for k,v in next, pl:GetChildren() do
|
||
if IsValid(v) and v.playerdynseat and IsValid(v.sittingPly) then
|
||
v.sittingPly:ExitVehicle()
|
||
end
|
||
end
|
||
|
||
DropEntityIfHeld(veh)
|
||
|
||
local parent = veh:GetParent()
|
||
if IsValid(parent) then
|
||
DropEntityIfHeld(parent)
|
||
end
|
||
end
|
||
|
||
function PLUGIN:OnPlayerSit(ply, pos, ang, parent, parentbone, vehicle)
|
||
if IsValid(parent) and parent ~= game.GetWorld() then
|
||
if parent:GetModel():sub(1, 6) ~= "models" then return false end
|
||
if parent:IsPlayer() then
|
||
if not ix.config.Get("sitOnPlayerEntities", true) then return false end
|
||
if parent:GetInfoNum("sitting_allow_on_me", 1) == 0 then
|
||
ply:ChatPrint(("%s отключил возможность сидеть на нём!"):format(parent:Name()))
|
||
return false
|
||
end
|
||
|
||
if IsValid(parent:GetVehicle()) then return false end
|
||
end
|
||
end
|
||
end
|
||
|
||
function PLUGIN:EntityRemoved(ent)
|
||
if ent.playerdynseat and IsValid(ent.sittingPly) then
|
||
UndoSitting(ent.sittingPly)
|
||
end
|
||
|
||
for _, v in next, ent:GetChildren() do
|
||
if IsValid(v) and v.playerdynseat and IsValid(v.sittingPly) then
|
||
v.sittingPly:ExitVehicle()
|
||
end
|
||
end
|
||
end
|
||
|
||
function PLUGIN:PhysgunPickup(ply, ent)
|
||
if ix.config.Get("sitAntiPropSurf", true) then
|
||
local function CheckSeat(checkPly, checkEnt, tbl)
|
||
if not checkPly:InVehicle() then return true end
|
||
|
||
local vehicle = checkPly:GetVehicle()
|
||
local parent = vehicle.parent
|
||
|
||
if parent == checkEnt then return false end
|
||
|
||
for _,v in next, checkEnt:GetChildren() do
|
||
if IsValid(v) and not tbl[v] then
|
||
tbl[v] = true
|
||
if v ~= checkEnt and CheckSeat(checkPly, v, tbl) == false then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
|
||
local cEnts = constraint.GetAllConstrainedEntities(checkEnt)
|
||
if cEnts then
|
||
for _,v in next, cEnts do
|
||
if IsValid(v) and not tbl[v] then
|
||
tbl[v] = true
|
||
if v ~= checkEnt and CheckSeat(checkPly, v, tbl) == false then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if IsValid(ply:GetVehicle()) and ply:GetVehicle().playerdynseat then
|
||
if CheckSeat(ply, ent, {}) == false then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function PLUGIN:CanTool(ply, tr)
|
||
if ix.config.Get("sitAntiToolAbuse", true) and IsValid(tr.Entity) then
|
||
local function CheckSeat(checkPly, checkEnt, tbl)
|
||
if not checkPly:InVehicle() then return true end
|
||
|
||
local vehicle = checkPly:GetVehicle()
|
||
local parent = vehicle.parent
|
||
|
||
if parent == checkEnt then return false end
|
||
|
||
for _,v in next, checkEnt:GetChildren() do
|
||
if IsValid(v) and not tbl[v] then
|
||
tbl[v] = true
|
||
if v ~= checkEnt and CheckSeat(checkPly, v, tbl) == false then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
|
||
local cEnts = constraint.GetAllConstrainedEntities(checkEnt)
|
||
if cEnts then
|
||
for _,v in next, cEnts do
|
||
if IsValid(v) and not tbl[v] then
|
||
tbl[v] = true
|
||
if v ~= checkEnt and CheckSeat(checkPly, v, tbl) == false then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if IsValid(ply:GetVehicle()) and ply:GetVehicle().playerdynseat then
|
||
if CheckSeat(ply, tr.Entity, {}) == false then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
timer.Create("SitAnywhere_RemoveSeats", 15, 0, function()
|
||
for k,v in pairs(ents.FindByClass("prop_vehicle_prisoner_pod")) do
|
||
if v.playerdynseat and (not IsValid(v.sittingPly) or v:GetDriver() == nil or not v:GetDriver():IsValid() or v:GetDriver():GetVehicle() ~= v) then
|
||
v:Remove()
|
||
end
|
||
end
|
||
end)
|