Hi, I have a AI check-in system for an airline, it runs through a whole process and works fine. However obviously if a player resets or leaves the game mid function that the system would break preventing any other players from using it.
We’re looking at 80-130+ passengers so its quite important that I can take into consideration any situations which could break the system. It communicates between a local script for the GUI elements and then a server script for the ensuring stuff is visible to all players.
Tired PlayerRemoving but couldn’t get it to work or unsure how to structure it.
It sounds like the issue is that the reference to a character in your script becomes nil. I’m not sure what your system looks like exactly, but I can suggest checking if the character exists before using it.
if character ~= nil then
-- Run code using the character --
end
You might also need to listen in to the Player’s CharacterAdded event and link the new character back into your main code if the player resets.
player.CharacterAdded:Connect(function(newCharacter)
-- Link new character into main code --
end)
It’s hard to say what might work without seeing the code, but I hope this helps!
We need more infos to know how to help you, but a way to maybe fix your issue is like you tried with PlayerRemoving but you have to make like a reset function for the check in so on removing, it gets resetted. But yeah, cant say more if we havent anything to base on
Ok well here’s the code for the serverscript. Player interaction done through the localscript within our dialog UI
local main = script.Parent.Parent
local AI = main.NPC
local Events = main.Events
local Dialog = main.Dialog.ChatDialog
local Animations = main.Animations
local Detector = script.Parent.Detector.Value
local Conv = script.Parent.Parent.Conveyor
local TP = script.Parent.Parent.TP
local begone = script.Parent.Parent.begone
local Sensor = script.Parent.Parent.Sensor
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- ATTACHMENTS
local StartInteract = main.InterationPoints.Start.Interact
local PassportAInteract = main.InterationPoints.PassportAttachGive.Interact
local TakeItems = main.InterationPoints.TakeItems.Interact -- (Passport & Printed Boarding Pass)
local PlaceBag = main.InterationPoints.PlaceBaggage
activeuser = ""
sensoractive = false
-- START UP ---------------------------------------------------------------------
-- Trigger
StartInteract.Triggered:Connect(function(Player)
Player.Character.HumanoidRootPart.CFrame = TP.CFrame
Player.Character.HumanoidRootPart.Anchored = true
activeuser = Player.Name
sensoractive = true
local gui = Dialog:Clone()
gui.Frame.HandlerLocal.Enabled = true
gui.Parent = Player.PlayerGui
StartInteract.MaxActivationDistance = 0
Events.Startup:FireClient(Player)
Conv.Buffer.CanCollide = true
end)
-- Go Away Sensor (no pedos)
Sensor.Touched:Connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if sensoractive == true then
if player.Name ~= activeuser then
player.Character.HumanoidRootPart.CFrame = begone.CFrame
end
end
end)
-- CHECK IN ---------------------------------------------------------------------
-- Passport Show/Hide
Events.Passport.OnServerEvent:Connect(function(Player, Passport, Show)
if Show == true then
Passport.Cover.Transparency = 0
Passport.Page.Transparency = 0
elseif Show == false then
Passport.Cover.Transparency = 1
Passport.Page.Transparency = 1
end
end)
-- Boarding Pass Show/Hide
Events.BoardingPass.OnServerEvent:Connect(function(Player, Passport, Show)
if Show == true then
Passport.Transparency = 0
elseif Show == false then
Passport.Transparency = 1
end
end)
-- Baggage Tag Show/Hide
Events.BagTag.OnServerEvent:Connect(function(Player, Passport, Show)
if Show == true then
Passport.Part1.Transparency = 0
Passport.Part2.Transparency = 0
elseif Show == false then
Passport.Part1.Transparency = 1
Passport.Part2.Transparency = 1
end
end)
-- Player Tools (Give / Remove)
Events.Tools.OnServerEvent:Connect(function(Player, ToolItem, Show)
if Show == true then -- Gives Tool
local Tool = ReplicatedStorage.CheckInSystem.Tools:FindFirstChild(ToolItem):Clone()
Tool.Parent = Player.Backpack
elseif Show == false then -- Removes Tool
local Tool = Player.Backpack:FindFirstChild(ToolItem):Destroy()
end
end)
-- Baggage Handling
local Slot = script.Parent.Parent.Detector
-- Places Bag on belt
Events.BaggagePlace.OnServerEvent:Connect(function(Player)
print("triggered place bag")
local SuitcaseModule = require(game.ServerScriptService.BaggageServer.Components.Suitcase)
Player.Character.Humanoid:UnequipTools()
Player.Backpack:FindFirstChild("Suitcase")
local tool = Player.Backpack:FindFirstChild("Suitcase")
local NewSuitcase = SuitcaseModule.New(tool)
NewSuitcase:SetAttribute("Color3", color3Value)
NewSuitcase.Parent = Slot
NewSuitcase:SetPrimaryPartCFrame(Slot.CFrame)
local tool = Player.Backpack:FindFirstChild("Suitcase"):Destroy()
wait(8)
NewSuitcase:SetAttribute("IsTagged", true)
NewSuitcase:SetAttribute("Name", Player.Name)
end)
--Sends Suitcase
Events.SendBaggage.OnServerEvent:Connect(function(Player)
for i,v in pairs(Slot.Suitcase:GetDescendants()) do
if (v:IsA("MeshPart") or v:IsA("BasePart")) then
v.Anchored = false
end
end
Slot.Suitcase.Parent = workspace.BaggageSystemV3.System.Suitcases
Conv.Buffer.CanCollide = false
wait(2)
Conv.Buffer.CanCollide = true
end)
-- Resets System
Events.Reset.OnServerEvent:Connect(function(Player)
print("Resettting System, Please Wait...")
Player.Character.HumanoidRootPart.Anchored = false
StartInteract.MaxActivationDistance = 10
activeuser = ""
sensoractive = false
end)
It works fine, however that’s only ran when the whole process is finished. And If the player were to die or leave the game midway through the check in process or mid function then it breaks. The issue is I don’t know how to get it to to-do something if the player were to leave or die.
Do you get an error in the output, or does the code continue to run but with undesirable behavior? If you’re not getting any errors in your output, what’s the undesirable behavior that’s occurring and breaking your system?
It’s very interactive with the player. Soon as it can’t find the activeuser when trying to run something relating to the camera, or giving a tool etc. The script then breaks at that point.
And even If they left/died during a point between functions when say waiting for the player to place their suitcase, it has no idea the player has left so isn’t able to reset itself to allow the next player to come and use the system.
Thanks, but the code in itself is working fine as intended. I get no issues in normal operation. However this system is for roaviation airline usage where we get 80-130+ passengers so to put it simply, our systems need to be robust and idiot proof for lack of a better word.
We can disable reset & ensure our staff are not refreshing passengers that are using the machines which fixes that issue. However we still need some function to monitor ingame players, if a player leaves that matches the ‘activeuser’ value then the system can then initiate a reset to be ready for the next player that wishes to checkin.
The suitcase stuff is talking to data for a tech group baggage system to allow integration with my system. All the modules and such are in the game on start up via their obscured loader.
It’s quite complex with voicelines & both facial and body animations (complex by roav standards). What I’ve sent is only half the code as a lot of stuff is done client side on the players dialog gui.
All I need is a way to monitor ingame players and if the player that is using the system leaves the game then it resets, which sets everything it needs todo first like prompts, clears the baggage belt, etc, destroy the current server script then clone & parent a fresh copy from replicated storage into the system before enabling it.
I tried doing this however it doesn’t work.
local Players = game:GetService('Players')
local ActiveUser = script.Parent.ActiveUser.Value
Players.PlayerRemoving:Connect(function(Player)
if Player.UserID == ActiveUser then
print("Player has left the game, resetting machine")
-- Does resetty system stuff
ActiveUser = nil
end
end)
I also added this line into the trigger on the serverscript, which when printed shows the correct user id.
ActiveUserV = Player.UserId
I tested this already with the players username and it didn’t work.
Bit complicated sure, but its only on the occasion a player leaves, crashes or whatever mid using it. Under normal usage the system is able to reset itself just fine.
Coroutines or the task library might be able to allow you to cancel the system once a player leaves. I’ve made an example that shows a per-player thread which cancels after the player leaves the game:
local Players = game:GetService("Players")
local threads = {}
local function onPlayerAdded(player)
threads[player] = task.spawn(function()
-- Initiate the system for the player in here
end)
end
local function onPlayerRemoving(player)
if threads[player] then
task.cancel(threads[player])
threads[player] = nil
-- Then reset the system
end
end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)
No idea what that is, but the system has to start with the proximity prompt at the check in desk. I can try get a video of it in operation which might clarify some things.
Tasks would be ideal to cancel this, I’ll write an example
Edit: @MissBasicallySoft Sorry for the late reply because a parcel got delivered, but this is esentially what you need to do:
local Players = game:GetService("Players")
local prompt = -- Where the prompt is located
local threads = {}
local function onPromptTrigger(player)
threads[player] = task.spawn(function()
-- Initiate the dialog system in here
end)
end
local function onPlayerRemoving(player)
if threads[player] then
task.cancel(threads[player])
threads[player] = nil
end
end
prompt.Triggered:Connect(onPromptTrigger)
Players.PlayerRemoving:Connect(onPlayerRemoving)
Although do note that canceling a thread does not disconnect connections created within it, in that case you’ll need to do something like this:
local Players = game:GetService("Players")
local prompt = -- Where the prompt is located
local threads = {}
local connections = {}
local function onPromptTrigger(player)
connections[player] = {}
threads[player] = task.spawn(function()
-- Initiate the dialog system in here
table.insert(connections[player], exampleEvent:Connect(function()
end))
end)
end
local function onPlayerRemoving(player)
if threads[player] then
task.cancel(threads[player])
threads[player] = nil
for _, connection in connections[player] do connection:Disconnect() end
connections[player] = nil
end
end
prompt.Triggered:Connect(onPromptTrigger)
Players.PlayerRemoving:Connect(onPlayerRemoving)